Add Accordion web part implementation with dynamic SharePoint list integration

- Created Accordion web part with SPFx 1.4.1 framework.
- Implemented dynamic loading of SharePoint lists and fields.
- Added configuration options for title, content, and category fields.
- Included support for multiple open sections and initial state settings.
- Developed HTML sanitizer for rich text content.
- Implemented accessible accordion UI with category grouping.
- Added localization support for English and German languages.
- Created necessary configuration files for deployment and asset management.
- Added validation script to ensure project compliance with standards.
This commit is contained in:
Torsten Brendgen
2026-08-23 22:34:12 +02:00
commit bf9781d043
27 changed files with 1009 additions and 0 deletions
+41
View File
@@ -0,0 +1,41 @@
'use strict';
var fs = require('fs');
var path = require('path');
var root = path.resolve(__dirname, '..');
var passed = 0;
function read(file) { return fs.readFileSync(path.join(root, file), 'utf8'); }
function json(file) { return JSON.parse(read(file)); }
function assert(condition, message) { if (!condition) { throw new Error(message); } passed++; }
var packageJson = json('package.json');
var solution = json('config/package-solution.json').solution;
var config = json('config/config.json');
var manifest = json('src/webparts/accordion/AccordionWebPart.manifest.json');
var webPart = read('src/webparts/accordion/AccordionWebPart.ts');
var component = read('src/webparts/accordion/components/Accordion.tsx');
var sanitizer = read('src/webparts/accordion/AccordionHtmlSanitizer.ts');
var styles = read('src/webparts/accordion/components/Accordion.module.scss');
assert(packageJson.version === '1.0.0', 'Package version must be 1.0.0.');
assert(solution.version === '1.0.0.0', 'Solution version must be 1.0.0.0.');
assert(solution.includeClientSideAssets === true, 'Client-side assets must be included.');
assert(solution.skipFeatureDeployment === true, 'Solution must support central deployment.');
assert(manifest.componentType === 'WebPart', 'Component must be a web part.');
assert(!!config.bundles['accordion-web-part'], 'Accordion bundle is missing.');
assert(webPart.indexOf("PropertyPaneDropdown('listId'") >= 0, 'Dynamic list selection is missing.');
assert(webPart.indexOf("PropertyPaneDropdown('contentField'") >= 0, 'Dynamic content field selection is missing.');
assert(webPart.indexOf("PropertyPaneDropdown('categoryField'") >= 0, 'Category field selection is missing.');
assert(component.indexOf("aria-expanded={open}") >= 0 && component.indexOf("role='region'") >= 0,
'Accessible accordion semantics are missing.');
assert(component.indexOf('sanitizeAccordionHtml(item.content)') >= 0, 'Rich text is not sanitized before rendering.');
var allowedTags = sanitizer.substring(sanitizer.indexOf('const AllowedTags'), sanitizer.indexOf('const DropContentTags'));
assert(allowedTags.indexOf("'script'") < 0 && allowedTags.indexOf("'img'") < 0 &&
sanitizer.indexOf("'script'") >= 0,
'Unsafe rich-text elements must be removed rather than allow-listed.');
['neutralPrimary', 'neutralLight', 'neutralLighter', 'themePrimary', 'white'].forEach(function (slot) {
assert(styles.indexOf('[theme: ' + slot + ', default:') >= 0, 'SharePoint theme slot is missing: ' + slot);
});
console.log('Accordion project validation passed:', passed);