feat: Update version to 3.0.5 and enhance CustomBranding with new search form functionality and improved styling

This commit is contained in:
Torsten Brendgen
2026-08-19 23:33:56 +02:00
parent 36bcef54e7
commit 281dfa68de
13 changed files with 353 additions and 60 deletions
+20 -2
View File
@@ -49,9 +49,9 @@ assert(customBottom.config.placeholderbottom.elements.length === 1 &&
var legacy = normalize({ elements: [{ type: 'span', content: 'Alt' }] }, siteUrl);
assert(legacy.config.placeholdertop.elements.length === 1, 'Das Legacy-Root-Array muss weiter funktionieren.');
['div', 'span', 'p', 'a', 'button', 'img', 'h1', 'h2', 'h3', 'strong', 'em', 'nav', 'section']
['div', 'span', 'p', 'a', 'button', 'form', 'input', 'img', 'h1', 'h2', 'h3', 'strong', 'em', 'nav', 'section']
.forEach(function (tag) {
var attributes = tag === 'img' ? { alt: '' } : undefined;
var attributes = tag === 'img' ? { alt: '' } : (tag === 'form' ? { action: '/search' } : undefined);
var content = tag === 'a' || tag === 'button' ? tag : undefined;
assert(!!element({ type: tag, content: content, attributes: attributes }), 'Erlaubter Tag fehlt: ' + tag);
});
@@ -83,6 +83,24 @@ assert(!element({ type: 'img', attributes: { src: '/logo.png' } }), 'Bilder ohne
assert(!!element({ type: 'img', attributes: { src: '/logo.png', alt: '' } }), 'Dekorative Bilder mit leerem alt sind erlaubt.');
assert(!element({ type: 'button' }), 'Leere Buttons muessen verworfen werden.');
var searchForm = element({
type: 'form',
attributes: { action: '~sitecollection/_layouts/15/search.aspx/siteall', method: 'post' },
children: [
{ type: 'input', attributes: { type: 'text', name: 'q', placeholder: 'Suchen', autocomplete: 'off' } },
{ type: 'button', attributes: { type: 'submit', 'aria-label': 'Suchen' } }
]
});
assert(searchForm.attributes.action === siteUrl + '/_layouts/15/search.aspx/siteall' && searchForm.attributes.method === 'get',
'Suchformulare muessen eine sichere GET-Action verwenden.');
assert(searchForm.children[0].attributes.type === 'search' && searchForm.children[0].attributes.name === 'q',
'Suchfelder muessen auf type=search begrenzt sein.');
assert(searchForm.children[1].attributes.type === 'submit', 'Submit-Buttons in Suchformularen muessen erhalten bleiben.');
assert(!element({ type: 'form', attributes: { action: 'javascript:alert(1)' } }),
'Formulare mit unsicherer Action muessen verworfen werden.');
assert(!element({ type: 'form', attributes: { action: '//evil.example.org/search' } }),
'Formulare mit protokollrelativer Action muessen verworfen werden.');
var css = normalize({
allowedCssHosts: ['cdn.example.org'],
cssfiles: [
+5 -2
View File
@@ -21,18 +21,21 @@ var packageJson = json('package.json');
var solution = json('config/package-solution.json').solution;
var serveText = read('config/serve.json').toLowerCase();
var appSource = read('src/extensions/customBranding/CustomBrandingApplicationCustomizer.ts');
var configSource = read('src/extensions/customBranding/BrandingConfig.ts');
var rendererSource = read('src/extensions/customBranding/BrandingDomRenderer.ts');
var classicSource = read('classic/custom-branding-classic.js');
var deploymentSource = read('deployment/add-custombranding.ps1');
assert(packageJson.version === '3.0.4', 'package.json hat nicht Version 3.0.4.');
assert(solution.version === '3.0.4.0', 'Solution-Version ist inkonsistent.');
assert(packageJson.version === '3.0.5', 'package.json hat nicht Version 3.0.5.');
assert(solution.version === '3.0.5.0', 'Solution-Version ist inkonsistent.');
assert(solution.skipFeatureDeployment === true, 'Tenantweite Bereitstellung ist nicht aktiviert.');
assert(!solution.features, 'Die alte web-scoped Feature-Registrierung ist noch vorhanden.');
assert(!fs.existsSync(path.join(root, 'sharepoint/assets/elements.xml')), 'elements.xml muss entfernt sein.');
assert(serveText.indexOf('onclick') < 0, 'serve.json enthaelt ein Event-Attribut.');
assert(serveText.indexOf('placeholdertop') >= 0, 'serve.json verwendet nicht das echte Schema.');
assert(rendererSource.indexOf('innerHTML') < 0 && appSource.indexOf('innerHTML') < 0, 'Der moderne Renderer darf innerHTML nicht verwenden.');
assert(configSource.indexOf("'form', 'input'") >= 0 && configSource.indexOf("result.method = 'get'") >= 0,
'Sichere deklarative Suchformulare sind nicht freigeschaltet.');
assert(classicSource.indexOf('innerHTML') < 0, 'Die Classic-Runtime darf innerHTML nicht verwenden.');
assert(classicSource.indexOf('~sitecollection/SitePages/PortalSettings.aspx') >= 0,
'Der Standard-Footer fehlt in der Classic-Runtime.');