@ccslabs/xtend 0.1.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +65 -0
- package/LICENSE +201 -0
- package/README.md +184 -0
- package/a11y/motion-contrast-policy.d.ts +32 -0
- package/a11y/motion-contrast-policy.js +261 -0
- package/a11y/runtime-a11y-contract.d.ts +44 -0
- package/a11y/runtime-a11y-contract.js +385 -0
- package/a11y/screenreader-signals.d.ts +32 -0
- package/a11y/screenreader-signals.js +372 -0
- package/api.d.ts +168 -0
- package/api.js +864 -0
- package/catalog/catalog-public-types.d.ts +66 -0
- package/catalog/component-catalog-coverage.d.ts +20 -0
- package/catalog/component-catalog-coverage.js +377 -0
- package/catalog/component-long-tail-migration.d.ts +18 -0
- package/catalog/component-long-tail-migration.js +305 -0
- package/catalog/component-regression-priority.d.ts +20 -0
- package/catalog/component-regression-priority.js +305 -0
- package/catalog/enterprise-component-flex-release-handoff.d.ts +32 -0
- package/catalog/enterprise-component-flex-release-handoff.js +437 -0
- package/catalog/enterprise-component-style-audit.d.ts +22 -0
- package/catalog/enterprise-component-style-audit.js +353 -0
- package/catalog/enterprise-form-control-theme-a11y.d.ts +19 -0
- package/catalog/enterprise-form-control-theme-a11y.js +220 -0
- package/catalog/enterprise-icon-control-audit.d.ts +21 -0
- package/catalog/enterprise-icon-control-audit.js +258 -0
- package/catalog/enterprise-layout-display-media-tokenization.d.ts +20 -0
- package/catalog/enterprise-layout-display-media-tokenization.js +237 -0
- package/catalog/enterprise-navigation-routing-state-hardening.d.ts +20 -0
- package/catalog/enterprise-navigation-routing-state-hardening.js +255 -0
- package/catalog/enterprise-overlay-mode-token-parity.d.ts +15 -0
- package/catalog/enterprise-overlay-mode-token-parity.js +178 -0
- package/catalog/enterprise-third-party-authoring-guide.d.ts +23 -0
- package/catalog/enterprise-third-party-authoring-guide.js +310 -0
- package/catalog/enterprise-visual-dom-snapshot-matrix.d.ts +31 -0
- package/catalog/enterprise-visual-dom-snapshot-matrix.js +357 -0
- package/catalog/epic10-existing-component-metadata.d.ts +25 -0
- package/catalog/epic10-existing-component-metadata.js +534 -0
- package/catalog/epic10-p0-component-wave.d.ts +28 -0
- package/catalog/epic10-p0-component-wave.js +688 -0
- package/catalog/epic10-platform-gates.d.ts +31 -0
- package/catalog/epic10-platform-gates.js +425 -0
- package/catalog/epic10-release-handoff.d.ts +30 -0
- package/catalog/epic10-release-handoff.js +195 -0
- package/catalog/epic11-enterprise-ux-handoff.d.ts +29 -0
- package/catalog/epic11-enterprise-ux-handoff.js +403 -0
- package/catalog/epic12-docs-adoption.d.ts +29 -0
- package/catalog/epic12-docs-adoption.js +183 -0
- package/catalog/epic12-rc0-gate-matrix.d.ts +36 -0
- package/catalog/epic12-rc0-gate-matrix.js +439 -0
- package/catalog/epic12-rc0-handoff.d.ts +30 -0
- package/catalog/epic12-rc0-handoff.js +385 -0
- package/catalog/epic13-conditional-network-evidence-ci.d.ts +35 -0
- package/catalog/epic13-conditional-network-evidence-ci.js +278 -0
- package/catalog/epic13-conditional-network-evidence.d.ts +34 -0
- package/catalog/epic13-conditional-network-evidence.js +280 -0
- package/catalog/epic13-docs-rmt-production-hardening.d.ts +39 -0
- package/catalog/epic13-docs-rmt-production-hardening.js +286 -0
- package/catalog/epic13-hydration-performance-closure.d.ts +33 -0
- package/catalog/epic13-hydration-performance-closure.js +234 -0
- package/catalog/epic13-known-residual-triage.d.ts +32 -0
- package/catalog/epic13-known-residual-triage.js +339 -0
- package/catalog/epic13-package-export-lock.d.ts +41 -0
- package/catalog/epic13-package-export-lock.js +604 -0
- package/catalog/epic13-prod-browser-csp-smoke.d.ts +35 -0
- package/catalog/epic13-prod-browser-csp-smoke.js +218 -0
- package/catalog/epic13-rc1-gate-matrix-ci-handoff.d.ts +36 -0
- package/catalog/epic13-rc1-gate-matrix-ci-handoff.js +418 -0
- package/catalog/epic13-rc1-migration-notes.d.ts +36 -0
- package/catalog/epic13-rc1-migration-notes.js +271 -0
- package/catalog/epic13-rc1-readiness.d.ts +33 -0
- package/catalog/epic13-rc1-readiness.js +487 -0
- package/catalog/epic13-release-owner-acceptance.d.ts +33 -0
- package/catalog/epic13-release-owner-acceptance.js +354 -0
- package/catalog/epic13-release-report-pack-dry-run-evidence.d.ts +36 -0
- package/catalog/epic13-release-report-pack-dry-run-evidence.js +253 -0
- package/catalog/epic13-rmt-production-readiness.d.ts +35 -0
- package/catalog/epic13-rmt-production-readiness.js +314 -0
- package/catalog/epic13-trusted-dom-boundary.d.ts +36 -0
- package/catalog/epic13-trusted-dom-boundary.js +230 -0
- package/catalog/epic13-visual-owner-artifact.d.ts +35 -0
- package/catalog/epic13-visual-owner-artifact.js +233 -0
- package/catalog/epic14-lsp-handoff.d.ts +28 -0
- package/catalog/epic14-lsp-handoff.js +312 -0
- package/catalog/epic14-rmt-tooling.d.ts +33 -0
- package/catalog/epic14-rmt-tooling.js +282 -0
- package/catalog/surface-manager-adapter-runtime.d.ts +37 -0
- package/catalog/surface-manager-adapter-runtime.js +203 -0
- package/catalog/surface-manager-browser-lab.d.ts +39 -0
- package/catalog/surface-manager-browser-lab.js +225 -0
- package/catalog/surface-manager-controller.d.ts +43 -0
- package/catalog/surface-manager-controller.js +290 -0
- package/catalog/surface-manager-layout-engines.d.ts +32 -0
- package/catalog/surface-manager-layout-engines.js +161 -0
- package/catalog/surface-manager-lazy-loading.d.ts +35 -0
- package/catalog/surface-manager-lazy-loading.js +173 -0
- package/catalog/surface-manager-materialization.d.ts +37 -0
- package/catalog/surface-manager-materialization.js +202 -0
- package/catalog/surface-manager-native-rmt-surfaces.d.ts +48 -0
- package/catalog/surface-manager-native-rmt-surfaces.js +325 -0
- package/catalog/surface-manager-overlay-bridge.d.ts +42 -0
- package/catalog/surface-manager-overlay-bridge.js +247 -0
- package/catalog/surface-manager-persistence.d.ts +37 -0
- package/catalog/surface-manager-persistence.js +178 -0
- package/catalog/surface-manager-quality-gates.d.ts +48 -0
- package/catalog/surface-manager-quality-gates.js +324 -0
- package/catalog/surface-manager-release-handoff.d.ts +47 -0
- package/catalog/surface-manager-release-handoff.js +274 -0
- package/catalog/surface-manager-remote-policy.d.ts +34 -0
- package/catalog/surface-manager-remote-policy.js +199 -0
- package/catalog/surface-manager-rmt-authoring.d.ts +44 -0
- package/catalog/surface-manager-rmt-authoring.js +368 -0
- package/catalog/surface-manager-route-lifecycle.d.ts +32 -0
- package/catalog/surface-manager-route-lifecycle.js +162 -0
- package/catalog/surface-manager-runtime-release-handoff.d.ts +36 -0
- package/catalog/surface-manager-runtime-release-handoff.js +245 -0
- package/catalog/surface-manager-side-panel-runtime.d.ts +46 -0
- package/catalog/surface-manager-side-panel-runtime.js +307 -0
- package/catalog/surface-manager-stack-policy.d.ts +32 -0
- package/catalog/surface-manager-stack-policy.js +169 -0
- package/catalog/surface-manager-window-runtime.d.ts +45 -0
- package/catalog/surface-manager-window-runtime.js +285 -0
- package/catalog/surface-manager-workbench-fixture.d.ts +50 -0
- package/catalog/surface-manager-workbench-fixture.js +315 -0
- package/catalog/type-exports-api.js +236 -0
- package/catalog/type-exports-builder.js +405 -0
- package/catalog/type-exports-catalog.js +394 -0
- package/catalog/type-exports-loader.js +266 -0
- package/catalog/type-exports-policy.js +461 -0
- package/catalog/type-exports-rmt.js +407 -0
- package/catalog/type-exports-vendor.js +365 -0
- package/catalog/type-exports.js +574 -0
- package/components/icon-packs/core.js +154 -0
- package/components/icon-packs/lucide.js +136 -0
- package/components/manifest.json +44 -0
- package/components/prism.d.ts +73 -0
- package/components/prism.js +300 -0
- package/components/turndown.d.ts +34 -0
- package/components/turndown.js +107 -0
- package/components/x-rmt-lifecycle-demo-build.d.ts +78 -0
- package/components/x-rmt-lifecycle-demo-build.js +1175 -0
- package/components/x-rmt-lifecycle-demo.d.ts +83 -0
- package/components/x-rmt-lifecycle-demo.js +1175 -0
- package/components/xalert.d.ts +42 -0
- package/components/xalert.js +538 -0
- package/components/xbutton.d.ts +127 -0
- package/components/xbutton.js +612 -0
- package/components/xcalendar.d.ts +39 -0
- package/components/xcalendar.js +338 -0
- package/components/xcards.d.ts +34 -0
- package/components/xcards.js +253 -0
- package/components/xcheckbox.d.ts +48 -0
- package/components/xcheckbox.js +448 -0
- package/components/xcode.d.ts +35 -0
- package/components/xcode.js +370 -0
- package/components/xdialog.d.ts +48 -0
- package/components/xdialog.js +763 -0
- package/components/xdrawer.d.ts +61 -0
- package/components/xdrawer.js +654 -0
- package/components/xfooter.d.ts +41 -0
- package/components/xfooter.js +351 -0
- package/components/xform.d.ts +43 -0
- package/components/xform.js +456 -0
- package/components/xheader.d.ts +68 -0
- package/components/xheader.js +1253 -0
- package/components/xhero.d.ts +42 -0
- package/components/xhero.js +475 -0
- package/components/xicon.d.ts +146 -0
- package/components/xicon.js +688 -0
- package/components/xinput.d.ts +37 -0
- package/components/xinput.js +444 -0
- package/components/xlightbox.d.ts +48 -0
- package/components/xlightbox.js +571 -0
- package/components/xlink.d.ts +63 -0
- package/components/xlink.js +565 -0
- package/components/xmasonry.d.ts +35 -0
- package/components/xmasonry.js +666 -0
- package/components/xmenu.d.ts +118 -0
- package/components/xmenu.js +1005 -0
- package/components/xmodal.d.ts +64 -0
- package/components/xmodal.js +831 -0
- package/components/xplayer.d.ts +57 -0
- package/components/xplayer.js +1748 -0
- package/components/xpopover.d.ts +54 -0
- package/components/xpopover.js +466 -0
- package/components/xprogress.d.ts +40 -0
- package/components/xprogress.js +345 -0
- package/components/xradio.d.ts +50 -0
- package/components/xradio.js +474 -0
- package/components/xrouter.d.ts +244 -0
- package/components/xrouter.js +1841 -0
- package/components/xsection.d.ts +34 -0
- package/components/xsection.js +253 -0
- package/components/xselect.d.ts +46 -0
- package/components/xselect.js +463 -0
- package/components/xsidepanel.d.ts +56 -0
- package/components/xsidepanel.js +728 -0
- package/components/xspinner.d.ts +38 -0
- package/components/xspinner.js +388 -0
- package/components/xstate.d.ts +137 -0
- package/components/xstate.js +493 -0
- package/components/xstatus.d.ts +41 -0
- package/components/xstatus.js +381 -0
- package/components/xsummary.d.ts +43 -0
- package/components/xsummary.js +293 -0
- package/components/xsurfacemanager-controller.d.ts +130 -0
- package/components/xsurfacemanager-controller.js +699 -0
- package/components/xsurfacemanager.d.ts +452 -0
- package/components/xsurfacemanager.js +3775 -0
- package/components/xsurfaceoverlay-bridge.d.ts +43 -0
- package/components/xsurfaceoverlay-bridge.js +238 -0
- package/components/xsurfacewindow.d.ts +50 -0
- package/components/xsurfacewindow.js +576 -0
- package/components/xtabs.d.ts +73 -0
- package/components/xtabs.js +611 -0
- package/components/xtend-public-types.d.ts +208 -0
- package/components/xtextarea.d.ts +46 -0
- package/components/xtextarea.js +451 -0
- package/components/xtheme.d.ts +253 -0
- package/components/xtheme.js +1438 -0
- package/components/xtoast.d.ts +39 -0
- package/components/xtoast.js +389 -0
- package/components/xtooltip.d.ts +53 -0
- package/components/xtooltip.js +432 -0
- package/components/xtype.d.ts +42 -0
- package/components/xtype.js +244 -0
- package/components/xutils.d.ts +164 -0
- package/components/xutils.js +496 -0
- package/components/xwriter.d.ts +67 -0
- package/components/xwriter.js +854 -0
- package/design-tokens/themes/enterprise-light.json +40 -0
- package/design-tokens/themes/xtend-signature.json +126 -0
- package/design-tokens/xtend-design-tokens.d.ts +95 -0
- package/design-tokens/xtend-design-tokens.js +395 -0
- package/design-tokens/xtheme-token-alias-layer.d.ts +84 -0
- package/design-tokens/xtheme-token-alias-layer.js +423 -0
- package/docs/.htaccess +51 -0
- package/docs/README.md +340 -0
- package/docs/XTend-ADR.md +221 -0
- package/docs/a11y-keyboard-smokes.md +62 -0
- package/docs/about.md +18 -0
- package/docs/api.md +157 -0
- package/docs/best-practices.md +76 -0
- package/docs/component-catalog-coverage.md +58 -0
- package/docs/component-lab.md +103 -0
- package/docs/component-long-tail-migration.md +41 -0
- package/docs/component-platform.md +159 -0
- package/docs/component-ux-app-authoring.md +130 -0
- package/docs/component-ux-authoring.md +96 -0
- package/docs/component-ux-gates.md +45 -0
- package/docs/components/x-rmt-lifecycle-demo-build.md +60 -0
- package/docs/components/xalert.md +81 -0
- package/docs/components/xbutton.md +103 -0
- package/docs/components/xcalendar.md +82 -0
- package/docs/components/xcards.md +128 -0
- package/docs/components/xcheckbox.md +102 -0
- package/docs/components/xcode.md +126 -0
- package/docs/components/xdialog.md +92 -0
- package/docs/components/xdrawer.md +84 -0
- package/docs/components/xfooter.md +126 -0
- package/docs/components/xform.md +128 -0
- package/docs/components/xheader.md +308 -0
- package/docs/components/xhero.md +142 -0
- package/docs/components/xicon.md +125 -0
- package/docs/components/xinput.md +129 -0
- package/docs/components/xlightbox.md +98 -0
- package/docs/components/xlink.md +109 -0
- package/docs/components/xmasonry.md +124 -0
- package/docs/components/xmenu.md +158 -0
- package/docs/components/xmodal.md +82 -0
- package/docs/components/xplayer.md +104 -0
- package/docs/components/xpopover.md +67 -0
- package/docs/components/xprogress.md +56 -0
- package/docs/components/xradio.md +103 -0
- package/docs/components/xrouter.md +260 -0
- package/docs/components/xsection.md +125 -0
- package/docs/components/xselect.md +105 -0
- package/docs/components/xsidepanel.md +30 -0
- package/docs/components/xspinner.md +102 -0
- package/docs/components/xstate.md +148 -0
- package/docs/components/xstatus.md +55 -0
- package/docs/components/xsummary.md +78 -0
- package/docs/components/xsurfacemanager.md +27 -0
- package/docs/components/xsurfacewindow.md +21 -0
- package/docs/components/xtabs.md +160 -0
- package/docs/components/xtextarea.md +98 -0
- package/docs/components/xtheme.md +167 -0
- package/docs/components/xtoast.md +62 -0
- package/docs/components/xtooltip.md +66 -0
- package/docs/components/xtype.md +82 -0
- package/docs/components/xutils.md +144 -0
- package/docs/components/xwriter.md +94 -0
- package/docs/components.md +117 -0
- package/docs/conditional-network-evidence-ci.md +38 -0
- package/docs/conditional-network-evidence.md +50 -0
- package/docs/core-migration-guide.md +110 -0
- package/docs/design-tokens.md +116 -0
- package/docs/docs-rmt-production-hardening.md +31 -0
- package/docs/enterprise-adoption.md +411 -0
- package/docs/enterprise-component-flex-release-handoff.md +129 -0
- package/docs/epic10-platform-gates.md +62 -0
- package/docs/epic10-release-handoff.md +81 -0
- package/docs/epic11-enterprise-ux-handoff.md +70 -0
- package/docs/epic12-rc0-handoff.md +61 -0
- package/docs/existing-component-metadata.md +67 -0
- package/docs/hydration-performance-closure.md +34 -0
- package/docs/hydration-policies.md +71 -0
- package/docs/index.php +1625 -0
- package/docs/known-residual-triage.md +22 -0
- package/docs/manifest-import-policy.md +79 -0
- package/docs/manifest.md +106 -0
- package/docs/menu.json +1190 -0
- package/docs/motion-contrast.md +67 -0
- package/docs/package-export-lock.md +44 -0
- package/docs/performance-measurements.md +106 -0
- package/docs/performance-regression.md +89 -0
- package/docs/performance.md +94 -0
- package/docs/previews/README.md +17 -0
- package/docs/prod-browser-csp-smokes.md +40 -0
- package/docs/public-component-types.md +79 -0
- package/docs/quick-start-guide.md +152 -0
- package/docs/rc0-adoption-guide.md +102 -0
- package/docs/rc0-gate-matrix.md +58 -0
- package/docs/rc1-gate-matrix-ci-handoff.md +56 -0
- package/docs/rc1-migration-notes.md +69 -0
- package/docs/rc1-readiness.md +46 -0
- package/docs/release-owner-acceptance.md +56 -0
- package/docs/release-report-pack-dry-run-evidence.md +39 -0
- package/docs/rmt-dsl-authoring-polish.md +122 -0
- package/docs/rmt-first-demo-app.md +77 -0
- package/docs/rmt-first-xtend-apps.md +105 -0
- package/docs/rmt-kernel-panic-recovery-incident-handoff.md +61 -0
- package/docs/rmt-kernel-security-hardening-migration.md +50 -0
- package/docs/rmt-kernel-trusted-output-authoring.md +69 -0
- package/docs/rmt-language-server.md +177 -0
- package/docs/rmt-lifecycle-demo.md +25 -0
- package/docs/rmt-linter.md +140 -0
- package/docs/rmt-production-readiness.md +63 -0
- package/docs/rmt-tooling-release-gates.md +77 -0
- package/docs/rmt-vnext-authoring.md +60 -0
- package/docs/rmt-vnext-cross-surface-events.md +68 -0
- package/docs/rmt-vnext-enterprise-mfe-handoff.md +70 -0
- package/docs/rmt-vnext-migration-notes.md +62 -0
- package/docs/rmt-vnext-release-handoff.md +69 -0
- package/docs/rmt-vnext-remote-surfaces.md +90 -0
- package/docs/rmt-vnext-surface-registry-enterprise.md +76 -0
- package/docs/screenreader-signals.md +56 -0
- package/docs/supply-chain-gates.md +100 -0
- package/docs/surface-manager-authoring-guide.md +94 -0
- package/docs/surface-manager-browser-lab.md +45 -0
- package/docs/surface-manager-component-lab.md +43 -0
- package/docs/surface-manager-controller.md +66 -0
- package/docs/surface-manager-layout-engines.md +32 -0
- package/docs/surface-manager-lazy-hydration.md +63 -0
- package/docs/surface-manager-migration-guide.md +94 -0
- package/docs/surface-manager-native-rmt-surfaces.md +38 -0
- package/docs/surface-manager-overlay-bridge.md +53 -0
- package/docs/surface-manager-persistence.md +30 -0
- package/docs/surface-manager-quality-gates.md +51 -0
- package/docs/surface-manager-release-handoff.md +68 -0
- package/docs/surface-manager-remote-policy.md +54 -0
- package/docs/surface-manager-rmt-authoring.md +86 -0
- package/docs/surface-manager-route-lifecycle.md +59 -0
- package/docs/surface-manager-runtime-release-handoff.md +69 -0
- package/docs/surface-manager-side-panel-runtime.md +36 -0
- package/docs/surface-manager-stack-policy.md +39 -0
- package/docs/surface-manager-window-runtime.md +47 -0
- package/docs/surface-manager-workbench-fixture.md +43 -0
- package/docs/third-party-design-authoring.md +406 -0
- package/docs/trusted-dom-boundary-browser-proof.md +32 -0
- package/docs/trusted-dom-sanitizing.md +110 -0
- package/docs/type-exports.md +61 -0
- package/docs/typescript-components.md +63 -0
- package/docs/utils/fabric-runtime.js +650 -0
- package/docs/utils/pageloader.js +2823 -0
- package/docs/utils/parsedown.php +298 -0
- package/docs/visual-browser-regression.md +83 -0
- package/docs/visual-owner-artifacts.md +46 -0
- package/docs/visual-snapshot-automation.md +87 -0
- package/docs/xtend-api-types.md +55 -0
- package/docs/xtend-builder-types.md +55 -0
- package/docs/xtend-catalog-types.md +44 -0
- package/docs/xtend-fabric-rmt-lane-mapping.md +143 -0
- package/docs/xtend-fabric.md +474 -0
- package/docs/xtend-loader-types.md +58 -0
- package/docs/xtend-loader.md +265 -0
- package/docs/xtend-policy-types.md +38 -0
- package/docs/xtend-rmt-types.md +39 -0
- package/docs/xtend-vendor-types.md +36 -0
- package/docs/xtendrmt-app-dsl.md +269 -0
- package/docs/xtendrmt-migration-guide.md +235 -0
- package/docs/xtendrmt-native-authoring.md +337 -0
- package/docs/xtendrmt-overview.md +89 -0
- package/docs/xtendrmt-parsedown-docs.rmt +956 -0
- package/docs/xtendrmt-parsedown-scheduling.md +301 -0
- package/docs/xtendrmt-runtime-bridge.md +155 -0
- package/fabric/hydration-policy.d.ts +27 -0
- package/fabric/hydration-policy.js +306 -0
- package/fabric/package.json +58 -0
- package/fabric/rmt-lane-mapping.d.ts +47 -0
- package/fabric/rmt-lane-mapping.js +504 -0
- package/fabric/xtend-fabric.d.ts +81 -0
- package/fabric/xtend-fabric.js +2669 -0
- package/fabric/xtend-policy-public-types.d.ts +135 -0
- package/package.json +8225 -0
- package/security/README.md +54 -0
- package/security/manifest-import-policy.d.ts +43 -0
- package/security/manifest-import-policy.js +260 -0
- package/security/supply-chain-gate-policy.d.ts +45 -0
- package/security/supply-chain-gate-policy.js +249 -0
- package/security/trusted-dom-policy.d.ts +36 -0
- package/security/trusted-dom-policy.js +316 -0
- package/tools/package.json +77 -0
- package/tools/rmt-editor/vscode/README.md +33 -0
- package/tools/rmt-editor/vscode/extension.d.ts +9 -0
- package/tools/rmt-editor/vscode/extension.js +55 -0
- package/tools/rmt-editor/vscode/language-configuration.json +28 -0
- package/tools/rmt-editor/vscode/package.json +83 -0
- package/tools/rmt-editor/vscode/snippets/rmt.code-snippets +243 -0
- package/tools/rmt-editor/vscode/syntaxes/rmt.tmLanguage.json +13 -0
- package/tools/rmt-editor/vscode/xtend-rmt-language-0.0.0-enterprise-readiness.vsix +0 -0
- package/tools/rmt-language/code-actions.d.ts +15 -0
- package/tools/rmt-language/code-actions.js +566 -0
- package/tools/rmt-language/completions.d.ts +22 -0
- package/tools/rmt-language/completions.js +475 -0
- package/tools/rmt-language/definitions.d.ts +13 -0
- package/tools/rmt-language/definitions.js +212 -0
- package/tools/rmt-language/diagnostics.d.ts +23 -0
- package/tools/rmt-language/diagnostics.js +486 -0
- package/tools/rmt-language/format-adapter.d.ts +16 -0
- package/tools/rmt-language/format-adapter.js +270 -0
- package/tools/rmt-language/hover.d.ts +12 -0
- package/tools/rmt-language/hover.js +326 -0
- package/tools/rmt-language/kernel-escalation.d.ts +122 -0
- package/tools/rmt-language/kernel-escalation.js +427 -0
- package/tools/rmt-language/kernel-panic-monitor.d.ts +176 -0
- package/tools/rmt-language/kernel-panic-monitor.js +674 -0
- package/tools/rmt-language/kernel-policy-parity.d.ts +142 -0
- package/tools/rmt-language/kernel-policy-parity.js +629 -0
- package/tools/rmt-language/kernel-recovery.d.ts +173 -0
- package/tools/rmt-language/kernel-recovery.js +666 -0
- package/tools/rmt-language/kernel-scheduler-failure.d.ts +136 -0
- package/tools/rmt-language/kernel-scheduler-failure.js +486 -0
- package/tools/rmt-language/kernel-security-regression.d.ts +154 -0
- package/tools/rmt-language/kernel-security-regression.js +465 -0
- package/tools/rmt-language/kernel-trust-authority.d.ts +120 -0
- package/tools/rmt-language/kernel-trust-authority.js +549 -0
- package/tools/rmt-language/parser.d.ts +14 -0
- package/tools/rmt-language/parser.js +111 -0
- package/tools/rmt-language/rmt-tooling-public-types.d.ts +179 -0
- package/tools/rmt-language/rules/boundary-policy.js +81 -0
- package/tools/rmt-language/rules/document-policy.js +65 -0
- package/tools/rmt-language/rules/index.js +29 -0
- package/tools/rmt-language/rules/route-policy.js +81 -0
- package/tools/rmt-language/rules/scheduler-policy.js +66 -0
- package/tools/rmt-language/rules/template-policy.js +130 -0
- package/tools/rmt-language/semantic-graph.d.ts +18 -0
- package/tools/rmt-language/semantic-graph.js +827 -0
- package/tools/rmt-language/snippets/README.md +17 -0
- package/tools/rmt-language/snippets/index.d.ts +17 -0
- package/tools/rmt-language/snippets/index.js +417 -0
- package/tools/rmt-language/snippets/rmt.code-snippets +243 -0
- package/tools/rmt-language/source-model.d.ts +14 -0
- package/tools/rmt-language/source-model.js +731 -0
- package/tools/rmt-language/symbols.d.ts +13 -0
- package/tools/rmt-language/symbols.js +183 -0
- package/tools/rmt-language/vnext-compatibility.d.ts +28 -0
- package/tools/rmt-language/vnext-compatibility.js +675 -0
- package/tools/rmt-language/vnext-compiler.d.ts +17 -0
- package/tools/rmt-language/vnext-compiler.js +716 -0
- package/tools/rmt-language/vnext-composition.d.ts +30 -0
- package/tools/rmt-language/vnext-composition.js +595 -0
- package/tools/rmt-language/vnext-conditions.d.ts +25 -0
- package/tools/rmt-language/vnext-conditions.js +474 -0
- package/tools/rmt-language/vnext-cross-surface-events.d.ts +30 -0
- package/tools/rmt-language/vnext-cross-surface-events.js +607 -0
- package/tools/rmt-language/vnext-degradation.d.ts +23 -0
- package/tools/rmt-language/vnext-degradation.js +428 -0
- package/tools/rmt-language/vnext-enterprise-fixtures.d.ts +28 -0
- package/tools/rmt-language/vnext-enterprise-fixtures.js +487 -0
- package/tools/rmt-language/vnext-enterprise-registry.d.ts +21 -0
- package/tools/rmt-language/vnext-enterprise-registry.js +495 -0
- package/tools/rmt-language/vnext-enterprise-release.d.ts +44 -0
- package/tools/rmt-language/vnext-enterprise-release.js +472 -0
- package/tools/rmt-language/vnext-event-governance.d.ts +29 -0
- package/tools/rmt-language/vnext-event-governance.js +488 -0
- package/tools/rmt-language/vnext-events.d.ts +44 -0
- package/tools/rmt-language/vnext-events.js +680 -0
- package/tools/rmt-language/vnext-import-resolver.d.ts +28 -0
- package/tools/rmt-language/vnext-import-resolver.js +642 -0
- package/tools/rmt-language/vnext-lifecycle.d.ts +22 -0
- package/tools/rmt-language/vnext-lifecycle.js +404 -0
- package/tools/rmt-language/vnext-parser.d.ts +21 -0
- package/tools/rmt-language/vnext-parser.js +1391 -0
- package/tools/rmt-language/vnext-regression.d.ts +25 -0
- package/tools/rmt-language/vnext-regression.js +394 -0
- package/tools/rmt-language/vnext-release.d.ts +29 -0
- package/tools/rmt-language/vnext-release.js +293 -0
- package/tools/rmt-language/vnext-remote-compatibility.d.ts +33 -0
- package/tools/rmt-language/vnext-remote-compatibility.js +892 -0
- package/tools/rmt-language/vnext-remote-compiler.d.ts +14 -0
- package/tools/rmt-language/vnext-remote-compiler.js +520 -0
- package/tools/rmt-language/vnext-remote-manifest.d.ts +33 -0
- package/tools/rmt-language/vnext-remote-manifest.js +538 -0
- package/tools/rmt-language/vnext-remote-security.d.ts +27 -0
- package/tools/rmt-language/vnext-remote-security.js +380 -0
- package/tools/rmt-language/vnext-remote-tooling.d.ts +25 -0
- package/tools/rmt-language/vnext-remote-tooling.js +805 -0
- package/tools/rmt-language/vnext-scheduler.d.ts +24 -0
- package/tools/rmt-language/vnext-scheduler.js +469 -0
- package/tools/rmt-language/vnext-security.d.ts +28 -0
- package/tools/rmt-language/vnext-security.js +597 -0
- package/tools/rmt-language/vnext-streaming.d.ts +28 -0
- package/tools/rmt-language/vnext-streaming.js +593 -0
- package/tools/rmt-language/vnext-surfaces.d.ts +24 -0
- package/tools/rmt-language/vnext-surfaces.js +406 -0
- package/tools/rmt-language/vnext-tooling.d.ts +25 -0
- package/tools/rmt-language/vnext-tooling.js +728 -0
- package/tools/rmt-language-server/protocol.d.ts +22 -0
- package/tools/rmt-language-server/protocol.js +352 -0
- package/tools/rmt-language-server/server.d.ts +15 -0
- package/tools/rmt-language-server/server.js +622 -0
- package/tools/rmt-linter/cli.d.ts +14 -0
- package/tools/rmt-linter/cli.js +450 -0
- package/tools/rmt-linter/reporter.d.ts +16 -0
- package/tools/rmt-linter/reporter.js +472 -0
- package/xtend-builder/README.md +83 -0
- package/xtend-builder/a11y/README.md +42 -0
- package/xtend-builder/a11y/component-a11y-profile.d.ts +14 -0
- package/xtend-builder/a11y/component-a11y-profile.js +314 -0
- package/xtend-builder/blueprints/README.md +105 -0
- package/xtend-builder/blueprints/component-blueprint.contract.d.ts +16 -0
- package/xtend-builder/blueprints/component-blueprint.contract.js +343 -0
- package/xtend-builder/builder-public-types.d.ts +234 -0
- package/xtend-builder/extensions/README.md +26 -0
- package/xtend-builder/extensions/component-extension-points.d.ts +11 -0
- package/xtend-builder/extensions/component-extension-points.js +277 -0
- package/xtend-builder/generators/README.md +149 -0
- package/xtend-builder/generators/component-files.d.ts +5 -0
- package/xtend-builder/generators/component-files.js +769 -0
- package/xtend-builder/generators/component-plan.d.ts +4 -0
- package/xtend-builder/generators/component-plan.js +104 -0
- package/xtend-builder/generators/registry.d.ts +6 -0
- package/xtend-builder/generators/registry.js +118 -0
- package/xtend-builder/generators/rmt-build.js +738 -0
- package/xtend-builder/generators/rmt-lifecycle-demo.js +922 -0
- package/xtend-builder/lib/cli.d.ts +9 -0
- package/xtend-builder/lib/cli.js +543 -0
- package/xtend-builder/lib/layout.d.ts +6 -0
- package/xtend-builder/lib/layout.js +153 -0
- package/xtend-builder/lib/package-resolver.js +25 -0
- package/xtend-builder/package.json +90 -0
- package/xtend-builder/performance/README.md +31 -0
- package/xtend-builder/performance/component-performance-profile.d.ts +11 -0
- package/xtend-builder/performance/component-performance-profile.js +347 -0
- package/xtend-builder/performance/component-ux-performance-contract.d.ts +27 -0
- package/xtend-builder/performance/component-ux-performance-contract.js +424 -0
- package/xtend-builder/preview/README.md +61 -0
- package/xtend-builder/preview/component-lab-ux-inspector.d.ts +20 -0
- package/xtend-builder/preview/component-lab-ux-inspector.js +448 -0
- package/xtend-builder/preview/component-lab.d.ts +14 -0
- package/xtend-builder/preview/component-lab.js +278 -0
- package/xtend-builder/preview/component-preview.d.ts +5 -0
- package/xtend-builder/preview/component-preview.js +160 -0
- package/xtend-builder/scaffold.config.d.ts +4 -0
- package/xtend-builder/scaffold.config.js +2056 -0
- package/xtend-builder/scaffold.d.ts +3 -0
- package/xtend-builder/scaffold.js +11 -0
- package/xtend-builder/templates/README.md +33 -0
- package/xtend-builder/templates/component/a11y.template.ts +11 -0
- package/xtend-builder/templates/component/component-suite.template.d.ts +2 -0
- package/xtend-builder/templates/component/component-suite.template.js +108 -0
- package/xtend-builder/templates/component/contract.template.ts +10 -0
- package/xtend-builder/templates/component/demo-plan.template.md +73 -0
- package/xtend-builder/templates/component/docs.template.md +301 -0
- package/xtend-builder/templates/component/fixture-data.template.ts +28 -0
- package/xtend-builder/templates/component/fixture.template.html +37 -0
- package/xtend-builder/templates/component/manifest-plan.template.json +22 -0
- package/xtend-builder/templates/component/performance.template.ts +13 -0
- package/xtend-builder/templates/component/rmt.template.ts +12 -0
- package/xtend-builder/templates/component/source.template.d.ts +2 -0
- package/xtend-builder/templates/component/source.template.js +137 -0
- package/xtend-builder/templates/component/source.template.ts +110 -0
- package/xtend-builder/templates/component/types.template.d.ts +423 -0
- package/xtend-builder/templates/loader.d.ts +4 -0
- package/xtend-builder/templates/loader.js +51 -0
- package/xtend-builder/templates/registry.d.ts +6 -0
- package/xtend-builder/templates/registry.js +119 -0
- package/xtend-builder/typing/README.md +130 -0
- package/xtend-builder/typing/component-contract-v2.d.ts +15 -0
- package/xtend-builder/typing/component-contract-v2.js +248 -0
- package/xtend-builder/typing/component-network-contract.d.ts +22 -0
- package/xtend-builder/typing/component-network-contract.js +478 -0
- package/xtend-builder/typing/component-shell-contract.d.ts +21 -0
- package/xtend-builder/typing/component-shell-contract.js +312 -0
- package/xtend-builder/typing/component-styling-contract.d.ts +22 -0
- package/xtend-builder/typing/component-styling-contract.js +301 -0
- package/xtend-builder/typing/component-types.d.ts +10 -0
- package/xtend-builder/typing/component-types.js +551 -0
- package/xtend-builder/typing/enterprise-component-flex-hardening-contract.d.ts +20 -0
- package/xtend-builder/typing/enterprise-component-flex-hardening-contract.js +332 -0
- package/xtend-builder/typing/feedback-status-ux-contract.d.ts +25 -0
- package/xtend-builder/typing/feedback-status-ux-contract.js +347 -0
- package/xtend-builder/typing/form-controls-ux-contract.d.ts +25 -0
- package/xtend-builder/typing/form-controls-ux-contract.js +357 -0
- package/xtend-builder/typing/layout-display-media-ux-contract.d.ts +25 -0
- package/xtend-builder/typing/layout-display-media-ux-contract.js +420 -0
- package/xtend-builder/typing/navigation-routing-ux-contract.d.ts +17 -0
- package/xtend-builder/typing/navigation-routing-ux-contract.js +297 -0
- package/xtend-builder/typing/overlay-interaction-ux-contract.d.ts +25 -0
- package/xtend-builder/typing/overlay-interaction-ux-contract.js +383 -0
- package/xtend-builder/typing/rmt-dsl-authoring-polish.d.ts +27 -0
- package/xtend-builder/typing/rmt-dsl-authoring-polish.js +419 -0
- package/xtend-builder/typing/rmt-shell-authoring-contract.d.ts +26 -0
- package/xtend-builder/typing/rmt-shell-authoring-contract.js +315 -0
- package/xtend-builder/utils/README.md +8 -0
- package/xtend-builder/utils/naming.d.ts +7 -0
- package/xtend-builder/utils/naming.js +36 -0
- package/xtend-builder/utils/validation.d.ts +5 -0
- package/xtend-builder/utils/validation.js +95 -0
- package/xtend-builder/wiring/README.md +46 -0
- package/xtend-builder/wiring/features.d.ts +5 -0
- package/xtend-builder/wiring/features.js +165 -0
- package/xtend-builder/wiring/hydration.d.ts +4 -0
- package/xtend-builder/wiring/hydration.js +44 -0
- package/xtend-builder/wiring/manifest.d.ts +5 -0
- package/xtend-builder/wiring/manifest.js +48 -0
- package/xtend-builder/workflows/README.md +47 -0
- package/xtend-builder/workflows/developer-workflow.d.ts +6 -0
- package/xtend-builder/workflows/developer-workflow.js +125 -0
- package/xtend-builder/writing/manifest-patcher.d.ts +49 -0
- package/xtend-builder/writing/manifest-patcher.js +391 -0
- package/xtend-builder/writing/write-plan.d.ts +148 -0
- package/xtend-builder/writing/write-plan.js +646 -0
- package/xtend-dev.d.ts +23 -0
- package/xtend-dev.js +4 -0
- package/xtend-loader.d.ts +201 -0
- package/xtend-loader.js +1704 -0
- package/xtend.css +402 -0
- package/xtendrmt/package.json +64 -0
- package/xtendrmt/rmt-core.d.ts +4452 -0
- package/xtendrmt/rmt-core.esm.js +25793 -0
- package/xtendrmt/rmt-first-demo-app.js +265 -0
- package/xtendrmt/rmt-first-demo-app.rmt +737 -0
- package/xtendrmt/rmt-lifecycle-demo.app.js +493 -0
- package/xtendrmt/rmt-lifecycle-demo.core.json +810 -0
- package/xtendrmt/rmt-lifecycle-demo.rmt +35 -0
- package/xtendrmt/rmt-lifecycle-demo.rmt-build.app.js +153 -0
- package/xtendrmt/rmt-lifecycle-demo.rmt-build.core.json +810 -0
- package/xtendrmt/rmt-lifecycle-demo.rmt-build.scaffold.json +202 -0
- package/xtendrmt/rmt-lifecycle-demo.scaffold.json +187 -0
- package/xtendrmt/rmt-manifest.json +548 -0
- package/xtendrmt/rmt-runtime.browser.js +26183 -0
- package/xtendrmt/rmt-runtime.esm.js +26214 -0
- package/xtendrmt/rmt-vnext-enterprise-mfe-demo.core.json +849 -0
- package/xtendrmt/rmt-vnext-enterprise-mfe-demo.rmt +50 -0
- package/xtendrmt/rmt-vnext-reference-demo.core.json +1069 -0
- package/xtendrmt/rmt-vnext-reference-demo.rmt +50 -0
- package/xtendrmt/rmt.schema.json +3145 -0
- package/xtendrmt/surface-workbench.js +316 -0
- package/xtendrmt/surface-workbench.rmt +762 -0
- package/xtendrmt/xtendrmt-bestcase-demo.core.json +1187 -0
- package/xtendrmt/xtendrmt-bestcase-demo.js +1728 -0
- package/xtendrmt/xtendrmt-bestcase-demo.rmt +57 -0
package/xtend-loader.js
ADDED
|
@@ -0,0 +1,1704 @@
|
|
|
1
|
+
const DEFAULT_MANIFEST_URL = 'components/manifest.json';
|
|
2
|
+
const LOADER_CONTRACT = 'xtend.loader.contract.v1';
|
|
3
|
+
const LOADER_POLICY_CONTRACT = 'xtend.security.loader-policy.v1';
|
|
4
|
+
const MANIFEST_POLICY_CONTRACT = 'xtend.security.manifest-policy.v1';
|
|
5
|
+
const IMPORT_POLICY_CONTRACT = 'xtend.security.import-policy.v1';
|
|
6
|
+
const PERFORMANCE_MEASUREMENT_CONTRACT = 'xtend.performance.measurement.v1';
|
|
7
|
+
const SKELETON_LOADER_CONTRACT = 'xtend.loader.skeleton-loader.v1';
|
|
8
|
+
const STYLE_REGISTRY_CONTRACT = 'xtend.loader.style-registry.v1';
|
|
9
|
+
const RUNTIME_STYLES_CONTRACT = 'xtend.loader.runtime-styles.v1';
|
|
10
|
+
const RUNTIME_STYLE_KEY = 'xtend.runtime-critical';
|
|
11
|
+
const RUNTIME_STYLE_ID = 'xtend-runtime-critical-styles';
|
|
12
|
+
const STANDARD_THEME_STYLESHEET = 'xtend.css';
|
|
13
|
+
const LOADER_PERFORMANCE_PHASES = Object.freeze({
|
|
14
|
+
'xtend.loader.manifest': 'load',
|
|
15
|
+
'xtend.loader.module': 'load',
|
|
16
|
+
'xtend.component.define': 'define'
|
|
17
|
+
});
|
|
18
|
+
const CUSTOM_ELEMENT_DEFINE_TIMEOUT_MS = 500;
|
|
19
|
+
const LOCAL_IMPORT_HOSTS = ['localhost', '127.0.0.1', '0.0.0.0', '::1'];
|
|
20
|
+
const ALLOWED_IMPORT_PROTOCOLS = ['http:', 'https:', 'file:'];
|
|
21
|
+
const REFUSED_IMPORT_PROTOCOLS = ['javascript:', 'data:', 'vbscript:', 'blob:'];
|
|
22
|
+
const ALLOWED_MANIFEST_EXTENSIONS = ['.json'];
|
|
23
|
+
const ALLOWED_MODULE_EXTENSIONS = ['.js', '.mjs'];
|
|
24
|
+
const RESERVED_MANIFEST_KEYS = ['xstate'];
|
|
25
|
+
const CUSTOM_ELEMENT_NAME_PATTERN = /^[a-z][a-z0-9]*-[a-z0-9-]*[a-z0-9]$/;
|
|
26
|
+
const MODULE_CACHE_BUST_PARAM = 'xtend-cache';
|
|
27
|
+
const LOADER_VERBOSE_CONTRACT = 'xtend.loader.verbose.v1';
|
|
28
|
+
const LOADER_VERBOSE_STORAGE_KEY = 'xtend.loader.verbose';
|
|
29
|
+
const XTEND_RUNTIME_CUSTOM_ELEMENT_TAGS = Object.freeze([
|
|
30
|
+
'x-alert',
|
|
31
|
+
'x-button',
|
|
32
|
+
'x-calendar',
|
|
33
|
+
'x-cards',
|
|
34
|
+
'x-checkbox',
|
|
35
|
+
'x-code',
|
|
36
|
+
'x-dialog',
|
|
37
|
+
'x-drawer',
|
|
38
|
+
'x-footer',
|
|
39
|
+
'x-form',
|
|
40
|
+
'x-header',
|
|
41
|
+
'x-hero',
|
|
42
|
+
'x-icon',
|
|
43
|
+
'x-input',
|
|
44
|
+
'x-lightbox',
|
|
45
|
+
'x-link',
|
|
46
|
+
'x-masonry',
|
|
47
|
+
'x-menu',
|
|
48
|
+
'x-modal',
|
|
49
|
+
'x-player',
|
|
50
|
+
'x-popover',
|
|
51
|
+
'x-progress',
|
|
52
|
+
'x-radio',
|
|
53
|
+
'x-router',
|
|
54
|
+
'x-section',
|
|
55
|
+
'x-select',
|
|
56
|
+
'x-side-panel',
|
|
57
|
+
'x-spinner',
|
|
58
|
+
'x-status',
|
|
59
|
+
'x-summary',
|
|
60
|
+
'x-surface-manager',
|
|
61
|
+
'x-surface-window',
|
|
62
|
+
'x-tabs',
|
|
63
|
+
'x-textarea',
|
|
64
|
+
'x-toast',
|
|
65
|
+
'x-tooltip',
|
|
66
|
+
'x-type',
|
|
67
|
+
'x-writer',
|
|
68
|
+
'xtend-doc-page'
|
|
69
|
+
]);
|
|
70
|
+
|
|
71
|
+
// Loader-local PROD verbosity switch. Supported values: 'true', 'false', 'auto'.
|
|
72
|
+
const verbose_mode = 'auto';
|
|
73
|
+
|
|
74
|
+
const loadedTags = new Set();
|
|
75
|
+
const loaderMeasurements = [];
|
|
76
|
+
const styleRegistryRecords = new Map();
|
|
77
|
+
const adoptedStyleSheetsByKey = new Map();
|
|
78
|
+
let loaderMeasurementCounter = 0;
|
|
79
|
+
let loaderVerboseRuntimeEnabled = readLoaderVerbosePreference();
|
|
80
|
+
let activeManifest = {};
|
|
81
|
+
let runtimeStylesInitialized = false;
|
|
82
|
+
const loaderStyleNonce = readCurrentScriptNonce();
|
|
83
|
+
|
|
84
|
+
function normalizeLoaderVerboseMode(mode) {
|
|
85
|
+
const normalized = String(mode || '').trim().toLowerCase();
|
|
86
|
+
return ['true', 'false', 'auto'].includes(normalized) ? normalized : 'auto';
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function getLoaderVerboseMode() {
|
|
90
|
+
return normalizeLoaderVerboseMode(verbose_mode);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function readLoaderVerbosePreference() {
|
|
94
|
+
if (getLoaderVerboseMode() !== 'auto') {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
if (typeof window === 'undefined' || !window.sessionStorage) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
return window.sessionStorage.getItem(LOADER_VERBOSE_STORAGE_KEY) === 'true';
|
|
102
|
+
} catch (_) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function writeLoaderVerbosePreference(enabled) {
|
|
108
|
+
if (getLoaderVerboseMode() !== 'auto') return;
|
|
109
|
+
if (typeof window === 'undefined' || !window.sessionStorage) return;
|
|
110
|
+
try {
|
|
111
|
+
window.sessionStorage.setItem(LOADER_VERBOSE_STORAGE_KEY, enabled ? 'true' : 'false');
|
|
112
|
+
} catch (_) {
|
|
113
|
+
// Storage access can be disabled by the host page; runtime state still works.
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function normalizeLoaderVerboseRequest(enabled) {
|
|
118
|
+
if (typeof enabled === 'string') {
|
|
119
|
+
const normalized = enabled.trim().toLowerCase();
|
|
120
|
+
return !['false', '0', 'off', 'no'].includes(normalized);
|
|
121
|
+
}
|
|
122
|
+
return enabled !== false;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function isLoaderVerboseEnabled() {
|
|
126
|
+
const mode = getLoaderVerboseMode();
|
|
127
|
+
return mode === 'true' || (mode === 'auto' && loaderVerboseRuntimeEnabled);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function getLoaderVerboseState() {
|
|
131
|
+
const mode = getLoaderVerboseMode();
|
|
132
|
+
return {
|
|
133
|
+
schema: LOADER_VERBOSE_CONTRACT,
|
|
134
|
+
mode,
|
|
135
|
+
enabled: isLoaderVerboseEnabled(),
|
|
136
|
+
locked: mode !== 'auto'
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function setLoaderVerbose(enabled = true) {
|
|
141
|
+
const mode = getLoaderVerboseMode();
|
|
142
|
+
const requested = normalizeLoaderVerboseRequest(enabled);
|
|
143
|
+
|
|
144
|
+
if (mode === 'false') {
|
|
145
|
+
return {
|
|
146
|
+
...getLoaderVerboseState(),
|
|
147
|
+
requested,
|
|
148
|
+
changed: false,
|
|
149
|
+
message: 'XTend Loader VerboseMode ist per verbose_mode = false gesperrt.'
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (mode === 'true') {
|
|
154
|
+
return {
|
|
155
|
+
...getLoaderVerboseState(),
|
|
156
|
+
requested,
|
|
157
|
+
changed: false,
|
|
158
|
+
message: 'XTend Loader VerboseMode ist per verbose_mode = true dauerhaft aktiv.'
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const previous = loaderVerboseRuntimeEnabled;
|
|
163
|
+
loaderVerboseRuntimeEnabled = requested;
|
|
164
|
+
writeLoaderVerbosePreference(loaderVerboseRuntimeEnabled);
|
|
165
|
+
const state = {
|
|
166
|
+
...getLoaderVerboseState(),
|
|
167
|
+
requested,
|
|
168
|
+
changed: previous !== loaderVerboseRuntimeEnabled,
|
|
169
|
+
message: loaderVerboseRuntimeEnabled
|
|
170
|
+
? 'XTend Loader VerboseMode aktiviert.'
|
|
171
|
+
: 'XTend Loader VerboseMode deaktiviert.'
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
if (loaderVerboseRuntimeEnabled && typeof console !== 'undefined' && typeof console.info === 'function') {
|
|
175
|
+
console.info(state.message);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return state;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function configureLoaderVerbose(enabled) {
|
|
182
|
+
if (arguments.length === 0) {
|
|
183
|
+
return getLoaderVerboseState();
|
|
184
|
+
}
|
|
185
|
+
return setLoaderVerbose(enabled);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function loaderVerboseLog(...args) {
|
|
189
|
+
if (isLoaderVerboseEnabled() && typeof console !== 'undefined' && typeof console.log === 'function') {
|
|
190
|
+
console.log(...args);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function loaderVerboseWarn(...args) {
|
|
195
|
+
if (isLoaderVerboseEnabled() && typeof console !== 'undefined' && typeof console.warn === 'function') {
|
|
196
|
+
console.warn(...args);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function readCurrentScriptNonce() {
|
|
201
|
+
if (typeof document === 'undefined' || !document.currentScript) return '';
|
|
202
|
+
const script = document.currentScript;
|
|
203
|
+
return script.nonce || (typeof script.getAttribute === 'function' ? script.getAttribute('nonce') : '') || '';
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function sanitizeStyleKey(key) {
|
|
207
|
+
return String(key || '').trim().replace(/[^a-z0-9_.:-]/gi, '-').replace(/-+/g, '-') || 'style';
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function normalizeStyleCss(cssText) {
|
|
211
|
+
return String(cssText || '').trim();
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function createRuntimeCustomElementHideCss() {
|
|
215
|
+
return XTEND_RUNTIME_CUSTOM_ELEMENT_TAGS
|
|
216
|
+
.map((tag) => `${tag}:not(:defined):not([data-xtend-skeleton])`)
|
|
217
|
+
.join(',\n');
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function createRuntimeCriticalCss() {
|
|
221
|
+
const hiddenSelectors = createRuntimeCustomElementHideCss();
|
|
222
|
+
return `
|
|
223
|
+
:root {
|
|
224
|
+
--primary-color: #007bff;
|
|
225
|
+
--secondary-color: #6c757d;
|
|
226
|
+
--info-color: #17a2b8;
|
|
227
|
+
--success-color: #28a745;
|
|
228
|
+
--warning-color: #ffc107;
|
|
229
|
+
--error-color: #dc3545;
|
|
230
|
+
--background-color: #ffffff;
|
|
231
|
+
--text-color: #000000;
|
|
232
|
+
--spacing-small: 0.5em;
|
|
233
|
+
--spacing-medium: 1em;
|
|
234
|
+
--spacing-large: 2em;
|
|
235
|
+
--font-size-small: 0.875rem;
|
|
236
|
+
--font-size-medium: 1rem;
|
|
237
|
+
--font-size-large: 1.25rem;
|
|
238
|
+
--shadow-light: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
239
|
+
--shadow-dark: 0 2px 4px rgba(0, 0, 0, 0.5);
|
|
240
|
+
--border-radius: 4px;
|
|
241
|
+
--padding: 0.5em 1em;
|
|
242
|
+
--focus-outline: 2px solid #0056b3;
|
|
243
|
+
--form-background: #ffffff;
|
|
244
|
+
--xtend-skeleton-bg: rgba(148, 163, 184, 0.16);
|
|
245
|
+
--xtend-skeleton-highlight: rgba(255, 255, 255, 0.72);
|
|
246
|
+
--xtend-skeleton-surface: rgba(148, 163, 184, 0.12);
|
|
247
|
+
--xtend-skeleton-line-bg: rgba(148, 163, 184, 0.24);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
[data-theme="dark"] {
|
|
251
|
+
--primary-color: #0d6efd;
|
|
252
|
+
--secondary-color: #adb5bd;
|
|
253
|
+
--info-color: #17a2b8;
|
|
254
|
+
--success-color: #28a745;
|
|
255
|
+
--warning-color: #ffc107;
|
|
256
|
+
--error-color: #dc3545;
|
|
257
|
+
--background-color: #121212;
|
|
258
|
+
--text-color: #f0f0f0;
|
|
259
|
+
--form-background: #1e1e1e;
|
|
260
|
+
--shadow-light: var(--shadow-dark);
|
|
261
|
+
--card-bg: #1e1e1e;
|
|
262
|
+
--card-text: #ffffff;
|
|
263
|
+
--section-bg: #1e1e1e;
|
|
264
|
+
--primary-color-hover: #0a58ca;
|
|
265
|
+
--xtend-skeleton-bg: rgba(148, 163, 184, 0.12);
|
|
266
|
+
--xtend-skeleton-highlight: rgba(226, 232, 240, 0.10);
|
|
267
|
+
--xtend-skeleton-surface: rgba(226, 232, 240, 0.045);
|
|
268
|
+
--xtend-skeleton-line-bg: rgba(148, 163, 184, 0.18);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
@media (prefers-color-scheme: dark) {
|
|
272
|
+
:root:not([data-theme="light"]) {
|
|
273
|
+
--xtend-skeleton-bg: rgba(148, 163, 184, 0.12);
|
|
274
|
+
--xtend-skeleton-highlight: rgba(226, 232, 240, 0.10);
|
|
275
|
+
--xtend-skeleton-surface: rgba(226, 232, 240, 0.045);
|
|
276
|
+
--xtend-skeleton-line-bg: rgba(148, 163, 184, 0.18);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
html {
|
|
281
|
+
box-sizing: border-box;
|
|
282
|
+
max-width: 100%;
|
|
283
|
+
overflow-x: hidden;
|
|
284
|
+
overflow-x: clip;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
*,
|
|
288
|
+
*::before,
|
|
289
|
+
*::after {
|
|
290
|
+
box-sizing: inherit;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
body {
|
|
294
|
+
min-width: 0;
|
|
295
|
+
max-width: 100%;
|
|
296
|
+
overflow-x: hidden;
|
|
297
|
+
overflow-x: clip;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
img,
|
|
301
|
+
video,
|
|
302
|
+
canvas,
|
|
303
|
+
iframe,
|
|
304
|
+
object,
|
|
305
|
+
embed {
|
|
306
|
+
max-width: 100%;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
img,
|
|
310
|
+
video {
|
|
311
|
+
height: auto;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
pre {
|
|
315
|
+
max-width: 100%;
|
|
316
|
+
overflow-x: auto;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
main {
|
|
320
|
+
box-sizing: border-box;
|
|
321
|
+
min-width: 0;
|
|
322
|
+
width: 100%;
|
|
323
|
+
padding: var(--xtend-main-padding, 0);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
section {
|
|
327
|
+
box-sizing: border-box;
|
|
328
|
+
min-width: 0;
|
|
329
|
+
margin-block-end: var(--xtend-section-margin-block-end, 0);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
body[xt-ui-effects~="fade-in"],
|
|
333
|
+
body[data-xt-ui-effects~="fade-in"] {
|
|
334
|
+
visibility: hidden;
|
|
335
|
+
opacity: 0;
|
|
336
|
+
transition: opacity var(--xt-ui-effects-fade-duration, 0.5s) ease;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
body[xt-ui-effects~="fade-in"][data-xt-ui-effects-ready="true"],
|
|
340
|
+
body[data-xt-ui-effects~="fade-in"][data-xt-ui-effects-ready="true"],
|
|
341
|
+
body[data-xt-ui-effects-state="ready"] {
|
|
342
|
+
visibility: visible;
|
|
343
|
+
opacity: 1;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
@keyframes xtend-skeleton-shimmer {
|
|
347
|
+
0% {
|
|
348
|
+
background-position: 160% 0;
|
|
349
|
+
}
|
|
350
|
+
100% {
|
|
351
|
+
background-position: -160% 0;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
[data-xtend-skeleton]:not(:defined) {
|
|
356
|
+
display: block;
|
|
357
|
+
position: relative;
|
|
358
|
+
min-width: 0;
|
|
359
|
+
min-height: var(--xtend-skeleton-min-height, 4rem);
|
|
360
|
+
overflow: hidden;
|
|
361
|
+
contain: layout paint;
|
|
362
|
+
pointer-events: none;
|
|
363
|
+
color: transparent !important;
|
|
364
|
+
border-radius: var(--xtend-skeleton-radius, 8px);
|
|
365
|
+
background:
|
|
366
|
+
linear-gradient(
|
|
367
|
+
90deg,
|
|
368
|
+
var(--xtend-skeleton-bg, rgba(148, 163, 184, 0.16)) 0%,
|
|
369
|
+
var(--xtend-skeleton-highlight, rgba(255, 255, 255, 0.72)) 48%,
|
|
370
|
+
var(--xtend-skeleton-bg, rgba(148, 163, 184, 0.16)) 100%
|
|
371
|
+
);
|
|
372
|
+
background-size: 220% 100%;
|
|
373
|
+
animation: xtend-skeleton-shimmer var(--xtend-skeleton-speed, 1.1s) ease-in-out infinite;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
[data-xtend-skeleton]:not(:defined) > * {
|
|
377
|
+
visibility: hidden !important;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
[data-xtend-skeleton="inline"]:not(:defined) {
|
|
381
|
+
display: inline-block;
|
|
382
|
+
min-width: var(--xtend-skeleton-width, 7rem);
|
|
383
|
+
min-height: var(--xtend-skeleton-min-height, 2.25rem);
|
|
384
|
+
vertical-align: middle;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
${hiddenSelectors} {
|
|
388
|
+
visibility: hidden;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
[data-xtend-skeleton-active="true"] > :not([data-xtend-skeleton-loader]) {
|
|
392
|
+
visibility: hidden;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
[data-xtend-skeleton-loader] {
|
|
396
|
+
display: grid;
|
|
397
|
+
gap: var(--xtend-skeleton-gap, 0.68rem);
|
|
398
|
+
width: var(--xtend-skeleton-width, 100%);
|
|
399
|
+
max-width: var(--xtend-skeleton-max-width, 100%);
|
|
400
|
+
margin-inline: var(--xtend-skeleton-margin-inline, 0);
|
|
401
|
+
min-width: 0;
|
|
402
|
+
box-sizing: border-box;
|
|
403
|
+
padding: var(--xtend-skeleton-padding, 1rem);
|
|
404
|
+
border-radius: var(--xtend-skeleton-radius, 8px);
|
|
405
|
+
background: var(--xtend-skeleton-surface, rgba(148, 163, 184, 0.12));
|
|
406
|
+
overflow: hidden;
|
|
407
|
+
contain: layout paint;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
[data-xtend-skeleton-line] {
|
|
411
|
+
display: block;
|
|
412
|
+
height: 0.82rem;
|
|
413
|
+
max-width: 100%;
|
|
414
|
+
border-radius: 999px;
|
|
415
|
+
background: var(--xtend-skeleton-line-bg, rgba(148, 163, 184, 0.24));
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
@media (prefers-reduced-motion: reduce) {
|
|
419
|
+
body[xt-ui-effects~="fade-in"],
|
|
420
|
+
body[data-xt-ui-effects~="fade-in"],
|
|
421
|
+
[data-xtend-skeleton]:not(:defined) {
|
|
422
|
+
transition-duration: 0.01ms;
|
|
423
|
+
animation-duration: 0.01ms;
|
|
424
|
+
animation-iteration-count: 1;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
`.trim();
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
function canUseConstructableStylesheets(root = document) {
|
|
431
|
+
return Boolean(
|
|
432
|
+
root &&
|
|
433
|
+
'adoptedStyleSheets' in root &&
|
|
434
|
+
typeof CSSStyleSheet !== 'undefined' &&
|
|
435
|
+
CSSStyleSheet.prototype &&
|
|
436
|
+
typeof CSSStyleSheet.prototype.replaceSync === 'function'
|
|
437
|
+
);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
function resolveStyleHost() {
|
|
441
|
+
if (typeof document === 'undefined') return null;
|
|
442
|
+
return document.head || document.getElementsByTagName('head')[0] || document.documentElement;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
function isStandardThemeStylesheetHref(href) {
|
|
446
|
+
const raw = String(href || '').trim();
|
|
447
|
+
if (!raw) return false;
|
|
448
|
+
try {
|
|
449
|
+
const url = new URL(raw, document.baseURI);
|
|
450
|
+
return url.pathname.split('/').pop() === STANDARD_THEME_STYLESHEET;
|
|
451
|
+
} catch (_) {
|
|
452
|
+
return raw.split('?')[0].split('#')[0].endsWith(STANDARD_THEME_STYLESHEET);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
function findStandardThemeStylesheet() {
|
|
457
|
+
if (typeof document === 'undefined' || typeof document.querySelectorAll !== 'function') return null;
|
|
458
|
+
return Array.from(document.querySelectorAll('link[rel~="stylesheet"]'))
|
|
459
|
+
.find((link) => isStandardThemeStylesheetHref(link.getAttribute('href') || link.href)) || null;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
function getThemeStylesheetState() {
|
|
463
|
+
const link = findStandardThemeStylesheet();
|
|
464
|
+
return {
|
|
465
|
+
schema: STYLE_REGISTRY_CONTRACT,
|
|
466
|
+
standardFileName: STANDARD_THEME_STYLESHEET,
|
|
467
|
+
present: Boolean(link),
|
|
468
|
+
href: link ? (link.getAttribute('href') || link.href || '') : '',
|
|
469
|
+
role: link ? 'optional-host-theme' : 'runtime-critical-only'
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
function markRuntimeStylesReady(record) {
|
|
474
|
+
if (typeof document !== 'undefined' && document.documentElement) {
|
|
475
|
+
const themeState = getThemeStylesheetState();
|
|
476
|
+
document.documentElement.setAttribute('data-xtend-runtime-styles', 'ready');
|
|
477
|
+
document.documentElement.setAttribute('data-xtend-theme-stylesheet', themeState.present ? 'external' : 'runtime');
|
|
478
|
+
if (record && record.mode) {
|
|
479
|
+
document.documentElement.setAttribute('data-xtend-runtime-styles-mode', record.mode);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
function ensureDocumentStyle(key, cssText, options = {}) {
|
|
485
|
+
if (typeof document === 'undefined') return null;
|
|
486
|
+
const css = normalizeStyleCss(cssText);
|
|
487
|
+
if (!css) return null;
|
|
488
|
+
|
|
489
|
+
const normalizedKey = sanitizeStyleKey(key);
|
|
490
|
+
const id = options.id || `xtend-style-${normalizedKey}`;
|
|
491
|
+
const preferStyleElement = options.strategy === 'style';
|
|
492
|
+
|
|
493
|
+
if (!preferStyleElement && canUseConstructableStylesheets(document)) {
|
|
494
|
+
try {
|
|
495
|
+
let sheet = adoptedStyleSheetsByKey.get(id);
|
|
496
|
+
const createdSheet = !sheet;
|
|
497
|
+
if (!sheet) {
|
|
498
|
+
sheet = new CSSStyleSheet();
|
|
499
|
+
adoptedStyleSheetsByKey.set(id, sheet);
|
|
500
|
+
}
|
|
501
|
+
if (createdSheet || !styleRegistryRecords.has(normalizedKey) || styleRegistryRecords.get(normalizedKey).cssText !== css) {
|
|
502
|
+
sheet.replaceSync(css);
|
|
503
|
+
}
|
|
504
|
+
if (!document.adoptedStyleSheets.includes(sheet)) {
|
|
505
|
+
document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];
|
|
506
|
+
}
|
|
507
|
+
const record = {
|
|
508
|
+
schema: STYLE_REGISTRY_CONTRACT,
|
|
509
|
+
key: normalizedKey,
|
|
510
|
+
id,
|
|
511
|
+
mode: 'adoptedStyleSheet',
|
|
512
|
+
cssText: css,
|
|
513
|
+
sheet,
|
|
514
|
+
source: options.source || 'xtend-loader'
|
|
515
|
+
};
|
|
516
|
+
styleRegistryRecords.set(normalizedKey, record);
|
|
517
|
+
return record;
|
|
518
|
+
} catch (error) {
|
|
519
|
+
loaderVerboseWarn('XTend StyleRegistry: Constructable Stylesheet fallback aktiviert.', error);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
const host = resolveStyleHost();
|
|
524
|
+
if (!host || typeof document.createElement !== 'function') return null;
|
|
525
|
+
|
|
526
|
+
let style = document.getElementById(id);
|
|
527
|
+
if (!style) {
|
|
528
|
+
style = document.createElement('style');
|
|
529
|
+
style.id = id;
|
|
530
|
+
style.setAttribute('data-xtend-style-registry', STYLE_REGISTRY_CONTRACT);
|
|
531
|
+
style.setAttribute('data-xtend-style-key', normalizedKey);
|
|
532
|
+
if (loaderStyleNonce) style.setAttribute('nonce', loaderStyleNonce);
|
|
533
|
+
host.appendChild(style);
|
|
534
|
+
}
|
|
535
|
+
if (style.textContent !== css) {
|
|
536
|
+
style.textContent = css;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
const record = {
|
|
540
|
+
schema: STYLE_REGISTRY_CONTRACT,
|
|
541
|
+
key: normalizedKey,
|
|
542
|
+
id,
|
|
543
|
+
mode: 'styleElement',
|
|
544
|
+
cssText: css,
|
|
545
|
+
element: style,
|
|
546
|
+
source: options.source || 'xtend-loader'
|
|
547
|
+
};
|
|
548
|
+
styleRegistryRecords.set(normalizedKey, record);
|
|
549
|
+
return record;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
function ensureRuntimeStyles(options = {}) {
|
|
553
|
+
if (runtimeStylesInitialized && !options.force) {
|
|
554
|
+
return styleRegistryRecords.get(RUNTIME_STYLE_KEY) || null;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
try {
|
|
558
|
+
const record = ensureDocumentStyle(RUNTIME_STYLE_KEY, createRuntimeCriticalCss(), {
|
|
559
|
+
id: RUNTIME_STYLE_ID,
|
|
560
|
+
source: options.source || 'xtend-loader.runtime',
|
|
561
|
+
strategy: options.strategy
|
|
562
|
+
});
|
|
563
|
+
runtimeStylesInitialized = Boolean(record);
|
|
564
|
+
if (record) markRuntimeStylesReady(record);
|
|
565
|
+
return record;
|
|
566
|
+
} catch (error) {
|
|
567
|
+
loaderVerboseWarn('XTend StyleRegistry: Runtime-Styles konnten nicht initialisiert werden.', error);
|
|
568
|
+
return null;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
function defineComponentStyle(tag, cssText, options = {}) {
|
|
573
|
+
const normalizedTag = normalizeComponentTag(tag);
|
|
574
|
+
const key = sanitizeStyleKey(options.key || `component:${normalizedTag || 'anonymous'}`);
|
|
575
|
+
const record = {
|
|
576
|
+
schema: STYLE_REGISTRY_CONTRACT,
|
|
577
|
+
key,
|
|
578
|
+
tag: normalizedTag,
|
|
579
|
+
cssText: normalizeStyleCss(cssText),
|
|
580
|
+
source: options.source || normalizedTag || 'component'
|
|
581
|
+
};
|
|
582
|
+
styleRegistryRecords.set(key, record);
|
|
583
|
+
return record;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
function resolveRegisteredStyle(styleOrKey) {
|
|
587
|
+
if (styleOrKey && typeof styleOrKey === 'object' && typeof styleOrKey.cssText === 'string') {
|
|
588
|
+
return styleOrKey;
|
|
589
|
+
}
|
|
590
|
+
if (typeof styleOrKey === 'string' && styleRegistryRecords.has(styleOrKey)) {
|
|
591
|
+
return styleRegistryRecords.get(styleOrKey);
|
|
592
|
+
}
|
|
593
|
+
return {
|
|
594
|
+
schema: STYLE_REGISTRY_CONTRACT,
|
|
595
|
+
key: sanitizeStyleKey('inline-style'),
|
|
596
|
+
cssText: normalizeStyleCss(styleOrKey),
|
|
597
|
+
source: 'inline'
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
function normalizeStyleRoot(root) {
|
|
602
|
+
if (root && typeof root === 'object' && (root.nodeType === 9 || root.nodeType === 11 || 'adoptedStyleSheets' in root)) return root;
|
|
603
|
+
if (root && root.shadowRoot) return root.shadowRoot;
|
|
604
|
+
if (root && root.ownerDocument) return root.ownerDocument;
|
|
605
|
+
return typeof document !== 'undefined' ? document : null;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
function adoptStyle(root, styleOrKey, options = {}) {
|
|
609
|
+
const target = normalizeStyleRoot(root);
|
|
610
|
+
const sourceRecord = resolveRegisteredStyle(styleOrKey);
|
|
611
|
+
const css = normalizeStyleCss(sourceRecord.cssText);
|
|
612
|
+
if (!target || !css) return null;
|
|
613
|
+
|
|
614
|
+
const key = sanitizeStyleKey(options.key || sourceRecord.key || 'adopted-style');
|
|
615
|
+
const id = options.id || `xtend-adopted-${key}`;
|
|
616
|
+
|
|
617
|
+
if (canUseConstructableStylesheets(target) && options.strategy !== 'style') {
|
|
618
|
+
let sheet = adoptedStyleSheetsByKey.get(id);
|
|
619
|
+
if (!sheet) {
|
|
620
|
+
sheet = new CSSStyleSheet();
|
|
621
|
+
adoptedStyleSheetsByKey.set(id, sheet);
|
|
622
|
+
}
|
|
623
|
+
sheet.replaceSync(css);
|
|
624
|
+
if (!target.adoptedStyleSheets.includes(sheet)) {
|
|
625
|
+
target.adoptedStyleSheets = [...target.adoptedStyleSheets, sheet];
|
|
626
|
+
}
|
|
627
|
+
return {
|
|
628
|
+
schema: STYLE_REGISTRY_CONTRACT,
|
|
629
|
+
key,
|
|
630
|
+
id,
|
|
631
|
+
mode: 'adoptedStyleSheet',
|
|
632
|
+
sheet,
|
|
633
|
+
target,
|
|
634
|
+
source: options.source || sourceRecord.source || 'xtend-style-registry'
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
const appendTarget = target.nodeType === 9 ? resolveStyleHost() : target;
|
|
639
|
+
const ownerDocument = target.ownerDocument || (target.nodeType === 9 ? target : document);
|
|
640
|
+
if (!ownerDocument || typeof ownerDocument.createElement !== 'function') return null;
|
|
641
|
+
if (!appendTarget || typeof appendTarget.appendChild !== 'function') return null;
|
|
642
|
+
let style = typeof appendTarget.querySelector === 'function'
|
|
643
|
+
? appendTarget.querySelector(`[data-xtend-adopted-style="${id}"]`)
|
|
644
|
+
: null;
|
|
645
|
+
if (!style) {
|
|
646
|
+
style = ownerDocument.createElement('style');
|
|
647
|
+
style.setAttribute('data-xtend-style-registry', STYLE_REGISTRY_CONTRACT);
|
|
648
|
+
style.setAttribute('data-xtend-adopted-style', id);
|
|
649
|
+
if (loaderStyleNonce) style.setAttribute('nonce', loaderStyleNonce);
|
|
650
|
+
appendTarget.appendChild(style);
|
|
651
|
+
}
|
|
652
|
+
if (style.textContent !== css) style.textContent = css;
|
|
653
|
+
return {
|
|
654
|
+
schema: STYLE_REGISTRY_CONTRACT,
|
|
655
|
+
key,
|
|
656
|
+
id,
|
|
657
|
+
mode: 'styleElement',
|
|
658
|
+
element: style,
|
|
659
|
+
target: appendTarget,
|
|
660
|
+
source: options.source || sourceRecord.source || 'xtend-style-registry'
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
function getRegisteredStyle(key) {
|
|
665
|
+
return styleRegistryRecords.get(sanitizeStyleKey(key)) || null;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
function listRegisteredStyles() {
|
|
669
|
+
return Array.from(styleRegistryRecords.values()).map((record) => ({
|
|
670
|
+
schema: record.schema,
|
|
671
|
+
key: record.key,
|
|
672
|
+
id: record.id || '',
|
|
673
|
+
mode: record.mode || 'registered',
|
|
674
|
+
tag: record.tag || '',
|
|
675
|
+
source: record.source || ''
|
|
676
|
+
}));
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
async function initiateXTend(options = {}) {
|
|
680
|
+
ensureRuntimeStyles({ source: 'loader.boot' });
|
|
681
|
+
const loaderScript = resolveLoaderScript();
|
|
682
|
+
const uiEffectsInput = resolveLoaderUiEffectsInput(options, loaderScript);
|
|
683
|
+
let uiEffectsController = null;
|
|
684
|
+
let manifestUrl = null;
|
|
685
|
+
let manifest = {};
|
|
686
|
+
|
|
687
|
+
try {
|
|
688
|
+
manifestUrl = resolveManifestUrl(options.manifestUrl, loaderScript);
|
|
689
|
+
const moduleCacheBust = resolveModuleCacheBust(options.moduleCacheBust, loaderScript, manifestUrl);
|
|
690
|
+
|
|
691
|
+
manifest = await fetchManifest(manifestUrl, { moduleCacheBust });
|
|
692
|
+
activeManifest = manifest;
|
|
693
|
+
uiEffectsController = await prepareConfiguredUiEffects(manifest, uiEffectsInput);
|
|
694
|
+
|
|
695
|
+
await loadCoreModules(manifest);
|
|
696
|
+
await preloadManifestComponents(manifest);
|
|
697
|
+
await loadDomComponents(manifest);
|
|
698
|
+
|
|
699
|
+
loaderVerboseLog('XTend Loader: Komponenten geladen.');
|
|
700
|
+
} catch (error) {
|
|
701
|
+
emitLoaderDiagnostic('xtend.loader.error', 'error', 'XTend Loader Fehler', {
|
|
702
|
+
message: error && error.message ? error.message : String(error)
|
|
703
|
+
});
|
|
704
|
+
console.error('XTend Loader Fehler:', error);
|
|
705
|
+
} finally {
|
|
706
|
+
releaseConfiguredUiEffects(uiEffectsController, uiEffectsInput);
|
|
707
|
+
await initializeApi(manifest);
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
return {
|
|
711
|
+
schema: LOADER_CONTRACT,
|
|
712
|
+
manifest,
|
|
713
|
+
loadedTags: Array.from(loadedTags),
|
|
714
|
+
performanceMeasurements: loaderMeasurements.slice(),
|
|
715
|
+
uiEffects: uiEffectsController && uiEffectsController.state ? uiEffectsController.state : null,
|
|
716
|
+
verbose: getLoaderVerboseState()
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
function resolveLoaderScript() {
|
|
721
|
+
const scripts = Array.from(document.scripts || []);
|
|
722
|
+
const moduleUrl = new URL(import.meta.url, document.baseURI).href;
|
|
723
|
+
|
|
724
|
+
return document.currentScript ||
|
|
725
|
+
scripts.find((script) => script.src && new URL(script.src, document.baseURI).href === moduleUrl) ||
|
|
726
|
+
scripts.find((script) => script.src && script.src.includes('xtend-loader.js')) ||
|
|
727
|
+
null;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
function resolveManifestUrl(explicitManifestUrl, loaderScript) {
|
|
731
|
+
const configuredManifestUrl =
|
|
732
|
+
explicitManifestUrl ||
|
|
733
|
+
(loaderScript && loaderScript.getAttribute('data-manifest')) ||
|
|
734
|
+
DEFAULT_MANIFEST_URL;
|
|
735
|
+
|
|
736
|
+
const policy = classifyLoaderUrl(configuredManifestUrl, {
|
|
737
|
+
kind: 'manifest',
|
|
738
|
+
baseUrl: document.baseURI,
|
|
739
|
+
source: 'data-manifest'
|
|
740
|
+
});
|
|
741
|
+
|
|
742
|
+
if (!policy.ok) {
|
|
743
|
+
emitSecurityDiagnostic('xtend.security.loader.refused', 'Manifest URL wurde durch die Loader Policy verweigert', {
|
|
744
|
+
policy: LOADER_POLICY_CONTRACT,
|
|
745
|
+
manifestPolicy: MANIFEST_POLICY_CONTRACT,
|
|
746
|
+
input: configuredManifestUrl,
|
|
747
|
+
diagnostics: policy.diagnostics
|
|
748
|
+
});
|
|
749
|
+
throw new Error(`XTend Loader Policy verweigert Manifest URL: ${configuredManifestUrl}`);
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
return policy.url;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
function resolveLoaderUiEffectsInput(options = {}, loaderScript = null) {
|
|
756
|
+
return {
|
|
757
|
+
target: document.body || null,
|
|
758
|
+
body: document.body || null,
|
|
759
|
+
script: loaderScript,
|
|
760
|
+
effects: options.uiEffects || options.uiEffect || options.effects || '',
|
|
761
|
+
durationMs: options.uiEffectDuration || options.uiEffectsDuration || '',
|
|
762
|
+
rmtDocument: options.rmtDocument ||
|
|
763
|
+
options.rmt ||
|
|
764
|
+
(typeof window !== 'undefined' && (
|
|
765
|
+
window.xtendRmtDocument ||
|
|
766
|
+
window.XTendRmtDocument ||
|
|
767
|
+
window.xtendDocsRmtDocument
|
|
768
|
+
)) ||
|
|
769
|
+
null
|
|
770
|
+
};
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
function normalizeUiEffectsHint(value) {
|
|
774
|
+
return String(value || '').trim().toLowerCase();
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
function isDisabledUiEffectsHint(value) {
|
|
778
|
+
const normalized = normalizeUiEffectsHint(value);
|
|
779
|
+
return normalized === '' ||
|
|
780
|
+
normalized === 'none' ||
|
|
781
|
+
normalized === 'off' ||
|
|
782
|
+
normalized === 'false' ||
|
|
783
|
+
normalized === '0' ||
|
|
784
|
+
normalized === 'disabled';
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
function readUiEffectsHintFromElement(element) {
|
|
788
|
+
if (!element || typeof element.getAttribute !== 'function') return '';
|
|
789
|
+
return element.getAttribute('xt-ui-effects') ||
|
|
790
|
+
element.getAttribute('data-xt-ui-effects') ||
|
|
791
|
+
element.getAttribute('data-ui-effects') ||
|
|
792
|
+
'';
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
function rmtDocumentHasUiEffectsHint(documentLike) {
|
|
796
|
+
if (!documentLike || typeof documentLike !== 'object') return false;
|
|
797
|
+
try {
|
|
798
|
+
return JSON.stringify(documentLike).includes('ui-effects') ||
|
|
799
|
+
JSON.stringify(documentLike).includes('uiEffects');
|
|
800
|
+
} catch (_) {
|
|
801
|
+
return false;
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
function hasConfiguredUiEffects(input = {}) {
|
|
806
|
+
const explicit = normalizeUiEffectsHint(input.effects);
|
|
807
|
+
const bodyHint = readUiEffectsHintFromElement(input.body);
|
|
808
|
+
const scriptHint = readUiEffectsHintFromElement(input.script);
|
|
809
|
+
const hasExplicitEffect = explicit && !isDisabledUiEffectsHint(explicit);
|
|
810
|
+
const hasBodyEffect = bodyHint && !isDisabledUiEffectsHint(bodyHint);
|
|
811
|
+
const hasScriptEffect = scriptHint && !isDisabledUiEffectsHint(scriptHint);
|
|
812
|
+
return Boolean(hasExplicitEffect || hasBodyEffect || hasScriptEffect || rmtDocumentHasUiEffectsHint(input.rmtDocument));
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
async function loadUiEffectsRuntime(manifest = {}) {
|
|
816
|
+
const url = manifest['x-utils'];
|
|
817
|
+
if (!url) return null;
|
|
818
|
+
const importPolicy = classifyLoaderUrl(url, {
|
|
819
|
+
kind: 'module',
|
|
820
|
+
baseUrl: document.baseURI,
|
|
821
|
+
source: 'x-utils'
|
|
822
|
+
});
|
|
823
|
+
if (!importPolicy.ok) {
|
|
824
|
+
emitSecurityDiagnostic('xtend.security.import.refused', 'Import fuer x-utils wurde durch die Loader Policy verweigert', {
|
|
825
|
+
policy: IMPORT_POLICY_CONTRACT,
|
|
826
|
+
tag: 'x-utils',
|
|
827
|
+
url,
|
|
828
|
+
diagnostics: importPolicy.diagnostics
|
|
829
|
+
});
|
|
830
|
+
return null;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
try {
|
|
834
|
+
const module = await import(importPolicy.url);
|
|
835
|
+
if (module && module.XUtils && typeof module.XUtils.prepareUiEffects === 'function') {
|
|
836
|
+
loadedTags.add('x-utils');
|
|
837
|
+
return module.XUtils;
|
|
838
|
+
}
|
|
839
|
+
} catch (error) {
|
|
840
|
+
emitLoaderDiagnostic('xtend.loader.ui_effects.load_failed', 'warn', 'x-utils UI Effects konnten nicht geladen werden', {
|
|
841
|
+
tag: 'x-utils',
|
|
842
|
+
url: importPolicy.url,
|
|
843
|
+
message: error && error.message ? error.message : String(error)
|
|
844
|
+
});
|
|
845
|
+
}
|
|
846
|
+
return null;
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
async function prepareConfiguredUiEffects(manifest, input) {
|
|
850
|
+
if (!hasConfiguredUiEffects(input)) return null;
|
|
851
|
+
const runtime = await loadUiEffectsRuntime(manifest);
|
|
852
|
+
if (runtime && typeof runtime.prepareUiEffects === 'function') {
|
|
853
|
+
return {
|
|
854
|
+
runtime,
|
|
855
|
+
state: runtime.prepareUiEffects(input)
|
|
856
|
+
};
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
return {
|
|
860
|
+
runtime: null,
|
|
861
|
+
state: prepareUiEffectsFallback(input)
|
|
862
|
+
};
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
function inputRequestsFadeIn(input = {}) {
|
|
866
|
+
const hints = [
|
|
867
|
+
input.effects,
|
|
868
|
+
readUiEffectsHintFromElement(input.body),
|
|
869
|
+
readUiEffectsHintFromElement(input.script)
|
|
870
|
+
].map(normalizeUiEffectsHint);
|
|
871
|
+
|
|
872
|
+
if (hints.some((hint) => isDisabledUiEffectsHint(hint))) return false;
|
|
873
|
+
return hints.some((hint) => hint.includes('fade-in') || hint.includes('fadein')) ||
|
|
874
|
+
rmtDocumentHasUiEffectsHint(input.rmtDocument);
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
function prepareUiEffectsFallback(input = {}) {
|
|
878
|
+
const target = input.target || input.body || document.body;
|
|
879
|
+
const active = Boolean(target && inputRequestsFadeIn(input));
|
|
880
|
+
const state = {
|
|
881
|
+
schema: 'xtend.utility.ui-effects.v1',
|
|
882
|
+
componentRef: 'x-utils',
|
|
883
|
+
target,
|
|
884
|
+
targetRef: target === document.body ? 'document.body' : 'custom-target',
|
|
885
|
+
effects: active ? ['fade-in'] : [],
|
|
886
|
+
active,
|
|
887
|
+
source: 'loader-fallback',
|
|
888
|
+
bodyAttribute: 'xt-ui-effects',
|
|
889
|
+
rmtTag: 'ui-effects',
|
|
890
|
+
supportedEffects: ['fade-in'],
|
|
891
|
+
durationMs: 500,
|
|
892
|
+
kernelBoundary: 'no-rmt-kernel-import-of-xtend-types',
|
|
893
|
+
prepared: active,
|
|
894
|
+
released: false
|
|
895
|
+
};
|
|
896
|
+
|
|
897
|
+
if (active) {
|
|
898
|
+
target.setAttribute('data-xt-ui-effects', 'fade-in');
|
|
899
|
+
target.setAttribute('data-xt-ui-effects-state', 'preparing');
|
|
900
|
+
target.removeAttribute('data-xt-ui-effects-ready');
|
|
901
|
+
target.style.visibility = 'hidden';
|
|
902
|
+
target.style.opacity = '0';
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
return state;
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
function releaseUiEffectsFallback(stateOrInput = {}) {
|
|
909
|
+
const target = stateOrInput.target || stateOrInput.body || document.body;
|
|
910
|
+
if (!target) return stateOrInput;
|
|
911
|
+
target.setAttribute('data-xt-ui-effects-ready', 'true');
|
|
912
|
+
target.setAttribute('data-xt-ui-effects-state', 'ready');
|
|
913
|
+
target.style.visibility = 'visible';
|
|
914
|
+
target.style.opacity = '1';
|
|
915
|
+
return {
|
|
916
|
+
...stateOrInput,
|
|
917
|
+
target,
|
|
918
|
+
released: true
|
|
919
|
+
};
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
function releaseConfiguredUiEffects(controller, input) {
|
|
923
|
+
if (controller && controller.runtime && typeof controller.runtime.releaseUiEffects === 'function') {
|
|
924
|
+
controller.state = controller.runtime.releaseUiEffects(controller.state);
|
|
925
|
+
return controller.state;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
if (controller && controller.state && controller.state.active) {
|
|
929
|
+
controller.state = releaseUiEffectsFallback(controller.state);
|
|
930
|
+
return controller.state;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
if (inputRequestsFadeIn(input)) {
|
|
934
|
+
return releaseUiEffectsFallback(input);
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
return null;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
async function fetchManifest(manifestUrl, options = {}) {
|
|
941
|
+
return measureLoaderPhase('xtend.loader.manifest', async () => {
|
|
942
|
+
const manifestPolicy = classifyLoaderUrl(manifestUrl, {
|
|
943
|
+
kind: 'manifest',
|
|
944
|
+
baseUrl: document.baseURI,
|
|
945
|
+
source: 'fetchManifest'
|
|
946
|
+
});
|
|
947
|
+
if (!manifestPolicy.ok) {
|
|
948
|
+
emitSecurityDiagnostic('xtend.security.loader.refused', 'Manifest Fetch wurde durch die Loader Policy verweigert', {
|
|
949
|
+
policy: LOADER_POLICY_CONTRACT,
|
|
950
|
+
manifestUrl,
|
|
951
|
+
diagnostics: manifestPolicy.diagnostics
|
|
952
|
+
});
|
|
953
|
+
throw new Error(`XTend Loader Policy verweigert Manifest Fetch: ${manifestUrl}`);
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
const response = await fetch(manifestUrl);
|
|
957
|
+
if (!response.ok) {
|
|
958
|
+
throw new Error(`Manifest konnte nicht geladen werden: HTTP ${response.status}`);
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
try {
|
|
962
|
+
const rawManifest = await response.json();
|
|
963
|
+
return resolveManifestUrls(rawManifest, response.url, options);
|
|
964
|
+
} catch (error) {
|
|
965
|
+
emitLoaderDiagnostic('xtend.loader.manifest.parse_failed', 'error', 'Manifest konnte nicht geparst werden', {
|
|
966
|
+
manifestUrl,
|
|
967
|
+
message: error && error.message ? error.message : String(error)
|
|
968
|
+
});
|
|
969
|
+
throw error;
|
|
970
|
+
}
|
|
971
|
+
}, { manifestUrl });
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
function resolveManifestUrls(rawManifest, baseUrl, options = {}) {
|
|
975
|
+
const resolvedManifest = {};
|
|
976
|
+
if (!rawManifest || typeof rawManifest !== 'object' || Array.isArray(rawManifest)) {
|
|
977
|
+
emitSecurityDiagnostic('xtend.security.manifest.invalid', 'Manifest wurde wegen ungueltiger Struktur verweigert', {
|
|
978
|
+
policy: MANIFEST_POLICY_CONTRACT,
|
|
979
|
+
baseUrl,
|
|
980
|
+
reason: 'invalid-shape'
|
|
981
|
+
});
|
|
982
|
+
return resolvedManifest;
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
for (const [tag, url] of Object.entries(rawManifest || {})) {
|
|
986
|
+
const record = classifyManifestRecord(tag, url, baseUrl);
|
|
987
|
+
if (!record.ok) {
|
|
988
|
+
emitSecurityDiagnostic('xtend.security.manifest.invalid', 'Manifest Record wurde durch die Manifest Policy verweigert', {
|
|
989
|
+
policy: MANIFEST_POLICY_CONTRACT,
|
|
990
|
+
tag,
|
|
991
|
+
diagnostics: record.diagnostics
|
|
992
|
+
});
|
|
993
|
+
continue;
|
|
994
|
+
}
|
|
995
|
+
resolvedManifest[record.tag] = appendModuleCacheBust(record.tag, record.url, options.moduleCacheBust);
|
|
996
|
+
}
|
|
997
|
+
return resolvedManifest;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
function resolveModuleCacheBust(explicitCacheBust, loaderScript, manifestUrl) {
|
|
1001
|
+
const configuredCacheBust =
|
|
1002
|
+
explicitCacheBust ||
|
|
1003
|
+
(loaderScript && (
|
|
1004
|
+
loaderScript.getAttribute('data-module-cache-bust') ||
|
|
1005
|
+
loaderScript.getAttribute('data-cache-bust')
|
|
1006
|
+
)) ||
|
|
1007
|
+
readCacheBustFromUrl(loaderScript && loaderScript.src) ||
|
|
1008
|
+
readCacheBustFromUrl(manifestUrl);
|
|
1009
|
+
|
|
1010
|
+
if (!configuredCacheBust) return '';
|
|
1011
|
+
return String(configuredCacheBust).trim().slice(0, 80);
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
function readCacheBustFromUrl(value) {
|
|
1015
|
+
if (!value) return '';
|
|
1016
|
+
try {
|
|
1017
|
+
const url = new URL(value, document.baseURI);
|
|
1018
|
+
return url.searchParams.get('v') ||
|
|
1019
|
+
url.searchParams.get('version') ||
|
|
1020
|
+
url.searchParams.get('cache') ||
|
|
1021
|
+
'';
|
|
1022
|
+
} catch (_) {
|
|
1023
|
+
return '';
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
function appendModuleCacheBust(tag, moduleUrl, cacheBust) {
|
|
1028
|
+
if (!cacheBust || tag === 'xstate') return moduleUrl;
|
|
1029
|
+
try {
|
|
1030
|
+
const url = new URL(moduleUrl, document.baseURI);
|
|
1031
|
+
if (url.searchParams.has(MODULE_CACHE_BUST_PARAM)) return url.href;
|
|
1032
|
+
url.searchParams.set(MODULE_CACHE_BUST_PARAM, cacheBust);
|
|
1033
|
+
return url.href;
|
|
1034
|
+
} catch (_) {
|
|
1035
|
+
return moduleUrl;
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
function loadScript(src, asModule = true) {
|
|
1040
|
+
return new Promise((resolve, reject) => {
|
|
1041
|
+
const script = document.createElement('script');
|
|
1042
|
+
script.src = src;
|
|
1043
|
+
script.type = asModule ? 'module' : 'text/javascript';
|
|
1044
|
+
script.onload = resolve;
|
|
1045
|
+
script.onerror = () => reject(new Error(`Fehler beim Laden von ${src}`));
|
|
1046
|
+
document.head.appendChild(script);
|
|
1047
|
+
});
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
async function loadCoreModules(manifest) {
|
|
1051
|
+
if (manifest.xstate) {
|
|
1052
|
+
await tryLoad('xstate', manifest.xstate);
|
|
1053
|
+
} else {
|
|
1054
|
+
emitLoaderDiagnostic('xtend.loader.core.xstate_missing', 'warn', 'Manifest enthaelt keinen xstate-Eintrag');
|
|
1055
|
+
loaderVerboseWarn('XTend Loader: Manifest enthaelt keinen xstate-Eintrag.');
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
if (manifest['x-theme']) {
|
|
1059
|
+
await tryLoad('x-theme', manifest['x-theme']);
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
async function preloadManifestComponents(manifest) {
|
|
1064
|
+
const preloadMeta = document.querySelector('meta[name="xtend-preload"]');
|
|
1065
|
+
if (!preloadMeta || !preloadMeta.content) return;
|
|
1066
|
+
|
|
1067
|
+
const preloadTags = preloadMeta.content
|
|
1068
|
+
.split(',')
|
|
1069
|
+
.map((tag) => tag.trim().toLowerCase())
|
|
1070
|
+
.filter(Boolean);
|
|
1071
|
+
|
|
1072
|
+
for (const tag of preloadTags) {
|
|
1073
|
+
if (!manifest[tag] || loadedTags.has(tag) || customElements.get(tag)) continue;
|
|
1074
|
+
await tryLoad(tag, manifest[tag]);
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
async function loadDomComponents(manifest) {
|
|
1079
|
+
const elements = Array.from(document.querySelectorAll('*'));
|
|
1080
|
+
const usedTags = new Set(
|
|
1081
|
+
elements
|
|
1082
|
+
.map((element) => element.tagName.toLowerCase())
|
|
1083
|
+
.filter((tag) => tag.startsWith('x') && Object.prototype.hasOwnProperty.call(manifest, tag))
|
|
1084
|
+
);
|
|
1085
|
+
|
|
1086
|
+
for (const tag of usedTags) {
|
|
1087
|
+
if (customElements.get(tag) || loadedTags.has(tag)) continue;
|
|
1088
|
+
const url = manifest[tag];
|
|
1089
|
+
if (!url) continue;
|
|
1090
|
+
|
|
1091
|
+
const element = document.querySelector(tag);
|
|
1092
|
+
if (element && isInViewport(element)) {
|
|
1093
|
+
await tryLoad(tag, url);
|
|
1094
|
+
} else if (element) {
|
|
1095
|
+
observeLazyLoad(tag, url, element);
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
function isInViewport(element) {
|
|
1101
|
+
const rect = element.getBoundingClientRect();
|
|
1102
|
+
return (
|
|
1103
|
+
rect.top < window.innerHeight &&
|
|
1104
|
+
rect.bottom > 0 &&
|
|
1105
|
+
rect.left < window.innerWidth &&
|
|
1106
|
+
rect.right > 0
|
|
1107
|
+
);
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
function observeLazyLoad(tag, url, element) {
|
|
1111
|
+
const observer = new IntersectionObserver(async (entries) => {
|
|
1112
|
+
for (const entry of entries) {
|
|
1113
|
+
if (entry.isIntersecting) {
|
|
1114
|
+
observer.disconnect();
|
|
1115
|
+
await tryLoad(tag, url);
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
}, { rootMargin: '100px' });
|
|
1119
|
+
observer.observe(element);
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
async function tryLoad(tag, url) {
|
|
1123
|
+
if (customElements.get(tag) || loadedTags.has(tag)) return;
|
|
1124
|
+
try {
|
|
1125
|
+
const importPolicy = classifyLoaderUrl(url, {
|
|
1126
|
+
kind: 'module',
|
|
1127
|
+
baseUrl: document.baseURI,
|
|
1128
|
+
source: tag
|
|
1129
|
+
});
|
|
1130
|
+
if (!importPolicy.ok) {
|
|
1131
|
+
emitSecurityDiagnostic('xtend.security.import.refused', `Import fuer ${tag} wurde durch die Loader Policy verweigert`, {
|
|
1132
|
+
policy: IMPORT_POLICY_CONTRACT,
|
|
1133
|
+
tag,
|
|
1134
|
+
url,
|
|
1135
|
+
diagnostics: importPolicy.diagnostics
|
|
1136
|
+
});
|
|
1137
|
+
return;
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
loaderVerboseLog(`Lade ${tag} als ES6-Modul von ${url}`);
|
|
1141
|
+
await measureLoaderPhase('xtend.loader.module', () => loadScript(importPolicy.url, true), { tag, url: importPolicy.url });
|
|
1142
|
+
if (isCustomElementTag(tag)) {
|
|
1143
|
+
await measureLoaderPhase('xtend.component.define', () => waitForCustomElementDefinition(tag), { tag, url: importPolicy.url });
|
|
1144
|
+
}
|
|
1145
|
+
loaderVerboseLog(`${tag} erfolgreich geladen`);
|
|
1146
|
+
loadedTags.add(tag);
|
|
1147
|
+
} catch (error) {
|
|
1148
|
+
emitLoaderDiagnostic('xtend.loader.component.load_failed', 'error', `Komponente ${tag} konnte nicht geladen werden`, {
|
|
1149
|
+
tag,
|
|
1150
|
+
url,
|
|
1151
|
+
message: error && error.message ? error.message : String(error)
|
|
1152
|
+
});
|
|
1153
|
+
console.error(`Fehler beim Laden von ${tag}:`, error);
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
function getActiveManifest() {
|
|
1158
|
+
return activeManifest && typeof activeManifest === 'object' ? activeManifest : {};
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
function normalizeComponentTag(tag) {
|
|
1162
|
+
return String(tag || '').trim().toLowerCase();
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
function collectTreeComponentTags(root = document, options = {}) {
|
|
1166
|
+
const tags = new Set();
|
|
1167
|
+
(Array.isArray(options.tags) ? options.tags : []).forEach((tag) => {
|
|
1168
|
+
const normalized = normalizeComponentTag(tag);
|
|
1169
|
+
if (isCustomElementTag(normalized)) tags.add(normalized);
|
|
1170
|
+
});
|
|
1171
|
+
|
|
1172
|
+
const scope = root && typeof root.querySelectorAll === 'function' ? root : document;
|
|
1173
|
+
if (root && root.tagName) {
|
|
1174
|
+
const rootTag = normalizeComponentTag(root.tagName);
|
|
1175
|
+
if (isCustomElementTag(rootTag)) tags.add(rootTag);
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
Array.from(scope.querySelectorAll('*')).forEach((element) => {
|
|
1179
|
+
const tag = normalizeComponentTag(element.tagName);
|
|
1180
|
+
if (isCustomElementTag(tag)) tags.add(tag);
|
|
1181
|
+
});
|
|
1182
|
+
|
|
1183
|
+
return Array.from(tags);
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
function collectTreeElements(root = document) {
|
|
1187
|
+
const scope = root && typeof root.querySelectorAll === 'function' ? root : document;
|
|
1188
|
+
const elements = [];
|
|
1189
|
+
if (root && root.nodeType === 1) elements.push(root);
|
|
1190
|
+
elements.push(...Array.from(scope.querySelectorAll('*')));
|
|
1191
|
+
return elements;
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
function normalizeSkeletonLoaderOptions(options = {}) {
|
|
1195
|
+
return {
|
|
1196
|
+
schema: SKELETON_LOADER_CONTRACT,
|
|
1197
|
+
variant: String(options.variant || options.kind || 'block').trim() || 'block',
|
|
1198
|
+
lines: Math.max(1, Math.min(24, Number(options.lines || options.lineCount || 4))),
|
|
1199
|
+
minHeight: String(options.minHeight || options.height || '').trim(),
|
|
1200
|
+
label: String(options.label || options.ariaLabel || 'Inhalt wird geladen').trim(),
|
|
1201
|
+
source: String(options.source || 'xtend-loader').trim(),
|
|
1202
|
+
schedule: String(options.schedule || 'component.dynamic.hydrate').trim()
|
|
1203
|
+
};
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
function applySkeletonLineStyle(line, index, total) {
|
|
1207
|
+
const widths = ['72%', '94%', '84%', '58%', '88%', '66%'];
|
|
1208
|
+
line.style.display = 'block';
|
|
1209
|
+
line.style.width = widths[index % widths.length];
|
|
1210
|
+
line.style.maxWidth = '100%';
|
|
1211
|
+
line.style.height = index === 0 && total > 5 ? '1.35rem' : '0.82rem';
|
|
1212
|
+
line.style.borderRadius = '999px';
|
|
1213
|
+
line.style.background = 'var(--xtend-skeleton-line-bg, rgba(148, 163, 184, 0.24))';
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
function createSkeletonLoader(options = {}) {
|
|
1217
|
+
ensureRuntimeStyles({ source: 'skeleton-loader' });
|
|
1218
|
+
const normalized = normalizeSkeletonLoaderOptions(options);
|
|
1219
|
+
const skeleton = document.createElement('div');
|
|
1220
|
+
skeleton.setAttribute('data-xtend-skeleton-loader', '');
|
|
1221
|
+
skeleton.setAttribute('data-xtend-skeleton-variant', normalized.variant);
|
|
1222
|
+
skeleton.setAttribute('data-xtend-skeleton-source', normalized.source);
|
|
1223
|
+
skeleton.setAttribute('data-xtend-skeleton-schedule', normalized.schedule);
|
|
1224
|
+
skeleton.setAttribute('role', 'status');
|
|
1225
|
+
skeleton.setAttribute('aria-live', 'polite');
|
|
1226
|
+
skeleton.setAttribute('aria-label', normalized.label);
|
|
1227
|
+
skeleton.style.display = 'grid';
|
|
1228
|
+
skeleton.style.gap = '0.68rem';
|
|
1229
|
+
skeleton.style.width = 'var(--xtend-skeleton-width, 100%)';
|
|
1230
|
+
skeleton.style.maxWidth = 'var(--xtend-skeleton-max-width, 100%)';
|
|
1231
|
+
skeleton.style.marginInline = 'var(--xtend-skeleton-margin-inline, 0)';
|
|
1232
|
+
skeleton.style.minWidth = '0';
|
|
1233
|
+
skeleton.style.boxSizing = 'border-box';
|
|
1234
|
+
skeleton.style.padding = 'var(--xtend-skeleton-padding, 1rem)';
|
|
1235
|
+
skeleton.style.borderRadius = 'var(--xtend-skeleton-radius, 8px)';
|
|
1236
|
+
skeleton.style.background = 'var(--xtend-skeleton-surface, rgba(148, 163, 184, 0.12))';
|
|
1237
|
+
skeleton.style.overflow = 'hidden';
|
|
1238
|
+
skeleton.style.contain = 'layout paint';
|
|
1239
|
+
if (normalized.minHeight) {
|
|
1240
|
+
skeleton.style.minHeight = normalized.minHeight;
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
for (let index = 0; index < normalized.lines; index += 1) {
|
|
1244
|
+
const line = document.createElement('span');
|
|
1245
|
+
line.setAttribute('data-xtend-skeleton-line', '');
|
|
1246
|
+
applySkeletonLineStyle(line, index, normalized.lines);
|
|
1247
|
+
skeleton.appendChild(line);
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
return skeleton;
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
function findDirectSkeleton(target) {
|
|
1254
|
+
if (!target || typeof target.querySelector !== 'function') return null;
|
|
1255
|
+
try {
|
|
1256
|
+
return target.querySelector(':scope > [data-xtend-skeleton-loader]');
|
|
1257
|
+
} catch (_) {
|
|
1258
|
+
return Array.from(target.children || []).find((child) => (
|
|
1259
|
+
child && child.getAttribute && child.hasAttribute('data-xtend-skeleton-loader')
|
|
1260
|
+
)) || null;
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
function showSkeleton(target, options = {}) {
|
|
1265
|
+
if (!target || typeof target.appendChild !== 'function') return null;
|
|
1266
|
+
const normalized = normalizeSkeletonLoaderOptions(options);
|
|
1267
|
+
const existing = findDirectSkeleton(target);
|
|
1268
|
+
if (existing) {
|
|
1269
|
+
existing.setAttribute('data-xtend-skeleton-source', normalized.source);
|
|
1270
|
+
existing.setAttribute('data-xtend-skeleton-schedule', normalized.schedule);
|
|
1271
|
+
existing.setAttribute('aria-label', normalized.label);
|
|
1272
|
+
return existing;
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
if (target.nodeType === 1 && typeof target.setAttribute === 'function') {
|
|
1276
|
+
target.setAttribute('data-xtend-skeleton-active', 'true');
|
|
1277
|
+
target.setAttribute('aria-busy', 'true');
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
const skeleton = createSkeletonLoader(normalized);
|
|
1281
|
+
target.appendChild(skeleton);
|
|
1282
|
+
return skeleton;
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
function hideSkeleton(target, options = {}) {
|
|
1286
|
+
if (!target) return 0;
|
|
1287
|
+
const skeletons = Array.from(target.children || []).filter((child) => (
|
|
1288
|
+
child && child.getAttribute && child.hasAttribute('data-xtend-skeleton-loader')
|
|
1289
|
+
));
|
|
1290
|
+
skeletons.forEach((skeleton) => skeleton.remove());
|
|
1291
|
+
if (target.nodeType === 1 && typeof target.removeAttribute === 'function') {
|
|
1292
|
+
target.removeAttribute('data-xtend-skeleton-active');
|
|
1293
|
+
if (!options.preserveBusy) {
|
|
1294
|
+
target.removeAttribute('aria-busy');
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
return skeletons.length;
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
const SkeletonLoader = Object.freeze({
|
|
1301
|
+
schema: SKELETON_LOADER_CONTRACT,
|
|
1302
|
+
create: createSkeletonLoader,
|
|
1303
|
+
show: showSkeleton,
|
|
1304
|
+
hide: hideSkeleton
|
|
1305
|
+
});
|
|
1306
|
+
|
|
1307
|
+
const XTendStyleRegistry = Object.freeze({
|
|
1308
|
+
schema: STYLE_REGISTRY_CONTRACT,
|
|
1309
|
+
runtimeStylesContract: RUNTIME_STYLES_CONTRACT,
|
|
1310
|
+
runtimeStyleKey: RUNTIME_STYLE_KEY,
|
|
1311
|
+
standardThemeStylesheet: STANDARD_THEME_STYLESHEET,
|
|
1312
|
+
ensureRuntimeStyles,
|
|
1313
|
+
ensureDocumentStyle,
|
|
1314
|
+
defineComponentStyle,
|
|
1315
|
+
adopt: adoptStyle,
|
|
1316
|
+
adoptStyle,
|
|
1317
|
+
get: getRegisteredStyle,
|
|
1318
|
+
getThemeStylesheetState,
|
|
1319
|
+
list: listRegisteredStyles
|
|
1320
|
+
});
|
|
1321
|
+
|
|
1322
|
+
async function ensureComponent(tag, options = {}) {
|
|
1323
|
+
const normalized = normalizeComponentTag(tag);
|
|
1324
|
+
if (!isCustomElementTag(normalized) || !window.customElements) return false;
|
|
1325
|
+
if (customElements.get(normalized)) return true;
|
|
1326
|
+
|
|
1327
|
+
if (!options.skipBootWait && window.__XTendLoaderBootPromise) {
|
|
1328
|
+
await Promise.resolve(window.__XTendLoaderBootPromise).catch(() => null);
|
|
1329
|
+
if (customElements.get(normalized)) return true;
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
const manifest = options.manifest || getActiveManifest();
|
|
1333
|
+
const url = manifest[normalized];
|
|
1334
|
+
if (url) {
|
|
1335
|
+
await tryLoad(normalized, url);
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
await waitForCustomElementDefinition(normalized);
|
|
1339
|
+
return Boolean(customElements.get(normalized));
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
async function hydrateTree(root = document, options = {}) {
|
|
1343
|
+
if (!options.skipBootWait && window.__XTendLoaderBootPromise) {
|
|
1344
|
+
await Promise.resolve(window.__XTendLoaderBootPromise).catch(() => null);
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
const tags = collectTreeComponentTags(root, options);
|
|
1348
|
+
await Promise.all(tags.map((tag) => ensureComponent(tag, { ...options, skipBootWait: true })));
|
|
1349
|
+
|
|
1350
|
+
let hydrated = 0;
|
|
1351
|
+
const elements = collectTreeElements(root);
|
|
1352
|
+
elements.forEach((element) => {
|
|
1353
|
+
if (!element || !element.isConnected) return;
|
|
1354
|
+
if (typeof element.hydrate === 'function') {
|
|
1355
|
+
element.hydrate();
|
|
1356
|
+
hydrated += 1;
|
|
1357
|
+
}
|
|
1358
|
+
});
|
|
1359
|
+
|
|
1360
|
+
const detail = {
|
|
1361
|
+
schema: 'xtend.loader.dynamic-tree-hydration.v1',
|
|
1362
|
+
source: options.source || 'xtend-loader',
|
|
1363
|
+
reason: options.reason || 'dynamic-subtree',
|
|
1364
|
+
schedule: options.schedule || 'component.dynamic.hydrate',
|
|
1365
|
+
tags,
|
|
1366
|
+
elementCount: elements.length,
|
|
1367
|
+
hydrated
|
|
1368
|
+
};
|
|
1369
|
+
window.dispatchEvent(new CustomEvent('xtend-loader-tree-hydrated', { detail }));
|
|
1370
|
+
return detail;
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
function isCustomElementTag(tag) {
|
|
1374
|
+
return typeof tag === 'string' && tag.includes('-');
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
function waitForCustomElementDefinition(tag) {
|
|
1378
|
+
if (!window.customElements || !isCustomElementTag(tag)) {
|
|
1379
|
+
return Promise.resolve();
|
|
1380
|
+
}
|
|
1381
|
+
if (customElements.get(tag)) {
|
|
1382
|
+
return Promise.resolve();
|
|
1383
|
+
}
|
|
1384
|
+
return Promise.race([
|
|
1385
|
+
customElements.whenDefined(tag),
|
|
1386
|
+
new Promise((resolve) => {
|
|
1387
|
+
window.setTimeout(resolve, CUSTOM_ELEMENT_DEFINE_TIMEOUT_MS);
|
|
1388
|
+
})
|
|
1389
|
+
]);
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
async function measureLoaderPhase(name, task, metadata = {}) {
|
|
1393
|
+
if (typeof task !== 'function') {
|
|
1394
|
+
throw new TypeError('XTend Loader performance measurement requires a task function.');
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
const target = getPerformanceTarget();
|
|
1398
|
+
const measurementId = `xtend.loader.measurement.${++loaderMeasurementCounter}`;
|
|
1399
|
+
const startMark = `${name}.start.${measurementId}`;
|
|
1400
|
+
const endMark = `${name}.end.${measurementId}`;
|
|
1401
|
+
const startedAt = performanceNow(target);
|
|
1402
|
+
markPerformance(target, startMark);
|
|
1403
|
+
|
|
1404
|
+
try {
|
|
1405
|
+
const value = await task();
|
|
1406
|
+
finishLoaderMeasurement({
|
|
1407
|
+
id: measurementId,
|
|
1408
|
+
name,
|
|
1409
|
+
status: 'completed',
|
|
1410
|
+
startedAt,
|
|
1411
|
+
target,
|
|
1412
|
+
startMark,
|
|
1413
|
+
endMark,
|
|
1414
|
+
metadata
|
|
1415
|
+
});
|
|
1416
|
+
return value;
|
|
1417
|
+
} catch (error) {
|
|
1418
|
+
finishLoaderMeasurement({
|
|
1419
|
+
id: measurementId,
|
|
1420
|
+
name,
|
|
1421
|
+
status: 'failed',
|
|
1422
|
+
startedAt,
|
|
1423
|
+
target,
|
|
1424
|
+
startMark,
|
|
1425
|
+
endMark,
|
|
1426
|
+
metadata: {
|
|
1427
|
+
...metadata,
|
|
1428
|
+
error: error && error.message ? error.message : String(error)
|
|
1429
|
+
}
|
|
1430
|
+
});
|
|
1431
|
+
throw error;
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
function finishLoaderMeasurement(measurement) {
|
|
1436
|
+
const target = measurement.target;
|
|
1437
|
+
markPerformance(target, measurement.endMark);
|
|
1438
|
+
measurePerformance(target, measurement.name, measurement.startMark, measurement.endMark);
|
|
1439
|
+
|
|
1440
|
+
const durationMs = Math.max(0, performanceNow(target) - measurement.startedAt);
|
|
1441
|
+
const detail = {
|
|
1442
|
+
schema: PERFORMANCE_MEASUREMENT_CONTRACT,
|
|
1443
|
+
id: measurement.id,
|
|
1444
|
+
name: measurement.name,
|
|
1445
|
+
phase: LOADER_PERFORMANCE_PHASES[measurement.name] || 'load',
|
|
1446
|
+
durationMs: Number(durationMs.toFixed(2)),
|
|
1447
|
+
sampleKind: 'local',
|
|
1448
|
+
status: measurement.status,
|
|
1449
|
+
metadata: measurement.metadata || {}
|
|
1450
|
+
};
|
|
1451
|
+
loaderMeasurements.push(detail);
|
|
1452
|
+
emitLoaderPerformance(detail);
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
function getPerformanceTarget() {
|
|
1456
|
+
return window && window.performance ? window.performance : null;
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
function performanceNow(target) {
|
|
1460
|
+
return target && typeof target.now === 'function' ? target.now() : Date.now();
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
function markPerformance(target, markName) {
|
|
1464
|
+
if (!target || typeof target.mark !== 'function') return;
|
|
1465
|
+
try {
|
|
1466
|
+
target.mark(markName);
|
|
1467
|
+
} catch (_) {
|
|
1468
|
+
// Partial Performance APIs must not break the loader path.
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
function measurePerformance(target, measureName, startMark, endMark) {
|
|
1473
|
+
if (!target || typeof target.measure !== 'function') return;
|
|
1474
|
+
try {
|
|
1475
|
+
target.measure(measureName, startMark, endMark);
|
|
1476
|
+
} catch (_) {
|
|
1477
|
+
// Some hosts expose mark without measure; the local measurement event still carries duration.
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
async function initializeApi(manifest) {
|
|
1482
|
+
try {
|
|
1483
|
+
const apiUrl = new URL('./api.js', import.meta.url).href;
|
|
1484
|
+
const importPolicy = classifyLoaderUrl(apiUrl, {
|
|
1485
|
+
kind: 'module',
|
|
1486
|
+
baseUrl: import.meta.url,
|
|
1487
|
+
source: 'api'
|
|
1488
|
+
});
|
|
1489
|
+
if (!importPolicy.ok) {
|
|
1490
|
+
emitSecurityDiagnostic('xtend.security.import.refused', 'XTend API Import wurde durch die Loader Policy verweigert', {
|
|
1491
|
+
policy: IMPORT_POLICY_CONTRACT,
|
|
1492
|
+
url: apiUrl,
|
|
1493
|
+
diagnostics: importPolicy.diagnostics
|
|
1494
|
+
});
|
|
1495
|
+
return;
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
const api = await import(importPolicy.url);
|
|
1499
|
+
if (api && typeof api.initXTendAPI === 'function') {
|
|
1500
|
+
await api.initXTendAPI(manifest);
|
|
1501
|
+
}
|
|
1502
|
+
} catch (error) {
|
|
1503
|
+
emitLoaderDiagnostic('xtend.loader.api.init_failed', 'error', 'XTend API konnte nicht initialisiert werden', {
|
|
1504
|
+
message: error && error.message ? error.message : String(error)
|
|
1505
|
+
});
|
|
1506
|
+
console.error('XTend API Initialisierung fehlgeschlagen:', error);
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
function classifyManifestRecord(tag, recordValue, baseUrl) {
|
|
1511
|
+
const normalizedTag = typeof tag === 'string' ? tag.trim().toLowerCase() : '';
|
|
1512
|
+
const diagnostics = [];
|
|
1513
|
+
|
|
1514
|
+
if (!normalizedTag || normalizedTag !== tag || !isAllowedManifestKey(normalizedTag)) {
|
|
1515
|
+
diagnostics.push('xtend.security.manifest.invalid.tag');
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
if (typeof recordValue !== 'string' || !recordValue.trim()) {
|
|
1519
|
+
diagnostics.push('xtend.security.manifest.invalid.url');
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1522
|
+
const importPolicy = typeof recordValue === 'string'
|
|
1523
|
+
? classifyLoaderUrl(recordValue, {
|
|
1524
|
+
kind: 'module',
|
|
1525
|
+
baseUrl,
|
|
1526
|
+
source: normalizedTag || 'manifest-record'
|
|
1527
|
+
})
|
|
1528
|
+
: null;
|
|
1529
|
+
|
|
1530
|
+
if (importPolicy && !importPolicy.ok) {
|
|
1531
|
+
diagnostics.push(...importPolicy.diagnostics);
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
return {
|
|
1535
|
+
schema: MANIFEST_POLICY_CONTRACT,
|
|
1536
|
+
ok: diagnostics.length === 0,
|
|
1537
|
+
tag: normalizedTag,
|
|
1538
|
+
url: importPolicy ? importPolicy.url : null,
|
|
1539
|
+
diagnostics
|
|
1540
|
+
};
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1543
|
+
function isAllowedManifestKey(tag) {
|
|
1544
|
+
return RESERVED_MANIFEST_KEYS.includes(tag) || CUSTOM_ELEMENT_NAME_PATTERN.test(tag);
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1547
|
+
function classifyLoaderUrl(value, options = {}) {
|
|
1548
|
+
const kind = options.kind || 'module';
|
|
1549
|
+
const baseUrl = options.baseUrl || document.baseURI;
|
|
1550
|
+
const currentUrl = safeUrl(window.location.href, document.baseURI);
|
|
1551
|
+
const targetUrl = safeUrl(value, baseUrl);
|
|
1552
|
+
const diagnostics = [];
|
|
1553
|
+
|
|
1554
|
+
if (!targetUrl || !currentUrl) {
|
|
1555
|
+
diagnostics.push('xtend.security.import.refused.invalid_url');
|
|
1556
|
+
} else if (hasTraversalLikeInput(value)) {
|
|
1557
|
+
diagnostics.push('xtend.security.import.refused.path_traversal');
|
|
1558
|
+
} else if (REFUSED_IMPORT_PROTOCOLS.includes(targetUrl.protocol)) {
|
|
1559
|
+
diagnostics.push('xtend.security.import.refused.protocol');
|
|
1560
|
+
} else if (!ALLOWED_IMPORT_PROTOCOLS.includes(targetUrl.protocol)) {
|
|
1561
|
+
diagnostics.push('xtend.security.import.refused.protocol');
|
|
1562
|
+
} else if (hasPathTraversal(targetUrl)) {
|
|
1563
|
+
diagnostics.push('xtend.security.import.refused.path_traversal');
|
|
1564
|
+
} else if (!hasAllowedImportExtension(targetUrl, kind)) {
|
|
1565
|
+
diagnostics.push(kind === 'manifest'
|
|
1566
|
+
? 'xtend.security.manifest.invalid.extension'
|
|
1567
|
+
: 'xtend.security.import.refused.extension');
|
|
1568
|
+
} else if (!isAllowedLocalUrl(targetUrl, currentUrl)) {
|
|
1569
|
+
diagnostics.push(kind === 'manifest'
|
|
1570
|
+
? 'xtend.security.loader.refused.external_manifest'
|
|
1571
|
+
: 'xtend.security.import.refused.external_module');
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
return {
|
|
1575
|
+
schema: IMPORT_POLICY_CONTRACT,
|
|
1576
|
+
ok: diagnostics.length === 0,
|
|
1577
|
+
kind,
|
|
1578
|
+
source: options.source || kind,
|
|
1579
|
+
url: targetUrl ? targetUrl.href : null,
|
|
1580
|
+
diagnostics
|
|
1581
|
+
};
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
function safeUrl(value, baseUrl) {
|
|
1585
|
+
try {
|
|
1586
|
+
return new URL(String(value), baseUrl);
|
|
1587
|
+
} catch (_) {
|
|
1588
|
+
return null;
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
function isAllowedLocalUrl(targetUrl, currentUrl) {
|
|
1593
|
+
if (targetUrl.origin === currentUrl.origin) {
|
|
1594
|
+
return true;
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
if (targetUrl.protocol === 'file:' && currentUrl.protocol === 'file:') {
|
|
1598
|
+
return true;
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
return isLocalHost(targetUrl.hostname) && (
|
|
1602
|
+
isLocalHost(currentUrl.hostname) ||
|
|
1603
|
+
currentUrl.protocol === 'file:'
|
|
1604
|
+
);
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
function isLocalHost(hostname = '') {
|
|
1608
|
+
const normalized = String(hostname).replace(/^\[|\]$/g, '').toLowerCase();
|
|
1609
|
+
return LOCAL_IMPORT_HOSTS.includes(normalized);
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
function hasPathTraversal(url) {
|
|
1613
|
+
try {
|
|
1614
|
+
return decodeURIComponent(url.pathname).split('/').includes('..');
|
|
1615
|
+
} catch (_) {
|
|
1616
|
+
return true;
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1620
|
+
function hasTraversalLikeInput(value) {
|
|
1621
|
+
try {
|
|
1622
|
+
const pathPart = decodeURIComponent(String(value)).split(/[?#]/)[0];
|
|
1623
|
+
return pathPart === '..' ||
|
|
1624
|
+
pathPart.startsWith('../') ||
|
|
1625
|
+
pathPart.includes('/../') ||
|
|
1626
|
+
pathPart.endsWith('/..');
|
|
1627
|
+
} catch (_) {
|
|
1628
|
+
return true;
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
function hasAllowedImportExtension(url, kind) {
|
|
1633
|
+
const pathname = url.pathname.toLowerCase();
|
|
1634
|
+
const extensions = kind === 'manifest'
|
|
1635
|
+
? ALLOWED_MANIFEST_EXTENSIONS
|
|
1636
|
+
: ALLOWED_MODULE_EXTENSIONS;
|
|
1637
|
+
return extensions.some((extension) => pathname.endsWith(extension));
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
function emitSecurityDiagnostic(code, message, metadata = {}) {
|
|
1641
|
+
emitLoaderDiagnostic(code, 'error', message, {
|
|
1642
|
+
security: true,
|
|
1643
|
+
loaderPolicy: LOADER_POLICY_CONTRACT,
|
|
1644
|
+
manifestPolicy: MANIFEST_POLICY_CONTRACT,
|
|
1645
|
+
importPolicy: IMPORT_POLICY_CONTRACT,
|
|
1646
|
+
...metadata
|
|
1647
|
+
});
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1650
|
+
function emitLoaderDiagnostic(code, level, message, metadata = {}) {
|
|
1651
|
+
const detail = {
|
|
1652
|
+
schema: 'xtend.fabric.diagnostic.v1',
|
|
1653
|
+
code,
|
|
1654
|
+
level,
|
|
1655
|
+
message,
|
|
1656
|
+
source: 'loader',
|
|
1657
|
+
phase: 'load',
|
|
1658
|
+
metadata
|
|
1659
|
+
};
|
|
1660
|
+
|
|
1661
|
+
window.dispatchEvent(new CustomEvent('xtend-loader-diagnostic', { detail }));
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
function emitLoaderPerformance(detail) {
|
|
1665
|
+
window.dispatchEvent(new CustomEvent('xtend-loader-performance', { detail }));
|
|
1666
|
+
}
|
|
1667
|
+
|
|
1668
|
+
window.XTendLoader = Object.freeze({
|
|
1669
|
+
schema: LOADER_CONTRACT,
|
|
1670
|
+
loaderPolicy: LOADER_POLICY_CONTRACT,
|
|
1671
|
+
manifestPolicy: MANIFEST_POLICY_CONTRACT,
|
|
1672
|
+
importPolicy: IMPORT_POLICY_CONTRACT,
|
|
1673
|
+
styleRegistry: XTendStyleRegistry,
|
|
1674
|
+
styles: XTendStyleRegistry,
|
|
1675
|
+
styleRegistryContract: STYLE_REGISTRY_CONTRACT,
|
|
1676
|
+
runtimeStylesContract: RUNTIME_STYLES_CONTRACT,
|
|
1677
|
+
skeletonLoader: SkeletonLoader,
|
|
1678
|
+
skeletonLoaderContract: SKELETON_LOADER_CONTRACT,
|
|
1679
|
+
verbose: configureLoaderVerbose,
|
|
1680
|
+
setVerbose: setLoaderVerbose,
|
|
1681
|
+
enableVerbose: () => setLoaderVerbose(true),
|
|
1682
|
+
disableVerbose: () => setLoaderVerbose(false),
|
|
1683
|
+
getVerboseMode: getLoaderVerboseMode,
|
|
1684
|
+
getVerboseState: getLoaderVerboseState,
|
|
1685
|
+
isVerbose: isLoaderVerboseEnabled,
|
|
1686
|
+
ensureRuntimeStyles,
|
|
1687
|
+
defineComponentStyle,
|
|
1688
|
+
adoptStyle,
|
|
1689
|
+
getThemeStylesheetState,
|
|
1690
|
+
createSkeleton: createSkeletonLoader,
|
|
1691
|
+
showSkeleton,
|
|
1692
|
+
hideSkeleton,
|
|
1693
|
+
ensureComponent,
|
|
1694
|
+
hydrateTree,
|
|
1695
|
+
initiateXTend
|
|
1696
|
+
});
|
|
1697
|
+
|
|
1698
|
+
window.XTendStyleRegistry = XTendStyleRegistry;
|
|
1699
|
+
window.XTendSkeletonLoader = SkeletonLoader;
|
|
1700
|
+
ensureRuntimeStyles({ source: 'loader.evaluate' });
|
|
1701
|
+
|
|
1702
|
+
if (!window.__XTendLoaderBootPromise) {
|
|
1703
|
+
window.__XTendLoaderBootPromise = initiateXTend();
|
|
1704
|
+
}
|