@pyreon/document 0.13.1 → 0.14.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.
Files changed (25) hide show
  1. package/lib/analysis/index.js.html +1 -1
  2. package/lib/{chunk-ErZ26oRB.js → chunk-B4VCYm32.js} +1 -1
  3. package/lib/{dist-CYL41kqQ.js → dist-dSdlKzJ8.js} +10 -4
  4. package/lib/{dist-CYL41kqQ.js.map → dist-dSdlKzJ8.js.map} +1 -1
  5. package/lib/{docx-CcB3jYd3.js → docx-D_wt3a7y.js} +2 -2
  6. package/lib/{docx-CcB3jYd3.js.map → docx-D_wt3a7y.js.map} +1 -1
  7. package/lib/{exceljs-BYETsesT.js → exceljs-Bj6LWg5N.js} +56 -42
  8. package/lib/exceljs-Bj6LWg5N.js.map +1 -0
  9. package/lib/index.js +10 -10
  10. package/lib/{pdf-IuBgTb3T.js → pdf-NApJCU6I.js} +4 -4
  11. package/lib/{pdf-IuBgTb3T.js.map → pdf-NApJCU6I.js.map} +1 -1
  12. package/lib/{pdfmake-CKMX5URW.js → pdfmake-DPyTSQ91.js} +14 -6
  13. package/lib/{pdfmake-CKMX5URW.js.map → pdfmake-DPyTSQ91.js.map} +1 -1
  14. package/lib/{pptx-DXiMiYFM.js → pptx-DLhvPIMn.js} +2 -2
  15. package/lib/{pptx-DXiMiYFM.js.map → pptx-DLhvPIMn.js.map} +1 -1
  16. package/lib/{pptxgen.es-FsqHs8mD.js → pptxgen.es-CFrPYgTY.js} +28 -23
  17. package/lib/{pptxgen.es-FsqHs8mD.js.map → pptxgen.es-CFrPYgTY.js.map} +1 -1
  18. package/lib/{svg-BKxumy-p.js → svg-uFnPWNCU.js} +2 -3
  19. package/lib/{svg-BKxumy-p.js.map → svg-uFnPWNCU.js.map} +1 -1
  20. package/lib/{vfs_fonts-Cap07Jg3.js → vfs_fonts-BSrGAfkk.js} +2 -2
  21. package/lib/{vfs_fonts-Cap07Jg3.js.map → vfs_fonts-BSrGAfkk.js.map} +1 -1
  22. package/lib/{xlsx-Cvu4LBNy.js → xlsx-D8XqTBoR.js} +2 -2
  23. package/lib/{xlsx-Cvu4LBNy.js.map → xlsx-D8XqTBoR.js.map} +1 -1
  24. package/package.json +5 -5
  25. package/lib/exceljs-BYETsesT.js.map +0 -1
