@pie-players/pie-players-shared 0.3.49 → 0.3.50

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/README.md CHANGED
@@ -27,9 +27,9 @@ Supported subpaths are declared in `package.json`:
27
27
 
28
28
  ## Browser ESM Element Contract
29
29
 
30
- The canonical producer-side contract lives in
31
- `pie-elements-ng/docs/PIE_ELEMENT_CONTRACT.md`. The loader assumptions here must
32
- stay aligned with that document.
30
+ The canonical producer-side contract lives with the `pie-elements-ng` package
31
+ contract. The loader assumptions here must stay aligned with that producer
32
+ surface.
33
33
 
34
34
  The ESM element loader consumes static `@pie-element/*` browser entries such as
35
35
  `dist/browser/delivery/index.js`; it does not transform element packages through
@@ -13,6 +13,7 @@
13
13
  * call `customElements.define`.
14
14
  */
15
15
  import type { InstrumentationProvider } from "../instrumentation/types.js";
16
+ import type { ElementMap } from "./ElementLoader.js";
16
17
  import { type ElementLoaderBackend } from "./element-loader-types.js";
17
18
  /** View configuration: how a PIE package's subpath maps to a tag suffix. */
18
19
  export type ViewConfig = {
@@ -54,3 +55,4 @@ export type EsmBackendConfig = {
54
55
  };
55
56
  export type EsmBackend = ElementLoaderBackend & {};
56
57
  export declare function createEsmBackend(config: EsmBackendConfig): EsmBackend;
58
+ export declare function mapEsmViewElements(elements: ElementMap, view?: string, viewConfig?: ViewConfig): ElementMap;
@@ -29,7 +29,7 @@ export function createEsmBackend(config) {
29
29
  const moduleResolution = config.moduleResolution ?? "url";
30
30
  const view = config.view ?? "delivery";
31
31
  const loadControllers = config.loadControllers ?? true;
32
- const viewConfig = config.viewConfig ?? BUILT_IN_VIEWS[view] ?? BUILT_IN_VIEWS.delivery;
32
+ const viewConfig = resolveEsmViewConfig(view, config.viewConfig);
33
33
  const injectedPackageVersions = new Set();
34
34
  const importMappedPackageVersions = new Map();
35
35
  let sharedDependencyVersions = {};
@@ -103,7 +103,7 @@ export function createEsmBackend(config) {
103
103
  const packageName = extractPackageName(packageVersion);
104
104
  let actualTag;
105
105
  try {
106
- actualTag = validateCustomElementTag(`${tag}${viewConfig.tagSuffix}`, `element tag for ${packageName}`);
106
+ actualTag = validateCustomElementTag(tag, `element tag for ${packageName}`);
107
107
  }
108
108
  catch (err) {
109
109
  reasons.set(tag, {
@@ -252,6 +252,13 @@ export function createEsmBackend(config) {
252
252
  };
253
253
  }
254
254
  // ─── Helpers ─────────────────────────────────────────────────────────────────
255
+ export function mapEsmViewElements(elements, view = "delivery", viewConfig) {
256
+ const resolvedViewConfig = resolveEsmViewConfig(view, viewConfig);
257
+ return Object.fromEntries(Object.entries(elements).map(([tag, packageVersion]) => [
258
+ `${tag}${resolvedViewConfig.tagSuffix}`,
259
+ packageVersion,
260
+ ]));
261
+ }
255
262
  function defaultImporter(specifier) {
256
263
  // @vite-ignore — dynamic import resolved at runtime.
257
264
  return import(/* @vite-ignore */ specifier);
@@ -330,6 +337,9 @@ function toRawEsmShBaseUrl(cdnBaseUrl) {
330
337
  }
331
338
  return "https://raw.esm.sh";
332
339
  }
340
+ function resolveEsmViewConfig(view, viewConfig) {
341
+ return viewConfig ?? BUILT_IN_VIEWS[view] ?? BUILT_IN_VIEWS.delivery;
342
+ }
333
343
  function assertBrowserEsmExports(metadata, packageVersion, viewConfig, loadControllers, viewName) {
334
344
  if (!metadata?.exports)
335
345
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"esm-adapter.js","sourceRoot":"","sources":["../../src/loaders/esm-adapter.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ESM backend adapter for the ElementLoader primitive.\n *\n * Loads PIE elements via dynamic `import()` from static browser ESM files on a\n * CDN, optionally resolving bare specifiers through an import map injected into\n * the host document. On any per-tag failure (module load, non-constructor\n * element class, define failure), throws `AdapterFailure` with a structured\n * `reasons` map.\n *\n * Like the IIFE adapter, this module does not gate its own promise on\n * `customElements.whenDefined`; the primitive performs that verification\n * uniformly. Here the adapter's job is narrowly to fetch, extract, and\n * call `customElements.define`.\n */\n\nimport { defineCustomElementSafely } from \"../pie/custom-element-define.js\";\nimport type { InstrumentationProvider } from \"../instrumentation/types.js\";\nimport { isInstrumentationProvider } from \"../instrumentation/provider-guards.js\";\nimport { pieRegistry } from \"../pie/registry.js\";\nimport { validateCustomElementTag } from \"../pie/tag-names.js\";\nimport { isCustomElementConstructor, Status } from \"../pie/types.js\";\nimport type { ElementMap } from \"./ElementLoader.js\";\nimport {\n\tAdapterFailure,\n\ttype BackendContext,\n\ttype ElementLoaderBackend,\n\ttype ElementTag,\n\ttype RegistrationFailureReason,\n} from \"./element-loader-types.js\";\n\n/** View configuration: how a PIE package's subpath maps to a tag suffix. */\nexport type ViewConfig = {\n\tsubpath: string;\n\ttagSuffix: string;\n\tfallback?: string;\n};\n\nexport const BUILT_IN_VIEWS: Record<string, ViewConfig> = {\n\tdelivery: { subpath: \"\", tagSuffix: \"\" },\n\tauthor: { subpath: \"/author\", tagSuffix: \"-config\", fallback: \"delivery\" },\n\tprint: { subpath: \"/print\", tagSuffix: \"-print\", fallback: \"delivery\" },\n};\n\nexport type BuiltInEsmCdnProviderName = \"jsdelivr\" | \"esm.sh\";\nexport type EsmCdnProviderName = BuiltInEsmCdnProviderName | (string & {});\n\nexport type EsmCdnProvider = {\n\tname: EsmCdnProviderName;\n\tpackageJsonUrl(packageVersion: string): string;\n\tbrowserViewUrl(packageVersion: string, view: string): string;\n\tbrowserControllerUrl(packageVersion: string): string;\n\tsharedDependencyUrl(\n\t\tdependencyName: string,\n\t\tversion: string,\n\t\tsubpath?: string,\n\t): string;\n};\n\nexport type EsmCdnProviderOption = EsmCdnProviderName | EsmCdnProvider;\n\nexport type EsmBackendConfig = {\n\tkind: \"esm\";\n\t/** Base URL for the ESM CDN (e.g., \"https://esm.sh\"). */\n\tcdnBaseUrl: string;\n\t/** CDN URL strategy. Defaults to jsDelivr, or is inferred from cdnBaseUrl when possible. */\n\tcdnProvider?: EsmCdnProviderOption;\n\t/** `\"url\"` loads via fully-qualified URLs; `\"import-map\"` uses bare specifiers. */\n\tmoduleResolution?: \"url\" | \"import-map\";\n\t/** View to load (`delivery`, `author`, `print`, or a custom name). */\n\tview?: string;\n\t/** Custom view configuration (overrides built-ins). */\n\tviewConfig?: ViewConfig;\n\t/** Whether to also load controller modules. */\n\tloadControllers?: boolean;\n\t/** Debug flag hook. */\n\tdebugEnabled?: () => boolean;\n\t/** Whether ESM dependency conflict/failure events should be instrumented. */\n\ttrackPageActions?: boolean;\n\t/** Instrumentation provider for ESM dependency conflict/failure events. */\n\tinstrumentationProvider?: InstrumentationProvider;\n};\n\ntype PackageMetadata = {\n\texports?: Record<string, unknown>;\n\tdependencies?: Record<string, string>;\n\toptionalDependencies?: Record<string, string>;\n\tpeerDependencies?: Record<string, string>;\n\tpie?: {\n\t\tbrowserSharedDependencies?: Record<string, string>;\n\t};\n};\n\n/** @internal */\nexport type EsmModuleImporter = (specifier: string) => Promise<unknown>;\n/** @internal */\nexport type EsmImportMapObserver = (json: string, doc: Document) => void;\n/** @internal */\nexport type EsmPackageMetadataLoader = (\n\tpackageVersion: string,\n\tpackageJsonUrl: string,\n) => Promise<PackageMetadata | null>;\n\n/**\n * Test-only seam exposed via `EsmBackend.__seams`. Lets contract tests\n * inject scripted import behaviour and observe import-map injection\n * without going through the network or the document. Not part of the\n * runtime API; production code must not touch this field.\n *\n * @internal\n */\nexport type EsmBackendTestSeams = {\n\treplaceImporter(fn: EsmModuleImporter): void;\n\tobserveImportMapInjection(cb: EsmImportMapObserver): void;\n\treplacePackageMetadataLoader(fn: EsmPackageMetadataLoader): void;\n\trestore(): void;\n};\n\nexport type EsmBackend = ElementLoaderBackend & {\n\t/** @internal Test-only seam — see {@link EsmBackendTestSeams}. */\n\treadonly __seams: EsmBackendTestSeams;\n};\n\nexport function createEsmBackend(config: EsmBackendConfig): EsmBackend {\n\tconst cdnBaseUrl = config.cdnBaseUrl.replace(/\\/+$/, \"\");\n\tconst cdnProvider = resolveCdnProvider(config.cdnProvider, cdnBaseUrl);\n\tconst moduleResolution = config.moduleResolution ?? \"url\";\n\tconst view = config.view ?? \"delivery\";\n\tconst loadControllers = config.loadControllers ?? true;\n\tconst viewConfig =\n\t\tconfig.viewConfig ?? BUILT_IN_VIEWS[view] ?? BUILT_IN_VIEWS.delivery;\n\n\tconst injectedPackageVersions = new Set<string>();\n\tconst importMappedPackageVersions = new Map<string, string>();\n\tlet sharedDependencyVersions: Record<string, string> = {};\n\tlet importer: EsmModuleImporter = defaultImporter;\n\tlet packageMetadataLoader: EsmPackageMetadataLoader =\n\t\tdefaultPackageMetadataLoader;\n\tlet importMapObserver: EsmImportMapObserver | undefined;\n\n\tconst __seams: EsmBackendTestSeams = {\n\t\treplaceImporter(fn) {\n\t\t\timporter = fn;\n\t\t},\n\t\tobserveImportMapInjection(cb) {\n\t\t\timportMapObserver = cb;\n\t\t},\n\t\treplacePackageMetadataLoader(fn) {\n\t\t\tpackageMetadataLoader = fn;\n\t\t},\n\t\trestore() {\n\t\t\timporter = defaultImporter;\n\t\t\tpackageMetadataLoader = defaultPackageMetadataLoader;\n\t\t\timportMapObserver = undefined;\n\t\t\tinjectedPackageVersions.clear();\n\t\t\timportMappedPackageVersions.clear();\n\t\t\tsharedDependencyVersions = {};\n\t\t},\n\t};\n\n\tasync function load(\n\t\telements: ElementMap,\n\t\tcontext: BackendContext,\n\t): Promise<void> {\n\t\tif (!elements || Object.keys(elements).length === 0) return;\n\t\tif (moduleResolution === \"import-map\") {\n\t\t\tassertImportMapSupported();\n\t\t}\n\n\t\tconst newEntries: ElementMap = {};\n\t\tfor (const [tag, pkg] of Object.entries(elements)) {\n\t\t\tconst packageName = extractPackageName(pkg);\n\t\t\tif (moduleResolution === \"import-map\") {\n\t\t\t\tconst existingVersion = importMappedPackageVersions.get(packageName);\n\t\t\t\tif (existingVersion && existingVersion !== pkg) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Conflicting browser ESM package version for ${packageName}: ${existingVersion} is already mapped, but ${pkg} was requested`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!injectedPackageVersions.has(pkg)) {\n\t\t\t\tnewEntries[tag] = pkg;\n\t\t\t}\n\t\t}\n\t\tif (Object.keys(newEntries).length > 0) {\n\t\t\tlet importMapResult: BrowserImportMapBuildResult;\n\t\t\ttry {\n\t\t\t\timportMapResult = await buildImportMapJson(\n\t\t\t\t\tnewEntries,\n\t\t\t\t\tviewConfig,\n\t\t\t\t\tcdnProvider,\n\t\t\t\t\tloadControllers,\n\t\t\t\t\tmoduleResolution === \"import-map\",\n\t\t\t\t\tpackageMetadataLoader,\n\t\t\t\t\tsharedDependencyVersions,\n\t\t\t\t\treportSharedDependencyConflict,\n\t\t\t\t);\n\t\t\t} catch (err) {\n\t\t\t\treportSharedDependencyError(err);\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t\tconst json = importMapResult.json;\n\t\t\tif (json) {\n\t\t\t\tassertImportMapSupported();\n\t\t\t\tinjectImportMap(json, context.doc);\n\t\t\t\timportMapObserver?.(json, context.doc);\n\t\t\t}\n\t\t\tsharedDependencyVersions = importMapResult.sharedDependencyVersions;\n\t\t\tfor (const pkg of Object.values(newEntries)) {\n\t\t\t\tinjectedPackageVersions.add(pkg);\n\t\t\t\tif (moduleResolution === \"import-map\") {\n\t\t\t\t\timportMappedPackageVersions.set(extractPackageName(pkg), pkg);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst reasons = new Map<ElementTag, RegistrationFailureReason>();\n\t\tconst registry = pieRegistry();\n\n\t\tawait Promise.all(\n\t\t\tObject.entries(elements).map(async ([tag, packageVersion]) => {\n\t\t\t\tconst packageName = extractPackageName(packageVersion);\n\t\t\t\tlet actualTag: string;\n\t\t\t\ttry {\n\t\t\t\t\tactualTag = validateCustomElementTag(\n\t\t\t\t\t\t`${tag}${viewConfig.tagSuffix}`,\n\t\t\t\t\t\t`element tag for ${packageName}`,\n\t\t\t\t\t);\n\t\t\t\t} catch (err) {\n\t\t\t\t\treasons.set(tag, {\n\t\t\t\t\t\tkind: \"define-failed\",\n\t\t\t\t\t\ttag,\n\t\t\t\t\t\tcause: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst specifier = resolveElementSpecifier(\n\t\t\t\t\tpackageName,\n\t\t\t\t\tpackageVersion,\n\t\t\t\t\tviewConfig,\n\t\t\t\t\tmoduleResolution,\n\t\t\t\t\tcdnProvider,\n\t\t\t\t\tview,\n\t\t\t\t);\n\n\t\t\t\tlet module: any;\n\t\t\t\ttry {\n\t\t\t\t\tmodule = await importer(specifier);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tif (viewConfig.fallback) {\n\t\t\t\t\t\tconst fallbackConfig =\n\t\t\t\t\t\t\tBUILT_IN_VIEWS[viewConfig.fallback] ?? BUILT_IN_VIEWS.delivery;\n\t\t\t\t\t\tconst fallbackSpecifier = resolveElementSpecifier(\n\t\t\t\t\t\t\tpackageName,\n\t\t\t\t\t\t\tpackageVersion,\n\t\t\t\t\t\t\tfallbackConfig,\n\t\t\t\t\t\t\tmoduleResolution,\n\t\t\t\t\t\t\tcdnProvider,\n\t\t\t\t\t\t\tviewConfig.fallback,\n\t\t\t\t\t\t);\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tmodule = await importer(fallbackSpecifier);\n\t\t\t\t\t\t} catch (fallbackErr) {\n\t\t\t\t\t\t\treasons.set(tag, {\n\t\t\t\t\t\t\t\tkind: \"module-load-failed\",\n\t\t\t\t\t\t\t\ttag,\n\t\t\t\t\t\t\t\tspecifier: fallbackSpecifier,\n\t\t\t\t\t\t\t\tcause:\n\t\t\t\t\t\t\t\t\tfallbackErr instanceof Error\n\t\t\t\t\t\t\t\t\t\t? fallbackErr.message\n\t\t\t\t\t\t\t\t\t\t: String(fallbackErr),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treasons.set(tag, {\n\t\t\t\t\t\t\tkind: \"module-load-failed\",\n\t\t\t\t\t\t\ttag,\n\t\t\t\t\t\t\tspecifier,\n\t\t\t\t\t\t\tcause: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst ElementClass = pickElementClass(module, view);\n\t\t\t\tif (!ElementClass) {\n\t\t\t\t\treasons.set(tag, {\n\t\t\t\t\t\tkind: \"no-element-class\",\n\t\t\t\t\t\ttag,\n\t\t\t\t\t\tpackageName,\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (!isCustomElementConstructor(ElementClass)) {\n\t\t\t\t\treasons.set(tag, {\n\t\t\t\t\t\tkind: \"not-a-constructor\",\n\t\t\t\t\t\ttag,\n\t\t\t\t\t\tpackageName,\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tdefineCustomElementSafely(\n\t\t\t\t\t\tactualTag,\n\t\t\t\t\t\tclass extends ElementClass {},\n\t\t\t\t\t\t`element tag for ${packageName}`,\n\t\t\t\t\t);\n\t\t\t\t} catch (err) {\n\t\t\t\t\treasons.set(tag, {\n\t\t\t\t\t\tkind: \"define-failed\",\n\t\t\t\t\t\ttag,\n\t\t\t\t\t\tcause: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tlet controller: any = null;\n\t\t\t\tif (loadControllers) {\n\t\t\t\t\tconst controllerSpecifier = resolveControllerSpecifier(\n\t\t\t\t\t\tpackageName,\n\t\t\t\t\t\tpackageVersion,\n\t\t\t\t\t\tmoduleResolution,\n\t\t\t\t\t\tcdnProvider,\n\t\t\t\t\t);\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst controllerModule: any = await importer(controllerSpecifier);\n\t\t\t\t\t\tcontroller = controllerModule?.default ?? controllerModule;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Controllers are best-effort; element registration is what the\n\t\t\t\t\t\t// primitive verifies.\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tregistry[actualTag] = {\n\t\t\t\t\tpackage: packageVersion,\n\t\t\t\t\tstatus: Status.loaded,\n\t\t\t\t\ttagName: actualTag,\n\t\t\t\t\telement: ElementClass,\n\t\t\t\t\tcontroller,\n\t\t\t\t\tconfig: null,\n\t\t\t\t\tbundleType: \"esm\" as unknown as import(\"../pie/types.js\").BundleType,\n\t\t\t\t};\n\t\t\t}),\n\t\t);\n\n\t\tif (reasons.size > 0) {\n\t\t\tthrow new AdapterFailure(reasons);\n\t\t}\n\t}\n\n\tfunction getInstrumentationProvider(): InstrumentationProvider | undefined {\n\t\tif (!config.trackPageActions) return undefined;\n\t\tconst provider = config.instrumentationProvider;\n\t\tif (!isInstrumentationProvider(provider)) return undefined;\n\t\tif (!provider.isReady()) return undefined;\n\t\treturn provider;\n\t}\n\n\tfunction reportSharedDependencyConflict(\n\t\tattributes: Record<string, unknown>,\n\t): void {\n\t\tif (typeof console !== \"undefined\" && console.warn) {\n\t\t\tconsole.warn(\n\t\t\t\t`[pie-esm] Shared dependency version conflict resolved for ${String(attributes.dependencyName)}`,\n\t\t\t\tattributes,\n\t\t\t);\n\t\t}\n\t\tconst provider = getInstrumentationProvider();\n\t\tif (!provider) return;\n\t\ttry {\n\t\t\tprovider.trackEvent(\"pie-esm-shared-dependency-conflict\", attributes);\n\t\t} catch {\n\t\t\t// Swallow: instrumentation must never break loading.\n\t\t}\n\t}\n\n\tfunction reportSharedDependencyError(error: unknown): void {\n\t\tconst err = error instanceof Error ? error : new Error(String(error));\n\t\tif (typeof console !== \"undefined\" && console.error) {\n\t\t\tconsole.error(\"[pie-esm] Shared dependency resolution failed\", err);\n\t\t}\n\t\tconst provider = getInstrumentationProvider();\n\t\tif (!provider) return;\n\t\ttry {\n\t\t\tprovider.trackError(err, {\n\t\t\t\tcomponent: \"esm-adapter\",\n\t\t\t\terrorType: \"EsmSharedDependencyError\",\n\t\t\t});\n\t\t} catch {\n\t\t\t// Swallow: instrumentation must never break loading.\n\t\t}\n\t}\n\n\treturn {\n\t\tload,\n\t\tget __seams() {\n\t\t\treturn __seams;\n\t\t},\n\t};\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction defaultImporter(specifier: string): Promise<unknown> {\n\t// @vite-ignore — dynamic import resolved at runtime.\n\treturn import(/* @vite-ignore */ specifier);\n}\n\nasync function defaultPackageMetadataLoader(\n\tpackageVersion: string,\n\tpackageJsonUrl: string,\n): Promise<PackageMetadata | null> {\n\tconst browserFetch =\n\t\ttypeof window !== \"undefined\" &&\n\t\ttypeof (window as Window & { fetch?: typeof fetch }).fetch === \"function\"\n\t\t\t? (window as Window & { fetch: typeof fetch }).fetch.bind(window)\n\t\t\t: undefined;\n\tif (!browserFetch) {\n\t\treturn null;\n\t}\n\n\tconst response = await browserFetch(packageJsonUrl);\n\tif (!response.ok) {\n\t\treturn null;\n\t}\n\treturn (await response.json()) as PackageMetadata;\n}\n\nfunction resolveCdnProvider(\n\tprovider: EsmCdnProviderOption | undefined,\n\tcdnBaseUrl: string,\n): EsmCdnProvider {\n\tif (isEsmCdnProvider(provider)) return provider;\n\tconst resolvedProviderName =\n\t\tprovider ?? (cdnBaseUrl.includes(\"esm.sh\") ? \"esm.sh\" : \"jsdelivr\");\n\tif (resolvedProviderName === \"esm.sh\") {\n\t\treturn createEsmShProvider(cdnBaseUrl);\n\t}\n\treturn createJsDelivrProvider(cdnBaseUrl, resolvedProviderName);\n}\n\nfunction isEsmCdnProvider(value: unknown): value is EsmCdnProvider {\n\tif (!value || typeof value !== \"object\") return false;\n\tconst candidate = value as Partial<Record<keyof EsmCdnProvider, unknown>>;\n\treturn (\n\t\ttypeof candidate.name === \"string\" &&\n\t\ttypeof candidate.packageJsonUrl === \"function\" &&\n\t\ttypeof candidate.browserViewUrl === \"function\" &&\n\t\ttypeof candidate.browserControllerUrl === \"function\" &&\n\t\ttypeof candidate.sharedDependencyUrl === \"function\"\n\t);\n}\n\nfunction createJsDelivrProvider(\n\tcdnBaseUrl: string,\n\tname: EsmCdnProviderName = \"jsdelivr\",\n): EsmCdnProvider {\n\treturn {\n\t\tname,\n\t\tpackageJsonUrl: (packageVersion) =>\n\t\t\t`${cdnBaseUrl}/${packageVersion}/package.json`,\n\t\tbrowserViewUrl: (packageVersion, view) =>\n\t\t\t`${cdnBaseUrl}/${packageVersion}/dist/browser/${view}/index.js`,\n\t\tbrowserControllerUrl: (packageVersion) =>\n\t\t\t`${cdnBaseUrl}/${packageVersion}/dist/browser/controller/index.js`,\n\t\tsharedDependencyUrl: (dependencyName, version, subpath) => {\n\t\t\tconst suffix = subpath ? `/${subpath}/+esm` : \"/+esm\";\n\t\t\treturn `${cdnBaseUrl}/${dependencyName}@${version}${suffix}`;\n\t\t},\n\t};\n}\n\nfunction createEsmShProvider(cdnBaseUrl: string): EsmCdnProvider {\n\tconst esmBaseUrl = cdnBaseUrl.replace(/\\/+$/, \"\");\n\tconst rawBaseUrl = toRawEsmShBaseUrl(esmBaseUrl);\n\treturn {\n\t\tname: \"esm.sh\",\n\t\tpackageJsonUrl: (packageVersion) =>\n\t\t\t`${rawBaseUrl}/${packageVersion}/package.json`,\n\t\tbrowserViewUrl: (packageVersion, view) =>\n\t\t\t`${rawBaseUrl}/${packageVersion}/dist/browser/${view}/index.js`,\n\t\tbrowserControllerUrl: (packageVersion) =>\n\t\t\t`${rawBaseUrl}/${packageVersion}/dist/browser/controller/index.js`,\n\t\tsharedDependencyUrl: (dependencyName, version, subpath) => {\n\t\t\tconst suffix = subpath ? `/${subpath}` : \"\";\n\t\t\treturn `${esmBaseUrl}/${dependencyName}@${version}${suffix}`;\n\t\t},\n\t};\n}\n\nfunction toRawEsmShBaseUrl(cdnBaseUrl: string): string {\n\ttry {\n\t\tconst url = new URL(cdnBaseUrl);\n\t\tif (url.hostname === \"raw.esm.sh\")\n\t\t\treturn url.toString().replace(/\\/+$/, \"\");\n\t\tif (url.hostname === \"esm.sh\") {\n\t\t\turl.hostname = \"raw.esm.sh\";\n\t\t\treturn url.toString().replace(/\\/+$/, \"\");\n\t\t}\n\t} catch {\n\t\t// Fall through to the public raw endpoint for non-URL test fixtures.\n\t}\n\treturn \"https://raw.esm.sh\";\n}\n\nfunction assertBrowserEsmExports(\n\tmetadata: PackageMetadata | null,\n\tpackageVersion: string,\n\tviewConfig: ViewConfig,\n\tloadControllers: boolean,\n\tviewName: string,\n): void {\n\tif (!metadata?.exports) return;\n\n\tconst requiredExports = new Set<string>([\n\t\t`./browser/${browserViewName(viewConfig, viewName)}`,\n\t]);\n\tif (viewConfig.fallback) {\n\t\tconst fallbackConfig = BUILT_IN_VIEWS[viewConfig.fallback];\n\t\tif (fallbackConfig) {\n\t\t\trequiredExports.add(\n\t\t\t\t`./browser/${browserViewName(fallbackConfig, viewConfig.fallback)}`,\n\t\t\t);\n\t\t}\n\t}\n\tif (loadControllers) {\n\t\trequiredExports.add(\"./browser/controller\");\n\t}\n\n\tfor (const exportKey of requiredExports) {\n\t\tif (!(exportKey in metadata.exports)) {\n\t\t\tthrow new Error(\n\t\t\t\t`${packageVersion} does not publish browser ESM export ${exportKey}; use IIFE/preloaded mode or publish browser ESM artifacts first`,\n\t\t\t);\n\t\t}\n\t}\n}\n\nfunction extractPackageName(packageVersion: string): string {\n\tconst parts = packageVersion.split(\"@\");\n\treturn parts.length >= 3 ? `@${parts[1]}` : parts[0];\n}\n\nfunction cleanViewSubpath(subpath: string): string | null {\n\tconst cleanSubpath = subpath.replace(/^\\/+|\\/+$/g, \"\");\n\treturn cleanSubpath.length > 0 ? cleanSubpath : null;\n}\n\nfunction browserViewName(\n\tviewConfig: ViewConfig,\n\tviewName = \"delivery\",\n): string {\n\tconst subpathView = cleanViewSubpath(viewConfig.subpath);\n\treturn subpathView ?? viewName;\n}\n\nfunction resolveBrowserViewUrl(\n\tpackageVersion: string,\n\tviewConfig: ViewConfig,\n\tcdnProvider: EsmCdnProvider,\n\tviewName = \"delivery\",\n): string {\n\tconst view = browserViewName(viewConfig, viewName);\n\treturn cdnProvider.browserViewUrl(packageVersion, view);\n}\n\nfunction resolveBrowserControllerUrl(\n\tpackageVersion: string,\n\tcdnProvider: EsmCdnProvider,\n): string {\n\treturn cdnProvider.browserControllerUrl(packageVersion);\n}\n\nfunction resolveElementSpecifier(\n\tpackageName: string,\n\tpackageVersion: string,\n\tviewConfig: ViewConfig,\n\tmoduleResolution: \"url\" | \"import-map\",\n\tcdnProvider: EsmCdnProvider,\n\tviewName: string,\n): string {\n\tif (moduleResolution === \"import-map\") {\n\t\treturn viewConfig.subpath\n\t\t\t? `${packageName}${viewConfig.subpath}`\n\t\t\t: packageName;\n\t}\n\treturn resolveBrowserViewUrl(\n\t\tpackageVersion,\n\t\tviewConfig,\n\t\tcdnProvider,\n\t\tviewName,\n\t);\n}\n\nfunction resolveControllerSpecifier(\n\tpackageName: string,\n\tpackageVersion: string,\n\tmoduleResolution: \"url\" | \"import-map\",\n\tcdnProvider: EsmCdnProvider,\n): string {\n\tif (moduleResolution === \"import-map\") {\n\t\treturn `${packageName}/controller`;\n\t}\n\treturn resolveBrowserControllerUrl(packageVersion, cdnProvider);\n}\n\nfunction pickElementClass(module: any, view: string): unknown {\n\tif (!module || typeof module !== \"object\") return undefined;\n\tif (view === \"author\") {\n\t\treturn module.default ?? module.Configure ?? module.Element;\n\t}\n\tif (view === \"print\") {\n\t\treturn module.default ?? module.Print ?? module.Element;\n\t}\n\treturn module.default ?? module.Element;\n}\n\nconst SHARED_BROWSER_DEPENDENCIES = [\"react\", \"react-dom\"] as const;\n\nfunction declaredSharedDependencyVersion(\n\tmetadata: PackageMetadata | null,\n\tdependencyName: (typeof SHARED_BROWSER_DEPENDENCIES)[number],\n\tpackageVersion: string,\n): string | undefined {\n\tconst version = metadata?.pie?.browserSharedDependencies?.[dependencyName];\n\tif (!version) {\n\t\tthrow new Error(\n\t\t\t`${packageVersion} is missing required pie.browserSharedDependencies.${dependencyName}`,\n\t\t);\n\t}\n\tif (!isExactVersion(version)) {\n\t\tthrow new Error(\n\t\t\t`${packageVersion} pie.browserSharedDependencies.${dependencyName} must be an exact version; received \"${version}\"`,\n\t\t);\n\t}\n\treturn version;\n}\n\nfunction packageUsesSharedDependency(\n\tmetadata: PackageMetadata | null,\n\tdependencyName: (typeof SHARED_BROWSER_DEPENDENCIES)[number],\n): boolean {\n\treturn Boolean(\n\t\tmetadata?.pie?.browserSharedDependencies?.[dependencyName] ||\n\t\t\tmetadata?.peerDependencies?.[dependencyName] ||\n\t\t\tmetadata?.dependencies?.[dependencyName] ||\n\t\t\tmetadata?.optionalDependencies?.[dependencyName],\n\t);\n}\n\nfunction addSharedDependencyImports(\n\timports: Record<string, string>,\n\tselectedVersions: Record<string, string>,\n\tlockedVersions: Set<string>,\n\tdependencyName: (typeof SHARED_BROWSER_DEPENDENCIES)[number],\n\tversion: string | undefined,\n\tcdnProvider: EsmCdnProvider,\n\tpackageVersion: string,\n\tonConflict: (attributes: Record<string, unknown>) => void,\n): void {\n\tif (!version) {\n\t\treturn;\n\t}\n\n\tconst currentVersion = selectedVersions[dependencyName];\n\tlet resolvedVersion = version;\n\tif (currentVersion && currentVersion !== version) {\n\t\tresolvedVersion = resolveSharedDependencyVersion(\n\t\t\tdependencyName,\n\t\t\tcurrentVersion,\n\t\t\tversion,\n\t\t\tpackageVersion,\n\t\t\tlockedVersions.has(dependencyName),\n\t\t);\n\t\tonConflict({\n\t\t\tdependencyName,\n\t\t\texistingVersion: currentVersion,\n\t\t\trequestedVersion: version,\n\t\t\tresolvedVersion,\n\t\t\tpackageVersion,\n\t\t});\n\t}\n\tselectedVersions[dependencyName] = resolvedVersion;\n\n\timports[dependencyName] = cdnProvider.sharedDependencyUrl(\n\t\tdependencyName,\n\t\tresolvedVersion,\n\t);\n\tif (dependencyName === \"react\") {\n\t\timports[\"react/jsx-runtime\"] = cdnProvider.sharedDependencyUrl(\n\t\t\t\"react\",\n\t\t\tresolvedVersion,\n\t\t\t\"jsx-runtime\",\n\t\t);\n\t\timports[\"react/jsx-dev-runtime\"] = cdnProvider.sharedDependencyUrl(\n\t\t\t\"react\",\n\t\t\tresolvedVersion,\n\t\t\t\"jsx-dev-runtime\",\n\t\t);\n\t}\n\tif (dependencyName === \"react-dom\") {\n\t\timports[\"react-dom/client\"] = cdnProvider.sharedDependencyUrl(\n\t\t\t\"react-dom\",\n\t\t\tresolvedVersion,\n\t\t\t\"client\",\n\t\t);\n\t}\n}\n\nfunction isExactVersion(version: string): boolean {\n\treturn /^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?$/.test(version);\n}\n\nfunction parseVersion(version: string): {\n\tmajor: number;\n\tminor: number;\n\tpatch: number;\n} {\n\tconst match = version.match(/^(\\d+)\\.(\\d+)\\.(\\d+)/);\n\tif (!match) {\n\t\tthrow new Error(`Invalid shared browser dependency version \"${version}\"`);\n\t}\n\treturn {\n\t\tmajor: Number(match[1]),\n\t\tminor: Number(match[2]),\n\t\tpatch: Number(match[3]),\n\t};\n}\n\nfunction compareVersions(a: string, b: string): number {\n\tconst parsedA = parseVersion(a);\n\tconst parsedB = parseVersion(b);\n\tif (parsedA.major !== parsedB.major) return parsedA.major - parsedB.major;\n\tif (parsedA.minor !== parsedB.minor) return parsedA.minor - parsedB.minor;\n\treturn parsedA.patch - parsedB.patch;\n}\n\nfunction resolveSharedDependencyVersion(\n\tdependencyName: string,\n\tcurrentVersion: string,\n\trequestedVersion: string,\n\tpackageVersion: string,\n\tisLocked: boolean,\n): string {\n\tconst current = parseVersion(currentVersion);\n\tconst requested = parseVersion(requestedVersion);\n\tif (current.major !== requested.major) {\n\t\tthrow new Error(\n\t\t\t`Conflicting shared browser dependency ${dependencyName}: ${currentVersion} vs ${requestedVersion} from ${packageVersion}; different major versions cannot share one browser singleton`,\n\t\t);\n\t}\n\tif (isLocked && compareVersions(requestedVersion, currentVersion) > 0) {\n\t\tthrow new Error(\n\t\t\t`Conflicting shared browser dependency ${dependencyName}: ${currentVersion} is already selected, but ${packageVersion} requires higher version ${requestedVersion}; the browser singleton cannot be upgraded after import-map injection`,\n\t\t);\n\t}\n\treturn compareVersions(currentVersion, requestedVersion) >= 0\n\t\t? currentVersion\n\t\t: requestedVersion;\n}\n\ntype BrowserImportMapBuildResult = {\n\tjson: string | null;\n\tsharedDependencyVersions: Record<string, string>;\n};\n\nasync function buildImportMapJson(\n\telements: ElementMap,\n\tviewConfig: ViewConfig,\n\tcdnProvider: EsmCdnProvider,\n\tloadControllers: boolean,\n\tincludeElementImports: boolean,\n\tpackageMetadataLoader: EsmPackageMetadataLoader,\n\tcurrentSharedDependencyVersions: Record<string, string>,\n\tonConflict: (attributes: Record<string, unknown>) => void,\n): Promise<BrowserImportMapBuildResult> {\n\tconst imports: Record<string, string> = {};\n\tconst selectedVersions: Record<string, string> = {\n\t\t...currentSharedDependencyVersions,\n\t};\n\tconst lockedVersions = new Set(Object.keys(currentSharedDependencyVersions));\n\tfor (const [, pkg] of Object.entries(elements)) {\n\t\tconst packageName = extractPackageName(pkg);\n\t\tif (includeElementImports) {\n\t\t\timports[packageName] = resolveBrowserViewUrl(\n\t\t\t\tpkg,\n\t\t\t\tBUILT_IN_VIEWS.delivery,\n\t\t\t\tcdnProvider,\n\t\t\t\t\"delivery\",\n\t\t\t);\n\t\t\tif (viewConfig.subpath) {\n\t\t\t\timports[`${packageName}${viewConfig.subpath}`] = resolveBrowserViewUrl(\n\t\t\t\t\tpkg,\n\t\t\t\t\tviewConfig,\n\t\t\t\t\tcdnProvider,\n\t\t\t\t\tcleanViewSubpath(viewConfig.subpath) ?? \"delivery\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (loadControllers) {\n\t\t\t\timports[`${packageName}/controller`] = resolveBrowserControllerUrl(\n\t\t\t\t\tpkg,\n\t\t\t\t\tcdnProvider,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (viewConfig.fallback) {\n\t\t\t\tconst fallbackConfig = BUILT_IN_VIEWS[viewConfig.fallback];\n\t\t\t\tif (fallbackConfig) {\n\t\t\t\t\tconst fallbackSpecifier = fallbackConfig.subpath\n\t\t\t\t\t\t? `${packageName}${fallbackConfig.subpath}`\n\t\t\t\t\t\t: packageName;\n\t\t\t\t\timports[fallbackSpecifier] = resolveBrowserViewUrl(\n\t\t\t\t\t\tpkg,\n\t\t\t\t\t\tfallbackConfig,\n\t\t\t\t\t\tcdnProvider,\n\t\t\t\t\t\tviewConfig.fallback,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst metadata = await packageMetadataLoader(\n\t\t\tpkg,\n\t\t\tcdnProvider.packageJsonUrl(pkg),\n\t\t);\n\t\tassertBrowserEsmExports(\n\t\t\tmetadata,\n\t\t\tpkg,\n\t\t\tviewConfig,\n\t\t\tloadControllers,\n\t\t\tcleanViewSubpath(viewConfig.subpath) ?? \"delivery\",\n\t\t);\n\t\tfor (const dependencyName of SHARED_BROWSER_DEPENDENCIES) {\n\t\t\tif (!packageUsesSharedDependency(metadata, dependencyName)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\taddSharedDependencyImports(\n\t\t\t\timports,\n\t\t\t\tselectedVersions,\n\t\t\t\tlockedVersions,\n\t\t\t\tdependencyName,\n\t\t\t\tdeclaredSharedDependencyVersion(metadata, dependencyName, pkg),\n\t\t\t\tcdnProvider,\n\t\t\t\tpkg,\n\t\t\t\tonConflict,\n\t\t\t);\n\t\t}\n\t}\n\tif (Object.keys(imports).length === 0) {\n\t\treturn { json: null, sharedDependencyVersions: selectedVersions };\n\t}\n\treturn {\n\t\tjson: JSON.stringify({ imports }, null, 2),\n\t\tsharedDependencyVersions: selectedVersions,\n\t};\n}\n\nfunction injectImportMap(json: string, doc: Document): void {\n\tconst script = doc.createElement(\"script\") as HTMLScriptElement;\n\tscript.type = \"importmap\";\n\tscript.textContent = json;\n\tdoc.head.appendChild(script);\n}\n\nfunction assertImportMapSupported(): void {\n\tconst htmlScriptElement = (\n\t\ttypeof HTMLScriptElement !== \"undefined\" ? HTMLScriptElement : undefined\n\t) as\n\t\t| (typeof HTMLScriptElement & {\n\t\t\t\tsupports?: (type: string) => boolean;\n\t\t })\n\t\t| undefined;\n\tconst supports =\n\t\ttypeof htmlScriptElement?.supports === \"function\" &&\n\t\thtmlScriptElement.supports(\"importmap\");\n\tif (!supports) {\n\t\tthrow new Error(\n\t\t\t'This browser does not support import maps. Use moduleResolution=\"url\" or switch to iife/preloaded strategy.',\n\t\t);\n\t}\n}\n"]}
1
+ {"version":3,"file":"esm-adapter.js","sourceRoot":"","sources":["../../src/loaders/esm-adapter.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ESM backend adapter for the ElementLoader primitive.\n *\n * Loads PIE elements via dynamic `import()` from static browser ESM files on a\n * CDN, optionally resolving bare specifiers through an import map injected into\n * the host document. On any per-tag failure (module load, non-constructor\n * element class, define failure), throws `AdapterFailure` with a structured\n * `reasons` map.\n *\n * Like the IIFE adapter, this module does not gate its own promise on\n * `customElements.whenDefined`; the primitive performs that verification\n * uniformly. Here the adapter's job is narrowly to fetch, extract, and\n * call `customElements.define`.\n */\n\nimport { defineCustomElementSafely } from \"../pie/custom-element-define.js\";\nimport type { InstrumentationProvider } from \"../instrumentation/types.js\";\nimport { isInstrumentationProvider } from \"../instrumentation/provider-guards.js\";\nimport { pieRegistry } from \"../pie/registry.js\";\nimport { validateCustomElementTag } from \"../pie/tag-names.js\";\nimport { isCustomElementConstructor, Status } from \"../pie/types.js\";\nimport type { ElementMap } from \"./ElementLoader.js\";\nimport {\n\tAdapterFailure,\n\ttype BackendContext,\n\ttype ElementLoaderBackend,\n\ttype ElementTag,\n\ttype RegistrationFailureReason,\n} from \"./element-loader-types.js\";\n\n/** View configuration: how a PIE package's subpath maps to a tag suffix. */\nexport type ViewConfig = {\n\tsubpath: string;\n\ttagSuffix: string;\n\tfallback?: string;\n};\n\nexport const BUILT_IN_VIEWS: Record<string, ViewConfig> = {\n\tdelivery: { subpath: \"\", tagSuffix: \"\" },\n\tauthor: { subpath: \"/author\", tagSuffix: \"-config\", fallback: \"delivery\" },\n\tprint: { subpath: \"/print\", tagSuffix: \"-print\", fallback: \"delivery\" },\n};\n\nexport type BuiltInEsmCdnProviderName = \"jsdelivr\" | \"esm.sh\";\nexport type EsmCdnProviderName = BuiltInEsmCdnProviderName | (string & {});\n\nexport type EsmCdnProvider = {\n\tname: EsmCdnProviderName;\n\tpackageJsonUrl(packageVersion: string): string;\n\tbrowserViewUrl(packageVersion: string, view: string): string;\n\tbrowserControllerUrl(packageVersion: string): string;\n\tsharedDependencyUrl(\n\t\tdependencyName: string,\n\t\tversion: string,\n\t\tsubpath?: string,\n\t): string;\n};\n\nexport type EsmCdnProviderOption = EsmCdnProviderName | EsmCdnProvider;\n\nexport type EsmBackendConfig = {\n\tkind: \"esm\";\n\t/** Base URL for the ESM CDN (e.g., \"https://esm.sh\"). */\n\tcdnBaseUrl: string;\n\t/** CDN URL strategy. Defaults to jsDelivr, or is inferred from cdnBaseUrl when possible. */\n\tcdnProvider?: EsmCdnProviderOption;\n\t/** `\"url\"` loads via fully-qualified URLs; `\"import-map\"` uses bare specifiers. */\n\tmoduleResolution?: \"url\" | \"import-map\";\n\t/** View to load (`delivery`, `author`, `print`, or a custom name). */\n\tview?: string;\n\t/** Custom view configuration (overrides built-ins). */\n\tviewConfig?: ViewConfig;\n\t/** Whether to also load controller modules. */\n\tloadControllers?: boolean;\n\t/** Debug flag hook. */\n\tdebugEnabled?: () => boolean;\n\t/** Whether ESM dependency conflict/failure events should be instrumented. */\n\ttrackPageActions?: boolean;\n\t/** Instrumentation provider for ESM dependency conflict/failure events. */\n\tinstrumentationProvider?: InstrumentationProvider;\n};\n\ntype PackageMetadata = {\n\texports?: Record<string, unknown>;\n\tdependencies?: Record<string, string>;\n\toptionalDependencies?: Record<string, string>;\n\tpeerDependencies?: Record<string, string>;\n\tpie?: {\n\t\tbrowserSharedDependencies?: Record<string, string>;\n\t};\n};\n\n/** @internal */\nexport type EsmModuleImporter = (specifier: string) => Promise<unknown>;\n/** @internal */\nexport type EsmImportMapObserver = (json: string, doc: Document) => void;\n/** @internal */\nexport type EsmPackageMetadataLoader = (\n\tpackageVersion: string,\n\tpackageJsonUrl: string,\n) => Promise<PackageMetadata | null>;\n\n/**\n * Test-only seam exposed via `EsmBackend.__seams`. Lets contract tests\n * inject scripted import behaviour and observe import-map injection\n * without going through the network or the document. Not part of the\n * runtime API; production code must not touch this field.\n *\n * @internal\n */\nexport type EsmBackendTestSeams = {\n\treplaceImporter(fn: EsmModuleImporter): void;\n\tobserveImportMapInjection(cb: EsmImportMapObserver): void;\n\treplacePackageMetadataLoader(fn: EsmPackageMetadataLoader): void;\n\trestore(): void;\n};\n\nexport type EsmBackend = ElementLoaderBackend & {\n\t/** @internal Test-only seam — see {@link EsmBackendTestSeams}. */\n\treadonly __seams: EsmBackendTestSeams;\n};\n\nexport function createEsmBackend(config: EsmBackendConfig): EsmBackend {\n\tconst cdnBaseUrl = config.cdnBaseUrl.replace(/\\/+$/, \"\");\n\tconst cdnProvider = resolveCdnProvider(config.cdnProvider, cdnBaseUrl);\n\tconst moduleResolution = config.moduleResolution ?? \"url\";\n\tconst view = config.view ?? \"delivery\";\n\tconst loadControllers = config.loadControllers ?? true;\n\tconst viewConfig = resolveEsmViewConfig(view, config.viewConfig);\n\n\tconst injectedPackageVersions = new Set<string>();\n\tconst importMappedPackageVersions = new Map<string, string>();\n\tlet sharedDependencyVersions: Record<string, string> = {};\n\tlet importer: EsmModuleImporter = defaultImporter;\n\tlet packageMetadataLoader: EsmPackageMetadataLoader =\n\t\tdefaultPackageMetadataLoader;\n\tlet importMapObserver: EsmImportMapObserver | undefined;\n\n\tconst __seams: EsmBackendTestSeams = {\n\t\treplaceImporter(fn) {\n\t\t\timporter = fn;\n\t\t},\n\t\tobserveImportMapInjection(cb) {\n\t\t\timportMapObserver = cb;\n\t\t},\n\t\treplacePackageMetadataLoader(fn) {\n\t\t\tpackageMetadataLoader = fn;\n\t\t},\n\t\trestore() {\n\t\t\timporter = defaultImporter;\n\t\t\tpackageMetadataLoader = defaultPackageMetadataLoader;\n\t\t\timportMapObserver = undefined;\n\t\t\tinjectedPackageVersions.clear();\n\t\t\timportMappedPackageVersions.clear();\n\t\t\tsharedDependencyVersions = {};\n\t\t},\n\t};\n\n\tasync function load(\n\t\telements: ElementMap,\n\t\tcontext: BackendContext,\n\t): Promise<void> {\n\t\tif (!elements || Object.keys(elements).length === 0) return;\n\t\tif (moduleResolution === \"import-map\") {\n\t\t\tassertImportMapSupported();\n\t\t}\n\n\t\tconst newEntries: ElementMap = {};\n\t\tfor (const [tag, pkg] of Object.entries(elements)) {\n\t\t\tconst packageName = extractPackageName(pkg);\n\t\t\tif (moduleResolution === \"import-map\") {\n\t\t\t\tconst existingVersion = importMappedPackageVersions.get(packageName);\n\t\t\t\tif (existingVersion && existingVersion !== pkg) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Conflicting browser ESM package version for ${packageName}: ${existingVersion} is already mapped, but ${pkg} was requested`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!injectedPackageVersions.has(pkg)) {\n\t\t\t\tnewEntries[tag] = pkg;\n\t\t\t}\n\t\t}\n\t\tif (Object.keys(newEntries).length > 0) {\n\t\t\tlet importMapResult: BrowserImportMapBuildResult;\n\t\t\ttry {\n\t\t\t\timportMapResult = await buildImportMapJson(\n\t\t\t\t\tnewEntries,\n\t\t\t\t\tviewConfig,\n\t\t\t\t\tcdnProvider,\n\t\t\t\t\tloadControllers,\n\t\t\t\t\tmoduleResolution === \"import-map\",\n\t\t\t\t\tpackageMetadataLoader,\n\t\t\t\t\tsharedDependencyVersions,\n\t\t\t\t\treportSharedDependencyConflict,\n\t\t\t\t);\n\t\t\t} catch (err) {\n\t\t\t\treportSharedDependencyError(err);\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t\tconst json = importMapResult.json;\n\t\t\tif (json) {\n\t\t\t\tassertImportMapSupported();\n\t\t\t\tinjectImportMap(json, context.doc);\n\t\t\t\timportMapObserver?.(json, context.doc);\n\t\t\t}\n\t\t\tsharedDependencyVersions = importMapResult.sharedDependencyVersions;\n\t\t\tfor (const pkg of Object.values(newEntries)) {\n\t\t\t\tinjectedPackageVersions.add(pkg);\n\t\t\t\tif (moduleResolution === \"import-map\") {\n\t\t\t\t\timportMappedPackageVersions.set(extractPackageName(pkg), pkg);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst reasons = new Map<ElementTag, RegistrationFailureReason>();\n\t\tconst registry = pieRegistry();\n\n\t\tawait Promise.all(\n\t\t\tObject.entries(elements).map(async ([tag, packageVersion]) => {\n\t\t\t\tconst packageName = extractPackageName(packageVersion);\n\t\t\t\tlet actualTag: string;\n\t\t\t\ttry {\n\t\t\t\t\tactualTag = validateCustomElementTag(\n\t\t\t\t\t\ttag,\n\t\t\t\t\t\t`element tag for ${packageName}`,\n\t\t\t\t\t);\n\t\t\t\t} catch (err) {\n\t\t\t\t\treasons.set(tag, {\n\t\t\t\t\t\tkind: \"define-failed\",\n\t\t\t\t\t\ttag,\n\t\t\t\t\t\tcause: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst specifier = resolveElementSpecifier(\n\t\t\t\t\tpackageName,\n\t\t\t\t\tpackageVersion,\n\t\t\t\t\tviewConfig,\n\t\t\t\t\tmoduleResolution,\n\t\t\t\t\tcdnProvider,\n\t\t\t\t\tview,\n\t\t\t\t);\n\n\t\t\t\tlet module: any;\n\t\t\t\ttry {\n\t\t\t\t\tmodule = await importer(specifier);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tif (viewConfig.fallback) {\n\t\t\t\t\t\tconst fallbackConfig =\n\t\t\t\t\t\t\tBUILT_IN_VIEWS[viewConfig.fallback] ?? BUILT_IN_VIEWS.delivery;\n\t\t\t\t\t\tconst fallbackSpecifier = resolveElementSpecifier(\n\t\t\t\t\t\t\tpackageName,\n\t\t\t\t\t\t\tpackageVersion,\n\t\t\t\t\t\t\tfallbackConfig,\n\t\t\t\t\t\t\tmoduleResolution,\n\t\t\t\t\t\t\tcdnProvider,\n\t\t\t\t\t\t\tviewConfig.fallback,\n\t\t\t\t\t\t);\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tmodule = await importer(fallbackSpecifier);\n\t\t\t\t\t\t} catch (fallbackErr) {\n\t\t\t\t\t\t\treasons.set(tag, {\n\t\t\t\t\t\t\t\tkind: \"module-load-failed\",\n\t\t\t\t\t\t\t\ttag,\n\t\t\t\t\t\t\t\tspecifier: fallbackSpecifier,\n\t\t\t\t\t\t\t\tcause:\n\t\t\t\t\t\t\t\t\tfallbackErr instanceof Error\n\t\t\t\t\t\t\t\t\t\t? fallbackErr.message\n\t\t\t\t\t\t\t\t\t\t: String(fallbackErr),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treasons.set(tag, {\n\t\t\t\t\t\t\tkind: \"module-load-failed\",\n\t\t\t\t\t\t\ttag,\n\t\t\t\t\t\t\tspecifier,\n\t\t\t\t\t\t\tcause: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst ElementClass = pickElementClass(module, view);\n\t\t\t\tif (!ElementClass) {\n\t\t\t\t\treasons.set(tag, {\n\t\t\t\t\t\tkind: \"no-element-class\",\n\t\t\t\t\t\ttag,\n\t\t\t\t\t\tpackageName,\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (!isCustomElementConstructor(ElementClass)) {\n\t\t\t\t\treasons.set(tag, {\n\t\t\t\t\t\tkind: \"not-a-constructor\",\n\t\t\t\t\t\ttag,\n\t\t\t\t\t\tpackageName,\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tdefineCustomElementSafely(\n\t\t\t\t\t\tactualTag,\n\t\t\t\t\t\tclass extends ElementClass {},\n\t\t\t\t\t\t`element tag for ${packageName}`,\n\t\t\t\t\t);\n\t\t\t\t} catch (err) {\n\t\t\t\t\treasons.set(tag, {\n\t\t\t\t\t\tkind: \"define-failed\",\n\t\t\t\t\t\ttag,\n\t\t\t\t\t\tcause: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tlet controller: any = null;\n\t\t\t\tif (loadControllers) {\n\t\t\t\t\tconst controllerSpecifier = resolveControllerSpecifier(\n\t\t\t\t\t\tpackageName,\n\t\t\t\t\t\tpackageVersion,\n\t\t\t\t\t\tmoduleResolution,\n\t\t\t\t\t\tcdnProvider,\n\t\t\t\t\t);\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst controllerModule: any = await importer(controllerSpecifier);\n\t\t\t\t\t\tcontroller = controllerModule?.default ?? controllerModule;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Controllers are best-effort; element registration is what the\n\t\t\t\t\t\t// primitive verifies.\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tregistry[actualTag] = {\n\t\t\t\t\tpackage: packageVersion,\n\t\t\t\t\tstatus: Status.loaded,\n\t\t\t\t\ttagName: actualTag,\n\t\t\t\t\telement: ElementClass,\n\t\t\t\t\tcontroller,\n\t\t\t\t\tconfig: null,\n\t\t\t\t\tbundleType: \"esm\" as unknown as import(\"../pie/types.js\").BundleType,\n\t\t\t\t};\n\t\t\t}),\n\t\t);\n\n\t\tif (reasons.size > 0) {\n\t\t\tthrow new AdapterFailure(reasons);\n\t\t}\n\t}\n\n\tfunction getInstrumentationProvider(): InstrumentationProvider | undefined {\n\t\tif (!config.trackPageActions) return undefined;\n\t\tconst provider = config.instrumentationProvider;\n\t\tif (!isInstrumentationProvider(provider)) return undefined;\n\t\tif (!provider.isReady()) return undefined;\n\t\treturn provider;\n\t}\n\n\tfunction reportSharedDependencyConflict(\n\t\tattributes: Record<string, unknown>,\n\t): void {\n\t\tif (typeof console !== \"undefined\" && console.warn) {\n\t\t\tconsole.warn(\n\t\t\t\t`[pie-esm] Shared dependency version conflict resolved for ${String(attributes.dependencyName)}`,\n\t\t\t\tattributes,\n\t\t\t);\n\t\t}\n\t\tconst provider = getInstrumentationProvider();\n\t\tif (!provider) return;\n\t\ttry {\n\t\t\tprovider.trackEvent(\"pie-esm-shared-dependency-conflict\", attributes);\n\t\t} catch {\n\t\t\t// Swallow: instrumentation must never break loading.\n\t\t}\n\t}\n\n\tfunction reportSharedDependencyError(error: unknown): void {\n\t\tconst err = error instanceof Error ? error : new Error(String(error));\n\t\tif (typeof console !== \"undefined\" && console.error) {\n\t\t\tconsole.error(\"[pie-esm] Shared dependency resolution failed\", err);\n\t\t}\n\t\tconst provider = getInstrumentationProvider();\n\t\tif (!provider) return;\n\t\ttry {\n\t\t\tprovider.trackError(err, {\n\t\t\t\tcomponent: \"esm-adapter\",\n\t\t\t\terrorType: \"EsmSharedDependencyError\",\n\t\t\t});\n\t\t} catch {\n\t\t\t// Swallow: instrumentation must never break loading.\n\t\t}\n\t}\n\n\treturn {\n\t\tload,\n\t\tget __seams() {\n\t\t\treturn __seams;\n\t\t},\n\t};\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nexport function mapEsmViewElements(\n\telements: ElementMap,\n\tview = \"delivery\",\n\tviewConfig?: ViewConfig,\n): ElementMap {\n\tconst resolvedViewConfig = resolveEsmViewConfig(view, viewConfig);\n\treturn Object.fromEntries(\n\t\tObject.entries(elements).map(([tag, packageVersion]) => [\n\t\t\t`${tag}${resolvedViewConfig.tagSuffix}`,\n\t\t\tpackageVersion,\n\t\t]),\n\t);\n}\n\nfunction defaultImporter(specifier: string): Promise<unknown> {\n\t// @vite-ignore — dynamic import resolved at runtime.\n\treturn import(/* @vite-ignore */ specifier);\n}\n\nasync function defaultPackageMetadataLoader(\n\tpackageVersion: string,\n\tpackageJsonUrl: string,\n): Promise<PackageMetadata | null> {\n\tconst browserFetch =\n\t\ttypeof window !== \"undefined\" &&\n\t\ttypeof (window as Window & { fetch?: typeof fetch }).fetch === \"function\"\n\t\t\t? (window as Window & { fetch: typeof fetch }).fetch.bind(window)\n\t\t\t: undefined;\n\tif (!browserFetch) {\n\t\treturn null;\n\t}\n\n\tconst response = await browserFetch(packageJsonUrl);\n\tif (!response.ok) {\n\t\treturn null;\n\t}\n\treturn (await response.json()) as PackageMetadata;\n}\n\nfunction resolveCdnProvider(\n\tprovider: EsmCdnProviderOption | undefined,\n\tcdnBaseUrl: string,\n): EsmCdnProvider {\n\tif (isEsmCdnProvider(provider)) return provider;\n\tconst resolvedProviderName =\n\t\tprovider ?? (cdnBaseUrl.includes(\"esm.sh\") ? \"esm.sh\" : \"jsdelivr\");\n\tif (resolvedProviderName === \"esm.sh\") {\n\t\treturn createEsmShProvider(cdnBaseUrl);\n\t}\n\treturn createJsDelivrProvider(cdnBaseUrl, resolvedProviderName);\n}\n\nfunction isEsmCdnProvider(value: unknown): value is EsmCdnProvider {\n\tif (!value || typeof value !== \"object\") return false;\n\tconst candidate = value as Partial<Record<keyof EsmCdnProvider, unknown>>;\n\treturn (\n\t\ttypeof candidate.name === \"string\" &&\n\t\ttypeof candidate.packageJsonUrl === \"function\" &&\n\t\ttypeof candidate.browserViewUrl === \"function\" &&\n\t\ttypeof candidate.browserControllerUrl === \"function\" &&\n\t\ttypeof candidate.sharedDependencyUrl === \"function\"\n\t);\n}\n\nfunction createJsDelivrProvider(\n\tcdnBaseUrl: string,\n\tname: EsmCdnProviderName = \"jsdelivr\",\n): EsmCdnProvider {\n\treturn {\n\t\tname,\n\t\tpackageJsonUrl: (packageVersion) =>\n\t\t\t`${cdnBaseUrl}/${packageVersion}/package.json`,\n\t\tbrowserViewUrl: (packageVersion, view) =>\n\t\t\t`${cdnBaseUrl}/${packageVersion}/dist/browser/${view}/index.js`,\n\t\tbrowserControllerUrl: (packageVersion) =>\n\t\t\t`${cdnBaseUrl}/${packageVersion}/dist/browser/controller/index.js`,\n\t\tsharedDependencyUrl: (dependencyName, version, subpath) => {\n\t\t\tconst suffix = subpath ? `/${subpath}/+esm` : \"/+esm\";\n\t\t\treturn `${cdnBaseUrl}/${dependencyName}@${version}${suffix}`;\n\t\t},\n\t};\n}\n\nfunction createEsmShProvider(cdnBaseUrl: string): EsmCdnProvider {\n\tconst esmBaseUrl = cdnBaseUrl.replace(/\\/+$/, \"\");\n\tconst rawBaseUrl = toRawEsmShBaseUrl(esmBaseUrl);\n\treturn {\n\t\tname: \"esm.sh\",\n\t\tpackageJsonUrl: (packageVersion) =>\n\t\t\t`${rawBaseUrl}/${packageVersion}/package.json`,\n\t\tbrowserViewUrl: (packageVersion, view) =>\n\t\t\t`${rawBaseUrl}/${packageVersion}/dist/browser/${view}/index.js`,\n\t\tbrowserControllerUrl: (packageVersion) =>\n\t\t\t`${rawBaseUrl}/${packageVersion}/dist/browser/controller/index.js`,\n\t\tsharedDependencyUrl: (dependencyName, version, subpath) => {\n\t\t\tconst suffix = subpath ? `/${subpath}` : \"\";\n\t\t\treturn `${esmBaseUrl}/${dependencyName}@${version}${suffix}`;\n\t\t},\n\t};\n}\n\nfunction toRawEsmShBaseUrl(cdnBaseUrl: string): string {\n\ttry {\n\t\tconst url = new URL(cdnBaseUrl);\n\t\tif (url.hostname === \"raw.esm.sh\")\n\t\t\treturn url.toString().replace(/\\/+$/, \"\");\n\t\tif (url.hostname === \"esm.sh\") {\n\t\t\turl.hostname = \"raw.esm.sh\";\n\t\t\treturn url.toString().replace(/\\/+$/, \"\");\n\t\t}\n\t} catch {\n\t\t// Fall through to the public raw endpoint for non-URL test fixtures.\n\t}\n\treturn \"https://raw.esm.sh\";\n}\n\nfunction resolveEsmViewConfig(view: string, viewConfig?: ViewConfig): ViewConfig {\n\treturn viewConfig ?? BUILT_IN_VIEWS[view] ?? BUILT_IN_VIEWS.delivery;\n}\n\nfunction assertBrowserEsmExports(\n\tmetadata: PackageMetadata | null,\n\tpackageVersion: string,\n\tviewConfig: ViewConfig,\n\tloadControllers: boolean,\n\tviewName: string,\n): void {\n\tif (!metadata?.exports) return;\n\n\tconst requiredExports = new Set<string>([\n\t\t`./browser/${browserViewName(viewConfig, viewName)}`,\n\t]);\n\tif (viewConfig.fallback) {\n\t\tconst fallbackConfig = BUILT_IN_VIEWS[viewConfig.fallback];\n\t\tif (fallbackConfig) {\n\t\t\trequiredExports.add(\n\t\t\t\t`./browser/${browserViewName(fallbackConfig, viewConfig.fallback)}`,\n\t\t\t);\n\t\t}\n\t}\n\tif (loadControllers) {\n\t\trequiredExports.add(\"./browser/controller\");\n\t}\n\n\tfor (const exportKey of requiredExports) {\n\t\tif (!(exportKey in metadata.exports)) {\n\t\t\tthrow new Error(\n\t\t\t\t`${packageVersion} does not publish browser ESM export ${exportKey}; use IIFE/preloaded mode or publish browser ESM artifacts first`,\n\t\t\t);\n\t\t}\n\t}\n}\n\nfunction extractPackageName(packageVersion: string): string {\n\tconst parts = packageVersion.split(\"@\");\n\treturn parts.length >= 3 ? `@${parts[1]}` : parts[0];\n}\n\nfunction cleanViewSubpath(subpath: string): string | null {\n\tconst cleanSubpath = subpath.replace(/^\\/+|\\/+$/g, \"\");\n\treturn cleanSubpath.length > 0 ? cleanSubpath : null;\n}\n\nfunction browserViewName(\n\tviewConfig: ViewConfig,\n\tviewName = \"delivery\",\n): string {\n\tconst subpathView = cleanViewSubpath(viewConfig.subpath);\n\treturn subpathView ?? viewName;\n}\n\nfunction resolveBrowserViewUrl(\n\tpackageVersion: string,\n\tviewConfig: ViewConfig,\n\tcdnProvider: EsmCdnProvider,\n\tviewName = \"delivery\",\n): string {\n\tconst view = browserViewName(viewConfig, viewName);\n\treturn cdnProvider.browserViewUrl(packageVersion, view);\n}\n\nfunction resolveBrowserControllerUrl(\n\tpackageVersion: string,\n\tcdnProvider: EsmCdnProvider,\n): string {\n\treturn cdnProvider.browserControllerUrl(packageVersion);\n}\n\nfunction resolveElementSpecifier(\n\tpackageName: string,\n\tpackageVersion: string,\n\tviewConfig: ViewConfig,\n\tmoduleResolution: \"url\" | \"import-map\",\n\tcdnProvider: EsmCdnProvider,\n\tviewName: string,\n): string {\n\tif (moduleResolution === \"import-map\") {\n\t\treturn viewConfig.subpath\n\t\t\t? `${packageName}${viewConfig.subpath}`\n\t\t\t: packageName;\n\t}\n\treturn resolveBrowserViewUrl(\n\t\tpackageVersion,\n\t\tviewConfig,\n\t\tcdnProvider,\n\t\tviewName,\n\t);\n}\n\nfunction resolveControllerSpecifier(\n\tpackageName: string,\n\tpackageVersion: string,\n\tmoduleResolution: \"url\" | \"import-map\",\n\tcdnProvider: EsmCdnProvider,\n): string {\n\tif (moduleResolution === \"import-map\") {\n\t\treturn `${packageName}/controller`;\n\t}\n\treturn resolveBrowserControllerUrl(packageVersion, cdnProvider);\n}\n\nfunction pickElementClass(module: any, view: string): unknown {\n\tif (!module || typeof module !== \"object\") return undefined;\n\tif (view === \"author\") {\n\t\treturn module.default ?? module.Configure ?? module.Element;\n\t}\n\tif (view === \"print\") {\n\t\treturn module.default ?? module.Print ?? module.Element;\n\t}\n\treturn module.default ?? module.Element;\n}\n\nconst SHARED_BROWSER_DEPENDENCIES = [\"react\", \"react-dom\"] as const;\n\nfunction declaredSharedDependencyVersion(\n\tmetadata: PackageMetadata | null,\n\tdependencyName: (typeof SHARED_BROWSER_DEPENDENCIES)[number],\n\tpackageVersion: string,\n): string | undefined {\n\tconst version = metadata?.pie?.browserSharedDependencies?.[dependencyName];\n\tif (!version) {\n\t\tthrow new Error(\n\t\t\t`${packageVersion} is missing required pie.browserSharedDependencies.${dependencyName}`,\n\t\t);\n\t}\n\tif (!isExactVersion(version)) {\n\t\tthrow new Error(\n\t\t\t`${packageVersion} pie.browserSharedDependencies.${dependencyName} must be an exact version; received \"${version}\"`,\n\t\t);\n\t}\n\treturn version;\n}\n\nfunction packageUsesSharedDependency(\n\tmetadata: PackageMetadata | null,\n\tdependencyName: (typeof SHARED_BROWSER_DEPENDENCIES)[number],\n): boolean {\n\treturn Boolean(\n\t\tmetadata?.pie?.browserSharedDependencies?.[dependencyName] ||\n\t\t\tmetadata?.peerDependencies?.[dependencyName] ||\n\t\t\tmetadata?.dependencies?.[dependencyName] ||\n\t\t\tmetadata?.optionalDependencies?.[dependencyName],\n\t);\n}\n\nfunction addSharedDependencyImports(\n\timports: Record<string, string>,\n\tselectedVersions: Record<string, string>,\n\tlockedVersions: Set<string>,\n\tdependencyName: (typeof SHARED_BROWSER_DEPENDENCIES)[number],\n\tversion: string | undefined,\n\tcdnProvider: EsmCdnProvider,\n\tpackageVersion: string,\n\tonConflict: (attributes: Record<string, unknown>) => void,\n): void {\n\tif (!version) {\n\t\treturn;\n\t}\n\n\tconst currentVersion = selectedVersions[dependencyName];\n\tlet resolvedVersion = version;\n\tif (currentVersion && currentVersion !== version) {\n\t\tresolvedVersion = resolveSharedDependencyVersion(\n\t\t\tdependencyName,\n\t\t\tcurrentVersion,\n\t\t\tversion,\n\t\t\tpackageVersion,\n\t\t\tlockedVersions.has(dependencyName),\n\t\t);\n\t\tonConflict({\n\t\t\tdependencyName,\n\t\t\texistingVersion: currentVersion,\n\t\t\trequestedVersion: version,\n\t\t\tresolvedVersion,\n\t\t\tpackageVersion,\n\t\t});\n\t}\n\tselectedVersions[dependencyName] = resolvedVersion;\n\n\timports[dependencyName] = cdnProvider.sharedDependencyUrl(\n\t\tdependencyName,\n\t\tresolvedVersion,\n\t);\n\tif (dependencyName === \"react\") {\n\t\timports[\"react/jsx-runtime\"] = cdnProvider.sharedDependencyUrl(\n\t\t\t\"react\",\n\t\t\tresolvedVersion,\n\t\t\t\"jsx-runtime\",\n\t\t);\n\t\timports[\"react/jsx-dev-runtime\"] = cdnProvider.sharedDependencyUrl(\n\t\t\t\"react\",\n\t\t\tresolvedVersion,\n\t\t\t\"jsx-dev-runtime\",\n\t\t);\n\t}\n\tif (dependencyName === \"react-dom\") {\n\t\timports[\"react-dom/client\"] = cdnProvider.sharedDependencyUrl(\n\t\t\t\"react-dom\",\n\t\t\tresolvedVersion,\n\t\t\t\"client\",\n\t\t);\n\t}\n}\n\nfunction isExactVersion(version: string): boolean {\n\treturn /^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?$/.test(version);\n}\n\nfunction parseVersion(version: string): {\n\tmajor: number;\n\tminor: number;\n\tpatch: number;\n} {\n\tconst match = version.match(/^(\\d+)\\.(\\d+)\\.(\\d+)/);\n\tif (!match) {\n\t\tthrow new Error(`Invalid shared browser dependency version \"${version}\"`);\n\t}\n\treturn {\n\t\tmajor: Number(match[1]),\n\t\tminor: Number(match[2]),\n\t\tpatch: Number(match[3]),\n\t};\n}\n\nfunction compareVersions(a: string, b: string): number {\n\tconst parsedA = parseVersion(a);\n\tconst parsedB = parseVersion(b);\n\tif (parsedA.major !== parsedB.major) return parsedA.major - parsedB.major;\n\tif (parsedA.minor !== parsedB.minor) return parsedA.minor - parsedB.minor;\n\treturn parsedA.patch - parsedB.patch;\n}\n\nfunction resolveSharedDependencyVersion(\n\tdependencyName: string,\n\tcurrentVersion: string,\n\trequestedVersion: string,\n\tpackageVersion: string,\n\tisLocked: boolean,\n): string {\n\tconst current = parseVersion(currentVersion);\n\tconst requested = parseVersion(requestedVersion);\n\tif (current.major !== requested.major) {\n\t\tthrow new Error(\n\t\t\t`Conflicting shared browser dependency ${dependencyName}: ${currentVersion} vs ${requestedVersion} from ${packageVersion}; different major versions cannot share one browser singleton`,\n\t\t);\n\t}\n\tif (isLocked && compareVersions(requestedVersion, currentVersion) > 0) {\n\t\tthrow new Error(\n\t\t\t`Conflicting shared browser dependency ${dependencyName}: ${currentVersion} is already selected, but ${packageVersion} requires higher version ${requestedVersion}; the browser singleton cannot be upgraded after import-map injection`,\n\t\t);\n\t}\n\treturn compareVersions(currentVersion, requestedVersion) >= 0\n\t\t? currentVersion\n\t\t: requestedVersion;\n}\n\ntype BrowserImportMapBuildResult = {\n\tjson: string | null;\n\tsharedDependencyVersions: Record<string, string>;\n};\n\nasync function buildImportMapJson(\n\telements: ElementMap,\n\tviewConfig: ViewConfig,\n\tcdnProvider: EsmCdnProvider,\n\tloadControllers: boolean,\n\tincludeElementImports: boolean,\n\tpackageMetadataLoader: EsmPackageMetadataLoader,\n\tcurrentSharedDependencyVersions: Record<string, string>,\n\tonConflict: (attributes: Record<string, unknown>) => void,\n): Promise<BrowserImportMapBuildResult> {\n\tconst imports: Record<string, string> = {};\n\tconst selectedVersions: Record<string, string> = {\n\t\t...currentSharedDependencyVersions,\n\t};\n\tconst lockedVersions = new Set(Object.keys(currentSharedDependencyVersions));\n\tfor (const [, pkg] of Object.entries(elements)) {\n\t\tconst packageName = extractPackageName(pkg);\n\t\tif (includeElementImports) {\n\t\t\timports[packageName] = resolveBrowserViewUrl(\n\t\t\t\tpkg,\n\t\t\t\tBUILT_IN_VIEWS.delivery,\n\t\t\t\tcdnProvider,\n\t\t\t\t\"delivery\",\n\t\t\t);\n\t\t\tif (viewConfig.subpath) {\n\t\t\t\timports[`${packageName}${viewConfig.subpath}`] = resolveBrowserViewUrl(\n\t\t\t\t\tpkg,\n\t\t\t\t\tviewConfig,\n\t\t\t\t\tcdnProvider,\n\t\t\t\t\tcleanViewSubpath(viewConfig.subpath) ?? \"delivery\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (loadControllers) {\n\t\t\t\timports[`${packageName}/controller`] = resolveBrowserControllerUrl(\n\t\t\t\t\tpkg,\n\t\t\t\t\tcdnProvider,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (viewConfig.fallback) {\n\t\t\t\tconst fallbackConfig = BUILT_IN_VIEWS[viewConfig.fallback];\n\t\t\t\tif (fallbackConfig) {\n\t\t\t\t\tconst fallbackSpecifier = fallbackConfig.subpath\n\t\t\t\t\t\t? `${packageName}${fallbackConfig.subpath}`\n\t\t\t\t\t\t: packageName;\n\t\t\t\t\timports[fallbackSpecifier] = resolveBrowserViewUrl(\n\t\t\t\t\t\tpkg,\n\t\t\t\t\t\tfallbackConfig,\n\t\t\t\t\t\tcdnProvider,\n\t\t\t\t\t\tviewConfig.fallback,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst metadata = await packageMetadataLoader(\n\t\t\tpkg,\n\t\t\tcdnProvider.packageJsonUrl(pkg),\n\t\t);\n\t\tassertBrowserEsmExports(\n\t\t\tmetadata,\n\t\t\tpkg,\n\t\t\tviewConfig,\n\t\t\tloadControllers,\n\t\t\tcleanViewSubpath(viewConfig.subpath) ?? \"delivery\",\n\t\t);\n\t\tfor (const dependencyName of SHARED_BROWSER_DEPENDENCIES) {\n\t\t\tif (!packageUsesSharedDependency(metadata, dependencyName)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\taddSharedDependencyImports(\n\t\t\t\timports,\n\t\t\t\tselectedVersions,\n\t\t\t\tlockedVersions,\n\t\t\t\tdependencyName,\n\t\t\t\tdeclaredSharedDependencyVersion(metadata, dependencyName, pkg),\n\t\t\t\tcdnProvider,\n\t\t\t\tpkg,\n\t\t\t\tonConflict,\n\t\t\t);\n\t\t}\n\t}\n\tif (Object.keys(imports).length === 0) {\n\t\treturn { json: null, sharedDependencyVersions: selectedVersions };\n\t}\n\treturn {\n\t\tjson: JSON.stringify({ imports }, null, 2),\n\t\tsharedDependencyVersions: selectedVersions,\n\t};\n}\n\nfunction injectImportMap(json: string, doc: Document): void {\n\tconst script = doc.createElement(\"script\") as HTMLScriptElement;\n\tscript.type = \"importmap\";\n\tscript.textContent = json;\n\tdoc.head.appendChild(script);\n}\n\nfunction assertImportMapSupported(): void {\n\tconst htmlScriptElement = (\n\t\ttypeof HTMLScriptElement !== \"undefined\" ? HTMLScriptElement : undefined\n\t) as\n\t\t| (typeof HTMLScriptElement & {\n\t\t\t\tsupports?: (type: string) => boolean;\n\t\t })\n\t\t| undefined;\n\tconst supports =\n\t\ttypeof htmlScriptElement?.supports === \"function\" &&\n\t\thtmlScriptElement.supports(\"importmap\");\n\tif (!supports) {\n\t\tthrow new Error(\n\t\t\t'This browser does not support import maps. Use moduleResolution=\"url\" or switch to iife/preloaded strategy.',\n\t\t);\n\t}\n}\n"]}
@@ -35,6 +35,6 @@ export { aggregateElements } from "./ElementLoader.js";
35
35
  export type { BackendContext, BackendOption, ElementLoaderBackend, ElementTag, EnsureRegisteredOptions, EsmBackendConfig, IifeBackendConfig, RegistrationFailureReason, } from "./element-loader.js";
36
36
  export { AdapterFailure, ElementAssertionError, ElementLoaderError, assertRegistered, ensureRegistered, } from "./element-loader.js";
37
37
  export type { BuiltInEsmCdnProviderName, EsmBackend, EsmCdnProvider, EsmCdnProviderName, EsmCdnProviderOption, ViewConfig, } from "./esm-adapter.js";
38
- export { BUILT_IN_VIEWS, createEsmBackend } from "./esm-adapter.js";
38
+ export { BUILT_IN_VIEWS, createEsmBackend, mapEsmViewElements, } from "./esm-adapter.js";
39
39
  export type { IifeBackend, IifeBundleRetryStatus, } from "./iife-adapter.js";
40
40
  export { createIifeBackend, DEFAULT_BUNDLE_HOST } from "./iife-adapter.js";
@@ -32,6 +32,6 @@
32
32
  */
33
33
  export { aggregateElements } from "./ElementLoader.js";
34
34
  export { AdapterFailure, ElementAssertionError, ElementLoaderError, assertRegistered, ensureRegistered, } from "./element-loader.js";
35
- export { BUILT_IN_VIEWS, createEsmBackend } from "./esm-adapter.js";
35
+ export { BUILT_IN_VIEWS, createEsmBackend, mapEsmViewElements, } from "./esm-adapter.js";
36
36
  export { createIifeBackend, DEFAULT_BUNDLE_HOST } from "./iife-adapter.js";
37
37
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/loaders/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAcvD,OAAO,EACN,cAAc,EACd,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,GAChB,MAAM,qBAAqB,CAAC;AAS7B,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAKpE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC","sourcesContent":["/**\n * PIE Element Loaders\n *\n * Deep `ElementLoader` primitive — the public entry point for registering\n * PIE custom elements at runtime. Exposes `ensureRegistered` (async) and\n * `assertRegistered` (sync) with a truthful promise contract: the returned\n * promise resolves iff every requested tag is actually in `customElements`.\n *\n * Backends (IIFE, ESM) are internal adapter modules; they implement the\n * `ElementLoaderBackend` interface and are wired via `{ backend: ... }`\n * options.\n *\n * @example\n * ```typescript\n * import {\n * ensureRegistered,\n * BundleType,\n * } from \"@pie-players/pie-players-shared/loaders\";\n *\n * await ensureRegistered(\n * { \"pie-multiple-choice\": \"@pie-element/multiple-choice@11.0.1\" },\n * {\n * backend: {\n * kind: \"iife\",\n * bundleHost: \"https://proxy.pie-api.com/bundles/\",\n * bundleType: BundleType.clientPlayer,\n * needsControllers: true,\n * },\n * },\n * );\n * ```\n */\n\nexport type { ElementMap } from \"./ElementLoader.js\";\nexport { aggregateElements } from \"./ElementLoader.js\";\n\n// ElementLoader primitive — truthful-promise loader. The public entry point\n// for ensureRegistered / assertRegistered.\nexport type {\n\tBackendContext,\n\tBackendOption,\n\tElementLoaderBackend,\n\tElementTag,\n\tEnsureRegisteredOptions,\n\tEsmBackendConfig,\n\tIifeBackendConfig,\n\tRegistrationFailureReason,\n} from \"./element-loader.js\";\nexport {\n\tAdapterFailure,\n\tElementAssertionError,\n\tElementLoaderError,\n\tassertRegistered,\n\tensureRegistered,\n} from \"./element-loader.js\";\nexport type {\n\tBuiltInEsmCdnProviderName,\n\tEsmBackend,\n\tEsmCdnProvider,\n\tEsmCdnProviderName,\n\tEsmCdnProviderOption,\n\tViewConfig,\n} from \"./esm-adapter.js\";\nexport { BUILT_IN_VIEWS, createEsmBackend } from \"./esm-adapter.js\";\nexport type {\n\tIifeBackend,\n\tIifeBundleRetryStatus,\n} from \"./iife-adapter.js\";\nexport { createIifeBackend, DEFAULT_BUNDLE_HOST } from \"./iife-adapter.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/loaders/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAcvD,OAAO,EACN,cAAc,EACd,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,GAChB,MAAM,qBAAqB,CAAC;AAS7B,OAAO,EACN,cAAc,EACd,gBAAgB,EAChB,kBAAkB,GAClB,MAAM,kBAAkB,CAAC;AAK1B,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC","sourcesContent":["/**\n * PIE Element Loaders\n *\n * Deep `ElementLoader` primitive — the public entry point for registering\n * PIE custom elements at runtime. Exposes `ensureRegistered` (async) and\n * `assertRegistered` (sync) with a truthful promise contract: the returned\n * promise resolves iff every requested tag is actually in `customElements`.\n *\n * Backends (IIFE, ESM) are internal adapter modules; they implement the\n * `ElementLoaderBackend` interface and are wired via `{ backend: ... }`\n * options.\n *\n * @example\n * ```typescript\n * import {\n * ensureRegistered,\n * BundleType,\n * } from \"@pie-players/pie-players-shared/loaders\";\n *\n * await ensureRegistered(\n * { \"pie-multiple-choice\": \"@pie-element/multiple-choice@11.0.1\" },\n * {\n * backend: {\n * kind: \"iife\",\n * bundleHost: \"https://proxy.pie-api.com/bundles/\",\n * bundleType: BundleType.clientPlayer,\n * needsControllers: true,\n * },\n * },\n * );\n * ```\n */\n\nexport type { ElementMap } from \"./ElementLoader.js\";\nexport { aggregateElements } from \"./ElementLoader.js\";\n\n// ElementLoader primitive — truthful-promise loader. The public entry point\n// for ensureRegistered / assertRegistered.\nexport type {\n\tBackendContext,\n\tBackendOption,\n\tElementLoaderBackend,\n\tElementTag,\n\tEnsureRegisteredOptions,\n\tEsmBackendConfig,\n\tIifeBackendConfig,\n\tRegistrationFailureReason,\n} from \"./element-loader.js\";\nexport {\n\tAdapterFailure,\n\tElementAssertionError,\n\tElementLoaderError,\n\tassertRegistered,\n\tensureRegistered,\n} from \"./element-loader.js\";\nexport type {\n\tBuiltInEsmCdnProviderName,\n\tEsmBackend,\n\tEsmCdnProvider,\n\tEsmCdnProviderName,\n\tEsmCdnProviderOption,\n\tViewConfig,\n} from \"./esm-adapter.js\";\nexport {\n\tBUILT_IN_VIEWS,\n\tcreateEsmBackend,\n\tmapEsmViewElements,\n} from \"./esm-adapter.js\";\nexport type {\n\tIifeBackend,\n\tIifeBundleRetryStatus,\n} from \"./iife-adapter.js\";\nexport { createIifeBackend, DEFAULT_BUNDLE_HOST } from \"./iife-adapter.js\";\n"]}
@@ -68,6 +68,20 @@ export function hasResponseField(value) {
68
68
  }
69
69
  return false;
70
70
  }
71
+ function isPlainObject(value) {
72
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
73
+ }
74
+ function mergeSessionEntry(existing, incoming) {
75
+ const merged = { ...existing };
76
+ for (const [key, value] of Object.entries(incoming)) {
77
+ const previous = merged[key];
78
+ merged[key] =
79
+ isPlainObject(previous) && isPlainObject(value)
80
+ ? mergeSessionEntry(previous, value)
81
+ : value;
82
+ }
83
+ return merged;
84
+ }
71
85
  export function mergeElementIntoSession(itemId, previousItemSession, entryId, entry) {
72
86
  const previous = normalizeItemSessionContainer(previousItemSession, itemId);
73
87
  const nextData = [...previous.data];
@@ -80,7 +94,7 @@ export function mergeElementIntoSession(itemId, previousItemSession, entryId, en
80
94
  const existing = nextData[existingIndex];
81
95
  nextData[existingIndex] =
82
96
  existing && typeof existing === "object"
83
- ? { ...existing, ...entry }
97
+ ? mergeSessionEntry(existing, entry)
84
98
  : entry;
85
99
  }
86
100
  else {
@@ -1 +1 @@
1
- {"version":3,"file":"item-session-contract.js","sourceRoot":"","sources":["../../src/pie/item-session-contract.ts"],"names":[],"mappings":"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","sourcesContent":["export type ItemSessionContainer = {\n\tid: string;\n\tdata: unknown[];\n};\n\nexport type ItemSessionUpdateIntent =\n\t| \"replace-item-session\"\n\t| \"merge-element-session\"\n\t| \"metadata-only\";\n\nexport type NormalizedItemSessionChange = {\n\titemId: string;\n\tsession: ItemSessionContainer | null;\n\tintent: ItemSessionUpdateIntent;\n\tcomponent?: string;\n\tcomplete?: boolean;\n};\n\nconst DEFAULT_SESSION_ID = \"\";\n\nfunction areSessionContainersEqual(\n\tleft: ItemSessionContainer | null,\n\tright: ItemSessionContainer | null,\n): boolean {\n\tif (!left && !right) return true;\n\tif (!left || !right) return false;\n\tif ((left.id || \"\") !== (right.id || \"\")) return false;\n\ttry {\n\t\treturn JSON.stringify(left.data || []) === JSON.stringify(right.data || []);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nexport function normalizeItemSessionContainer(\n\tinput: unknown,\n\tfallbackSessionId: string = DEFAULT_SESSION_ID,\n): ItemSessionContainer {\n\tif (input && typeof input === \"object\") {\n\t\tconst candidate = input as Record<string, unknown>;\n\t\tif (Array.isArray(candidate.data)) {\n\t\t\treturn {\n\t\t\t\tid: typeof candidate.id === \"string\" ? candidate.id : fallbackSessionId,\n\t\t\t\tdata: candidate.data,\n\t\t\t};\n\t\t}\n\t\tif (Array.isArray(input)) {\n\t\t\treturn { id: fallbackSessionId, data: input };\n\t\t}\n\t\treturn { id: fallbackSessionId, data: [input] };\n\t}\n\tif (Array.isArray(input)) {\n\t\treturn { id: fallbackSessionId, data: input };\n\t}\n\treturn { id: fallbackSessionId, data: [] };\n}\n\nexport function hasResponseValue(value: unknown): boolean {\n\tif (value == null) return false;\n\tif (Array.isArray(value))\n\t\treturn value.some((entry) => hasResponseValue(entry));\n\tif (typeof value !== \"object\") return false;\n\tfor (const [key, nested] of Object.entries(\n\t\tvalue as Record<string, unknown>,\n\t)) {\n\t\tif (\n\t\t\tkey === \"value\" &&\n\t\t\tnested !== undefined &&\n\t\t\tnested !== null &&\n\t\t\t!(typeof nested === \"string\" && nested.trim() === \"\") &&\n\t\t\t!(Array.isArray(nested) && nested.length === 0)\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t\tif (hasResponseValue(nested)) return true;\n\t}\n\treturn false;\n}\n\nexport function hasResponseField(value: unknown): boolean {\n\tif (value == null) return false;\n\tif (Array.isArray(value))\n\t\treturn value.some((entry) => hasResponseField(entry));\n\tif (typeof value !== \"object\") return false;\n\tfor (const [key, nested] of Object.entries(\n\t\tvalue as Record<string, unknown>,\n\t)) {\n\t\tif (key === \"value\") {\n\t\t\treturn true;\n\t\t}\n\t\tif (hasResponseField(nested)) return true;\n\t}\n\treturn false;\n}\n\nexport function mergeElementIntoSession(\n\titemId: string,\n\tpreviousItemSession: unknown,\n\tentryId: string,\n\tentry: Record<string, unknown>,\n): ItemSessionContainer {\n\tconst previous = normalizeItemSessionContainer(previousItemSession, itemId);\n\tconst nextData = [...previous.data];\n\tconst existingIndex = nextData.findIndex((candidate) => {\n\t\tif (!candidate || typeof candidate !== \"object\") return false;\n\t\treturn (candidate as Record<string, unknown>).id === entryId;\n\t});\n\tif (existingIndex >= 0) {\n\t\tconst existing = nextData[existingIndex];\n\t\tnextData[existingIndex] =\n\t\t\texisting && typeof existing === \"object\"\n\t\t\t\t? { ...(existing as Record<string, unknown>), ...entry }\n\t\t\t\t: entry;\n\t} else {\n\t\tnextData.push(entry);\n\t}\n\treturn {\n\t\tid: previous.id || itemId,\n\t\tdata: nextData,\n\t};\n}\n\nexport function normalizeItemSessionChange(args: {\n\titemId: string;\n\tsessionDetail: unknown;\n\tpreviousItemSession?: unknown;\n}): NormalizedItemSessionChange {\n\tconst sessionDetail = (args.sessionDetail || {}) as Record<string, unknown>;\n\tconst actualSession =\n\t\tsessionDetail &&\n\t\ttypeof sessionDetail === \"object\" &&\n\t\t\"session\" in sessionDetail\n\t\t\t? sessionDetail.session\n\t\t\t: args.sessionDetail;\n\n\tconst safeItemId =\n\t\ttypeof args.itemId === \"string\" && args.itemId\n\t\t\t? args.itemId\n\t\t\t: typeof (actualSession as Record<string, unknown> | null)?.id ===\n\t\t\t\t\t\"string\"\n\t\t\t\t? String((actualSession as Record<string, unknown>).id)\n\t\t\t\t: \"\";\n\n\tif (!actualSession || typeof actualSession !== \"object\") {\n\t\treturn {\n\t\t\titemId: safeItemId,\n\t\t\tsession: null,\n\t\t\tintent: \"metadata-only\",\n\t\t\tcomponent:\n\t\t\t\ttypeof sessionDetail.component === \"string\"\n\t\t\t\t\t? sessionDetail.component\n\t\t\t\t\t: undefined,\n\t\t\tcomplete:\n\t\t\t\ttypeof sessionDetail.complete === \"boolean\"\n\t\t\t\t\t? sessionDetail.complete\n\t\t\t\t\t: undefined,\n\t\t};\n\t}\n\n\tconst candidate = actualSession as Record<string, unknown>;\n\tif (Array.isArray(candidate.data)) {\n\t\tconst normalizedCandidate = normalizeItemSessionContainer(\n\t\t\tcandidate,\n\t\t\tsafeItemId,\n\t\t);\n\t\tconst previousNormalized =\n\t\t\targs.previousItemSession !== undefined\n\t\t\t\t? normalizeItemSessionContainer(args.previousItemSession, safeItemId)\n\t\t\t\t: null;\n\t\tconst sessionDetailKeys = Object.keys(sessionDetail);\n\t\tconst metadataWithSessionOnly =\n\t\t\tsessionDetailKeys.length > 0 &&\n\t\t\tsessionDetailKeys.every(\n\t\t\t\t(key) =>\n\t\t\t\t\tkey === \"session\" ||\n\t\t\t\t\tkey === \"complete\" ||\n\t\t\t\t\tkey === \"component\" ||\n\t\t\t\t\tkey === \"timestamp\" ||\n\t\t\t\t\tkey === \"sourceRuntimeId\",\n\t\t\t);\n\t\tif (\n\t\t\tmetadataWithSessionOnly &&\n\t\t\tpreviousNormalized &&\n\t\t\tareSessionContainersEqual(normalizedCandidate, previousNormalized)\n\t\t) {\n\t\t\treturn {\n\t\t\t\titemId: safeItemId,\n\t\t\t\tsession: null,\n\t\t\t\tintent: \"metadata-only\",\n\t\t\t\tcomponent:\n\t\t\t\t\ttypeof sessionDetail.component === \"string\"\n\t\t\t\t\t\t? sessionDetail.component\n\t\t\t\t\t\t: undefined,\n\t\t\t\tcomplete:\n\t\t\t\t\ttypeof sessionDetail.complete === \"boolean\"\n\t\t\t\t\t\t? sessionDetail.complete\n\t\t\t\t\t\t: undefined,\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\titemId: safeItemId,\n\t\t\tsession: normalizedCandidate,\n\t\t\tintent: \"replace-item-session\",\n\t\t\tcomponent:\n\t\t\t\ttypeof sessionDetail.component === \"string\"\n\t\t\t\t\t? sessionDetail.component\n\t\t\t\t\t: undefined,\n\t\t\tcomplete:\n\t\t\t\ttypeof sessionDetail.complete === \"boolean\"\n\t\t\t\t\t? sessionDetail.complete\n\t\t\t\t\t: undefined,\n\t\t};\n\t}\n\n\tconst candidateKeys = Object.keys(candidate);\n\tconst isMetadataOnlyPayload =\n\t\tcandidateKeys.length > 0 &&\n\t\tcandidateKeys.every(\n\t\t\t(key) =>\n\t\t\t\tkey === \"complete\" ||\n\t\t\t\tkey === \"component\" ||\n\t\t\t\tkey === \"timestamp\" ||\n\t\t\t\tkey === \"sourceRuntimeId\",\n\t\t);\n\tif (isMetadataOnlyPayload) {\n\t\treturn {\n\t\t\titemId: safeItemId,\n\t\t\tsession: null,\n\t\t\tintent: \"metadata-only\",\n\t\t\tcomponent:\n\t\t\t\ttypeof sessionDetail.component === \"string\"\n\t\t\t\t\t? sessionDetail.component\n\t\t\t\t\t: undefined,\n\t\t\tcomplete:\n\t\t\t\ttypeof sessionDetail.complete === \"boolean\"\n\t\t\t\t\t? sessionDetail.complete\n\t\t\t\t\t: undefined,\n\t\t};\n\t}\n\n\tconst component =\n\t\ttypeof sessionDetail.component === \"string\"\n\t\t\t? sessionDetail.component\n\t\t\t: typeof candidate.component === \"string\"\n\t\t\t\t? candidate.component\n\t\t\t\t: \"response\";\n\tconst elementEntryId =\n\t\ttypeof candidate.id === \"string\" && candidate.id ? candidate.id : component;\n\tconst merged = mergeElementIntoSession(\n\t\tsafeItemId,\n\t\targs.previousItemSession,\n\t\telementEntryId,\n\t\t{ id: elementEntryId, ...candidate },\n\t);\n\treturn {\n\t\titemId: safeItemId,\n\t\tsession: merged,\n\t\tintent: \"merge-element-session\",\n\t\tcomponent,\n\t\tcomplete:\n\t\t\ttypeof sessionDetail.complete === \"boolean\"\n\t\t\t\t? sessionDetail.complete\n\t\t\t\t: undefined,\n\t};\n}\n"]}
1
+ {"version":3,"file":"item-session-contract.js","sourceRoot":"","sources":["../../src/pie/item-session-contract.ts"],"names":[],"mappings":"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","sourcesContent":["export type ItemSessionContainer = {\n\tid: string;\n\tdata: unknown[];\n};\n\nexport type ItemSessionUpdateIntent =\n\t| \"replace-item-session\"\n\t| \"merge-element-session\"\n\t| \"metadata-only\";\n\nexport type NormalizedItemSessionChange = {\n\titemId: string;\n\tsession: ItemSessionContainer | null;\n\tintent: ItemSessionUpdateIntent;\n\tcomponent?: string;\n\tcomplete?: boolean;\n};\n\nconst DEFAULT_SESSION_ID = \"\";\n\nfunction areSessionContainersEqual(\n\tleft: ItemSessionContainer | null,\n\tright: ItemSessionContainer | null,\n): boolean {\n\tif (!left && !right) return true;\n\tif (!left || !right) return false;\n\tif ((left.id || \"\") !== (right.id || \"\")) return false;\n\ttry {\n\t\treturn JSON.stringify(left.data || []) === JSON.stringify(right.data || []);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nexport function normalizeItemSessionContainer(\n\tinput: unknown,\n\tfallbackSessionId: string = DEFAULT_SESSION_ID,\n): ItemSessionContainer {\n\tif (input && typeof input === \"object\") {\n\t\tconst candidate = input as Record<string, unknown>;\n\t\tif (Array.isArray(candidate.data)) {\n\t\t\treturn {\n\t\t\t\tid: typeof candidate.id === \"string\" ? candidate.id : fallbackSessionId,\n\t\t\t\tdata: candidate.data,\n\t\t\t};\n\t\t}\n\t\tif (Array.isArray(input)) {\n\t\t\treturn { id: fallbackSessionId, data: input };\n\t\t}\n\t\treturn { id: fallbackSessionId, data: [input] };\n\t}\n\tif (Array.isArray(input)) {\n\t\treturn { id: fallbackSessionId, data: input };\n\t}\n\treturn { id: fallbackSessionId, data: [] };\n}\n\nexport function hasResponseValue(value: unknown): boolean {\n\tif (value == null) return false;\n\tif (Array.isArray(value))\n\t\treturn value.some((entry) => hasResponseValue(entry));\n\tif (typeof value !== \"object\") return false;\n\tfor (const [key, nested] of Object.entries(\n\t\tvalue as Record<string, unknown>,\n\t)) {\n\t\tif (\n\t\t\tkey === \"value\" &&\n\t\t\tnested !== undefined &&\n\t\t\tnested !== null &&\n\t\t\t!(typeof nested === \"string\" && nested.trim() === \"\") &&\n\t\t\t!(Array.isArray(nested) && nested.length === 0)\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t\tif (hasResponseValue(nested)) return true;\n\t}\n\treturn false;\n}\n\nexport function hasResponseField(value: unknown): boolean {\n\tif (value == null) return false;\n\tif (Array.isArray(value))\n\t\treturn value.some((entry) => hasResponseField(entry));\n\tif (typeof value !== \"object\") return false;\n\tfor (const [key, nested] of Object.entries(\n\t\tvalue as Record<string, unknown>,\n\t)) {\n\t\tif (key === \"value\") {\n\t\t\treturn true;\n\t\t}\n\t\tif (hasResponseField(nested)) return true;\n\t}\n\treturn false;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n\treturn Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction mergeSessionEntry(\n\texisting: Record<string, unknown>,\n\tincoming: Record<string, unknown>,\n): Record<string, unknown> {\n\tconst merged = { ...existing };\n\tfor (const [key, value] of Object.entries(incoming)) {\n\t\tconst previous = merged[key];\n\t\tmerged[key] =\n\t\t\tisPlainObject(previous) && isPlainObject(value)\n\t\t\t\t? mergeSessionEntry(previous, value)\n\t\t\t\t: value;\n\t}\n\treturn merged;\n}\n\nexport function mergeElementIntoSession(\n\titemId: string,\n\tpreviousItemSession: unknown,\n\tentryId: string,\n\tentry: Record<string, unknown>,\n): ItemSessionContainer {\n\tconst previous = normalizeItemSessionContainer(previousItemSession, itemId);\n\tconst nextData = [...previous.data];\n\tconst existingIndex = nextData.findIndex((candidate) => {\n\t\tif (!candidate || typeof candidate !== \"object\") return false;\n\t\treturn (candidate as Record<string, unknown>).id === entryId;\n\t});\n\tif (existingIndex >= 0) {\n\t\tconst existing = nextData[existingIndex];\n\t\tnextData[existingIndex] =\n\t\t\texisting && typeof existing === \"object\"\n\t\t\t\t? mergeSessionEntry(existing as Record<string, unknown>, entry)\n\t\t\t\t: entry;\n\t} else {\n\t\tnextData.push(entry);\n\t}\n\treturn {\n\t\tid: previous.id || itemId,\n\t\tdata: nextData,\n\t};\n}\n\nexport function normalizeItemSessionChange(args: {\n\titemId: string;\n\tsessionDetail: unknown;\n\tpreviousItemSession?: unknown;\n}): NormalizedItemSessionChange {\n\tconst sessionDetail = (args.sessionDetail || {}) as Record<string, unknown>;\n\tconst actualSession =\n\t\tsessionDetail &&\n\t\ttypeof sessionDetail === \"object\" &&\n\t\t\"session\" in sessionDetail\n\t\t\t? sessionDetail.session\n\t\t\t: args.sessionDetail;\n\n\tconst safeItemId =\n\t\ttypeof args.itemId === \"string\" && args.itemId\n\t\t\t? args.itemId\n\t\t\t: typeof (actualSession as Record<string, unknown> | null)?.id ===\n\t\t\t\t\t\"string\"\n\t\t\t\t? String((actualSession as Record<string, unknown>).id)\n\t\t\t\t: \"\";\n\n\tif (!actualSession || typeof actualSession !== \"object\") {\n\t\treturn {\n\t\t\titemId: safeItemId,\n\t\t\tsession: null,\n\t\t\tintent: \"metadata-only\",\n\t\t\tcomponent:\n\t\t\t\ttypeof sessionDetail.component === \"string\"\n\t\t\t\t\t? sessionDetail.component\n\t\t\t\t\t: undefined,\n\t\t\tcomplete:\n\t\t\t\ttypeof sessionDetail.complete === \"boolean\"\n\t\t\t\t\t? sessionDetail.complete\n\t\t\t\t\t: undefined,\n\t\t};\n\t}\n\n\tconst candidate = actualSession as Record<string, unknown>;\n\tif (Array.isArray(candidate.data)) {\n\t\tconst normalizedCandidate = normalizeItemSessionContainer(\n\t\t\tcandidate,\n\t\t\tsafeItemId,\n\t\t);\n\t\tconst previousNormalized =\n\t\t\targs.previousItemSession !== undefined\n\t\t\t\t? normalizeItemSessionContainer(args.previousItemSession, safeItemId)\n\t\t\t\t: null;\n\t\tconst sessionDetailKeys = Object.keys(sessionDetail);\n\t\tconst metadataWithSessionOnly =\n\t\t\tsessionDetailKeys.length > 0 &&\n\t\t\tsessionDetailKeys.every(\n\t\t\t\t(key) =>\n\t\t\t\t\tkey === \"session\" ||\n\t\t\t\t\tkey === \"complete\" ||\n\t\t\t\t\tkey === \"component\" ||\n\t\t\t\t\tkey === \"timestamp\" ||\n\t\t\t\t\tkey === \"sourceRuntimeId\",\n\t\t\t);\n\t\tif (\n\t\t\tmetadataWithSessionOnly &&\n\t\t\tpreviousNormalized &&\n\t\t\tareSessionContainersEqual(normalizedCandidate, previousNormalized)\n\t\t) {\n\t\t\treturn {\n\t\t\t\titemId: safeItemId,\n\t\t\t\tsession: null,\n\t\t\t\tintent: \"metadata-only\",\n\t\t\t\tcomponent:\n\t\t\t\t\ttypeof sessionDetail.component === \"string\"\n\t\t\t\t\t\t? sessionDetail.component\n\t\t\t\t\t\t: undefined,\n\t\t\t\tcomplete:\n\t\t\t\t\ttypeof sessionDetail.complete === \"boolean\"\n\t\t\t\t\t\t? sessionDetail.complete\n\t\t\t\t\t\t: undefined,\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\titemId: safeItemId,\n\t\t\tsession: normalizedCandidate,\n\t\t\tintent: \"replace-item-session\",\n\t\t\tcomponent:\n\t\t\t\ttypeof sessionDetail.component === \"string\"\n\t\t\t\t\t? sessionDetail.component\n\t\t\t\t\t: undefined,\n\t\t\tcomplete:\n\t\t\t\ttypeof sessionDetail.complete === \"boolean\"\n\t\t\t\t\t? sessionDetail.complete\n\t\t\t\t\t: undefined,\n\t\t};\n\t}\n\n\tconst candidateKeys = Object.keys(candidate);\n\tconst isMetadataOnlyPayload =\n\t\tcandidateKeys.length > 0 &&\n\t\tcandidateKeys.every(\n\t\t\t(key) =>\n\t\t\t\tkey === \"complete\" ||\n\t\t\t\tkey === \"component\" ||\n\t\t\t\tkey === \"timestamp\" ||\n\t\t\t\tkey === \"sourceRuntimeId\",\n\t\t);\n\tif (isMetadataOnlyPayload) {\n\t\treturn {\n\t\t\titemId: safeItemId,\n\t\t\tsession: null,\n\t\t\tintent: \"metadata-only\",\n\t\t\tcomponent:\n\t\t\t\ttypeof sessionDetail.component === \"string\"\n\t\t\t\t\t? sessionDetail.component\n\t\t\t\t\t: undefined,\n\t\t\tcomplete:\n\t\t\t\ttypeof sessionDetail.complete === \"boolean\"\n\t\t\t\t\t? sessionDetail.complete\n\t\t\t\t\t: undefined,\n\t\t};\n\t}\n\n\tconst component =\n\t\ttypeof sessionDetail.component === \"string\"\n\t\t\t? sessionDetail.component\n\t\t\t: typeof candidate.component === \"string\"\n\t\t\t\t? candidate.component\n\t\t\t\t: \"response\";\n\tconst elementEntryId =\n\t\ttypeof candidate.id === \"string\" && candidate.id ? candidate.id : component;\n\tconst merged = mergeElementIntoSession(\n\t\tsafeItemId,\n\t\targs.previousItemSession,\n\t\telementEntryId,\n\t\t{ id: elementEntryId, ...candidate },\n\t);\n\treturn {\n\t\titemId: safeItemId,\n\t\tsession: merged,\n\t\tintent: \"merge-element-session\",\n\t\tcomponent,\n\t\tcomplete:\n\t\t\ttypeof sessionDetail.complete === \"boolean\"\n\t\t\t\t? sessionDetail.complete\n\t\t\t\t: undefined,\n\t};\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  export { buildAuthoringAllowList, createDefaultItemMarkupSanitizer, resetPurifierForTesting, sanitizeItemMarkup, type ItemMarkupSanitizer, type SanitizeItemMarkupOptions, } from "./sanitize-item-markup.js";
2
2
  export { parseAllowedStyleOrigins, validateExternalStyleUrl, type StyleUrlValidationError, type StyleUrlValidationOk, type StyleUrlValidationOptions, type StyleUrlValidationResult, } from "./validate-style-url.js";
3
3
  export { resetSvgSanitizerForTesting, sanitizeSvgIcon, } from "./sanitize-svg-icon.js";
4
- export { wrapOverwideImages } from "./wrap-overwide-images.js";
4
+ export { wrapOverwideImages, wrapOverwideImagesInElement, } from "./wrap-overwide-images.js";
5
5
  export { wrapModelRichContent } from "./wrap-model-rich-content.js";
6
- export { wrapOverwideTables } from "./wrap-overwide-tables.js";
6
+ export { wrapOverwideTables, wrapOverwideTablesInElement, } from "./wrap-overwide-tables.js";
@@ -1,7 +1,7 @@
1
1
  export { buildAuthoringAllowList, createDefaultItemMarkupSanitizer, resetPurifierForTesting, sanitizeItemMarkup, } from "./sanitize-item-markup.js";
2
2
  export { parseAllowedStyleOrigins, validateExternalStyleUrl, } from "./validate-style-url.js";
3
3
  export { resetSvgSanitizerForTesting, sanitizeSvgIcon, } from "./sanitize-svg-icon.js";
4
- export { wrapOverwideImages } from "./wrap-overwide-images.js";
4
+ export { wrapOverwideImages, wrapOverwideImagesInElement, } from "./wrap-overwide-images.js";
5
5
  export { wrapModelRichContent } from "./wrap-model-rich-content.js";
6
- export { wrapOverwideTables } from "./wrap-overwide-tables.js";
6
+ export { wrapOverwideTables, wrapOverwideTablesInElement, } from "./wrap-overwide-tables.js";
7
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,uBAAuB,EACvB,gCAAgC,EAChC,uBAAuB,EACvB,kBAAkB,GAGlB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACN,wBAAwB,EACxB,wBAAwB,GAKxB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACN,2BAA2B,EAC3B,eAAe,GACf,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC","sourcesContent":["export {\n\tbuildAuthoringAllowList,\n\tcreateDefaultItemMarkupSanitizer,\n\tresetPurifierForTesting,\n\tsanitizeItemMarkup,\n\ttype ItemMarkupSanitizer,\n\ttype SanitizeItemMarkupOptions,\n} from \"./sanitize-item-markup.js\";\nexport {\n\tparseAllowedStyleOrigins,\n\tvalidateExternalStyleUrl,\n\ttype StyleUrlValidationError,\n\ttype StyleUrlValidationOk,\n\ttype StyleUrlValidationOptions,\n\ttype StyleUrlValidationResult,\n} from \"./validate-style-url.js\";\nexport {\n\tresetSvgSanitizerForTesting,\n\tsanitizeSvgIcon,\n} from \"./sanitize-svg-icon.js\";\nexport { wrapOverwideImages } from \"./wrap-overwide-images.js\";\nexport { wrapModelRichContent } from \"./wrap-model-rich-content.js\";\nexport { wrapOverwideTables } from \"./wrap-overwide-tables.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,uBAAuB,EACvB,gCAAgC,EAChC,uBAAuB,EACvB,kBAAkB,GAGlB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACN,wBAAwB,EACxB,wBAAwB,GAKxB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACN,2BAA2B,EAC3B,eAAe,GACf,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACN,kBAAkB,EAClB,2BAA2B,GAC3B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EACN,kBAAkB,EAClB,2BAA2B,GAC3B,MAAM,2BAA2B,CAAC","sourcesContent":["export {\n\tbuildAuthoringAllowList,\n\tcreateDefaultItemMarkupSanitizer,\n\tresetPurifierForTesting,\n\tsanitizeItemMarkup,\n\ttype ItemMarkupSanitizer,\n\ttype SanitizeItemMarkupOptions,\n} from \"./sanitize-item-markup.js\";\nexport {\n\tparseAllowedStyleOrigins,\n\tvalidateExternalStyleUrl,\n\ttype StyleUrlValidationError,\n\ttype StyleUrlValidationOk,\n\ttype StyleUrlValidationOptions,\n\ttype StyleUrlValidationResult,\n} from \"./validate-style-url.js\";\nexport {\n\tresetSvgSanitizerForTesting,\n\tsanitizeSvgIcon,\n} from \"./sanitize-svg-icon.js\";\nexport {\n\twrapOverwideImages,\n\twrapOverwideImagesInElement,\n} from \"./wrap-overwide-images.js\";\nexport { wrapModelRichContent } from \"./wrap-model-rich-content.js\";\nexport {\n\twrapOverwideTables,\n\twrapOverwideTablesInElement,\n} from \"./wrap-overwide-tables.js\";\n"]}
@@ -11,10 +11,34 @@
11
11
  * space (including at higher browser-zoom levels, which is the original driver
12
12
  * for this change — WCAG 1.4.10 Reflow at 400% zoom).
13
13
  *
14
- * This helper runs as a post-sanitization step inside `sanitizeItemMarkup`, so
15
- * every host that renders authored markup through the shared
16
- * `pie-item-player` (including the section player) benefits uniformly.
14
+ * Two callable surfaces share the same wrapping logic:
15
+ *
16
+ * - `wrapOverwideImages(markup)` string-in / string-out, used as a
17
+ * post-sanitization step inside `sanitizeItemMarkup`. By design it skips
18
+ * images inside `pie-*` elements; those are the element's own template and
19
+ * should not be restructured by the authored-markup pipeline.
20
+ * - `wrapOverwideImagesInElement(root)` — operates on a live DOM subtree.
21
+ * Used by the post-render pass in `PieItemPlayer.svelte` so that images a
22
+ * PIE element paints into its own light DOM (e.g. a `pie-passage`'s
23
+ * model-driven content) get the same scrollable affordance even though
24
+ * they never appeared in the authored markup string.
25
+ */
26
+ export interface WrapOverwideImagesInElementOptions {
27
+ /**
28
+ * When `true`, images whose nearest `pie-*` ancestor is *strictly between*
29
+ * the image and `root` are left alone. Used by the string pipeline so the
30
+ * authored-markup pass doesn't restructure a PIE element's own template.
31
+ * Defaults to `false` so the live-DOM pass *does* wrap element-rendered
32
+ * images.
33
+ */
34
+ skipPieDescendants?: boolean;
35
+ }
36
+ /**
37
+ * Wrap every unwrapped `<img>` descendant of `root` with the shared
38
+ * horizontal-scroll span. Returns the number of newly-wrapped images so
39
+ * callers can short-circuit when nothing changed. Idempotent.
17
40
  */
41
+ export declare function wrapOverwideImagesInElement(root: Element, options?: WrapOverwideImagesInElementOptions): number;
18
42
  /**
19
43
  * Wrap `<img>` elements in `markup` with a horizontal-scroll container.
20
44
  *
@@ -25,6 +49,8 @@
25
49
  * `pie-image-scroll` class are left alone.
26
50
  * - Leaves images inside PIE custom elements (`<pie-*>`) alone. Those are
27
51
  * rendered by the element's own template / shadow DOM and should not be
28
- * restructured by the authored-markup pipeline.
52
+ * restructured by the authored-markup pipeline. Use
53
+ * `wrapOverwideImagesInElement` for the post-render pass that *does* want
54
+ * to wrap element-rendered images.
29
55
  */
30
56
  export declare function wrapOverwideImages(markup: string): string;
@@ -11,12 +11,20 @@
11
11
  * space (including at higher browser-zoom levels, which is the original driver
12
12
  * for this change — WCAG 1.4.10 Reflow at 400% zoom).
13
13
  *
14
- * This helper runs as a post-sanitization step inside `sanitizeItemMarkup`, so
15
- * every host that renders authored markup through the shared
16
- * `pie-item-player` (including the section player) benefits uniformly.
14
+ * Two callable surfaces share the same wrapping logic:
15
+ *
16
+ * - `wrapOverwideImages(markup)` string-in / string-out, used as a
17
+ * post-sanitization step inside `sanitizeItemMarkup`. By design it skips
18
+ * images inside `pie-*` elements; those are the element's own template and
19
+ * should not be restructured by the authored-markup pipeline.
20
+ * - `wrapOverwideImagesInElement(root)` — operates on a live DOM subtree.
21
+ * Used by the post-render pass in `PieItemPlayer.svelte` so that images a
22
+ * PIE element paints into its own light DOM (e.g. a `pie-passage`'s
23
+ * model-driven content) get the same scrollable affordance even though
24
+ * they never appeared in the authored markup string.
17
25
  */
18
- const PIE_CUSTOM_ELEMENT_TAG_REGEX = /^pie-/i;
19
26
  const SCROLL_WRAPPER_CLASS = "pie-image-scroll";
27
+ const PIE_CUSTOM_ELEMENT_TAG_REGEX = /^pie-/i;
20
28
  function isInsidePieCustomElement(image, root) {
21
29
  let ancestor = image.parentElement;
22
30
  while (ancestor && ancestor !== root) {
@@ -32,6 +40,42 @@ function buildAriaLabel(image) {
32
40
  const trimmed = alt ? alt.trim() : "";
33
41
  return trimmed ? `Scrollable image: ${trimmed}` : "Scrollable image";
34
42
  }
43
+ /**
44
+ * Wrap every unwrapped `<img>` descendant of `root` with the shared
45
+ * horizontal-scroll span. Returns the number of newly-wrapped images so
46
+ * callers can short-circuit when nothing changed. Idempotent.
47
+ */
48
+ export function wrapOverwideImagesInElement(root, options = {}) {
49
+ const { skipPieDescendants = false } = options;
50
+ const images = Array.from(root.querySelectorAll("img"));
51
+ if (images.length === 0)
52
+ return 0;
53
+ const ownerDocument = root.ownerDocument;
54
+ if (!ownerDocument)
55
+ return 0;
56
+ let wrapped = 0;
57
+ for (const image of images) {
58
+ const parent = image.parentElement;
59
+ if (!parent)
60
+ continue;
61
+ // Idempotency — already wrapped.
62
+ if (parent.classList && parent.classList.contains(SCROLL_WRAPPER_CLASS)) {
63
+ continue;
64
+ }
65
+ // Authored-markup pass: leave PIE custom-element internals alone.
66
+ if (skipPieDescendants && isInsidePieCustomElement(image, root))
67
+ continue;
68
+ const wrapper = ownerDocument.createElement("span");
69
+ wrapper.className = SCROLL_WRAPPER_CLASS;
70
+ wrapper.setAttribute("tabindex", "0");
71
+ wrapper.setAttribute("role", "region");
72
+ wrapper.setAttribute("aria-label", buildAriaLabel(image));
73
+ parent.insertBefore(wrapper, image);
74
+ wrapper.appendChild(image);
75
+ wrapped += 1;
76
+ }
77
+ return wrapped;
78
+ }
35
79
  /**
36
80
  * Wrap `<img>` elements in `markup` with a horizontal-scroll container.
37
81
  *
@@ -42,7 +86,9 @@ function buildAriaLabel(image) {
42
86
  * `pie-image-scroll` class are left alone.
43
87
  * - Leaves images inside PIE custom elements (`<pie-*>`) alone. Those are
44
88
  * rendered by the element's own template / shadow DOM and should not be
45
- * restructured by the authored-markup pipeline.
89
+ * restructured by the authored-markup pipeline. Use
90
+ * `wrapOverwideImagesInElement` for the post-render pass that *does* want
91
+ * to wrap element-rendered images.
46
92
  */
47
93
  export function wrapOverwideImages(markup) {
48
94
  if (!markup)
@@ -62,30 +108,9 @@ export function wrapOverwideImages(markup) {
62
108
  const body = doc.body;
63
109
  if (!body)
64
110
  return markup;
65
- const images = Array.from(body.querySelectorAll("img"));
66
- if (images.length === 0)
67
- return markup;
68
- let mutated = false;
69
- for (const image of images) {
70
- const parent = image.parentElement;
71
- if (!parent)
72
- continue;
73
- // Idempotency — already wrapped.
74
- if (parent.classList && parent.classList.contains(SCROLL_WRAPPER_CLASS)) {
75
- continue;
76
- }
77
- // Leave PIE custom-element internals alone.
78
- if (isInsidePieCustomElement(image, body))
79
- continue;
80
- const wrapper = doc.createElement("span");
81
- wrapper.className = SCROLL_WRAPPER_CLASS;
82
- wrapper.setAttribute("tabindex", "0");
83
- wrapper.setAttribute("role", "region");
84
- wrapper.setAttribute("aria-label", buildAriaLabel(image));
85
- parent.insertBefore(wrapper, image);
86
- wrapper.appendChild(image);
87
- mutated = true;
88
- }
89
- return mutated ? body.innerHTML : markup;
111
+ const wrapped = wrapOverwideImagesInElement(body, {
112
+ skipPieDescendants: true,
113
+ });
114
+ return wrapped > 0 ? body.innerHTML : markup;
90
115
  }
91
116
  //# sourceMappingURL=wrap-overwide-images.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"wrap-overwide-images.js","sourceRoot":"","sources":["../../src/security/wrap-overwide-images.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Wraps authored `<img>` elements with a horizontally scrollable container so\n * images that are wider than their column surface a scrollbar instead of being\n * clipped by ancestor `overflow-x: hidden` regions (PIE-94).\n *\n * The wrapper is rendered as\n * `<span class=\"pie-image-scroll\" tabindex=\"0\" role=\"region\" aria-label=\"...\">`\n * and receives the accompanying CSS from `@pie-players/pie-theme`. The CSS uses\n * `overflow-x: auto` so small images stay visually unchanged: a scrollbar only\n * appears when the image's intrinsic width exceeds the wrapper's available\n * space (including at higher browser-zoom levels, which is the original driver\n * for this change — WCAG 1.4.10 Reflow at 400% zoom).\n *\n * This helper runs as a post-sanitization step inside `sanitizeItemMarkup`, so\n * every host that renders authored markup through the shared\n * `pie-item-player` (including the section player) benefits uniformly.\n */\n\nconst PIE_CUSTOM_ELEMENT_TAG_REGEX = /^pie-/i;\nconst SCROLL_WRAPPER_CLASS = \"pie-image-scroll\";\n\nfunction isInsidePieCustomElement(image: Element, root: Element): boolean {\n\tlet ancestor: Element | null = image.parentElement;\n\twhile (ancestor && ancestor !== root) {\n\t\tif (PIE_CUSTOM_ELEMENT_TAG_REGEX.test(ancestor.tagName)) {\n\t\t\treturn true;\n\t\t}\n\t\tancestor = ancestor.parentElement;\n\t}\n\treturn false;\n}\n\nfunction buildAriaLabel(image: Element): string {\n\tconst alt = image.getAttribute(\"alt\");\n\tconst trimmed = alt ? alt.trim() : \"\";\n\treturn trimmed ? `Scrollable image: ${trimmed}` : \"Scrollable image\";\n}\n\n/**\n * Wrap `<img>` elements in `markup` with a horizontal-scroll container.\n *\n * - No-ops on empty input.\n * - No-ops during SSR (no `window` / `DOMParser`) — the markup is returned\n * unchanged; the browser re-run on hydrate will perform the wrap.\n * - Idempotent: images whose direct parent already carries the\n * `pie-image-scroll` class are left alone.\n * - Leaves images inside PIE custom elements (`<pie-*>`) alone. Those are\n * rendered by the element's own template / shadow DOM and should not be\n * restructured by the authored-markup pipeline.\n */\nexport function wrapOverwideImages(markup: string): string {\n\tif (!markup) return \"\";\n\n\t// Fast path: avoid the DOM round-trip entirely when the markup carries no\n\t// images. Keeps the sanitize pipeline cheap for the common case.\n\tif (!/<img\\b/i.test(markup)) return markup;\n\n\tif (typeof window === \"undefined\" || !window.document) return markup;\n\n\tconst ParserCtor =\n\t\ttypeof DOMParser !== \"undefined\"\n\t\t\t? DOMParser\n\t\t\t: (window as unknown as { DOMParser?: typeof DOMParser }).DOMParser;\n\tif (!ParserCtor) return markup;\n\n\tconst doc = new ParserCtor().parseFromString(\n\t\t`<!DOCTYPE html><html><body>${markup}</body></html>`,\n\t\t\"text/html\",\n\t);\n\tconst body = doc.body;\n\tif (!body) return markup;\n\n\tconst images = Array.from(body.querySelectorAll(\"img\"));\n\tif (images.length === 0) return markup;\n\n\tlet mutated = false;\n\tfor (const image of images) {\n\t\tconst parent = image.parentElement;\n\t\tif (!parent) continue;\n\n\t\t// Idempotency — already wrapped.\n\t\tif (parent.classList && parent.classList.contains(SCROLL_WRAPPER_CLASS)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Leave PIE custom-element internals alone.\n\t\tif (isInsidePieCustomElement(image, body)) continue;\n\n\t\tconst wrapper = doc.createElement(\"span\");\n\t\twrapper.className = SCROLL_WRAPPER_CLASS;\n\t\twrapper.setAttribute(\"tabindex\", \"0\");\n\t\twrapper.setAttribute(\"role\", \"region\");\n\t\twrapper.setAttribute(\"aria-label\", buildAriaLabel(image));\n\n\t\tparent.insertBefore(wrapper, image);\n\t\twrapper.appendChild(image);\n\t\tmutated = true;\n\t}\n\n\treturn mutated ? body.innerHTML : markup;\n}\n"]}
1
+ {"version":3,"file":"wrap-overwide-images.js","sourceRoot":"","sources":["../../src/security/wrap-overwide-images.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,MAAM,oBAAoB,GAAG,kBAAkB,CAAC;AAChD,MAAM,4BAA4B,GAAG,QAAQ,CAAC;AAE9C,SAAS,wBAAwB,CAAC,KAAc,EAAE,IAAa;IAC9D,IAAI,QAAQ,GAAmB,KAAK,CAAC,aAAa,CAAC;IACnD,OAAO,QAAQ,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtC,IAAI,4BAA4B,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YACzD,OAAO,IAAI,CAAC;QACb,CAAC;QACD,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC;IACnC,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACrC,MAAM,GAAG,GAAG,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACtC,OAAO,OAAO,CAAC,CAAC,CAAC,qBAAqB,OAAO,EAAE,CAAC,CAAC,CAAC,kBAAkB,CAAC;AACtE,CAAC;AAaD;;;;GAIG;AACH,MAAM,UAAU,2BAA2B,CAC1C,IAAa,EACb,UAA8C,EAAE;IAEhD,MAAM,EAAE,kBAAkB,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAC/C,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC;IACxD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAElC,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC;IACzC,IAAI,CAAC,aAAa;QAAE,OAAO,CAAC,CAAC;IAE7B,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,KAAK,CAAC,aAAa,CAAC;QACnC,IAAI,CAAC,MAAM;YAAE,SAAS;QAEtB,iCAAiC;QACjC,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,CAAC;YACzE,SAAS;QACV,CAAC;QAED,kEAAkE;QAClE,IAAI,kBAAkB,IAAI,wBAAwB,CAAC,KAAK,EAAE,IAAI,CAAC;YAAE,SAAS;QAE1E,MAAM,OAAO,GAAG,aAAa,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACpD,OAAO,CAAC,SAAS,GAAG,oBAAoB,CAAC;QACzC,OAAO,CAAC,YAAY,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QACtC,OAAO,CAAC,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACvC,OAAO,CAAC,YAAY,CAAC,YAAY,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;QAE1D,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACpC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC3B,OAAO,IAAI,CAAC,CAAC;IACd,CAAC;IACD,OAAO,OAAO,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAChD,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IAEvB,0EAA0E;IAC1E,iEAAiE;IACjE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC;IAE3C,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,CAAC,MAAM,CAAC,QAAQ;QAAE,OAAO,MAAM,CAAC;IAErE,MAAM,UAAU,GACf,OAAO,SAAS,KAAK,WAAW;QAC/B,CAAC,CAAC,SAAS;QACX,CAAC,CAAE,MAAsD,CAAC,SAAS,CAAC;IACtE,IAAI,CAAC,UAAU;QAAE,OAAO,MAAM,CAAC;IAE/B,MAAM,GAAG,GAAG,IAAI,UAAU,EAAE,CAAC,eAAe,CAC3C,8BAA8B,MAAM,gBAAgB,EACpD,WAAW,CACX,CAAC;IACF,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;IACtB,IAAI,CAAC,IAAI;QAAE,OAAO,MAAM,CAAC;IAEzB,MAAM,OAAO,GAAG,2BAA2B,CAAC,IAAI,EAAE;QACjD,kBAAkB,EAAE,IAAI;KACxB,CAAC,CAAC;IACH,OAAO,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;AAC9C,CAAC","sourcesContent":["/**\n * Wraps authored `<img>` elements with a horizontally scrollable container so\n * images that are wider than their column surface a scrollbar instead of being\n * clipped by ancestor `overflow-x: hidden` regions (PIE-94).\n *\n * The wrapper is rendered as\n * `<span class=\"pie-image-scroll\" tabindex=\"0\" role=\"region\" aria-label=\"...\">`\n * and receives the accompanying CSS from `@pie-players/pie-theme`. The CSS uses\n * `overflow-x: auto` so small images stay visually unchanged: a scrollbar only\n * appears when the image's intrinsic width exceeds the wrapper's available\n * space (including at higher browser-zoom levels, which is the original driver\n * for this change — WCAG 1.4.10 Reflow at 400% zoom).\n *\n * Two callable surfaces share the same wrapping logic:\n *\n * - `wrapOverwideImages(markup)` — string-in / string-out, used as a\n * post-sanitization step inside `sanitizeItemMarkup`. By design it skips\n * images inside `pie-*` elements; those are the element's own template and\n * should not be restructured by the authored-markup pipeline.\n * - `wrapOverwideImagesInElement(root)` — operates on a live DOM subtree.\n * Used by the post-render pass in `PieItemPlayer.svelte` so that images a\n * PIE element paints into its own light DOM (e.g. a `pie-passage`'s\n * model-driven content) get the same scrollable affordance even though\n * they never appeared in the authored markup string.\n */\n\nconst SCROLL_WRAPPER_CLASS = \"pie-image-scroll\";\nconst PIE_CUSTOM_ELEMENT_TAG_REGEX = /^pie-/i;\n\nfunction isInsidePieCustomElement(image: Element, root: Element): boolean {\n\tlet ancestor: Element | null = image.parentElement;\n\twhile (ancestor && ancestor !== root) {\n\t\tif (PIE_CUSTOM_ELEMENT_TAG_REGEX.test(ancestor.tagName)) {\n\t\t\treturn true;\n\t\t}\n\t\tancestor = ancestor.parentElement;\n\t}\n\treturn false;\n}\n\nfunction buildAriaLabel(image: Element): string {\n\tconst alt = image.getAttribute(\"alt\");\n\tconst trimmed = alt ? alt.trim() : \"\";\n\treturn trimmed ? `Scrollable image: ${trimmed}` : \"Scrollable image\";\n}\n\nexport interface WrapOverwideImagesInElementOptions {\n\t/**\n\t * When `true`, images whose nearest `pie-*` ancestor is *strictly between*\n\t * the image and `root` are left alone. Used by the string pipeline so the\n\t * authored-markup pass doesn't restructure a PIE element's own template.\n\t * Defaults to `false` so the live-DOM pass *does* wrap element-rendered\n\t * images.\n\t */\n\tskipPieDescendants?: boolean;\n}\n\n/**\n * Wrap every unwrapped `<img>` descendant of `root` with the shared\n * horizontal-scroll span. Returns the number of newly-wrapped images so\n * callers can short-circuit when nothing changed. Idempotent.\n */\nexport function wrapOverwideImagesInElement(\n\troot: Element,\n\toptions: WrapOverwideImagesInElementOptions = {},\n): number {\n\tconst { skipPieDescendants = false } = options;\n\tconst images = Array.from(root.querySelectorAll(\"img\"));\n\tif (images.length === 0) return 0;\n\n\tconst ownerDocument = root.ownerDocument;\n\tif (!ownerDocument) return 0;\n\n\tlet wrapped = 0;\n\tfor (const image of images) {\n\t\tconst parent = image.parentElement;\n\t\tif (!parent) continue;\n\n\t\t// Idempotency — already wrapped.\n\t\tif (parent.classList && parent.classList.contains(SCROLL_WRAPPER_CLASS)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Authored-markup pass: leave PIE custom-element internals alone.\n\t\tif (skipPieDescendants && isInsidePieCustomElement(image, root)) continue;\n\n\t\tconst wrapper = ownerDocument.createElement(\"span\");\n\t\twrapper.className = SCROLL_WRAPPER_CLASS;\n\t\twrapper.setAttribute(\"tabindex\", \"0\");\n\t\twrapper.setAttribute(\"role\", \"region\");\n\t\twrapper.setAttribute(\"aria-label\", buildAriaLabel(image));\n\n\t\tparent.insertBefore(wrapper, image);\n\t\twrapper.appendChild(image);\n\t\twrapped += 1;\n\t}\n\treturn wrapped;\n}\n\n/**\n * Wrap `<img>` elements in `markup` with a horizontal-scroll container.\n *\n * - No-ops on empty input.\n * - No-ops during SSR (no `window` / `DOMParser`) — the markup is returned\n * unchanged; the browser re-run on hydrate will perform the wrap.\n * - Idempotent: images whose direct parent already carries the\n * `pie-image-scroll` class are left alone.\n * - Leaves images inside PIE custom elements (`<pie-*>`) alone. Those are\n * rendered by the element's own template / shadow DOM and should not be\n * restructured by the authored-markup pipeline. Use\n * `wrapOverwideImagesInElement` for the post-render pass that *does* want\n * to wrap element-rendered images.\n */\nexport function wrapOverwideImages(markup: string): string {\n\tif (!markup) return \"\";\n\n\t// Fast path: avoid the DOM round-trip entirely when the markup carries no\n\t// images. Keeps the sanitize pipeline cheap for the common case.\n\tif (!/<img\\b/i.test(markup)) return markup;\n\n\tif (typeof window === \"undefined\" || !window.document) return markup;\n\n\tconst ParserCtor =\n\t\ttypeof DOMParser !== \"undefined\"\n\t\t\t? DOMParser\n\t\t\t: (window as unknown as { DOMParser?: typeof DOMParser }).DOMParser;\n\tif (!ParserCtor) return markup;\n\n\tconst doc = new ParserCtor().parseFromString(\n\t\t`<!DOCTYPE html><html><body>${markup}</body></html>`,\n\t\t\"text/html\",\n\t);\n\tconst body = doc.body;\n\tif (!body) return markup;\n\n\tconst wrapped = wrapOverwideImagesInElement(body, {\n\t\tskipPieDescendants: true,\n\t});\n\treturn wrapped > 0 ? body.innerHTML : markup;\n}\n"]}
@@ -11,8 +11,32 @@
11
11
  * space (including at higher browser-zoom levels — WCAG 1.4.10 Reflow at 400%
12
12
  * zoom is the same driver as for `wrapOverwideImages`).
13
13
  *
14
- * This helper runs as a post-sanitization step inside `sanitizeItemMarkup`, so
15
- * every host that renders authored markup through the shared
16
- * `pie-item-player` (including the section player) benefits uniformly.
14
+ * Two callable surfaces share the same wrapping logic:
15
+ *
16
+ * - `wrapOverwideTables(markup)` string-in / string-out, used as a
17
+ * post-sanitization step inside `sanitizeItemMarkup`. By design it skips
18
+ * tables inside `pie-*` elements; those are the element's own template and
19
+ * should not be restructured by the authored-markup pipeline.
20
+ * - `wrapOverwideTablesInElement(root)` — operates on a live DOM subtree.
21
+ * Used by the post-render pass in `PieItemPlayer.svelte` so that tables a
22
+ * PIE element paints into its own light DOM (e.g. a `pie-passage`'s
23
+ * model-driven content) get the same scrollable affordance even though
24
+ * they never appeared in the authored markup string.
25
+ */
26
+ export interface WrapOverwideTablesInElementOptions {
27
+ /**
28
+ * When `true`, tables whose nearest `pie-*` ancestor is *strictly between*
29
+ * the table and `root` are left alone. Used by the string pipeline so the
30
+ * authored-markup pass doesn't restructure a PIE element's own template.
31
+ * Defaults to `false` so the live-DOM pass *does* wrap element-rendered
32
+ * tables.
33
+ */
34
+ skipPieDescendants?: boolean;
35
+ }
36
+ /**
37
+ * Wrap every unwrapped `<table>` descendant of `root` with the shared
38
+ * horizontal-scroll div. Returns the number of newly-wrapped tables so
39
+ * callers can short-circuit when nothing changed. Idempotent.
17
40
  */
41
+ export declare function wrapOverwideTablesInElement(root: Element, options?: WrapOverwideTablesInElementOptions): number;
18
42
  export declare function wrapOverwideTables(markup: string): string;
@@ -11,12 +11,20 @@
11
11
  * space (including at higher browser-zoom levels — WCAG 1.4.10 Reflow at 400%
12
12
  * zoom is the same driver as for `wrapOverwideImages`).
13
13
  *
14
- * This helper runs as a post-sanitization step inside `sanitizeItemMarkup`, so
15
- * every host that renders authored markup through the shared
16
- * `pie-item-player` (including the section player) benefits uniformly.
14
+ * Two callable surfaces share the same wrapping logic:
15
+ *
16
+ * - `wrapOverwideTables(markup)` string-in / string-out, used as a
17
+ * post-sanitization step inside `sanitizeItemMarkup`. By design it skips
18
+ * tables inside `pie-*` elements; those are the element's own template and
19
+ * should not be restructured by the authored-markup pipeline.
20
+ * - `wrapOverwideTablesInElement(root)` — operates on a live DOM subtree.
21
+ * Used by the post-render pass in `PieItemPlayer.svelte` so that tables a
22
+ * PIE element paints into its own light DOM (e.g. a `pie-passage`'s
23
+ * model-driven content) get the same scrollable affordance even though
24
+ * they never appeared in the authored markup string.
17
25
  */
18
- const PIE_CUSTOM_ELEMENT_TAG_REGEX = /^pie-/i;
19
26
  const SCROLL_WRAPPER_CLASS = "pie-table-scroll";
27
+ const PIE_CUSTOM_ELEMENT_TAG_REGEX = /^pie-/i;
20
28
  function isInsidePieCustomElement(table, root) {
21
29
  let ancestor = table.parentElement;
22
30
  while (ancestor && ancestor !== root) {
@@ -57,6 +65,42 @@ function buildAriaLabel(table) {
57
65
  }
58
66
  return "Scrollable table";
59
67
  }
68
+ /**
69
+ * Wrap every unwrapped `<table>` descendant of `root` with the shared
70
+ * horizontal-scroll div. Returns the number of newly-wrapped tables so
71
+ * callers can short-circuit when nothing changed. Idempotent.
72
+ */
73
+ export function wrapOverwideTablesInElement(root, options = {}) {
74
+ const { skipPieDescendants = false } = options;
75
+ const tables = Array.from(root.querySelectorAll("table"));
76
+ if (tables.length === 0)
77
+ return 0;
78
+ const ownerDocument = root.ownerDocument;
79
+ if (!ownerDocument)
80
+ return 0;
81
+ let wrapped = 0;
82
+ for (const table of tables) {
83
+ const parent = table.parentElement;
84
+ if (!parent)
85
+ continue;
86
+ // Idempotency — already wrapped.
87
+ if (parent.classList && parent.classList.contains(SCROLL_WRAPPER_CLASS)) {
88
+ continue;
89
+ }
90
+ // Authored-markup pass: leave PIE custom-element internals alone.
91
+ if (skipPieDescendants && isInsidePieCustomElement(table, root))
92
+ continue;
93
+ const wrapper = ownerDocument.createElement("div");
94
+ wrapper.className = SCROLL_WRAPPER_CLASS;
95
+ wrapper.setAttribute("tabindex", "0");
96
+ wrapper.setAttribute("role", "region");
97
+ wrapper.setAttribute("aria-label", buildAriaLabel(table));
98
+ parent.insertBefore(wrapper, table);
99
+ wrapper.appendChild(table);
100
+ wrapped += 1;
101
+ }
102
+ return wrapped;
103
+ }
60
104
  export function wrapOverwideTables(markup) {
61
105
  if (!markup)
62
106
  return "";
@@ -75,30 +119,9 @@ export function wrapOverwideTables(markup) {
75
119
  const body = doc.body;
76
120
  if (!body)
77
121
  return markup;
78
- const tables = Array.from(body.querySelectorAll("table"));
79
- if (tables.length === 0)
80
- return markup;
81
- let mutated = false;
82
- for (const table of tables) {
83
- const parent = table.parentElement;
84
- if (!parent)
85
- continue;
86
- // Idempotency — already wrapped.
87
- if (parent.classList && parent.classList.contains(SCROLL_WRAPPER_CLASS)) {
88
- continue;
89
- }
90
- // Leave PIE custom-element internals alone.
91
- if (isInsidePieCustomElement(table, body))
92
- continue;
93
- const wrapper = doc.createElement("div");
94
- wrapper.className = SCROLL_WRAPPER_CLASS;
95
- wrapper.setAttribute("tabindex", "0");
96
- wrapper.setAttribute("role", "region");
97
- wrapper.setAttribute("aria-label", buildAriaLabel(table));
98
- parent.insertBefore(wrapper, table);
99
- wrapper.appendChild(table);
100
- mutated = true;
101
- }
102
- return mutated ? body.innerHTML : markup;
122
+ const wrapped = wrapOverwideTablesInElement(body, {
123
+ skipPieDescendants: true,
124
+ });
125
+ return wrapped > 0 ? body.innerHTML : markup;
103
126
  }
104
127
  //# sourceMappingURL=wrap-overwide-tables.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"wrap-overwide-tables.js","sourceRoot":"","sources":["../../src/security/wrap-overwide-tables.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Wraps authored `<table>` elements with a horizontally scrollable container so\n * tables that are wider than their column surface a scrollbar instead of being\n * clipped by ancestor `overflow-x: hidden` regions.\n *\n * The wrapper is rendered as\n * `<div class=\"pie-table-scroll\" tabindex=\"0\" role=\"region\" aria-label=\"...\">`\n * and receives the accompanying CSS from `@pie-players/pie-theme`. The CSS uses\n * `overflow-x: auto` so narrow tables stay visually unchanged: a scrollbar only\n * appears when the table's intrinsic width exceeds the wrapper's available\n * space (including at higher browser-zoom levels — WCAG 1.4.10 Reflow at 400%\n * zoom is the same driver as for `wrapOverwideImages`).\n *\n * This helper runs as a post-sanitization step inside `sanitizeItemMarkup`, so\n * every host that renders authored markup through the shared\n * `pie-item-player` (including the section player) benefits uniformly.\n */\n\nconst PIE_CUSTOM_ELEMENT_TAG_REGEX = /^pie-/i;\nconst SCROLL_WRAPPER_CLASS = \"pie-table-scroll\";\n\nfunction isInsidePieCustomElement(table: Element, root: Element): boolean {\n\tlet ancestor: Element | null = table.parentElement;\n\twhile (ancestor && ancestor !== root) {\n\t\tif (PIE_CUSTOM_ELEMENT_TAG_REGEX.test(ancestor.tagName)) {\n\t\t\treturn true;\n\t\t}\n\t\tancestor = ancestor.parentElement;\n\t}\n\treturn false;\n}\n\nfunction buildAriaLabel(table: Element): string {\n\t// Authors commonly label tables via <caption>, aria-label, or aria-labelledby.\n\t// Prefer the most explicit signal and fall back to the generic label so\n\t// every wrapper still announces itself as a region.\n\tconst ariaLabel = table.getAttribute(\"aria-label\");\n\tif (ariaLabel?.trim()) {\n\t\treturn `Scrollable table: ${ariaLabel.trim()}`;\n\t}\n\tconst labelledBy = table.getAttribute(\"aria-labelledby\");\n\tif (labelledBy?.trim()) {\n\t\tconst ownerDocument = table.ownerDocument;\n\t\tconst ids = labelledBy.trim().split(/\\s+/);\n\t\tconst labels: string[] = [];\n\t\tfor (const id of ids) {\n\t\t\tconst labelEl = ownerDocument?.getElementById(id);\n\t\t\tconst text = labelEl?.textContent?.trim();\n\t\t\tif (text) labels.push(text);\n\t\t}\n\t\tif (labels.length > 0) {\n\t\t\treturn `Scrollable table: ${labels.join(\" \")}`;\n\t\t}\n\t}\n\tconst caption = table.querySelector(\"caption\");\n\tconst captionText = caption?.textContent?.trim();\n\tif (captionText) {\n\t\treturn `Scrollable table: ${captionText}`;\n\t}\n\treturn \"Scrollable table\";\n}\n\nexport function wrapOverwideTables(markup: string): string {\n\tif (!markup) return \"\";\n\n\t// Fast path: avoid the DOM round-trip entirely when the markup carries no\n\t// tables. Keeps the sanitize pipeline cheap for the common case.\n\tif (!/<table\\b/i.test(markup)) return markup;\n\n\tif (typeof window === \"undefined\" || !window.document) return markup;\n\n\tconst ParserCtor =\n\t\ttypeof DOMParser !== \"undefined\"\n\t\t\t? DOMParser\n\t\t\t: (window as unknown as { DOMParser?: typeof DOMParser }).DOMParser;\n\tif (!ParserCtor) return markup;\n\n\tconst doc = new ParserCtor().parseFromString(\n\t\t`<!DOCTYPE html><html><body>${markup}</body></html>`,\n\t\t\"text/html\",\n\t);\n\tconst body = doc.body;\n\tif (!body) return markup;\n\n\tconst tables = Array.from(body.querySelectorAll(\"table\"));\n\tif (tables.length === 0) return markup;\n\n\tlet mutated = false;\n\tfor (const table of tables) {\n\t\tconst parent = table.parentElement;\n\t\tif (!parent) continue;\n\n\t\t// Idempotency — already wrapped.\n\t\tif (parent.classList && parent.classList.contains(SCROLL_WRAPPER_CLASS)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Leave PIE custom-element internals alone.\n\t\tif (isInsidePieCustomElement(table, body)) continue;\n\n\t\tconst wrapper = doc.createElement(\"div\");\n\t\twrapper.className = SCROLL_WRAPPER_CLASS;\n\t\twrapper.setAttribute(\"tabindex\", \"0\");\n\t\twrapper.setAttribute(\"role\", \"region\");\n\t\twrapper.setAttribute(\"aria-label\", buildAriaLabel(table));\n\n\t\tparent.insertBefore(wrapper, table);\n\t\twrapper.appendChild(table);\n\t\tmutated = true;\n\t}\n\n\treturn mutated ? body.innerHTML : markup;\n}\n"]}
1
+ {"version":3,"file":"wrap-overwide-tables.js","sourceRoot":"","sources":["../../src/security/wrap-overwide-tables.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Wraps authored `<table>` elements with a horizontally scrollable container so\n * tables that are wider than their column surface a scrollbar instead of being\n * clipped by ancestor `overflow-x: hidden` regions.\n *\n * The wrapper is rendered as\n * `<div class=\"pie-table-scroll\" tabindex=\"0\" role=\"region\" aria-label=\"...\">`\n * and receives the accompanying CSS from `@pie-players/pie-theme`. The CSS uses\n * `overflow-x: auto` so narrow tables stay visually unchanged: a scrollbar only\n * appears when the table's intrinsic width exceeds the wrapper's available\n * space (including at higher browser-zoom levels — WCAG 1.4.10 Reflow at 400%\n * zoom is the same driver as for `wrapOverwideImages`).\n *\n * Two callable surfaces share the same wrapping logic:\n *\n * - `wrapOverwideTables(markup)` — string-in / string-out, used as a\n * post-sanitization step inside `sanitizeItemMarkup`. By design it skips\n * tables inside `pie-*` elements; those are the element's own template and\n * should not be restructured by the authored-markup pipeline.\n * - `wrapOverwideTablesInElement(root)` — operates on a live DOM subtree.\n * Used by the post-render pass in `PieItemPlayer.svelte` so that tables a\n * PIE element paints into its own light DOM (e.g. a `pie-passage`'s\n * model-driven content) get the same scrollable affordance even though\n * they never appeared in the authored markup string.\n */\n\nconst SCROLL_WRAPPER_CLASS = \"pie-table-scroll\";\nconst PIE_CUSTOM_ELEMENT_TAG_REGEX = /^pie-/i;\n\nfunction isInsidePieCustomElement(table: Element, root: Element): boolean {\n\tlet ancestor: Element | null = table.parentElement;\n\twhile (ancestor && ancestor !== root) {\n\t\tif (PIE_CUSTOM_ELEMENT_TAG_REGEX.test(ancestor.tagName)) {\n\t\t\treturn true;\n\t\t}\n\t\tancestor = ancestor.parentElement;\n\t}\n\treturn false;\n}\n\nfunction buildAriaLabel(table: Element): string {\n\t// Authors commonly label tables via <caption>, aria-label, or aria-labelledby.\n\t// Prefer the most explicit signal and fall back to the generic label so\n\t// every wrapper still announces itself as a region.\n\tconst ariaLabel = table.getAttribute(\"aria-label\");\n\tif (ariaLabel?.trim()) {\n\t\treturn `Scrollable table: ${ariaLabel.trim()}`;\n\t}\n\tconst labelledBy = table.getAttribute(\"aria-labelledby\");\n\tif (labelledBy?.trim()) {\n\t\tconst ownerDocument = table.ownerDocument;\n\t\tconst ids = labelledBy.trim().split(/\\s+/);\n\t\tconst labels: string[] = [];\n\t\tfor (const id of ids) {\n\t\t\tconst labelEl = ownerDocument?.getElementById(id);\n\t\t\tconst text = labelEl?.textContent?.trim();\n\t\t\tif (text) labels.push(text);\n\t\t}\n\t\tif (labels.length > 0) {\n\t\t\treturn `Scrollable table: ${labels.join(\" \")}`;\n\t\t}\n\t}\n\tconst caption = table.querySelector(\"caption\");\n\tconst captionText = caption?.textContent?.trim();\n\tif (captionText) {\n\t\treturn `Scrollable table: ${captionText}`;\n\t}\n\treturn \"Scrollable table\";\n}\n\nexport interface WrapOverwideTablesInElementOptions {\n\t/**\n\t * When `true`, tables whose nearest `pie-*` ancestor is *strictly between*\n\t * the table and `root` are left alone. Used by the string pipeline so the\n\t * authored-markup pass doesn't restructure a PIE element's own template.\n\t * Defaults to `false` so the live-DOM pass *does* wrap element-rendered\n\t * tables.\n\t */\n\tskipPieDescendants?: boolean;\n}\n\n/**\n * Wrap every unwrapped `<table>` descendant of `root` with the shared\n * horizontal-scroll div. Returns the number of newly-wrapped tables so\n * callers can short-circuit when nothing changed. Idempotent.\n */\nexport function wrapOverwideTablesInElement(\n\troot: Element,\n\toptions: WrapOverwideTablesInElementOptions = {},\n): number {\n\tconst { skipPieDescendants = false } = options;\n\tconst tables = Array.from(root.querySelectorAll(\"table\"));\n\tif (tables.length === 0) return 0;\n\n\tconst ownerDocument = root.ownerDocument;\n\tif (!ownerDocument) return 0;\n\n\tlet wrapped = 0;\n\tfor (const table of tables) {\n\t\tconst parent = table.parentElement;\n\t\tif (!parent) continue;\n\n\t\t// Idempotency — already wrapped.\n\t\tif (parent.classList && parent.classList.contains(SCROLL_WRAPPER_CLASS)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Authored-markup pass: leave PIE custom-element internals alone.\n\t\tif (skipPieDescendants && isInsidePieCustomElement(table, root)) continue;\n\n\t\tconst wrapper = ownerDocument.createElement(\"div\");\n\t\twrapper.className = SCROLL_WRAPPER_CLASS;\n\t\twrapper.setAttribute(\"tabindex\", \"0\");\n\t\twrapper.setAttribute(\"role\", \"region\");\n\t\twrapper.setAttribute(\"aria-label\", buildAriaLabel(table));\n\n\t\tparent.insertBefore(wrapper, table);\n\t\twrapper.appendChild(table);\n\t\twrapped += 1;\n\t}\n\treturn wrapped;\n}\n\nexport function wrapOverwideTables(markup: string): string {\n\tif (!markup) return \"\";\n\n\t// Fast path: avoid the DOM round-trip entirely when the markup carries no\n\t// tables. Keeps the sanitize pipeline cheap for the common case.\n\tif (!/<table\\b/i.test(markup)) return markup;\n\n\tif (typeof window === \"undefined\" || !window.document) return markup;\n\n\tconst ParserCtor =\n\t\ttypeof DOMParser !== \"undefined\"\n\t\t\t? DOMParser\n\t\t\t: (window as unknown as { DOMParser?: typeof DOMParser }).DOMParser;\n\tif (!ParserCtor) return markup;\n\n\tconst doc = new ParserCtor().parseFromString(\n\t\t`<!DOCTYPE html><html><body>${markup}</body></html>`,\n\t\t\"text/html\",\n\t);\n\tconst body = doc.body;\n\tif (!body) return markup;\n\n\tconst wrapped = wrapOverwideTablesInElement(body, {\n\t\tskipPieDescendants: true,\n\t});\n\treturn wrapped > 0 ? body.innerHTML : markup;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pie-players/pie-players-shared",
3
- "version": "0.3.49",
3
+ "version": "0.3.50",
4
4
  "type": "module",
5
5
  "description": "Shared runtime + UI utilities for PIE players",
6
6
  "license": "MIT",