CustomBranding
CustomBranding 3.0.5 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
├── Branding-Elemente mit `data-custom-branding-placement="top"`
└── CustomNavigation (wird nicht verändert)
CustomFooter
└── CustomBrandingBottomHost
CustomBranding rendert seine Top-Elemente direkt in CustomHeader und entfernt beim erneuten Rendern nur die über data-custom-branding-owner markierten eigenen Knoten. CustomNavigation und andere Erweiterungen im selben Placeholder bleiben erhalten.
Die zentrale Custom-Branding-Action verwendet Sequence = 90. MegaMenu verwendet 100 und Current Navigation 110, sodass Custom Branding den gemeinsamen Header zuerst vorbereitet. Die DOM-Integration bleibt trotzdem unabhängig von der tatsächlichen asynchronen Fertigstellungsreihenfolge.
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,
"portalSettings": {
"providerKey": "custombranding",
"contractVersion": 1,
"minimumPortalSettingsVersion": "3.0.0"
},
"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.
Eine eigene Suche kann deklarativ als form mit einem input type="search" und einem Submit-Button unter
placeholdertop.elements konfiguriert werden. Formulare werden ausschließlich als GET-Formulare akzeptiert;
unsichere oder protokollrelative Action-URLs werden verworfen. Das vollständige Beispiel enthält eine solche Suche.
Ist placeholderbottom.elements leer oder fehlt die Eigenschaft, rendert CustomBranding automatisch den bisherigen
Portal Settings-Link auf ~sitecollection/SitePages/PortalSettings.aspx. Sobald eigene Footer-Elemente konfiguriert
sind, ersetzen sie diesen Standard.
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. PortalSettings ab Version 3.0.1 kann die zentrale Action anhand folgender Werte erkennen, die Properties schemaerhaltend bearbeiten und eine noch fehlende Action beim ersten Speichern selbst anlegen:
- Component ID:
035ba968-6488-4d42-86b3-0470ffcc95b9 - Location:
ClientSideExtension.ApplicationCustomizer - Scope:
SPSite.UserCustomActions - Schema:
schemaVersion: 2 - Provider-Marker:
portalSettings.providerKey: custombranding
Ist noch keine Action vorhanden, erscheint CustomBranding in PortalSettings als Bereit zur Aktivierung. Voraussetzung ist lediglich, dass custom-branding.sppkg bereits im App Catalog bereitgestellt wurde. Der Button CustomBranding aktivieren erzeugt anschließend genau eine site-scoped Action. Das PowerShell-Skript bleibt für automatisierte Rollouts und Classic-ScriptLink-Registrierungen verfügbar.
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.querySelectorAll('#CustomHeader > [data-custom-branding-placement="top"]').length,
megaMenu: !!document.getElementById('CustomNavigation')
});
Classic-Diagnose:
typeof window.CustomBrandingClassic
window.CustomBrandingClassic.reload()
Upgrade von 1.x
- Paket im App Catalog durch Version
3.0.1.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.