@@ -231,7 +231,7 @@ function processSlide(pageNode, pptx) {
231
231
  const pptxRenderer = { async render(node, _options) {
232
232
  let PptxGenJS;
233
233
  try {
234
- PptxGenJS = await import("./pptxgen.es-FsqHs8mD.js");
234
+ PptxGenJS = await import("./pptxgen.es-CFrPYgTY.js");
235
235
  } catch {
236
236
  throw new Error("[@pyreon/document] PPTX renderer requires \"pptxgenjs\" package. Install it: bun add pptxgenjs");
237
237
  }
@@ -256,4 +256,4 @@ const pptxRenderer = { async render(node, _options) {
256
256
 
257
257
  //#endregion
258
258
  export { pptxRenderer };
259
- //# sourceMappingURL=pptx-DXiMiYFM.js.map
259
+ //# sourceMappingURL=pptx-DLhvPIMn.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pptx-DXiMiYFM.js","names":[],"sources":["../src/renderers/pptx.ts"],"sourcesContent":["import { sanitizeHref, sanitizeImageSrc, sanitizeXmlColor } from '../sanitize'\nimport type { DocChild, DocNode, DocumentRenderer, RenderOptions, TableColumn } from '../types'\n\n/**\n * PPTX renderer — lazy-loads pptxgenjs on first use.\n * Each `<Page>` becomes a slide. Document nodes map to PPTX elements.\n *\n * @example\n * ```ts\n * import { render, Document, Page, Heading, Text } from '@pyreon/document'\n *\n * const doc = Document({\n * title: 'Presentation',\n * children: [\n * Page({ children: [Heading({ children: 'Slide 1' }), Text({ children: 'Hello' })] }),\n * Page({ children: [Heading({ children: 'Slide 2' })] }),\n * ],\n * })\n * const pptx = await render(doc, 'pptx') // → Uint8Array\n * ```\n */\n\nfunction resolveColumn(col: string | TableColumn): TableColumn {\n return typeof col === 'string' ? { header: col } : col\n}\n\nfunction getTextContent(children: DocChild[]): string {\n return children\n .map((c) => (typeof c === 'string' ? c : getTextContent((c as DocNode).children)))\n .join('')\n}\n\n/** Vertical position tracker for placing elements on a slide. */\ninterface SlideContext {\n slide: PptxSlide\n y: number\n}\n\n// Duck-typed pptxgenjs interfaces to avoid hard dependency on types\ninterface PptxSlide {\n addText(text: string | PptxTextProps[], opts?: Record<string, unknown>): void\n addImage(opts: Record<string, unknown>): void\n addTable(rows: unknown[][], opts?: Record<string, unknown>): void\n}\n\ninterface PptxTextProps {\n text: string\n options?: Record<string, unknown>\n}\n\ninterface PptxGen {\n addSlide(): PptxSlide\n write(outputType: string): Promise<unknown>\n title: string\n author: string\n subject: string\n}\n\nconst HEADING_SIZES: Record<number, number> = {\n 1: 28,\n 2: 24,\n 3: 20,\n 4: 18,\n 5: 16,\n 6: 14,\n}\n\nconst SLIDE_WIDTH = 10 // inches\nconst CONTENT_MARGIN = 0.5\nconst CONTENT_WIDTH = SLIDE_WIDTH - CONTENT_MARGIN * 2\n\nfunction processNode(node: DocNode, ctx: SlideContext): void {\n const p = node.props\n\n switch (node.type) {\n case 'heading': {\n const level = (p.level as number) ?? 1\n const fontSize = HEADING_SIZES[level] ?? 20\n ctx.slide.addText(getTextContent(node.children), {\n x: CONTENT_MARGIN,\n y: ctx.y,\n w: CONTENT_WIDTH,\n h: 0.6,\n fontSize,\n bold: true,\n color: sanitizeXmlColor((p.color as string) ?? '#000000'),\n align: (p.align as string) ?? 'left',\n })\n ctx.y += 0.7\n break\n }\n\n case 'text': {\n const text = getTextContent(node.children)\n ctx.slide.addText(text, {\n x: CONTENT_MARGIN,\n y: ctx.y,\n w: CONTENT_WIDTH,\n h: 0.4,\n fontSize: (p.size as number) ?? 14,\n bold: p.bold ?? false,\n italic: p.italic ?? false,\n underline: p.underline ? { style: 'sng' } : undefined,\n strike: p.strikethrough ? 'sngStrike' : undefined,\n color: sanitizeXmlColor((p.color as string) ?? '#333333'),\n align: (p.align as string) ?? 'left',\n })\n ctx.y += 0.5\n break\n }\n\n case 'image': {\n const src = sanitizeImageSrc(p.src as string)\n const w = Math.min(((p.width as number) ?? 400) / 96, CONTENT_WIDTH)\n const h = ((p.height as number) ?? 300) / 96\n\n if (src.startsWith('data:')) {\n ctx.slide.addImage({\n data: src,\n x: CONTENT_MARGIN,\n y: ctx.y,\n w,\n h,\n })\n ctx.y += h + 0.2\n }\n // HTTP URLs and local paths are not supported — skip silently\n break\n }\n\n case 'table': {\n const columns = ((p.columns ?? []) as (string | TableColumn)[]).map(resolveColumn)\n const rows = (p.rows ?? []) as (string | number)[][]\n const hs = p.headerStyle as { background?: string; color?: string } | undefined\n\n const headerRow = columns.map((col) => ({\n text: col.header,\n options: {\n bold: true,\n fill: { color: sanitizeXmlColor(hs?.background ?? '#f5f5f5') },\n color: sanitizeXmlColor(hs?.color ?? '#000000'),\n align: col.align ?? 'left',\n fontSize: 12,\n },\n }))\n\n const dataRows = rows.map((row, rowIdx) =>\n columns.map((col, colIdx) => ({\n text: String(row[colIdx] ?? ''),\n options: {\n align: col.align ?? 'left',\n fontSize: 11,\n fill: p.striped && rowIdx % 2 === 1 ? { color: 'F9F9F9' } : undefined,\n },\n })),\n )\n\n const allRows = [headerRow, ...dataRows]\n const rowHeight = 0.35\n const tableHeight = allRows.length * rowHeight\n\n ctx.slide.addTable(allRows, {\n x: CONTENT_MARGIN,\n y: ctx.y,\n w: CONTENT_WIDTH,\n border: { pt: 0.5, color: 'DDDDDD' },\n rowH: rowHeight,\n })\n ctx.y += tableHeight + 0.2\n break\n }\n\n case 'list': {\n const items = node.children\n .filter((c): c is DocNode => typeof c !== 'string')\n .map((item) => getTextContent(item.children))\n\n const isOrdered = p.ordered as boolean\n const listText = items.map((item, i) => ({\n text: isOrdered ? `${i + 1}. ${item}\\n` : `\\u2022 ${item}\\n`,\n options: { fontSize: 13, bullet: false },\n }))\n\n ctx.slide.addText(listText, {\n x: CONTENT_MARGIN,\n y: ctx.y,\n w: CONTENT_WIDTH,\n h: items.length * 0.35,\n })\n ctx.y += items.length * 0.35 + 0.1\n break\n }\n\n case 'code': {\n const text = getTextContent(node.children)\n ctx.slide.addText(text, {\n x: CONTENT_MARGIN,\n y: ctx.y,\n w: CONTENT_WIDTH,\n h: 0.5,\n fontSize: 10,\n fontFace: 'Courier New',\n fill: { color: 'F5F5F5' },\n color: '333333',\n })\n ctx.y += 0.6\n break\n }\n\n case 'quote': {\n const text = getTextContent(node.children)\n ctx.slide.addText(text, {\n x: CONTENT_MARGIN + 0.3,\n y: ctx.y,\n w: CONTENT_WIDTH - 0.3,\n h: 0.5,\n fontSize: 13,\n italic: true,\n color: '555555',\n })\n ctx.y += 0.6\n break\n }\n\n case 'link': {\n ctx.slide.addText(getTextContent(node.children), {\n x: CONTENT_MARGIN,\n y: ctx.y,\n w: CONTENT_WIDTH,\n h: 0.4,\n fontSize: 13,\n color: '4F46E5',\n underline: { style: 'sng' },\n hyperlink: { url: sanitizeHref(p.href as string) },\n })\n ctx.y += 0.5\n break\n }\n\n case 'button': {\n ctx.slide.addText(getTextContent(node.children), {\n x: CONTENT_MARGIN,\n y: ctx.y,\n w: 3,\n h: 0.5,\n fontSize: 14,\n bold: true,\n color: sanitizeXmlColor((p.color as string) ?? '#ffffff'),\n fill: {\n color: sanitizeXmlColor((p.background as string) ?? '#4f46e5'),\n },\n align: 'center',\n hyperlink: { url: sanitizeHref(p.href as string) },\n })\n ctx.y += 0.6\n break\n }\n\n case 'spacer': {\n ctx.y += ((p.height as number) ?? 12) / 72\n break\n }\n\n case 'divider': {\n // Render as a thin line using a text element with top border\n ctx.slide.addText('', {\n x: CONTENT_MARGIN,\n y: ctx.y,\n w: CONTENT_WIDTH,\n h: 0.02,\n fill: { color: sanitizeXmlColor((p.color as string) ?? '#DDDDDD') },\n })\n ctx.y += 0.2\n break\n }\n\n // Container types — recurse into children\n case 'section':\n case 'row':\n case 'column':\n for (const child of node.children) {\n if (typeof child !== 'string') {\n processNode(child, ctx)\n }\n }\n break\n\n default:\n break\n }\n}\n\nfunction processSlide(pageNode: DocNode, pptx: PptxGen): void {\n const slide = pptx.addSlide()\n const ctx: SlideContext = { slide, y: CONTENT_MARGIN }\n\n for (const child of pageNode.children) {\n if (typeof child !== 'string') {\n processNode(child, ctx)\n }\n }\n}\n\nexport const pptxRenderer: DocumentRenderer = {\n async render(node: DocNode, _options?: RenderOptions): Promise<Uint8Array> {\n let PptxGenJS: any\n try {\n PptxGenJS = await import('pptxgenjs')\n } catch {\n throw new Error(\n '[@pyreon/document] PPTX renderer requires \"pptxgenjs\" package. Install it: bun add pptxgenjs',\n )\n }\n const PptxGenClass = PptxGenJS.default ?? PptxGenJS\n\n const pptx = new PptxGenClass() as PptxGen\n\n // Set metadata\n if (node.props.title) pptx.title = node.props.title as string\n if (node.props.author) pptx.author = node.props.author as string\n if (node.props.subject) pptx.subject = node.props.subject as string\n\n // Collect pages — each becomes a slide\n const pages: DocNode[] = []\n for (const child of node.children) {\n if (typeof child !== 'string' && child.type === 'page') {\n pages.push(child)\n }\n }\n\n // If no explicit pages, treat entire document content as one slide\n if (pages.length === 0) {\n const syntheticPage: DocNode = {\n type: 'page',\n props: {},\n children: node.children,\n }\n pages.push(syntheticPage)\n }\n\n for (const page of pages) {\n processSlide(page, pptx)\n }\n\n const output = await pptx.write('arraybuffer')\n return new Uint8Array(output as ArrayBuffer)\n },\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"pptx-DLhvPIMn.js","names":[],"sources":["../src/renderers/pptx.ts"],"sourcesContent":["import { sanitizeHref, sanitizeImageSrc, sanitizeXmlColor } from '../sanitize'\nimport type { DocChild, DocNode, DocumentRenderer, RenderOptions, TableColumn } from '../types'\n\n/**\n * PPTX renderer — lazy-loads pptxgenjs on first use.\n * Each `<Page>` becomes a slide. Document nodes map to PPTX elements.\n *\n * @example\n * ```ts\n * import { render, Document, Page, Heading, Text } from '@pyreon/document'\n *\n * const doc = Document({\n * title: 'Presentation',\n * children: [\n * Page({ children: [Heading({ children: 'Slide 1' }), Text({ children: 'Hello' })] }),\n * Page({ children: [Heading({ children: 'Slide 2' })] }),\n * ],\n * })\n * const pptx = await render(doc, 'pptx') // → Uint8Array\n * ```\n */\n\nfunction resolveColumn(col: string | TableColumn): TableColumn {\n return typeof col === 'string' ? { header: col } : col\n}\n\nfunction getTextContent(children: DocChild[]): string {\n return children\n .map((c) => (typeof c === 'string' ? c : getTextContent((c as DocNode).children)))\n .join('')\n}\n\n/** Vertical position tracker for placing elements on a slide. */\ninterface SlideContext {\n slide: PptxSlide\n y: number\n}\n\n// Duck-typed pptxgenjs interfaces to avoid hard dependency on types\ninterface PptxSlide {\n addText(text: string | PptxTextProps[], opts?: Record<string, unknown>): void\n addImage(opts: Record<string, unknown>): void\n addTable(rows: unknown[][], opts?: Record<string, unknown>): void\n}\n\ninterface PptxTextProps {\n text: string\n options?: Record<string, unknown>\n}\n\ninterface PptxGen {\n addSlide(): PptxSlide\n write(outputType: string): Promise<unknown>\n title: string\n author: string\n subject: string\n}\n\nconst HEADING_SIZES: Record<number, number> = {\n 1: 28,\n 2: 24,\n 3: 20,\n 4: 18,\n 5: 16,\n 6: 14,\n}\n\nconst SLIDE_WIDTH = 10 // inches\nconst CONTENT_MARGIN = 0.5\nconst CONTENT_WIDTH = SLIDE_WIDTH - CONTENT_MARGIN * 2\n\nfunction processNode(node: DocNode, ctx: SlideContext): void {\n const p = node.props\n\n switch (node.type) {\n case 'heading': {\n const level = (p.level as number) ?? 1\n const fontSize = HEADING_SIZES[level] ?? 20\n ctx.slide.addText(getTextContent(node.children), {\n x: CONTENT_MARGIN,\n y: ctx.y,\n w: CONTENT_WIDTH,\n h: 0.6,\n fontSize,\n bold: true,\n color: sanitizeXmlColor((p.color as string) ?? '#000000'),\n align: (p.align as string) ?? 'left',\n })\n ctx.y += 0.7\n break\n }\n\n case 'text': {\n const text = getTextContent(node.children)\n ctx.slide.addText(text, {\n x: CONTENT_MARGIN,\n y: ctx.y,\n w: CONTENT_WIDTH,\n h: 0.4,\n fontSize: (p.size as number) ?? 14,\n bold: p.bold ?? false,\n italic: p.italic ?? false,\n underline: p.underline ? { style: 'sng' } : undefined,\n strike: p.strikethrough ? 'sngStrike' : undefined,\n color: sanitizeXmlColor((p.color as string) ?? '#333333'),\n align: (p.align as string) ?? 'left',\n })\n ctx.y += 0.5\n break\n }\n\n case 'image': {\n const src = sanitizeImageSrc(p.src as string)\n const w = Math.min(((p.width as number) ?? 400) / 96, CONTENT_WIDTH)\n const h = ((p.height as number) ?? 300) / 96\n\n if (src.startsWith('data:')) {\n ctx.slide.addImage({\n data: src,\n x: CONTENT_MARGIN,\n y: ctx.y,\n w,\n h,\n })\n ctx.y += h + 0.2\n }\n // HTTP URLs and local paths are not supported — skip silently\n break\n }\n\n case 'table': {\n const columns = ((p.columns ?? []) as (string | TableColumn)[]).map(resolveColumn)\n const rows = (p.rows ?? []) as (string | number)[][]\n const hs = p.headerStyle as { background?: string; color?: string } | undefined\n\n const headerRow = columns.map((col) => ({\n text: col.header,\n options: {\n bold: true,\n fill: { color: sanitizeXmlColor(hs?.background ?? '#f5f5f5') },\n color: sanitizeXmlColor(hs?.color ?? '#000000'),\n align: col.align ?? 'left',\n fontSize: 12,\n },\n }))\n\n const dataRows = rows.map((row, rowIdx) =>\n columns.map((col, colIdx) => ({\n text: String(row[colIdx] ?? ''),\n options: {\n align: col.align ?? 'left',\n fontSize: 11,\n fill: p.striped && rowIdx % 2 === 1 ? { color: 'F9F9F9' } : undefined,\n },\n })),\n )\n\n const allRows = [headerRow, ...dataRows]\n const rowHeight = 0.35\n const tableHeight = allRows.length * rowHeight\n\n ctx.slide.addTable(allRows, {\n x: CONTENT_MARGIN,\n y: ctx.y,\n w: CONTENT_WIDTH,\n border: { pt: 0.5, color: 'DDDDDD' },\n rowH: rowHeight,\n })\n ctx.y += tableHeight + 0.2\n break\n }\n\n case 'list': {\n const items = node.children\n .filter((c): c is DocNode => typeof c !== 'string')\n .map((item) => getTextContent(item.children))\n\n const isOrdered = p.ordered as boolean\n const listText = items.map((item, i) => ({\n text: isOrdered ? `${i + 1}. ${item}\\n` : `\\u2022 ${item}\\n`,\n options: { fontSize: 13, bullet: false },\n }))\n\n ctx.slide.addText(listText, {\n x: CONTENT_MARGIN,\n y: ctx.y,\n w: CONTENT_WIDTH,\n h: items.length * 0.35,\n })\n ctx.y += items.length * 0.35 + 0.1\n break\n }\n\n case 'code': {\n const text = getTextContent(node.children)\n ctx.slide.addText(text, {\n x: CONTENT_MARGIN,\n y: ctx.y,\n w: CONTENT_WIDTH,\n h: 0.5,\n fontSize: 10,\n fontFace: 'Courier New',\n fill: { color: 'F5F5F5' },\n color: '333333',\n })\n ctx.y += 0.6\n break\n }\n\n case 'quote': {\n const text = getTextContent(node.children)\n ctx.slide.addText(text, {\n x: CONTENT_MARGIN + 0.3,\n y: ctx.y,\n w: CONTENT_WIDTH - 0.3,\n h: 0.5,\n fontSize: 13,\n italic: true,\n color: '555555',\n })\n ctx.y += 0.6\n break\n }\n\n case 'link': {\n ctx.slide.addText(getTextContent(node.children), {\n x: CONTENT_MARGIN,\n y: ctx.y,\n w: CONTENT_WIDTH,\n h: 0.4,\n fontSize: 13,\n color: '4F46E5',\n underline: { style: 'sng' },\n hyperlink: { url: sanitizeHref(p.href as string) },\n })\n ctx.y += 0.5\n break\n }\n\n case 'button': {\n ctx.slide.addText(getTextContent(node.children), {\n x: CONTENT_MARGIN,\n y: ctx.y,\n w: 3,\n h: 0.5,\n fontSize: 14,\n bold: true,\n color: sanitizeXmlColor((p.color as string) ?? '#ffffff'),\n fill: {\n color: sanitizeXmlColor((p.background as string) ?? '#4f46e5'),\n },\n align: 'center',\n hyperlink: { url: sanitizeHref(p.href as string) },\n })\n ctx.y += 0.6\n break\n }\n\n case 'spacer': {\n ctx.y += ((p.height as number) ?? 12) / 72\n break\n }\n\n case 'divider': {\n // Render as a thin line using a text element with top border\n ctx.slide.addText('', {\n x: CONTENT_MARGIN,\n y: ctx.y,\n w: CONTENT_WIDTH,\n h: 0.02,\n fill: { color: sanitizeXmlColor((p.color as string) ?? '#DDDDDD') },\n })\n ctx.y += 0.2\n break\n }\n\n // Container types — recurse into children\n case 'section':\n case 'row':\n case 'column':\n for (const child of node.children) {\n if (typeof child !== 'string') {\n processNode(child, ctx)\n }\n }\n break\n\n default:\n break\n }\n}\n\nfunction processSlide(pageNode: DocNode, pptx: PptxGen): void {\n const slide = pptx.addSlide()\n const ctx: SlideContext = { slide, y: CONTENT_MARGIN }\n\n for (const child of pageNode.children) {\n if (typeof child !== 'string') {\n processNode(child, ctx)\n }\n }\n}\n\nexport const pptxRenderer: DocumentRenderer = {\n async render(node: DocNode, _options?: RenderOptions): Promise<Uint8Array> {\n let PptxGenJS: any\n try {\n PptxGenJS = await import('pptxgenjs')\n } catch {\n throw new Error(\n '[@pyreon/document] PPTX renderer requires \"pptxgenjs\" package. Install it: bun add pptxgenjs',\n )\n }\n const PptxGenClass = PptxGenJS.default ?? PptxGenJS\n\n const pptx = new PptxGenClass() as PptxGen\n\n // Set metadata\n if (node.props.title) pptx.title = node.props.title as string\n if (node.props.author) pptx.author = node.props.author as string\n if (node.props.subject) pptx.subject = node.props.subject as string\n\n // Collect pages — each becomes a slide\n const pages: DocNode[] = []\n for (const child of node.children) {\n if (typeof child !== 'string' && child.type === 'page') {\n pages.push(child)\n }\n }\n\n // If no explicit pages, treat entire document content as one slide\n if (pages.length === 0) {\n const syntheticPage: DocNode = {\n type: 'page',\n props: {},\n children: node.children,\n }\n pages.push(syntheticPage)\n }\n\n for (const page of pages) {\n processSlide(page, pptx)\n }\n\n const output = await pptx.write('arraybuffer')\n return new Uint8Array(output as ArrayBuffer)\n },\n}\n"],"mappings":"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"}
@@ -2463,10 +2463,11 @@ var Slide = class {
2463
2463
  * @return {Slide} this Slide
2464
2464
  */
2465
2465
  addText(text, options) {
2466
- addTextDefinition(this, typeof text === "string" || typeof text === "number" ? [{
2466
+ const textParam = typeof text === "string" || typeof text === "number" ? [{
2467
2467
  text,
2468
2468
  options
2469
- }] : text, options, false);
2469
+ }] : text;
2470
+ addTextDefinition(this, textParam, options, false);
2470
2471
  return this;
2471
2472
  }
2472
2473
  };
@@ -5443,27 +5444,31 @@ var PptxGenJS = class {
5443
5444
  }));
5444
5445
  }));
