- 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.
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
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
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
custom-branding.sppkgim App Catalog hochladen oder ersetzen und zentral bereitstellen.- Das Skript in der SharePoint Management Shell ausführen.
- Eine moderne Seite mit
Strg+F5neu laden.
.\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:
# 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:
{
"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, alleon*-Attribute,javascript:,data:und CSS miturl()oderexpression()werden verworfen.- Bilder benötigen immer ein
alt; dekorative Bilder verwendenalt: "". - Leere Links und Buttons sind nicht erlaubt; Buttons erhalten immer
type="button". - Links mit
target="_blank"erhalten automatischrel="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.
npm run build:classic
Danach classic/dist/custom-branding-classic.js nach beispielsweise /SiteAssets/custom-branding/ hochladen und zentral registrieren:
.\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:
$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:
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:
typeof window.CustomBrandingClassic
window.CustomBrandingClassic.reload()
Upgrade von 1.x
- Paket im App Catalog durch Version
3.0.0.0ersetzen und bereitstellen. add-custombranding.ps1einmal pro Site Collection ausführen; bestehende Properties bleiben erhalten.- Moderne und gegebenenfalls klassische Seiten testen.
- Erst nach erfolgreicher Abnahme alte web-scoped Aktionen als bereinigt bestätigen.
Ein Downgrade sollte nur zusammen mit einer Sicherung der ClientSideComponentProperties erfolgen.