- Introduced custom branding CSS styles in `custom-branding.css`. - Created example JSON configuration for custom branding in `custom-branding.example.json`. - Implemented branding configuration logic in `BrandingConfig.ts` to normalize and validate branding settings. - Developed CSS loader to manage loading and unloading of custom stylesheets in `BrandingCssLoader.ts`. - Added DOM rendering capabilities for branding elements in `BrandingDomRenderer.ts`. - Defined types and interfaces for branding elements and configurations in `BrandingTypes.ts`. - Included localization support for German in `de-de.js`. - Added unit tests for branding configuration, CSS loader, and DOM renderer. - Validated project structure and static assets with new validation scripts.
204 lines
7.3 KiB
Markdown
204 lines
7.3 KiB
Markdown
# CustomBranding
|
|
|
|
CustomBranding 3.0 ist ein zentraler SPFx-1.4.1-Application-Customizer für SharePoint Server Subscription Edition. Die Solution lädt freigegebene Stylesheets und rendert eine kontrollierte Komponentenstruktur im oberen oder unteren SharePoint-Placeholder. Moderne und klassische Seiten verwenden dieselben `ClientSideComponentProperties`.
|
|
|
|
Die Konfiguration liegt in genau einer `SPSite.UserCustomAction` pro Site Collection. Es werden weder eine versteckte Liste noch ein Property Bag benötigt. Dadurch gilt das Branding automatisch für das Root Web, vorhandene Subwebs und später angelegte Subwebs.
|
|
|
|
## Architektur
|
|
|
|
```text
|
|
App Catalog
|
|
└── zentral bereitgestelltes SPFx-Bundle
|
|
|
|
Site Collection
|
|
├── SPSite.UserCustomAction mit ClientSideComponentProperties
|
|
├── moderne Seiten: SPFx Application Customizer
|
|
└── klassische Seiten: optionaler SPSite ScriptLink
|
|
|
|
CustomHeader
|
|
├── CustomBrandingTopHost
|
|
└── MegaMenuHost (wird nicht verändert)
|
|
|
|
CustomFooter
|
|
└── CustomBrandingBottomHost
|
|
```
|
|
|
|
CustomBranding verändert nur seine eigenen Host-Elemente. Das MegaMenu und andere Erweiterungen im selben Placeholder bleiben bei Navigation und erneutem Rendern erhalten.
|
|
|
|
## Voraussetzungen und Build
|
|
|
|
- SharePoint Server Subscription Edition
|
|
- SPFx 1.4.1
|
|
- Node.js 8.17.0
|
|
- npm 6.13.4
|
|
- lokale Gulp-Version 3.9.1
|
|
|
|
```powershell
|
|
npm install
|
|
npm test
|
|
npm run package
|
|
```
|
|
|
|
`npm run package` führt zuerst die Tests und den Classic-Build aus. Das SharePoint-Paket entsteht unter `sharepoint/solution/custom-branding.sppkg`. Die Classic-Dateien liegen anschließend unter `classic/dist`.
|
|
|
|
Die alte SPFx-Toolchain lässt sich mit aktuellen Node-Versionen nicht zuverlässig paketieren. Der abschließende Ship-Build muss deshalb mit Node.js 8.17.0 erfolgen.
|
|
|
|
## Installation und zentrale Registrierung
|
|
|
|
1. `custom-branding.sppkg` im App Catalog hochladen oder ersetzen und zentral bereitstellen.
|
|
2. Das Skript in der SharePoint Management Shell ausführen.
|
|
3. Eine moderne Seite mit `Strg+F5` neu laden.
|
|
|
|
```powershell
|
|
.\deployment\add-custombranding.ps1 `
|
|
-SiteUrl 'http://clshp001/sites/portal' `
|
|
-CssPath '~sitecollection/SiteAssets/branding/custom-branding.css'
|
|
```
|
|
|
|
Das Skript arbeitet idempotent: Es erhält vorhandene Properties, entfernt doppelte oder alte web-scoped Registrierungen und erzeugt genau eine site-scoped Action. Ein bewusstes Zurücksetzen erfolgt nur mit `-ResetConfiguration`.
|
|
|
|
Weitere Optionen:
|
|
|
|
```powershell
|
|
# Debug-Ausgaben einschalten und einen externen HTTPS-CSS-Host freigeben
|
|
.\deployment\add-custombranding.ps1 `
|
|
-SiteUrl 'http://clshp001/sites/portal' `
|
|
-EnableDebug `
|
|
-AllowedCssHost 'cdn.example.org'
|
|
|
|
# Extension deaktivieren, Konfiguration aber erhalten
|
|
.\deployment\add-custombranding.ps1 `
|
|
-SiteUrl 'http://clshp001/sites/portal' `
|
|
-Disable
|
|
```
|
|
|
|
## Konfiguration
|
|
|
|
Das aktuelle Konfigurationsschema hat die Version 2:
|
|
|
|
```json
|
|
{
|
|
"schemaVersion": 2,
|
|
"enabled": true,
|
|
"debug": false,
|
|
"allowedCssHosts": [],
|
|
"cssfiles": [
|
|
{
|
|
"path": "~sitecollection/SiteAssets/branding/custom-branding.css",
|
|
"media": "all"
|
|
}
|
|
],
|
|
"placeholdertop": {
|
|
"elements": [
|
|
{
|
|
"type": "section",
|
|
"attributes": {
|
|
"class": "custom-branding-banner",
|
|
"role": "region",
|
|
"aria-label": "Portalhinweis"
|
|
},
|
|
"children": [
|
|
{
|
|
"type": "strong",
|
|
"content": "Willkommen im Portal"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
"placeholderbottom": {
|
|
"elements": []
|
|
}
|
|
}
|
|
```
|
|
|
|
Bestehende 1.x-Konfigurationen mit einem Root-Array `elements` werden weiterhin als Top-Inhalt gelesen. Unbekannte Properties ignoriert die Runtime. Das vollständige Beispiel liegt unter `examples/custom-branding.example.json`.
|
|
|
|
### Sicherheitsgrenzen
|
|
|
|
Erlaubte Elemente:
|
|
|
|
`div`, `span`, `p`, `a`, `button`, `img`, `h1`, `h2`, `h3`, `strong`, `em`, `nav`, `section`
|
|
|
|
Attribute und Styles werden pro Element über feste Allowlisten geprüft. Insbesondere gelten folgende Regeln:
|
|
|
|
- `script`, `iframe`, alle `on*`-Attribute, `javascript:`, `data:` und CSS mit `url()` oder `expression()` werden verworfen.
|
|
- Bilder benötigen immer ein `alt`; dekorative Bilder verwenden `alt: ""`.
|
|
- Leere Links und Buttons sind nicht erlaubt; Buttons erhalten immer `type="button"`.
|
|
- Links mit `target="_blank"` erhalten automatisch `rel="noopener noreferrer"`.
|
|
- Relative CSS-Pfade und CSS derselben Origin sind erlaubt. Fremde Quellen benötigen HTTPS und einen Eintrag in `allowedCssHosts`.
|
|
- Maximal 20 Stylesheets, 200 Elemente, acht Ebenen und 100.000 Zeichen Konfiguration werden verarbeitet.
|
|
|
|
Unsichere Teilwerte werden kontrolliert verworfen, ohne die SharePoint-Seite zu blockieren. Details erscheinen nur bei `debug: true` in der Browserkonsole mit dem Präfix `[CustomBranding]`.
|
|
|
|
## Classic SharePoint
|
|
|
|
Der SPFx Application Customizer selbst läuft nicht auf klassischen Seiten. Version 3.0 enthält deshalb eine separate ES5-Runtime mit demselben Sicherheits- und Konfigurationsmodell.
|
|
|
|
```powershell
|
|
npm run build:classic
|
|
```
|
|
|
|
Danach `classic/dist/custom-branding-classic.js` nach beispielsweise `/SiteAssets/custom-branding/` hochladen und zentral registrieren:
|
|
|
|
```powershell
|
|
.\deployment\add-custombranding.ps1 `
|
|
-SiteUrl 'http://clshp001/sites/portal' `
|
|
-ClassicScriptUrl '~sitecollection/SiteAssets/custom-branding/custom-branding-classic.js'
|
|
```
|
|
|
|
Der site-scoped ScriptLink gilt auch für später angelegte Subwebs. Entfernen lässt er sich mit `-RemoveClassicScriptLink`. Weitere Hinweise stehen in `classic/classic-deployment.md`.
|
|
|
|
## PortalSettings v3
|
|
|
|
CustomBranding funktioniert unabhängig von PortalSettings. Das geplante PortalSettings-v3-Webpart kann die Action anhand folgender Werte erkennen und die Properties schemaerhaltend bearbeiten:
|
|
|
|
- Component ID: `035ba968-6488-4d42-86b3-0470ffcc95b9`
|
|
- Location: `ClientSideExtension.ApplicationCustomizer`
|
|
- Scope: `SPSite.UserCustomActions`
|
|
- Schema: `schemaVersion: 2`
|
|
|
|
Ein Editor muss unbekannte Properties erhalten und vor dem Speichern dieselben Element-, Attribut-, URL- und CSS-Grenzen beachten.
|
|
|
|
## Diagnose
|
|
|
|
Zentrale Registrierung prüfen:
|
|
|
|
```powershell
|
|
$site = Get-SPSite 'http://clshp001/sites/portal'
|
|
$site.UserCustomActions | Where-Object {
|
|
$_.ClientSideComponentId -eq [Guid]'035ba968-6488-4d42-86b3-0470ffcc95b9'
|
|
} | Select-Object Id, Title, Location, ClientSideComponentProperties
|
|
$site.Dispose()
|
|
```
|
|
|
|
Browserkonsole auf einer modernen Seite:
|
|
|
|
```javascript
|
|
performance.getEntriesByType('resource')
|
|
.map(function (entry) { return entry.name; })
|
|
.filter(function (url) { return url.toLowerCase().indexOf('custom-branding') >= 0; });
|
|
|
|
({
|
|
header: !!document.getElementById('CustomHeader'),
|
|
branding: !!document.getElementById('CustomBrandingTopHost'),
|
|
megaMenu: !!document.getElementById('MegaMenuHost')
|
|
});
|
|
```
|
|
|
|
Classic-Diagnose:
|
|
|
|
```javascript
|
|
typeof window.CustomBrandingClassic
|
|
window.CustomBrandingClassic.reload()
|
|
```
|
|
|
|
## Upgrade von 1.x
|
|
|
|
1. Paket im App Catalog durch Version `3.0.0.0` ersetzen und bereitstellen.
|
|
2. `add-custombranding.ps1` einmal pro Site Collection ausführen; bestehende Properties bleiben erhalten.
|
|
3. Moderne und gegebenenfalls klassische Seiten testen.
|
|
4. Erst nach erfolgreicher Abnahme alte web-scoped Aktionen als bereinigt bestätigen.
|
|
|
|
Ein Downgrade sollte nur zusammen mit einer Sicherung der `ClientSideComponentProperties` erfolgen.
|