5445
5446
  });
5447
+ const layout4x3 = {
5448
+ name: "screen4x3",
5449
+ width: 9144e3,
5450
+ height: 6858e3
5451
+ };
5452
+ const layout16x9 = {
5453
+ name: "screen16x9",
5454
+ width: 9144e3,
5455
+ height: 5143500
5456
+ };
5457
+ const layout16x10 = {
5458
+ name: "screen16x10",
5459
+ width: 9144e3,
5460
+ height: 5715e3
5461
+ };
5462
+ const layoutWide = {
5463
+ name: "custom",
5464
+ width: 12192e3,
5465
+ height: 6858e3
5466
+ };
5446
5467
  this.LAYOUTS = {
5447
- LAYOUT_4x3: {
5448
- name: "screen4x3",
5449
- width: 9144e3,
5450
- height: 6858e3
5451
- },
5452
- LAYOUT_16x9: {
5453
- name: "screen16x9",
5454
- width: 9144e3,
5455
- height: 5143500
5456
- },
5457
- LAYOUT_16x10: {
5458
- name: "screen16x10",
5459
- width: 9144e3,
5460
- height: 5715e3
5461
- },
5462
- LAYOUT_WIDE: {
5463
- name: "custom",
5464
- width: 12192e3,
5465
- height: 6858e3
5466
- }
5468
+ LAYOUT_4x3: layout4x3,
5469
+ LAYOUT_16x9: layout16x9,
5470
+ LAYOUT_16x10: layout16x10,
5471
+ LAYOUT_WIDE: layoutWide
5467
5472
  };
5468
5473
  this._author = "PptxGenJS";
5469
5474
  this._company = "PptxGenJS";
@@ -5691,4 +5696,4 @@ var PptxGenJS = class {
5691
5696
 
5692
5697
  //#endregion
5693
5698
  export { PptxGenJS as default };
5694
- //# sourceMappingURL=pptxgen.es-FsqHs8mD.js.map
5699
+ //# sourceMappingURL=pptxgen.es-CFrPYgTY.js.map