@bendyline/squisq-formats 1.4.1 → 2.0.0
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 +48 -2
- package/dist/{chunk-WWBIKRNP.js → chunk-2CSZJEAL.js} +13 -11
- package/dist/chunk-2CSZJEAL.js.map +1 -0
- package/dist/{chunk-RTS5XBZ7.js → chunk-2EFDWKC6.js} +262 -84
- package/dist/chunk-2EFDWKC6.js.map +1 -0
- package/dist/chunk-2PRVLAU3.js +740 -0
- package/dist/chunk-2PRVLAU3.js.map +1 -0
- package/dist/{chunk-SHLPSADL.js → chunk-4HJ6AK2Q.js} +54 -193
- package/dist/chunk-4HJ6AK2Q.js.map +1 -0
- package/dist/{chunk-5LSSWZPU.js → chunk-4VUWTSGM.js} +72 -25
- package/dist/chunk-4VUWTSGM.js.map +1 -0
- package/dist/{chunk-YESS7VY3.js → chunk-CVNVD7VH.js} +154 -39
- package/dist/chunk-CVNVD7VH.js.map +1 -0
- package/dist/chunk-CX3LH47J.js +99 -0
- package/dist/chunk-CX3LH47J.js.map +1 -0
- package/dist/{chunk-D7IFPWNZ.js → chunk-GVS2XXV6.js} +27 -26
- package/dist/chunk-GVS2XXV6.js.map +1 -0
- package/dist/chunk-H7T5DXUU.js +479 -0
- package/dist/chunk-H7T5DXUU.js.map +1 -0
- package/dist/{chunk-EHLGMSTE.js → chunk-HBSCRS5P.js} +10 -8
- package/dist/chunk-HBSCRS5P.js.map +1 -0
- package/dist/{chunk-46FMDOWZ.js → chunk-LXYLOOST.js} +49 -17
- package/dist/chunk-LXYLOOST.js.map +1 -0
- package/dist/{chunk-MJGRI6XR.js → chunk-MLX2BOJC.js} +12 -7
- package/dist/chunk-MLX2BOJC.js.map +1 -0
- package/dist/chunk-NKAJPJ4G.js +106 -0
- package/dist/chunk-NKAJPJ4G.js.map +1 -0
- package/dist/{chunk-DQAZR57U.js → chunk-O3GVVND4.js} +1 -1
- package/dist/chunk-ODL3SSPT.js +18 -0
- package/dist/chunk-ODL3SSPT.js.map +1 -0
- package/dist/chunk-X4USWOQ2.js +131 -0
- package/dist/chunk-X4USWOQ2.js.map +1 -0
- package/dist/chunk-XTLQXR4U.js +195 -0
- package/dist/chunk-XTLQXR4U.js.map +1 -0
- package/dist/chunk-YRT7GQ5Y.js +28 -0
- package/dist/chunk-YRT7GQ5Y.js.map +1 -0
- package/dist/chunk-ZZ7D4DN6.js +97 -0
- package/dist/chunk-ZZ7D4DN6.js.map +1 -0
- package/dist/container/index.d.ts +6 -2
- package/dist/container/index.js +15 -17
- package/dist/container/index.js.map +1 -1
- package/dist/docx/index.d.ts +6 -2
- package/dist/docx/index.js +5 -3
- package/dist/epub/index.d.ts +3 -1
- package/dist/epub/index.js +3 -3
- package/dist/export-Djev9BLU.d.ts +69 -0
- package/dist/extract-LNOA7DBK.js +15 -0
- package/dist/extract-LNOA7DBK.js.map +1 -0
- package/dist/html/index.d.ts +15 -85
- package/dist/html/index.js +3 -3
- package/dist/images-7FBWPKE3.js +7 -0
- package/dist/images-7FBWPKE3.js.map +1 -0
- package/dist/import-DTkDxHmZ.d.ts +84 -0
- package/dist/import-Yivc3kZM.d.ts +136 -0
- package/dist/index.d.ts +13 -4
- package/dist/index.js +30 -11
- package/dist/infer/index.d.ts +138 -0
- package/dist/infer/index.js +28 -0
- package/dist/infer/index.js.map +1 -0
- package/dist/layouts-7OUUVAGU.js +12 -0
- package/dist/layouts-7OUUVAGU.js.map +1 -0
- package/dist/layouts-CZ0bdsNL.d.ts +150 -0
- package/dist/mapTheme-IR27S6IV.js +11 -0
- package/dist/mapTheme-IR27S6IV.js.map +1 -0
- package/dist/ooxml/index.d.ts +21 -127
- package/dist/ooxml/index.js +31 -9
- package/dist/pdf/index.d.ts +3 -1
- package/dist/pdf/index.js +1 -1
- package/dist/pptx/index.d.ts +8 -108
- package/dist/pptx/index.js +13 -4
- package/dist/reader-Gof6OrJX.d.ts +140 -0
- package/dist/registry/index.d.ts +46 -8
- package/dist/registry/index.js +5 -2
- package/dist/themeReader-DPw4J5Ss.d.ts +56 -0
- package/dist/xlsx/index.d.ts +6 -66
- package/dist/xlsx/index.js +4 -2
- package/dist/zipLimits-bGYMS9cI.d.ts +29 -0
- package/package.json +8 -2
- package/src/__tests__/container.test.ts +41 -0
- package/src/__tests__/convert.test.ts +167 -0
- package/src/__tests__/epub.test.ts +102 -1
- package/src/__tests__/html.test.ts +62 -0
- package/src/__tests__/inferTheme.test.ts +135 -0
- package/src/__tests__/lossyWarnings.test.ts +41 -0
- package/src/__tests__/ooxml.test.ts +59 -2
- package/src/__tests__/ooxmlThemeReader.test.ts +92 -0
- package/src/__tests__/plainHtml.test.ts +15 -1
- package/src/__tests__/plainHtmlBundle.test.ts +18 -0
- package/src/__tests__/pptxImport.test.ts +30 -0
- package/src/__tests__/pptxInferFixtures.ts +314 -0
- package/src/__tests__/pptxLayoutInfer.test.ts +395 -0
- package/src/__tests__/zipSafety.test.ts +317 -0
- package/src/container/index.ts +20 -29
- package/src/docx/export.ts +4 -2
- package/src/docx/import.ts +4 -3
- package/src/epub/export.ts +94 -25
- package/src/html/docsHtmlBundle.ts +6 -2
- package/src/html/htmlTemplate.ts +31 -6
- package/src/html/imageUtils.ts +14 -5
- package/src/html/index.ts +12 -1
- package/src/html/plainHtml.ts +7 -3
- package/src/html/plainHtmlBundle.ts +11 -9
- package/src/index.ts +20 -0
- package/src/infer/extract.ts +127 -0
- package/src/infer/index.ts +168 -0
- package/src/infer/mapTheme.ts +176 -0
- package/src/infer/types.ts +27 -0
- package/src/ooxml/index.ts +14 -0
- package/src/ooxml/readUtils.ts +44 -0
- package/src/ooxml/reader.ts +87 -28
- package/src/ooxml/themeReader.ts +197 -0
- package/src/ooxml/types.ts +8 -9
- package/src/ooxml/writer.ts +28 -10
- package/src/pdf/export.ts +4 -2
- package/src/pdf/import.ts +40 -34
- package/src/pptx/export.ts +4 -2
- package/src/pptx/import.ts +214 -32
- package/src/pptx/index.ts +14 -0
- package/src/pptx/layouts.ts +1168 -0
- package/src/registry/convert.ts +54 -23
- package/src/registry/defaultFormats.ts +131 -44
- package/src/registry/index.ts +3 -0
- package/src/registry/types.ts +52 -6
- package/src/shared/boundedZipArchive.ts +342 -0
- package/src/shared/fidelity.ts +130 -0
- package/src/shared/zipEntryCount.ts +97 -0
- package/src/shared/zipLimits.ts +286 -0
- package/src/shared/zipSafety.ts +19 -0
- package/src/xlsx/import.ts +3 -2
- package/dist/chunk-46FMDOWZ.js.map +0 -1
- package/dist/chunk-5LSSWZPU.js.map +0 -1
- package/dist/chunk-D7IFPWNZ.js.map +0 -1
- package/dist/chunk-EHLGMSTE.js.map +0 -1
- package/dist/chunk-MJGRI6XR.js.map +0 -1
- package/dist/chunk-RTS5XBZ7.js.map +0 -1
- package/dist/chunk-SHLPSADL.js.map +0 -1
- package/dist/chunk-WWBIKRNP.js.map +0 -1
- package/dist/chunk-YESS7VY3.js.map +0 -1
- /package/dist/{chunk-DQAZR57U.js.map → chunk-O3GVVND4.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/pptx/layouts.ts"],"sourcesContent":["/**\n * PPTX slide-layout inference — reads the layouts/masters a deck actually\n * uses and, per layout, either matches it to a close built-in Squisq\n * template (title, sectionHeader, twoColumn, leftFeature, …) or generates a\n * reusable `CustomTemplateDefinition` from its placeholder geometry.\n *\n * The classifier is a deterministic three-stage waterfall — the layout's\n * `type` attribute, then well-known layout names, then placeholder-set\n * geometry — biased toward *not* templating: a title over a single body\n * flows better as plain markdown, and only genuinely distinctive geometry\n * (side-by-side content, positioned picture placeholders) becomes a custom\n * template.\n *\n * Shared by the PPTX importer (`inferLayouts`) and the theme dialog's\n * `inspectPptxLayouts` — one implementation, two consumers.\n */\n\nimport type {\n CustomTemplateDefinition,\n CustomTemplateLayer,\n ImageLayer,\n Position,\n ShapeLayer,\n TextLayer,\n TextStyle,\n} from '@bendyline/squisq/schemas';\nimport { getPartRelationships, getPartXml, openPackage } from '../ooxml/reader.js';\nimport type { OoxmlOpenOptions } from '../ooxml/reader.js';\nimport type { OoxmlPackage } from '../ooxml/types.js';\nimport {\n CONTENT_TYPE_PPTX_SLIDE_LAYOUT,\n NS_DRAWINGML,\n NS_PML,\n NS_R,\n REL_SLIDE_LAYOUT,\n REL_SLIDE_MASTER,\n} from '../ooxml/namespaces.js';\nimport { attrNS, baseDirOf, findRelByType, resolveTarget } from '../ooxml/readUtils.js';\n\n// ── Public types ─────────────────────────────────────────────────────\n\nexport interface EmuRect {\n x: number;\n y: number;\n cx: number;\n cy: number;\n}\n\n/** Percent-of-slide rect, 0–100 per axis (2-decimal precision). */\nexport interface PctRect {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\nexport type PlaceholderKind =\n | 'title'\n | 'subtitle'\n | 'text'\n | 'picture'\n | 'table'\n | 'chart'\n | 'other';\n\nexport interface PlaceholderTextStyle {\n fontSizePt?: number;\n bold?: boolean;\n align?: 'left' | 'center' | 'right';\n anchor?: 'top' | 'middle' | 'bottom';\n}\n\nexport interface ExtractedPlaceholder {\n kind: PlaceholderKind;\n /** `p:ph@type` verbatim ('' when absent — spec default is body). */\n rawType: string;\n /** `p:ph@idx`, default 0. */\n idx: number;\n /** Geometry resolved through the layout→master inheritance chain. */\n rect: PctRect;\n inheritedFromMaster: boolean;\n vertical: boolean;\n textStyle?: PlaceholderTextStyle;\n}\n\nexport interface ExtractedDecoration {\n shape: 'rect' | 'line';\n rect: PctRect;\n fill?: string;\n stroke?: string;\n strokeWidthPx?: number;\n borderRadius?: number;\n}\n\nexport interface ExtractedSlideLayout {\n partPath: string;\n /** `p:cSld@name` ('' when absent). */\n name: string;\n /** `p:sldLayout@type` (ST_SlideLayoutType) when present. */\n typeAttr?: string;\n masterPath?: string;\n masterName?: string;\n /** Content placeholders — dt/ftr/sldNum/hdr chrome already excluded. */\n placeholders: ExtractedPlaceholder[];\n decorations: ExtractedDecoration[];\n /** Number of slides in this deck using this layout (0 = defined but unused). */\n slideCount: number;\n}\n\n/** Scheme-color hints for decoration fills, supplied by theme extraction. */\nexport interface PptxColorHints {\n text?: string;\n background?: string;\n /** `a:schemeClr@val` (accent1…, bg1, tx1, dk1, …) → resolved hex. */\n schemeColors?: Record<string, string>;\n}\n\nexport type BuiltinParamSpec =\n | 'titleSubtitle'\n | 'comparisonPairs'\n | 'featureImage'\n | 'photoGridGate';\n\nexport type LayoutVerdict =\n | { kind: 'plain' }\n | { kind: 'skip' }\n | {\n kind: 'builtin';\n template: string;\n paramSpec?: BuiltinParamSpec;\n /** For `comparisonPairs`: placeholder idx lists per column, top-to-bottom. */\n columns?: { left: number[]; right: number[] };\n }\n | { kind: 'custom'; def: CustomTemplateDefinition };\n\nexport interface AnalyzedLayout {\n extracted: ExtractedSlideLayout;\n verdict: LayoutVerdict;\n /** Human-readable caveats: dropped regions, unsupported placeholders, … */\n notes: string[];\n}\n\nexport interface PptxLayoutInference {\n slideSize: { cx: number; cy: number };\n layouts: AnalyzedLayout[];\n byLayoutPath: Map<string, AnalyzedLayout>;\n layoutPathBySlide: Map<string, string>;\n warnings: string[];\n}\n\nexport interface AnalyzePptxLayoutsOptions extends OoxmlOpenOptions {\n /** Also analyze layouts no slide references (default false). */\n includeUnused?: boolean;\n colors?: PptxColorHints;\n /** Cap on generated custom templates (default 12); excess downgrades to plain. */\n maxTemplates?: number;\n}\n\n// ── Constants ────────────────────────────────────────────────────────\n\nconst DEFAULT_SLIDE_SIZE = { cx: 12192000, cy: 6858000 };\nconst CHROME_PH_TYPES = new Set(['dt', 'ftr', 'sldNum', 'hdr']);\nconst MAX_INFERRED_TEMPLATES = 12;\nconst MAX_DECORATIONS = 4;\n/** Decorative rects smaller than this share of the slide are clutter. */\nconst MIN_DECORATION_AREA_PCT = 2;\n\n/** Default rects mirroring the exporter's slide proportions (percent). */\nconst DEFAULT_TITLE_RECT: PctRect = { x: 5, y: 4, w: 90, h: 16.7 };\nconst DEFAULT_BODY_RECT: PctRect = { x: 5, y: 23.3, w: 90, h: 66 };\n\nconst DEFAULT_TITLE_PT = 44;\nconst DEFAULT_SUBTITLE_PT = 24;\nconst DEFAULT_BODY_PT = 22;\n\n// ── Small helpers ────────────────────────────────────────────────────\n\nfunction firstPml(parent: Element | Document, local: string): Element | null {\n const els = parent.getElementsByTagNameNS(NS_PML, local);\n return els.length > 0 ? els[0]! : null;\n}\n\nfunction firstDml(parent: Element | Document, local: string): Element | null {\n const els = parent.getElementsByTagNameNS(NS_DRAWINGML, local);\n return els.length > 0 ? els[0]! : null;\n}\n\nfunction intAttr(el: Element | null, name: string): number | undefined {\n const raw = el?.getAttribute(name);\n if (!raw) return undefined;\n const n = parseInt(raw, 10);\n return Number.isFinite(n) ? n : undefined;\n}\n\nfunction pct(value: number, total: number): number {\n const raw = (value / total) * 100;\n const clamped = Math.max(-10, Math.min(110, raw));\n return Math.round(clamped * 100) / 100;\n}\n\nfunction emuToPct(rect: EmuRect, sldSz: { cx: number; cy: number }): PctRect {\n return {\n x: pct(rect.x, sldSz.cx),\n y: pct(rect.y, sldSz.cy),\n w: pct(rect.cx, sldSz.cx),\n h: pct(rect.cy, sldSz.cy),\n };\n}\n\n/** Read `a:xfrm` (off + ext) under a shape's `p:spPr`. Degenerate extents count as missing. */\nfunction readXfrm(sp: Element): EmuRect | null {\n const spPr = firstPml(sp, 'spPr');\n if (!spPr) return null;\n const xfrm = firstDml(spPr, 'xfrm');\n if (!xfrm) return null;\n const off = firstDml(xfrm, 'off');\n const ext = firstDml(xfrm, 'ext');\n const x = intAttr(off, 'x');\n const y = intAttr(off, 'y');\n const cx = intAttr(ext, 'cx');\n const cy = intAttr(ext, 'cy');\n if (x === undefined || y === undefined || cx === undefined || cy === undefined) return null;\n if (cx <= 0 || cy <= 0) return null;\n return { x, y, cx, cy };\n}\n\nfunction placeholderKind(rawType: string): PlaceholderKind {\n switch (rawType) {\n case 'title':\n case 'ctrTitle':\n return 'title';\n case 'subTitle':\n return 'subtitle';\n case '':\n case 'body':\n case 'obj':\n return 'text';\n case 'pic':\n case 'clipArt':\n case 'media':\n return 'picture';\n case 'tbl':\n return 'table';\n case 'chart':\n case 'dgm':\n return 'chart';\n default:\n return 'other';\n }\n}\n\n/** Collapse a ph type onto the master-matching base type (ECMA-376 inheritance). */\nfunction basePhType(rawType: string): string {\n switch (rawType) {\n case 'ctrTitle':\n return 'title';\n case '':\n case 'subTitle':\n case 'obj':\n case 'pic':\n case 'clipArt':\n case 'media':\n case 'tbl':\n case 'chart':\n case 'dgm':\n return 'body';\n default:\n return rawType;\n }\n}\n\nfunction parseLvl1Style(container: Element): PlaceholderTextStyle | undefined {\n const lvl1 = firstDml(container, 'lvl1pPr');\n if (!lvl1) return undefined;\n const style: PlaceholderTextStyle = {};\n const algn = lvl1.getAttribute('algn');\n if (algn === 'ctr') style.align = 'center';\n else if (algn === 'r') style.align = 'right';\n else if (algn === 'l') style.align = 'left';\n const defRPr = firstDml(lvl1, 'defRPr');\n const sz = intAttr(defRPr, 'sz');\n if (sz !== undefined && sz > 0) style.fontSizePt = sz / 100;\n const b = defRPr?.getAttribute('b');\n if (b === '1' || b === 'true') style.bold = true;\n else if (b === '0' || b === 'false') style.bold = false;\n return Object.keys(style).length > 0 ? style : undefined;\n}\n\nfunction mergeTextStyle(\n primary: PlaceholderTextStyle | undefined,\n fallback: PlaceholderTextStyle | undefined,\n): PlaceholderTextStyle | undefined {\n if (!primary) return fallback;\n if (!fallback) return primary;\n return {\n fontSizePt: primary.fontSizePt ?? fallback.fontSizePt,\n bold: primary.bold ?? fallback.bold,\n align: primary.align ?? fallback.align,\n anchor: primary.anchor ?? fallback.anchor,\n };\n}\n\n// ── Master placeholder index ─────────────────────────────────────────\n\ninterface MasterEntry {\n rect: EmuRect | null;\n style?: PlaceholderTextStyle;\n}\n\ninterface MasterIndex {\n name: string;\n exact: Map<string, MasterEntry>;\n baseIdx: Map<string, MasterEntry>;\n base: Map<string, MasterEntry>;\n titleStyle?: PlaceholderTextStyle;\n bodyStyle?: PlaceholderTextStyle;\n}\n\nasync function readMasterIndex(pkg: OoxmlPackage, masterPath: string): Promise<MasterIndex> {\n const index: MasterIndex = { name: '', exact: new Map(), baseIdx: new Map(), base: new Map() };\n const doc = await getPartXml(pkg, masterPath);\n if (!doc) return index;\n\n index.name = firstPml(doc, 'cSld')?.getAttribute('name')?.trim() ?? '';\n\n const txStyles = firstPml(doc, 'txStyles');\n if (txStyles) {\n const titleStyle = firstPml(txStyles, 'titleStyle');\n const bodyStyle = firstPml(txStyles, 'bodyStyle');\n if (titleStyle) index.titleStyle = parseLvl1Style(titleStyle);\n if (bodyStyle) index.bodyStyle = parseLvl1Style(bodyStyle);\n }\n\n const shapes = doc.getElementsByTagNameNS(NS_PML, 'sp');\n for (let i = 0; i < shapes.length; i++) {\n const sp = shapes[i]!;\n const ph = firstPml(sp, 'ph');\n if (!ph) continue;\n const rawType = ph.getAttribute('type') ?? '';\n const idx = intAttr(ph, 'idx') ?? 0;\n const entry: MasterEntry = { rect: readXfrm(sp) };\n const txBody = firstPml(sp, 'txBody');\n const lstStyle = txBody ? firstDml(txBody, 'lstStyle') : null;\n if (lstStyle) entry.style = parseLvl1Style(lstStyle);\n\n const typeKey = `${rawType || 'body'}:${idx}`;\n if (!index.exact.has(typeKey)) index.exact.set(typeKey, entry);\n const base = basePhType(rawType);\n const baseIdxKey = `${base}:${idx}`;\n if (!index.baseIdx.has(baseIdxKey)) index.baseIdx.set(baseIdxKey, entry);\n if (!index.base.has(base)) index.base.set(base, entry);\n }\n return index;\n}\n\n// ── Layout extraction ────────────────────────────────────────────────\n\nfunction resolveFillColor(solidFill: Element, hints: PptxColorHints): string | undefined {\n const srgb = firstDml(solidFill, 'srgbClr');\n const srgbVal = srgb?.getAttribute('val');\n if (srgbVal && /^[0-9a-fA-F]{6}$/.test(srgbVal)) return `#${srgbVal.toLowerCase()}`;\n const scheme = firstDml(solidFill, 'schemeClr');\n const schemeVal = scheme?.getAttribute('val');\n if (schemeVal && hints.schemeColors?.[schemeVal]) return hints.schemeColors[schemeVal];\n return undefined;\n}\n\n/** Direct child element of `parent` with the given DrawingML local name. */\nfunction directDmlChild(parent: Element, local: string): Element | null {\n for (let i = 0; i < parent.childNodes.length; i++) {\n const child = parent.childNodes[i];\n if (child && child.nodeType === 1 && (child as Element).localName === local) {\n const el = child as Element;\n if (el.namespaceURI === NS_DRAWINGML) return el;\n }\n }\n return null;\n}\n\nfunction extractDecoration(\n sp: Element,\n sldSz: { cx: number; cy: number },\n pxPerPt: number,\n hints: PptxColorHints,\n): ExtractedDecoration | null {\n const rectEmu = readXfrm(sp);\n if (!rectEmu) return null;\n const spPr = firstPml(sp, 'spPr');\n if (!spPr) return null;\n const prst = firstDml(spPr, 'prstGeom')?.getAttribute('prst');\n\n if (prst === 'line' || prst === 'straightConnector1') {\n const ln = directDmlChild(spPr, 'ln');\n const lnFill = ln ? directDmlChild(ln, 'solidFill') : null;\n const stroke = lnFill ? resolveFillColor(lnFill, hints) : undefined;\n if (!stroke) return null;\n const wEmu = intAttr(ln, 'w');\n const strokeWidthPx = wEmu\n ? Math.max(1, Math.min(40, Math.round((wEmu / 12700) * pxPerPt)))\n : 2;\n return { shape: 'line', rect: emuToPct(rectEmu, sldSz), stroke, strokeWidthPx };\n }\n\n if (prst === 'rect' || prst === 'roundRect') {\n const solidFill = directDmlChild(spPr, 'solidFill');\n const fill = solidFill ? resolveFillColor(solidFill, hints) : undefined;\n if (!fill) return null;\n const areaPct = ((rectEmu.cx * rectEmu.cy) / (sldSz.cx * sldSz.cy)) * 100;\n if (areaPct < MIN_DECORATION_AREA_PCT) return null;\n return {\n shape: 'rect',\n rect: emuToPct(rectEmu, sldSz),\n fill,\n ...(prst === 'roundRect' ? { borderRadius: 8 } : {}),\n };\n }\n\n return null;\n}\n\nasync function extractLayout(\n pkg: OoxmlPackage,\n layoutPath: string,\n sldSz: { cx: number; cy: number },\n pxPerPt: number,\n hints: PptxColorHints,\n masterCache: Map<string, Promise<MasterIndex>>,\n): Promise<ExtractedSlideLayout | null> {\n const doc = await getPartXml(pkg, layoutPath);\n if (!doc) return null;\n\n const name = firstPml(doc, 'cSld')?.getAttribute('name')?.trim() ?? '';\n const typeAttr = doc.documentElement?.getAttribute('type') ?? undefined;\n\n let masterPath: string | undefined;\n let master: MasterIndex | undefined;\n const layoutRels = await getPartRelationships(pkg, layoutPath);\n const masterRel = findRelByType(layoutRels, REL_SLIDE_MASTER);\n if (masterRel) {\n masterPath = resolveTarget(baseDirOf(layoutPath), masterRel.target);\n let cached = masterCache.get(masterPath);\n if (!cached) {\n cached = readMasterIndex(pkg, masterPath);\n masterCache.set(masterPath, cached);\n }\n master = await cached;\n }\n\n const placeholders: ExtractedPlaceholder[] = [];\n const decorations: ExtractedDecoration[] = [];\n\n const shapes = doc.getElementsByTagNameNS(NS_PML, 'sp');\n for (let i = 0; i < shapes.length; i++) {\n const sp = shapes[i]!;\n const ph = firstPml(sp, 'ph');\n\n if (!ph) {\n if (decorations.length < MAX_DECORATIONS) {\n const decoration = extractDecoration(sp, sldSz, pxPerPt, hints);\n if (decoration) decorations.push(decoration);\n }\n continue;\n }\n\n const rawType = ph.getAttribute('type') ?? '';\n if (CHROME_PH_TYPES.has(rawType)) continue;\n const idx = intAttr(ph, 'idx') ?? 0;\n const kind = placeholderKind(rawType);\n\n // Geometry: own xfrm → master by (type, idx) → by (base, idx) → by base → defaults.\n const own = readXfrm(sp);\n let rectEmu = own;\n let inheritedFromMaster = false;\n if (!rectEmu && master) {\n const base = basePhType(rawType);\n const entry =\n master.exact.get(`${rawType || 'body'}:${idx}`) ??\n master.baseIdx.get(`${base}:${idx}`) ??\n master.base.get(base);\n if (entry?.rect) {\n rectEmu = entry.rect;\n inheritedFromMaster = true;\n }\n }\n const rect = rectEmu\n ? emuToPct(rectEmu, sldSz)\n : kind === 'title'\n ? { ...DEFAULT_TITLE_RECT }\n : { ...DEFAULT_BODY_RECT };\n\n // Text style: layout lstStyle → master ph style → master txStyles.\n const txBody = firstPml(sp, 'txBody');\n const lstStyle = txBody ? firstDml(txBody, 'lstStyle') : null;\n let textStyle = lstStyle ? parseLvl1Style(lstStyle) : undefined;\n if (master) {\n const base = basePhType(rawType);\n const masterEntry =\n master.exact.get(`${rawType || 'body'}:${idx}`) ?? master.baseIdx.get(`${base}:${idx}`);\n textStyle = mergeTextStyle(textStyle, masterEntry?.style);\n textStyle = mergeTextStyle(\n textStyle,\n kind === 'title' || kind === 'subtitle' ? master.titleStyle : master.bodyStyle,\n );\n }\n\n const bodyPr = txBody ? firstDml(txBody, 'bodyPr') : null;\n const anchor = bodyPr?.getAttribute('anchor');\n if (anchor === 't' || anchor === 'ctr' || anchor === 'b') {\n textStyle = {\n ...(textStyle ?? {}),\n anchor: anchor === 't' ? 'top' : anchor === 'ctr' ? 'middle' : 'bottom',\n };\n }\n\n const orient = ph.getAttribute('orient');\n const vert = bodyPr?.getAttribute('vert');\n const vertical = orient === 'vert' || (!!vert && vert !== 'horz');\n\n placeholders.push({\n kind,\n rawType,\n idx,\n rect,\n inheritedFromMaster,\n vertical,\n ...(textStyle ? { textStyle } : {}),\n });\n }\n\n return {\n partPath: layoutPath,\n name,\n ...(typeAttr ? { typeAttr } : {}),\n ...(masterPath ? { masterPath } : {}),\n ...(master?.name ? { masterName: master.name } : {}),\n placeholders,\n decorations,\n slideCount: 0,\n };\n}\n\n// ── Geometry predicates ──────────────────────────────────────────────\n\nfunction overlap1D(aStart: number, aLen: number, bStart: number, bLen: number): number {\n return Math.max(0, Math.min(aStart + aLen, bStart + bLen) - Math.max(aStart, bStart));\n}\n\nfunction sideBySide(a: PctRect, b: PctRect): boolean {\n const xOverlap = overlap1D(a.x, a.w, b.x, b.w);\n const yOverlap = overlap1D(a.y, a.h, b.y, b.h);\n return (\n xOverlap <= 0.15 * Math.min(a.w, b.w) &&\n yOverlap >= 0.5 * Math.min(a.h, b.h) &&\n a.w >= 25 &&\n b.w >= 25\n );\n}\n\nfunction stackedAbove(a: PctRect, b: PctRect): boolean {\n const xOverlap = overlap1D(a.x, a.w, b.x, b.w);\n const yOverlap = overlap1D(a.y, a.h, b.y, b.h);\n return yOverlap <= 0.15 * Math.min(a.h, b.h) && xOverlap >= 0.5 * Math.min(a.w, b.w) && a.y < b.y;\n}\n\nfunction fullBleed(p: PctRect): boolean {\n return p.w >= 85 && p.h >= 80;\n}\n\nfunction nearEqualWidth(a: PctRect, b: PctRect): boolean {\n return Math.abs(a.w - b.w) <= 0.15 * Math.max(a.w, b.w);\n}\n\nfunction rectsOverlap(a: PctRect, b: PctRect): boolean {\n return overlap1D(a.x, a.w, b.x, b.w) > 2 && overlap1D(a.y, a.h, b.y, b.h) > 2;\n}\n\nfunction centerX(r: PctRect): number {\n return r.x + r.w / 2;\n}\n\n// ── Classifier ───────────────────────────────────────────────────────\n\ntype Directive =\n | { kind: 'plain' }\n | { kind: 'skip' }\n | { kind: 'builtin'; template: string; paramSpec?: BuiltinParamSpec }\n | { kind: 'feature-by-geometry' }\n | { kind: 'comparison' }\n | { kind: 'custom-two-column' }\n | { kind: 'custom-caption' }\n | { kind: 'custom-generic' }\n | { kind: 'by-geometry' };\n\nconst PLAIN_LAYOUT_TYPES = new Set([\n 'titleOnly',\n 'tx',\n 'obj',\n 'objOnly',\n 'objTx',\n 'txOverObj',\n 'objOverTx',\n 'tbl',\n 'chart',\n 'dgm',\n 'txAndChart',\n 'chartAndTx',\n 'vertTitleAndTxOverChart',\n 'txAndTwoObj',\n 'twoObjAndTx',\n 'twoObjOverTx',\n 'objAndTwoObj',\n 'twoObjAndObj',\n 'fourObj',\n 'vertTx',\n 'vertTitleAndTx',\n 'clipArtAndVertTx',\n]);\n\nfunction stage1(typeAttr: string | undefined): Directive | null {\n if (!typeAttr || typeAttr === 'cust') return null;\n if (typeAttr === 'title')\n return { kind: 'builtin', template: 'title', paramSpec: 'titleSubtitle' };\n if (typeAttr === 'secHead') return { kind: 'builtin', template: 'sectionHeader' };\n if (typeAttr === 'blank') return { kind: 'skip' };\n if (PLAIN_LAYOUT_TYPES.has(typeAttr)) return { kind: 'plain' };\n if (typeAttr === 'picTx') return { kind: 'feature-by-geometry' };\n if (typeAttr === 'clipArtAndTx' || typeAttr === 'mediaAndTx') {\n return { kind: 'builtin', template: 'leftFeature', paramSpec: 'featureImage' };\n }\n if (typeAttr === 'txAndClipArt' || typeAttr === 'txAndMedia') {\n return { kind: 'builtin', template: 'rightFeature', paramSpec: 'featureImage' };\n }\n if (\n typeAttr === 'twoColTx' ||\n typeAttr === 'twoObj' ||\n typeAttr === 'txAndObj' ||\n typeAttr === 'objAndTx'\n ) {\n return { kind: 'custom-two-column' };\n }\n if (typeAttr === 'twoTxTwoObj') return { kind: 'comparison' };\n // Unknown/future type values fall through to name + geometry stages.\n return null;\n}\n\nconst WELL_KNOWN_NAMES: Record<string, Directive> = {\n 'title slide': { kind: 'builtin', template: 'title', paramSpec: 'titleSubtitle' },\n 'section header': { kind: 'builtin', template: 'sectionHeader' },\n 'two content': { kind: 'custom-two-column' },\n comparison: { kind: 'comparison' },\n 'content with caption': { kind: 'custom-caption' },\n 'picture with caption': { kind: 'feature-by-geometry' },\n 'title and content': { kind: 'plain' },\n 'title only': { kind: 'plain' },\n blank: { kind: 'skip' },\n 'vertical title and text': { kind: 'plain' },\n 'title and vertical text': { kind: 'plain' },\n};\n\nfunction stage2(name: string): Directive | null {\n return WELL_KNOWN_NAMES[name.trim().toLowerCase()] ?? null;\n}\n\nfunction contentPlaceholders(layout: ExtractedSlideLayout): ExtractedPlaceholder[] {\n return layout.placeholders.filter((p) => p.kind !== 'title' && p.kind !== 'subtitle');\n}\n\nfunction stage3(layout: ExtractedSlideLayout): Directive {\n if (layout.placeholders.some((p) => p.vertical)) return { kind: 'plain' };\n const hasTitle = layout.placeholders.some((p) => p.kind === 'title');\n const content = contentPlaceholders(layout);\n if (content.length === 0) return hasTitle ? { kind: 'plain' } : { kind: 'skip' };\n\n const texts = content.filter((p) => p.kind === 'text');\n const pictures = content.filter((p) => p.kind === 'picture');\n const others = content.filter((p) => p.kind !== 'text' && p.kind !== 'picture');\n\n if (pictures.length === 0 && others.length === 0) {\n if (texts.length === 1) return { kind: 'plain' };\n if (texts.length === 2 && sideBySide(texts[0]!.rect, texts[1]!.rect)) {\n return nearEqualWidth(texts[0]!.rect, texts[1]!.rect)\n ? { kind: 'custom-two-column' }\n : { kind: 'custom-caption' };\n }\n if (texts.length === 4 && findComparisonColumns(texts)) return { kind: 'comparison' };\n return { kind: 'plain' };\n }\n\n if (pictures.length === 1 && others.length === 0) {\n if (texts.length === 0) {\n return fullBleed(pictures[0]!.rect)\n ? { kind: 'builtin', template: 'imageWithCaption', paramSpec: 'featureImage' }\n : { kind: 'custom-generic' };\n }\n return { kind: 'feature-by-geometry' };\n }\n\n if (\n pictures.length >= 2 &&\n pictures.length <= 4 &&\n texts.length === 0 &&\n others.length === 0 &&\n pictures.every((a, i) => pictures.every((b, j) => i === j || !rectsOverlap(a.rect, b.rect)))\n ) {\n return { kind: 'builtin', template: 'photoGrid', paramSpec: 'photoGridGate' };\n }\n\n return { kind: 'plain' };\n}\n\n/**\n * Detect the Comparison shape: 4 texts forming two side-by-side columns of a\n * short header over a taller body. Returns placeholder idx lists per column,\n * or null when the rects don't form that shape.\n */\nfunction findComparisonColumns(\n texts: ExtractedPlaceholder[],\n): { left: number[]; right: number[] } | null {\n if (texts.length !== 4) return null;\n const sorted = [...texts].sort((a, b) => centerX(a.rect) - centerX(b.rect));\n const leftPair = [sorted[0]!, sorted[1]!];\n const rightPair = [sorted[2]!, sorted[3]!];\n const columnWidth = (pair: ExtractedPlaceholder[]) =>\n Math.abs(centerX(pair[0]!.rect) - centerX(pair[1]!.rect));\n if (columnWidth(leftPair) > 10 || columnWidth(rightPair) > 10) return null;\n if (centerX(rightPair[0]!.rect) - centerX(leftPair[1]!.rect) <= 10) return null;\n\n const orderColumn = (pair: ExtractedPlaceholder[]): number[] | null => {\n const byY = [...pair].sort((a, b) => a.rect.y - b.rect.y);\n const header = byY[0]!;\n const body = byY[1]!;\n if (header.rect.h > 20 || header.rect.y + header.rect.h > body.rect.y + 2) return null;\n return [header.idx, body.idx];\n };\n const left = orderColumn(leftPair);\n const right = orderColumn(rightPair);\n return left && right ? { left, right } : null;\n}\n\n// ── Custom template generation ───────────────────────────────────────\n\nfunction slugify(name: string): string {\n const slug = name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n return slug;\n}\n\nfunction pctPosition(rect: PctRect): Position {\n return { x: `${rect.x}%`, y: `${rect.y}%`, width: `${rect.w}%`, height: `${rect.h}%` };\n}\n\ninterface GeneratorContext {\n hints: PptxColorHints;\n pxPerPt: number;\n viewport: { width: number; height: number };\n notes: string[];\n}\n\nfunction fontPx(pt: number | undefined, defaultPt: number, pxPerPt: number): number {\n const sizePt = pt && pt > 0 ? pt : defaultPt;\n return Math.max(16, Math.min(140, Math.round(sizePt * pxPerPt)));\n}\n\nfunction textLayerFor(\n id: string,\n ph: ExtractedPlaceholder,\n text: string,\n role: 'title' | 'subtitle' | 'body',\n gen: GeneratorContext,\n): TextLayer {\n const defaultPt =\n role === 'title'\n ? DEFAULT_TITLE_PT\n : role === 'subtitle'\n ? DEFAULT_SUBTITLE_PT\n : DEFAULT_BODY_PT;\n const style: TextStyle = {\n fontSize: fontPx(ph.textStyle?.fontSizePt, defaultPt, gen.pxPerPt),\n color: gen.hints.text ?? '#1a1a1a',\n lineHeight: role === 'title' ? 1.15 : 1.4,\n ...(role === 'title'\n ? { fontWeight: ph.textStyle?.bold === false ? 'normal' : 'bold' }\n : ph.textStyle?.bold\n ? { fontWeight: 'bold' }\n : {}),\n ...(ph.textStyle?.align ? { textAlign: ph.textStyle.align } : {}),\n ...(ph.textStyle?.anchor ? { verticalAlign: ph.textStyle.anchor } : {}),\n };\n return { id, type: 'text', position: pctPosition(ph.rect), content: { text, style } };\n}\n\nfunction imageLayerFor(id: string, ph: ExtractedPlaceholder, imageIndex: number): ImageLayer {\n // {image:N} is 0-based; a layer whose token resolves to no image is\n // dropped whole at render time, so picture placeholders degrade cleanly\n // on slides without pictures.\n return {\n id,\n type: 'image',\n position: pctPosition(ph.rect),\n content: { src: `{image:${imageIndex}}`, alt: `{image:${imageIndex}}`, fit: 'cover' },\n };\n}\n\nfunction decorationLayers(layout: ExtractedSlideLayout): ShapeLayer[] {\n return layout.decorations.map((d, i) => ({\n id: `decor-${i + 1}`,\n type: 'shape' as const,\n position: pctPosition(d.rect),\n content:\n d.shape === 'line'\n ? { shape: 'line' as const, stroke: d.stroke, strokeWidth: d.strokeWidthPx ?? 2 }\n : {\n shape: 'rect' as const,\n fill: d.fill,\n ...(d.borderRadius ? { borderRadius: d.borderRadius } : {}),\n },\n }));\n}\n\nfunction titlePlaceholder(layout: ExtractedSlideLayout): ExtractedPlaceholder | undefined {\n return layout.placeholders.find((p) => p.kind === 'title');\n}\n\n/** Synthetic title placeholder used when a layout omits one but a template needs it. */\nfunction defaultTitlePlaceholder(): ExtractedPlaceholder {\n return {\n kind: 'title',\n rawType: 'title',\n idx: 0,\n rect: { ...DEFAULT_TITLE_RECT },\n inheritedFromMaster: false,\n vertical: false,\n };\n}\n\nfunction buildTwoColumnDef(\n layout: ExtractedSlideLayout,\n gen: GeneratorContext,\n): CustomTemplateLayer[] {\n const texts = contentPlaceholders(layout).filter((p) => p.kind === 'text');\n let left: ExtractedPlaceholder;\n let right: ExtractedPlaceholder;\n const sorted = [...texts].sort((a, b) => a.rect.x - b.rect.x);\n if (sorted.length >= 2 && sideBySide(sorted[0]!.rect, sorted[sorted.length - 1]!.rect)) {\n left = sorted[0]!;\n right = sorted[sorted.length - 1]!;\n } else {\n // Geometry unavailable (defaulted rects) — synthesize equal columns\n // inside the standard body area with a 4% gutter.\n left = {\n ...defaultTitlePlaceholder(),\n kind: 'text',\n rawType: 'body',\n rect: { x: 5, y: 23.3, w: 43, h: 66 },\n };\n right = { ...left, rect: { x: 52, y: 23.3, w: 43, h: 66 } };\n }\n\n const gap = Math.max(0, Math.round((right.rect.x - (left.rect.x + left.rect.w)) * 100) / 100);\n const layers: CustomTemplateLayer[] = [...decorationLayers(layout)];\n const title = titlePlaceholder(layout) ?? defaultTitlePlaceholder();\n layers.push(textLayerFor('title', title, '{title}', 'title', gen));\n const itemLayer: CustomTemplateLayer = {\n ...textLayerFor('column', left, '{item}', 'body', gen),\n // gap is in percentage points because the layer's width is a %-string;\n // the repeat resolver offsets clones by width + gap in the same unit.\n repeat: { source: 'listItems', direction: 'row', gap, max: 2 },\n };\n layers.push(itemLayer);\n return layers;\n}\n\nfunction buildCaptionDef(\n layout: ExtractedSlideLayout,\n gen: GeneratorContext,\n): CustomTemplateLayer[] {\n const texts = contentPlaceholders(layout).filter((p) => p.kind === 'text');\n const byWidth = [...texts].sort((a, b) => b.rect.w - a.rect.w);\n const wide = byWidth[0];\n const narrow = byWidth[1];\n const layers: CustomTemplateLayer[] = [...decorationLayers(layout)];\n const title = titlePlaceholder(layout) ?? defaultTitlePlaceholder();\n layers.push(textLayerFor('title', title, '{title}', 'title', gen));\n if (wide) layers.push(textLayerFor('body', wide, '{content}', 'body', gen));\n if (narrow) {\n // Empty pipe-default: the caption region stays invisible until the\n // author fills it via `{[name caption=\"…\"]}`.\n layers.push(textLayerFor('caption', narrow, '{attr:caption|}', 'body', gen));\n }\n return layers;\n}\n\nfunction buildGenericDef(\n layout: ExtractedSlideLayout,\n gen: GeneratorContext,\n): CustomTemplateLayer[] {\n const layers: CustomTemplateLayer[] = [...decorationLayers(layout)];\n const title = titlePlaceholder(layout);\n if (title) layers.push(textLayerFor('title', title, '{title}', 'title', gen));\n\n const content = contentPlaceholders(layout);\n const pictures = content\n .filter((p) => p.kind === 'picture')\n .sort((a, b) => a.idx - b.idx || a.rect.y - b.rect.y);\n pictures.forEach((ph, k) => layers.push(imageLayerFor(`image-${k}`, ph, k)));\n\n const texts = content.filter((p) => p.kind === 'text');\n if (texts.length > 0) layers.push(textLayerFor('body', texts[0]!, '{content}', 'body', gen));\n if (texts.length > 1) {\n gen.notes.push(\n `${texts.length - 1} additional text region(s) could not be bound — the token grammar has no per-region address; full text stays in the markdown body.`,\n );\n }\n const dropped = content.filter(\n (p) => p.kind === 'table' || p.kind === 'chart' || p.kind === 'other',\n );\n if (dropped.length > 0) {\n gen.notes.push(\n `${dropped.length} table/chart placeholder(s) dropped (content flows as markdown).`,\n );\n }\n return layers;\n}\n\n/**\n * Whether generated layers contain any content-bearing layer (something a\n * slide's title/body/images will bind to) beyond decorations.\n */\nfunction hasContentLayer(layers: CustomTemplateLayer[]): boolean {\n return layers.some((l) => l.type === 'text' || l.type === 'image');\n}\n\n// ── Verdict resolution ───────────────────────────────────────────────\n\nfunction resolveFeatureByGeometry(layout: ExtractedSlideLayout): LayoutVerdict {\n const content = contentPlaceholders(layout);\n const pic = content.find((p) => p.kind === 'picture');\n if (!pic) return { kind: 'plain' };\n const texts = content.filter((p) => p.kind === 'text');\n const beside = texts.find((t) => sideBySide(pic.rect, t.rect));\n if (beside) {\n const template = centerX(pic.rect) < centerX(beside.rect) ? 'leftFeature' : 'rightFeature';\n return { kind: 'builtin', template, paramSpec: 'featureImage' };\n }\n if (texts.some((t) => stackedAbove(pic.rect, t.rect)) || fullBleed(pic.rect)) {\n return { kind: 'builtin', template: 'imageWithCaption', paramSpec: 'featureImage' };\n }\n return { kind: 'builtin', template: 'leftFeature', paramSpec: 'featureImage' };\n}\n\nfunction classifyLayout(layout: ExtractedSlideLayout): Directive {\n return stage1(layout.typeAttr) ?? stage2(layout.name) ?? stage3(layout);\n}\n\nfunction resolveVerdict(\n layout: ExtractedSlideLayout,\n directive: Directive,\n gen: GeneratorContext,\n templateName: string,\n): LayoutVerdict {\n switch (directive.kind) {\n case 'plain':\n case 'skip':\n return { kind: directive.kind };\n case 'builtin':\n return directive;\n case 'feature-by-geometry':\n return resolveFeatureByGeometry(layout);\n case 'comparison': {\n const texts = contentPlaceholders(layout).filter((p) => p.kind === 'text');\n const columns = findComparisonColumns(texts);\n // Without resolvable column geometry the importer can't attribute\n // slide texts to sides — and a bare {[twoColumn]} renders empty.\n if (!columns) return { kind: 'plain' };\n return { kind: 'builtin', template: 'twoColumn', paramSpec: 'comparisonPairs', columns };\n }\n case 'custom-two-column':\n case 'custom-caption':\n case 'custom-generic':\n case 'by-geometry': {\n const layers =\n directive.kind === 'custom-two-column'\n ? buildTwoColumnDef(layout, gen)\n : directive.kind === 'custom-caption'\n ? buildCaptionDef(layout, gen)\n : buildGenericDef(layout, gen);\n if (!hasContentLayer(layers)) return { kind: 'plain' };\n const def: CustomTemplateDefinition = {\n name: templateName,\n label: layout.name || 'Imported layout',\n description: `Imported from PowerPoint layout \"${layout.name || templateName}\"${\n layout.masterName ? ` (master \"${layout.masterName}\")` : ''\n }`,\n viewport: gen.viewport,\n layers,\n };\n return { kind: 'custom', def };\n }\n }\n}\n\n// ── Deck-level analysis ──────────────────────────────────────────────\n\nasync function readSlideSize(pkg: OoxmlPackage): Promise<{ cx: number; cy: number }> {\n const pres = await getPartXml(pkg, 'ppt/presentation.xml');\n const sldSz = pres ? firstPml(pres, 'sldSz') : null;\n const cx = intAttr(sldSz, 'cx');\n const cy = intAttr(sldSz, 'cy');\n if (cx && cy && cx > 0 && cy > 0) return { cx, cy };\n return { ...DEFAULT_SLIDE_SIZE };\n}\n\nasync function orderedSlidePathsForLayouts(pkg: OoxmlPackage): Promise<string[]> {\n const pres = await getPartXml(pkg, 'ppt/presentation.xml');\n if (!pres) return [];\n const rels = await getPartRelationships(pkg, 'ppt/presentation.xml');\n const relById = new Map(rels.map((r) => [r.id, r.target]));\n const out: string[] = [];\n const ids = pres.getElementsByTagNameNS(NS_PML, 'sldId');\n for (let i = 0; i < ids.length; i++) {\n const rid = attrNS(ids[i]!, NS_R, 'id', 'r:id');\n const target = rid ? relById.get(rid) : undefined;\n if (target) out.push(resolveTarget('ppt', target));\n }\n return out;\n}\n\nfunction viewportFor(sldSz: { cx: number; cy: number }): { width: number; height: number } {\n if (sldSz.cy > sldSz.cx) {\n return { width: 1080, height: Math.round((1080 * sldSz.cy) / sldSz.cx) };\n }\n return { width: Math.round((1080 * sldSz.cx) / sldSz.cy), height: 1080 };\n}\n\n/**\n * Analyze the deck's slide layouts: extract placeholder geometry (with\n * master inheritance), classify each layout against the built-in template\n * set, and generate custom template definitions for the distinctive ones.\n */\nexport async function analyzePptxLayouts(\n pkg: OoxmlPackage,\n options: AnalyzePptxLayoutsOptions = {},\n): Promise<PptxLayoutInference> {\n const warnings: string[] = [];\n const hints = options.colors ?? {};\n const maxTemplates = options.maxTemplates ?? MAX_INFERRED_TEMPLATES;\n\n const sldSz = await readSlideSize(pkg);\n const viewport = viewportFor(sldSz);\n const pxPerPt = viewport.height / (sldSz.cy / 12700);\n\n // Layouts used by slides, in first-use order, with usage counts.\n const slidePaths = await orderedSlidePathsForLayouts(pkg);\n const layoutPathBySlide = new Map<string, string>();\n const usage = new Map<string, number>();\n const orderedLayoutPaths: string[] = [];\n for (const slidePath of slidePaths) {\n const rels = await getPartRelationships(pkg, slidePath);\n const layoutRel = findRelByType(rels, REL_SLIDE_LAYOUT);\n if (!layoutRel) continue;\n const layoutPath = resolveTarget(baseDirOf(slidePath), layoutRel.target);\n layoutPathBySlide.set(slidePath, layoutPath);\n if (!usage.has(layoutPath)) orderedLayoutPaths.push(layoutPath);\n usage.set(layoutPath, (usage.get(layoutPath) ?? 0) + 1);\n }\n\n if (options.includeUnused) {\n const unused: string[] = [];\n for (const [partPath, contentType] of pkg.contentTypes.overrides) {\n if (contentType === CONTENT_TYPE_PPTX_SLIDE_LAYOUT && !usage.has(partPath)) {\n unused.push(partPath);\n }\n }\n unused.sort();\n orderedLayoutPaths.push(...unused);\n }\n\n // Extract + classify each layout.\n const masterCache = new Map<string, Promise<MasterIndex>>();\n const layouts: AnalyzedLayout[] = [];\n const usedNames = new Set<string>();\n for (let i = 0; i < orderedLayoutPaths.length; i++) {\n const layoutPath = orderedLayoutPaths[i]!;\n const extracted = await extractLayout(pkg, layoutPath, sldSz, pxPerPt, hints, masterCache);\n if (!extracted) {\n warnings.push(`layout ${layoutPath} could not be read; its slides import plain`);\n continue;\n }\n extracted.slideCount = usage.get(layoutPath) ?? 0;\n\n // Unique slug for the (potential) custom template. Reserved up front so\n // two masters sharing a layout name get -2/-3 suffixes deterministically.\n const baseSlug = slugify(extracted.name) || `layout-${i + 1}`;\n let templateName = `pptx-${baseSlug}`;\n for (let n = 2; usedNames.has(templateName); n++) templateName = `pptx-${baseSlug}-${n}`;\n\n const notes: string[] = [];\n const gen: GeneratorContext = { hints, pxPerPt, viewport, notes };\n const directive = classifyLayout(extracted);\n const verdict = resolveVerdict(extracted, directive, gen, templateName);\n if (verdict.kind === 'custom') usedNames.add(templateName);\n layouts.push({ extracted, verdict, notes });\n }\n\n // Cap generated templates, keeping the most-used layouts.\n const customs = layouts.filter((l) => l.verdict.kind === 'custom');\n if (customs.length > maxTemplates) {\n const ranked = [...customs].sort((a, b) => b.extracted.slideCount - a.extracted.slideCount);\n for (const layout of ranked.slice(maxTemplates)) {\n layout.verdict = { kind: 'plain' };\n layout.notes.push('dropped: more inferred layouts than the template cap');\n }\n warnings.push(\n `deck defines ${customs.length} distinctive layouts; kept the ${maxTemplates} most used as custom templates`,\n );\n }\n\n const byLayoutPath = new Map(layouts.map((l) => [l.extracted.partPath, l]));\n return { slideSize: sldSz, layouts, byLayoutPath, layoutPathBySlide, warnings };\n}\n\n// ── Dialog-path inspection API ───────────────────────────────────────\n\nexport interface PptxLayoutSummary {\n layoutPath: string;\n name: string;\n masterName?: string;\n typeAttr?: string;\n slideCount: number;\n verdict: 'builtin' | 'custom' | 'plain' | 'skip';\n /** Set when verdict is 'builtin' — the close built-in alternative. */\n builtinTemplate?: string;\n /** Set when verdict is 'custom' — ready to save as a doc/library template. */\n customTemplate?: CustomTemplateDefinition;\n notes?: string[];\n}\n\nexport type InspectPptxLayoutsOptions = AnalyzePptxLayoutsOptions;\n\n/**\n * Inspect a deck's layouts without importing it — used by the theme dialog\n * to list what a PPTX would contribute (built-in matches shown as\n * informational rows; custom templates offered for confirmation).\n */\nexport async function inspectPptxLayouts(\n data: ArrayBuffer | Blob,\n options: InspectPptxLayoutsOptions = {},\n): Promise<{ layouts: PptxLayoutSummary[]; slideSize: { cx: number; cy: number } }> {\n const pkg = await openPackage(data, options);\n const analysis = await analyzePptxLayouts(pkg, options);\n const layouts = analysis.layouts.map((l, i): PptxLayoutSummary => {\n const { extracted, verdict, notes } = l;\n return {\n layoutPath: extracted.partPath,\n name: extracted.name || `Layout ${i + 1}`,\n ...(extracted.masterName ? { masterName: extracted.masterName } : {}),\n ...(extracted.typeAttr ? { typeAttr: extracted.typeAttr } : {}),\n slideCount: extracted.slideCount,\n verdict: verdict.kind,\n ...(verdict.kind === 'builtin' ? { builtinTemplate: verdict.template } : {}),\n ...(verdict.kind === 'custom' ? { customTemplate: verdict.def } : {}),\n ...(notes.length > 0 ? { notes } : {}),\n };\n });\n return { layouts, slideSize: analysis.slideSize };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
} from "./chunk-U4MRIFKL.js";
|
|
2
|
+
openBoundedZipArchive
|
|
3
|
+
} from "./chunk-H7T5DXUU.js";
|
|
5
4
|
|
|
6
5
|
// src/ooxml/namespaces.ts
|
|
7
6
|
var NS_RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships";
|
|
@@ -51,182 +50,38 @@ var CONTENT_TYPE_XLSX_WORKSHEET = "application/vnd.openxmlformats-officedocument
|
|
|
51
50
|
var CONTENT_TYPE_XLSX_STYLES = "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml";
|
|
52
51
|
var REL_WORKSHEET = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet";
|
|
53
52
|
|
|
54
|
-
// src/ooxml/writer.ts
|
|
55
|
-
import JSZip from "jszip";
|
|
56
|
-
function createPackage() {
|
|
57
|
-
const parts = [];
|
|
58
|
-
const relationships = [];
|
|
59
|
-
let coreProps;
|
|
60
|
-
return {
|
|
61
|
-
addPart(path, content, contentType) {
|
|
62
|
-
parts.push({ path, content, contentType });
|
|
63
|
-
},
|
|
64
|
-
addBinaryPart(path, data, contentType) {
|
|
65
|
-
parts.push({ path, binaryContent: data, contentType });
|
|
66
|
-
},
|
|
67
|
-
addRelationship(sourcePart, rel) {
|
|
68
|
-
relationships.push({ sourcePart, relationship: rel });
|
|
69
|
-
},
|
|
70
|
-
setCoreProperties(props) {
|
|
71
|
-
coreProps = props;
|
|
72
|
-
},
|
|
73
|
-
async toBlob() {
|
|
74
|
-
const zip = assemble(parts, relationships, coreProps);
|
|
75
|
-
return zip.generateAsync({ type: "blob" });
|
|
76
|
-
},
|
|
77
|
-
async toArrayBuffer() {
|
|
78
|
-
const zip = assemble(parts, relationships, coreProps);
|
|
79
|
-
return zip.generateAsync({ type: "arraybuffer" });
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
function assemble(parts, relationships, coreProps) {
|
|
84
|
-
const zip = new JSZip();
|
|
85
|
-
for (const part of parts) {
|
|
86
|
-
if (part.content !== void 0) {
|
|
87
|
-
zip.file(part.path, part.content);
|
|
88
|
-
} else if (part.binaryContent !== void 0) {
|
|
89
|
-
zip.file(part.path, part.binaryContent);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
if (coreProps) {
|
|
93
|
-
const coreXml = buildCorePropertiesXml(coreProps);
|
|
94
|
-
zip.file("docProps/core.xml", coreXml);
|
|
95
|
-
relationships.push({
|
|
96
|
-
sourcePart: "",
|
|
97
|
-
relationship: {
|
|
98
|
-
id: `rId${relationships.length + 100}`,
|
|
99
|
-
type: REL_CORE_PROPERTIES,
|
|
100
|
-
target: "docProps/core.xml"
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
zip.file("[Content_Types].xml", buildContentTypesXml(parts, coreProps));
|
|
105
|
-
const relsBySource = groupRelationshipsBySource(relationships);
|
|
106
|
-
for (const [sourcePart, rels] of relsBySource) {
|
|
107
|
-
const relsPath = sourcePart === "" ? "_rels/.rels" : buildRelsPath(sourcePart);
|
|
108
|
-
zip.file(relsPath, buildRelationshipsXml(rels));
|
|
109
|
-
}
|
|
110
|
-
return zip;
|
|
111
|
-
}
|
|
112
|
-
function buildContentTypesXml(parts, coreProps) {
|
|
113
|
-
const lines = [xmlDeclaration()];
|
|
114
|
-
lines.push(`<Types xmlns="${NS_CONTENT_TYPES}">`);
|
|
115
|
-
const extensionTypes = /* @__PURE__ */ new Map();
|
|
116
|
-
extensionTypes.set("rels", CONTENT_TYPE_RELATIONSHIPS);
|
|
117
|
-
extensionTypes.set("xml", "application/xml");
|
|
118
|
-
for (const part of parts) {
|
|
119
|
-
if (part.binaryContent !== void 0) {
|
|
120
|
-
const ext = getExtension(part.path);
|
|
121
|
-
if (ext && !extensionTypes.has(ext)) {
|
|
122
|
-
extensionTypes.set(ext, part.contentType);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
for (const [ext, ct] of extensionTypes) {
|
|
127
|
-
lines.push(` <Default Extension="${escapeXml(ext)}" ContentType="${escapeXml(ct)}"/>`);
|
|
128
|
-
}
|
|
129
|
-
for (const part of parts) {
|
|
130
|
-
if (part.content !== void 0) {
|
|
131
|
-
lines.push(
|
|
132
|
-
` <Override PartName="/${escapeXml(part.path)}" ContentType="${escapeXml(part.contentType)}"/>`
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
if (coreProps) {
|
|
137
|
-
lines.push(
|
|
138
|
-
` <Override PartName="/docProps/core.xml" ContentType="${CONTENT_TYPE_CORE_PROPERTIES}"/>`
|
|
139
|
-
);
|
|
140
|
-
}
|
|
141
|
-
lines.push("</Types>");
|
|
142
|
-
return lines.join("\n");
|
|
143
|
-
}
|
|
144
|
-
function buildRelationshipsXml(rels) {
|
|
145
|
-
const lines = [xmlDeclaration()];
|
|
146
|
-
lines.push(`<Relationships xmlns="${NS_RELATIONSHIPS}">`);
|
|
147
|
-
for (const rel of rels) {
|
|
148
|
-
const attrs = [
|
|
149
|
-
`Id="${escapeXml(rel.id)}"`,
|
|
150
|
-
`Type="${escapeXml(rel.type)}"`,
|
|
151
|
-
`Target="${escapeXml(rel.target)}"`
|
|
152
|
-
];
|
|
153
|
-
if (rel.targetMode) {
|
|
154
|
-
attrs.push(`TargetMode="${escapeXml(rel.targetMode)}"`);
|
|
155
|
-
}
|
|
156
|
-
lines.push(` <Relationship ${attrs.join(" ")}/>`);
|
|
157
|
-
}
|
|
158
|
-
lines.push("</Relationships>");
|
|
159
|
-
return lines.join("\n");
|
|
160
|
-
}
|
|
161
|
-
function buildCorePropertiesXml(props) {
|
|
162
|
-
const lines = [xmlDeclaration()];
|
|
163
|
-
lines.push(
|
|
164
|
-
`<cp:coreProperties xmlns:cp="${NS_CORE_PROPERTIES}" xmlns:dc="${NS_DC}" xmlns:dcterms="${NS_DCTERMS}" xmlns:xsi="${NS_XSI}">`
|
|
165
|
-
);
|
|
166
|
-
if (props.title) lines.push(` <dc:title>${escapeXml(props.title)}</dc:title>`);
|
|
167
|
-
if (props.subject) lines.push(` <dc:subject>${escapeXml(props.subject)}</dc:subject>`);
|
|
168
|
-
if (props.creator) lines.push(` <dc:creator>${escapeXml(props.creator)}</dc:creator>`);
|
|
169
|
-
if (props.description)
|
|
170
|
-
lines.push(` <dc:description>${escapeXml(props.description)}</dc:description>`);
|
|
171
|
-
if (props.keywords) lines.push(` <cp:keywords>${escapeXml(props.keywords)}</cp:keywords>`);
|
|
172
|
-
if (props.lastModifiedBy)
|
|
173
|
-
lines.push(` <cp:lastModifiedBy>${escapeXml(props.lastModifiedBy)}</cp:lastModifiedBy>`);
|
|
174
|
-
if (props.revision) lines.push(` <cp:revision>${escapeXml(props.revision)}</cp:revision>`);
|
|
175
|
-
if (props.created) {
|
|
176
|
-
lines.push(
|
|
177
|
-
` <dcterms:created xsi:type="dcterms:W3CDTF">${escapeXml(props.created)}</dcterms:created>`
|
|
178
|
-
);
|
|
179
|
-
}
|
|
180
|
-
if (props.modified) {
|
|
181
|
-
lines.push(
|
|
182
|
-
` <dcterms:modified xsi:type="dcterms:W3CDTF">${escapeXml(props.modified)}</dcterms:modified>`
|
|
183
|
-
);
|
|
184
|
-
}
|
|
185
|
-
lines.push("</cp:coreProperties>");
|
|
186
|
-
return lines.join("\n");
|
|
187
|
-
}
|
|
188
|
-
function getExtension(path) {
|
|
189
|
-
const dot = path.lastIndexOf(".");
|
|
190
|
-
if (dot === -1) return void 0;
|
|
191
|
-
return path.substring(dot + 1).toLowerCase();
|
|
192
|
-
}
|
|
193
|
-
function buildRelsPath(partPath) {
|
|
194
|
-
const lastSlash = partPath.lastIndexOf("/");
|
|
195
|
-
if (lastSlash === -1) {
|
|
196
|
-
return `_rels/${partPath}.rels`;
|
|
197
|
-
}
|
|
198
|
-
const dir = partPath.substring(0, lastSlash);
|
|
199
|
-
const file = partPath.substring(lastSlash + 1);
|
|
200
|
-
return `${dir}/_rels/${file}.rels`;
|
|
201
|
-
}
|
|
202
|
-
function groupRelationshipsBySource(pending) {
|
|
203
|
-
const grouped = /* @__PURE__ */ new Map();
|
|
204
|
-
for (const { sourcePart, relationship } of pending) {
|
|
205
|
-
let list = grouped.get(sourcePart);
|
|
206
|
-
if (!list) {
|
|
207
|
-
list = [];
|
|
208
|
-
grouped.set(sourcePart, list);
|
|
209
|
-
}
|
|
210
|
-
list.push(relationship);
|
|
211
|
-
}
|
|
212
|
-
return grouped;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
53
|
// src/ooxml/reader.ts
|
|
216
|
-
import
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
54
|
+
import { DOMParser as XmldomDOMParser } from "@xmldom/xmldom";
|
|
55
|
+
var packageArchives = /* @__PURE__ */ new WeakMap();
|
|
56
|
+
var MAX_CONTENT_TYPES_BYTES = 1024 * 1024;
|
|
57
|
+
var MAX_RELATIONSHIPS_BYTES = 4 * 1024 * 1024;
|
|
58
|
+
function parseXml(source) {
|
|
59
|
+
const nativeParser = globalThis.DOMParser;
|
|
60
|
+
const Parser = nativeParser ?? XmldomDOMParser;
|
|
61
|
+
const doc = new Parser().parseFromString(source, "application/xml");
|
|
62
|
+
const parserErrors = doc.getElementsByTagName("parsererror");
|
|
63
|
+
if (parserErrors.length > 0) {
|
|
64
|
+
throw new Error(`Invalid OOXML XML part: ${parserErrors[0]?.textContent ?? "parse error"}`);
|
|
65
|
+
}
|
|
66
|
+
return doc;
|
|
67
|
+
}
|
|
68
|
+
async function openPackage(data, limits = {}) {
|
|
69
|
+
const archive = await openBoundedZipArchive(data, limits);
|
|
70
|
+
const contentTypes = await parseContentTypes(archive);
|
|
71
|
+
const rootRelationships = await parseRelationships(archive, "");
|
|
72
|
+
const pkg = {
|
|
73
|
+
contentTypes,
|
|
74
|
+
rootRelationships
|
|
75
|
+
};
|
|
76
|
+
packageArchives.set(pkg, archive);
|
|
77
|
+
return pkg;
|
|
222
78
|
}
|
|
223
|
-
async function parseContentTypes(
|
|
79
|
+
async function parseContentTypes(archive) {
|
|
224
80
|
const overrides = /* @__PURE__ */ new Map();
|
|
225
81
|
const defaults = /* @__PURE__ */ new Map();
|
|
226
|
-
const
|
|
227
|
-
if (
|
|
228
|
-
const
|
|
229
|
-
const doc = new DOMParser().parseFromString(text, "application/xml");
|
|
82
|
+
const text = await archive.readText("[Content_Types].xml", MAX_CONTENT_TYPES_BYTES);
|
|
83
|
+
if (text === null) return { overrides, defaults };
|
|
84
|
+
const doc = parseXml(text);
|
|
230
85
|
const defaultEls = doc.getElementsByTagName("Default");
|
|
231
86
|
for (let i = 0; i < defaultEls.length; i++) {
|
|
232
87
|
const el = defaultEls[i];
|
|
@@ -246,14 +101,14 @@ async function parseContentTypes(zip) {
|
|
|
246
101
|
return { overrides, defaults };
|
|
247
102
|
}
|
|
248
103
|
async function getPartRelationships(pkg, partPath) {
|
|
249
|
-
return parseRelationships(pkg
|
|
250
|
-
}
|
|
251
|
-
async function parseRelationships(
|
|
252
|
-
const relsPath = partPath === "" ? "_rels/.rels" :
|
|
253
|
-
const
|
|
254
|
-
if (!
|
|
255
|
-
const text =
|
|
256
|
-
const doc =
|
|
104
|
+
return parseRelationships(pkg, partPath);
|
|
105
|
+
}
|
|
106
|
+
async function parseRelationships(source, partPath) {
|
|
107
|
+
const relsPath = partPath === "" ? "_rels/.rels" : buildRelsPath(partPath);
|
|
108
|
+
const bytes = await readArchivePart(source, relsPath, MAX_RELATIONSHIPS_BYTES);
|
|
109
|
+
if (!bytes) return [];
|
|
110
|
+
const text = new TextDecoder().decode(bytes);
|
|
111
|
+
const doc = parseXml(text);
|
|
257
112
|
const result = [];
|
|
258
113
|
const els = doc.getElementsByTagNameNS(NS_RELATIONSHIPS, "Relationship");
|
|
259
114
|
const fallbackEls = els.length > 0 ? els : doc.getElementsByTagName("Relationship");
|
|
@@ -274,7 +129,7 @@ async function parseRelationships(zip, partPath) {
|
|
|
274
129
|
}
|
|
275
130
|
return result;
|
|
276
131
|
}
|
|
277
|
-
function
|
|
132
|
+
function buildRelsPath(partPath) {
|
|
278
133
|
const lastSlash = partPath.lastIndexOf("/");
|
|
279
134
|
if (lastSlash === -1) {
|
|
280
135
|
return `_rels/${partPath}.rels`;
|
|
@@ -284,15 +139,22 @@ function buildRelsPath2(partPath) {
|
|
|
284
139
|
return `${dir}/_rels/${file}.rels`;
|
|
285
140
|
}
|
|
286
141
|
async function getPartXml(pkg, partPath) {
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
const text = await file.async("text");
|
|
290
|
-
return new DOMParser().parseFromString(text, "application/xml");
|
|
142
|
+
const bytes = await readPackagePart(pkg, partPath);
|
|
143
|
+
return bytes ? parseXml(new TextDecoder().decode(bytes)) : null;
|
|
291
144
|
}
|
|
292
145
|
async function getPartBinary(pkg, partPath) {
|
|
293
|
-
const
|
|
294
|
-
|
|
295
|
-
|
|
146
|
+
const bytes = await readPackagePart(pkg, partPath);
|
|
147
|
+
return bytes ? bytes.slice().buffer : null;
|
|
148
|
+
}
|
|
149
|
+
function readArchivePart(source, path, maxBytes) {
|
|
150
|
+
return "entries" in source ? source.read(path, maxBytes) : readPackagePart(source, path, maxBytes);
|
|
151
|
+
}
|
|
152
|
+
async function readPackagePart(pkg, path, maxBytes) {
|
|
153
|
+
const archive = packageArchives.get(pkg);
|
|
154
|
+
if (!archive) {
|
|
155
|
+
throw new TypeError("Invalid OoxmlPackage: create packages with openPackage().");
|
|
156
|
+
}
|
|
157
|
+
return archive.read(path, maxBytes);
|
|
296
158
|
}
|
|
297
159
|
async function getCoreProperties(pkg) {
|
|
298
160
|
const doc = await getPartXml(pkg, "docProps/core.xml");
|
|
@@ -364,11 +226,10 @@ export {
|
|
|
364
226
|
CONTENT_TYPE_XLSX_WORKSHEET,
|
|
365
227
|
CONTENT_TYPE_XLSX_STYLES,
|
|
366
228
|
REL_WORKSHEET,
|
|
367
|
-
createPackage,
|
|
368
229
|
openPackage,
|
|
369
230
|
getPartRelationships,
|
|
370
231
|
getPartXml,
|
|
371
232
|
getPartBinary,
|
|
372
233
|
getCoreProperties
|
|
373
234
|
};
|
|
374
|
-
//# sourceMappingURL=chunk-
|
|
235
|
+
//# sourceMappingURL=chunk-4HJ6AK2Q.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ooxml/namespaces.ts","../src/ooxml/reader.ts"],"sourcesContent":["/**\n * OOXML Namespace Constants\n *\n * All Office Open XML namespace URIs used across DOCX, PPTX, and XLSX.\n * Organized by category for easy reference.\n */\n\n// ============================================\n// Package-level namespaces (shared by all formats)\n// ============================================\n\n/** Relationships namespace (used in _rels/*.rels files) */\nexport const NS_RELATIONSHIPS = 'http://schemas.openxmlformats.org/package/2006/relationships';\n\n/** Content Types namespace ([Content_Types].xml) */\nexport const NS_CONTENT_TYPES = 'http://schemas.openxmlformats.org/package/2006/content-types';\n\n// ============================================\n// Relationship type URIs\n// ============================================\n\n/** Relationship type: Office document (main part) */\nexport const REL_OFFICE_DOCUMENT =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument';\n\n/** Relationship type: Core properties */\nexport const REL_CORE_PROPERTIES =\n 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties';\n\n/** Relationship type: Extended properties (app.xml) */\nexport const REL_EXTENDED_PROPERTIES =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties';\n\n/** Relationship type: Styles */\nexport const REL_STYLES =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles';\n\n/** Relationship type: Numbering */\nexport const REL_NUMBERING =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering';\n\n/** Relationship type: Font table */\nexport const REL_FONT_TABLE =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable';\n\n/** Relationship type: Settings */\nexport const REL_SETTINGS =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings';\n\n/** Relationship type: Hyperlink */\nexport const REL_HYPERLINK =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink';\n\n/** Relationship type: Image */\nexport const REL_IMAGE =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image';\n\n/** Relationship type: Footnotes */\nexport const REL_FOOTNOTES =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes';\n\n/** Relationship type: Theme */\nexport const REL_THEME =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme';\n\n// ============================================\n// WordprocessingML (DOCX)\n// ============================================\n\n/** WordprocessingML main namespace (w:) */\nexport const NS_WML = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';\n\n// ============================================\n// PresentationML (PPTX)\n// ============================================\n\n/** PresentationML main namespace (p:) */\nexport const NS_PML = 'http://schemas.openxmlformats.org/presentationml/2006/main';\n\n/** PowerPoint 2010 extension namespace (p14:) */\nexport const NS_PML_2010 = 'http://schemas.microsoft.com/office/powerpoint/2010/main';\n\n// ============================================\n// SpreadsheetML (XLSX)\n// ============================================\n\n/** SpreadsheetML main namespace */\nexport const NS_SML = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main';\n\n// ============================================\n// DrawingML (shared across formats)\n// ============================================\n\n/** DrawingML main namespace (a:) */\nexport const NS_DRAWINGML = 'http://schemas.openxmlformats.org/drawingml/2006/main';\n\n/** DrawingML WordprocessingML drawing namespace (wp:) */\nexport const NS_WP_DRAWING =\n 'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing';\n\n/** DrawingML picture namespace (pic:) */\nexport const NS_PICTURE = 'http://schemas.openxmlformats.org/drawingml/2006/picture';\n\n// ============================================\n// Dublin Core / Core Properties\n// ============================================\n\n/** Dublin Core elements namespace */\nexport const NS_DC = 'http://purl.org/dc/elements/1.1/';\n\n/** Dublin Core terms namespace */\nexport const NS_DCTERMS = 'http://purl.org/dc/terms/';\n\n/** Core properties namespace */\nexport const NS_CORE_PROPERTIES =\n 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties';\n\n/** XML Schema Instance namespace */\nexport const NS_XSI = 'http://www.w3.org/2001/XMLSchema-instance';\n\n// ============================================\n// Markup Compatibility\n// ============================================\n\n/** Markup Compatibility namespace (mc:) */\nexport const NS_MC = 'http://schemas.openxmlformats.org/markup-compatibility/2006';\n\n/** Office relationships namespace (r:) */\nexport const NS_R = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships';\n\n// ============================================\n// Content type strings\n// ============================================\n\nexport const CONTENT_TYPE_RELATIONSHIPS =\n 'application/vnd.openxmlformats-package.relationships+xml';\n\nexport const CONTENT_TYPE_CORE_PROPERTIES =\n 'application/vnd.openxmlformats-package.core-properties+xml';\n\nexport const CONTENT_TYPE_DOCX_DOCUMENT =\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml';\n\nexport const CONTENT_TYPE_DOCX_STYLES =\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml';\n\nexport const CONTENT_TYPE_DOCX_NUMBERING =\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml';\n\nexport const CONTENT_TYPE_DOCX_SETTINGS =\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml';\n\nexport const CONTENT_TYPE_DOCX_FONT_TABLE =\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml';\n\nexport const CONTENT_TYPE_DOCX_FOOTNOTES =\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml';\n\nexport const CONTENT_TYPE_PPTX_PRESENTATION =\n 'application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml';\n\nexport const CONTENT_TYPE_PPTX_SLIDE =\n 'application/vnd.openxmlformats-officedocument.presentationml.slide+xml';\n\nexport const CONTENT_TYPE_PPTX_SLIDE_LAYOUT =\n 'application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml';\n\nexport const CONTENT_TYPE_PPTX_SLIDE_MASTER =\n 'application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml';\n\nexport const CONTENT_TYPE_PPTX_THEME = 'application/vnd.openxmlformats-officedocument.theme+xml';\n\n/** Relationship type: Slide */\nexport const REL_SLIDE =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide';\n\n/** Relationship type: Slide layout */\nexport const REL_SLIDE_LAYOUT =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout';\n\n/** Relationship type: Slide master */\nexport const REL_SLIDE_MASTER =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster';\n\nexport const CONTENT_TYPE_XLSX_WORKBOOK =\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml';\n\nexport const CONTENT_TYPE_XLSX_WORKSHEET =\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml';\n\nexport const CONTENT_TYPE_XLSX_STYLES =\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml';\n\n/** Relationship type: Worksheet */\nexport const REL_WORKSHEET =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet';\n","/**\n * OOXML Package Reader\n *\n * Opens OOXML archives (.docx, .pptx, .xlsx) and parses their\n * structural metadata: [Content_Types].xml, relationships, and\n * core properties.\n *\n * Uses bounded JSZip member streams and a platform DOMParser (with an xmldom\n * fallback in bare Node/SSR) to parse XML.\n */\n\nimport { DOMParser as XmldomDOMParser } from '@xmldom/xmldom';\nimport type { OoxmlPackage, ContentTypeMap, Relationship, CoreProperties } from './types.js';\nimport { NS_RELATIONSHIPS, NS_DC, NS_DCTERMS, NS_CORE_PROPERTIES } from './namespaces.js';\nimport {\n openBoundedZipArchive,\n type BoundedZipArchive,\n type ZipSafetyLimits,\n} from '../shared/zipSafety.js';\n\nexport type OoxmlOpenOptions = ZipSafetyLimits;\n\ntype DomParserLike = new () => {\n parseFromString(source: string, mimeType: string): unknown;\n};\n\n/** Safe read sessions for opaque packages opened by this module. */\nconst packageArchives = new WeakMap<OoxmlPackage, BoundedZipArchive>();\nconst MAX_CONTENT_TYPES_BYTES = 1024 * 1024;\nconst MAX_RELATIONSHIPS_BYTES = 4 * 1024 * 1024;\n\n/**\n * Parse XML in browsers and bare Node. Browser DOMParser is preferred; the\n * pure-JS xmldom implementation is the package-owned fallback for Node/SSR.\n */\nfunction parseXml(source: string): Document {\n const nativeParser = (globalThis as { DOMParser?: DomParserLike }).DOMParser;\n const Parser = nativeParser ?? (XmldomDOMParser as unknown as DomParserLike);\n const doc = new Parser().parseFromString(source, 'application/xml') as Document;\n const parserErrors = doc.getElementsByTagName('parsererror');\n if (parserErrors.length > 0) {\n throw new Error(`Invalid OOXML XML part: ${parserErrors[0]?.textContent ?? 'parse error'}`);\n }\n return doc;\n}\n\n// ============================================\n// Package Opening\n// ============================================\n\n/**\n * Open an OOXML package from raw data.\n *\n * Parses the ZIP archive, [Content_Types].xml, and root relationships.\n *\n * @param data - The raw .docx/.pptx/.xlsx file as ArrayBuffer or Blob\n * @param limits - Optional archive count, size, and compression-ratio limits\n * @returns A parsed OoxmlPackage\n */\nexport async function openPackage(\n data: ArrayBuffer | Blob,\n limits: OoxmlOpenOptions = {},\n): Promise<OoxmlPackage> {\n const archive = await openBoundedZipArchive(data, limits);\n const contentTypes = await parseContentTypes(archive);\n const rootRelationships = await parseRelationships(archive, '');\n\n const pkg = {\n contentTypes,\n rootRelationships,\n } as unknown as OoxmlPackage;\n packageArchives.set(pkg, archive);\n return pkg;\n}\n\n// ============================================\n// Content Types\n// ============================================\n\n/**\n * Parse [Content_Types].xml from the archive.\n */\nasync function parseContentTypes(archive: BoundedZipArchive): Promise<ContentTypeMap> {\n const overrides = new Map<string, string>();\n const defaults = new Map<string, string>();\n\n const text = await archive.readText('[Content_Types].xml', MAX_CONTENT_TYPES_BYTES);\n if (text === null) return { overrides, defaults };\n const doc = parseXml(text);\n\n // Parse <Default Extension=\"rels\" ContentType=\"...\" />\n const defaultEls = doc.getElementsByTagName('Default');\n for (let i = 0; i < defaultEls.length; i++) {\n const el = defaultEls[i];\n const ext = el.getAttribute('Extension');\n const ct = el.getAttribute('ContentType');\n if (ext && ct) defaults.set(ext, ct);\n }\n\n // Parse <Override PartName=\"/word/document.xml\" ContentType=\"...\" />\n const overrideEls = doc.getElementsByTagName('Override');\n for (let i = 0; i < overrideEls.length; i++) {\n const el = overrideEls[i];\n const partName = el.getAttribute('PartName');\n const ct = el.getAttribute('ContentType');\n if (partName && ct) {\n // Normalize: strip leading slash\n overrides.set(partName.replace(/^\\//, ''), ct);\n }\n }\n\n return { overrides, defaults };\n}\n\n// ============================================\n// Relationships\n// ============================================\n\n/**\n * Parse relationships for a specific part.\n *\n * @param pkg - The OOXML package (or the zip directly)\n * @param partPath - The part path (e.g., \"word/document.xml\").\n * Use \"\" for root-level relationships (_rels/.rels).\n * @returns Array of relationship entries\n */\nexport async function getPartRelationships(\n pkg: OoxmlPackage,\n partPath: string,\n): Promise<Relationship[]> {\n return parseRelationships(pkg, partPath);\n}\n\n/**\n * Parse a _rels/*.rels file from the ZIP.\n *\n * For root relationships, relsPath = \"_rels/.rels\".\n * For part relationships, relsPath = \"<dir>/_rels/<filename>.rels\".\n */\nasync function parseRelationships(\n source: OoxmlPackage | BoundedZipArchive,\n partPath: string,\n): Promise<Relationship[]> {\n const relsPath = partPath === '' ? '_rels/.rels' : buildRelsPath(partPath);\n\n const bytes = await readArchivePart(source, relsPath, MAX_RELATIONSHIPS_BYTES);\n if (!bytes) return [];\n const text = new TextDecoder().decode(bytes);\n const doc = parseXml(text);\n const result: Relationship[] = [];\n\n const els = doc.getElementsByTagNameNS(NS_RELATIONSHIPS, 'Relationship');\n // Fallback in case namespace isn't used (some generators omit it)\n const fallbackEls = els.length > 0 ? els : doc.getElementsByTagName('Relationship');\n\n for (let i = 0; i < fallbackEls.length; i++) {\n const el = fallbackEls[i];\n const id = el.getAttribute('Id');\n const type = el.getAttribute('Type');\n const target = el.getAttribute('Target');\n if (id && type && target) {\n const targetMode = el.getAttribute('TargetMode') as 'Internal' | 'External' | null;\n result.push({\n id,\n type,\n target,\n ...(targetMode ? { targetMode } : {}),\n });\n }\n }\n\n return result;\n}\n\n/**\n * Build the _rels path for a given part path.\n *\n * \"word/document.xml\" → \"word/_rels/document.xml.rels\"\n * \"xl/workbook.xml\" → \"xl/_rels/workbook.xml.rels\"\n */\nfunction buildRelsPath(partPath: string): string {\n const lastSlash = partPath.lastIndexOf('/');\n if (lastSlash === -1) {\n return `_rels/${partPath}.rels`;\n }\n const dir = partPath.substring(0, lastSlash);\n const file = partPath.substring(lastSlash + 1);\n return `${dir}/_rels/${file}.rels`;\n}\n\n// ============================================\n// Part Access\n// ============================================\n\n/**\n * Extract an XML part from the package and parse it as a DOM Document.\n *\n * @param pkg - The OOXML package\n * @param partPath - Path within the archive (e.g., \"word/document.xml\")\n * @returns Parsed XML Document, or null if the part doesn't exist\n */\nexport async function getPartXml(pkg: OoxmlPackage, partPath: string): Promise<Document | null> {\n const bytes = await readPackagePart(pkg, partPath);\n return bytes ? parseXml(new TextDecoder().decode(bytes)) : null;\n}\n\n/**\n * Extract a binary part from the package (e.g., an image from word/media/).\n *\n * @param pkg - The OOXML package\n * @param partPath - Path within the archive\n * @returns The binary content, or null if the part doesn't exist\n */\nexport async function getPartBinary(\n pkg: OoxmlPackage,\n partPath: string,\n): Promise<ArrayBuffer | null> {\n const bytes = await readPackagePart(pkg, partPath);\n return bytes ? bytes.slice().buffer : null;\n}\n\nfunction readArchivePart(\n source: OoxmlPackage | BoundedZipArchive,\n path: string,\n maxBytes?: number,\n): Promise<Uint8Array | null> {\n return 'entries' in source\n ? source.read(path, maxBytes)\n : readPackagePart(source, path, maxBytes);\n}\n\nasync function readPackagePart(\n pkg: OoxmlPackage,\n path: string,\n maxBytes?: number,\n): Promise<Uint8Array | null> {\n const archive = packageArchives.get(pkg);\n if (!archive) {\n throw new TypeError('Invalid OoxmlPackage: create packages with openPackage().');\n }\n return archive.read(path, maxBytes);\n}\n\n// ============================================\n// Core Properties\n// ============================================\n\n/**\n * Parse core document properties from docProps/core.xml.\n *\n * @param pkg - The OOXML package\n * @returns Parsed core properties (all fields optional)\n */\nexport async function getCoreProperties(pkg: OoxmlPackage): Promise<CoreProperties> {\n const doc = await getPartXml(pkg, 'docProps/core.xml');\n if (!doc) return {};\n\n function getText(ns: string, localName: string): string | undefined {\n const els = doc!.getElementsByTagNameNS(ns, localName);\n if (els.length > 0 && els[0].textContent) {\n return els[0].textContent;\n }\n return undefined;\n }\n\n return {\n title: getText(NS_DC, 'title'),\n subject: getText(NS_DC, 'subject'),\n creator: getText(NS_DC, 'creator'),\n description: getText(NS_DC, 'description'),\n keywords: getText(NS_CORE_PROPERTIES, 'keywords'),\n lastModifiedBy: getText(NS_CORE_PROPERTIES, 'lastModifiedBy'),\n revision: getText(NS_CORE_PROPERTIES, 'revision'),\n created: getText(NS_DCTERMS, 'created'),\n modified: getText(NS_DCTERMS, 'modified'),\n };\n}\n"],"mappings":"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","names":[]}
|