@openpresentation/opf 0.18.4 → 0.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -17
- package/dist/browser.js +17 -19
- package/dist/{catalog-refs-BSfGELpt.d.ts → catalog-refs-CSHevLn1.d.ts} +1 -1
- package/dist/{chunk-IM337HP5.js → chunk-2AGWO7RM.js} +4 -5
- package/dist/{chunk-WHHLGDCQ.js → chunk-2XJUXMBS.js} +1 -1
- package/dist/{chunk-JCOSZTOI.js → chunk-32MHL3B3.js} +7 -2
- package/dist/{chunk-ECP7QPGK.js → chunk-4FBXVST6.js} +6 -6
- package/dist/{chunk-KA3ZPFVT.js → chunk-7QUAOKS6.js} +96 -40
- package/dist/{chunk-FO3WGS4R.js → chunk-BDXJYO6R.js} +25 -16
- package/dist/chunk-BYEIFHWS.js +16 -0
- package/dist/{chunk-K5EG3UMS.js → chunk-JMYM44I4.js} +50 -20
- package/dist/{chunk-L5YACLWK.js → chunk-L6RRLN6Q.js} +2 -2
- package/dist/{chunk-GVOLSWAJ.js → chunk-NZDWCYDI.js} +5 -5
- package/dist/{chunk-R7KIASS4.js → chunk-P6LMWUXV.js} +1 -1
- package/dist/{chunk-MSFE2HUK.js → chunk-RFJ5TR3V.js} +16 -13
- package/dist/{chunk-PNINP5IF.js → chunk-UA5EROLC.js} +1 -1
- package/dist/{chunk-MBU42S5Y.js → chunk-UAXSW6VV.js} +1237 -293
- package/dist/chunk-UJSAR6GF.js +181 -0
- package/dist/{chunk-2PEWUUBR.js → chunk-VEHLQVGQ.js} +381 -314
- package/dist/{chunk-ZCFSDSUX.js → chunk-W7G5LSXI.js} +1 -1
- package/dist/{chunk-TRELE6I6.js → chunk-ZU5EQ23T.js} +1 -1
- package/dist/{composition-C-OoqvAr.d.ts → composition-MFjGwuN_.d.ts} +395 -99
- package/dist/composition.d.ts +2 -2
- package/dist/composition.js +1 -2
- package/dist/{conversion-BxZbBd_0.d.ts → conversion-DDd1mdIj.d.ts} +11 -11
- package/dist/conversion-WHN4D4WH.js +19 -0
- package/dist/convert.d.ts +3 -3
- package/dist/convert.js +7 -9
- package/dist/data.d.ts +1 -1
- package/dist/data.js +2 -3
- package/dist/{deck-report-DiDf_Vew.d.ts → deck-report-DldBcTHe.d.ts} +3 -3
- package/dist/deck.d.ts +6 -6
- package/dist/deck.js +10 -12
- package/dist/diff.js +5 -7
- package/dist/docs.js +34 -22
- package/dist/examples.d.ts +1 -1
- package/dist/examples.js +27210 -20994
- package/dist/format.js +2 -2
- package/dist/index.d.ts +22 -21
- package/dist/index.js +23 -26
- package/dist/markdown.d.ts +4 -4
- package/dist/markdown.js +7 -9
- package/dist/node-engine.d.ts +27 -9
- package/dist/node-engine.js +22 -23
- package/dist/{pagination-BaUjDrTz.d.ts → pagination-BKsZIEcA.d.ts} +3 -3
- package/dist/pagination.d.ts +3 -3
- package/dist/pagination.js +4 -6
- package/dist/patch.js +4 -6
- package/dist/{presentation-81rNihF0.d.ts → presentation-B_e2Djga.d.ts} +35 -19
- package/dist/repo-readme.js +1 -1
- package/dist/schemas.d.ts +2 -18
- package/dist/schemas.js +1 -1
- package/dist/spec/README.md +12 -19
- package/dist/spec/reference/engine-vocabularies.json +1 -1
- package/dist/spec/schemas/catalog-index.schema.json +3 -3
- package/dist/spec/schemas/catalog-manifest.schema.json +1 -1
- package/dist/spec/schemas/chart-type.schema.json +2 -2
- package/dist/spec/schemas/language.schema.json +1 -1
- package/dist/spec/schemas/layout-preview-index.schema.json +25 -11
- package/dist/spec/schemas/layout.schema.json +212 -272
- package/dist/spec/schemas/opf.schema.json +63 -18
- package/dist/spec/schemas/social-platform.schema.json +1 -1
- package/dist/spec/schemas/theme.schema.json +60 -0
- package/dist/spec-files.d.ts +2 -2
- package/dist/spec-files.js +1 -1
- package/dist/types.d.ts +115 -40
- package/dist/{validation-types-PbGDrNUr.d.ts → validation-types-DtN8X_HZ.d.ts} +2 -2
- package/dist/validator-1d29Z3YY.d.ts +73 -0
- package/dist/validator.d.ts +6 -60
- package/dist/validator.js +3 -5
- package/dist/yaml.d.ts +4 -4
- package/dist/yaml.js +7 -9
- package/package.json +8 -11
- package/dist/catalog-schemas-CinPh5WA.d.ts +0 -12
- package/dist/catalog.d.ts +0 -91
- package/dist/catalog.js +0 -3
- package/dist/chunk-HXHOZ7AH.js +0 -4937
- package/dist/chunk-SPFV27O5.js +0 -210
- package/dist/chunk-TRDXRRQK.js +0 -17
- package/dist/chunk-WCG3THTD.js +0 -23712
- package/dist/conversion-SHYVL7FC.js +0 -21
- package/dist/spec/catalogs/audiences/academic.json +0 -24
- package/dist/spec/catalogs/audiences/all-hands.json +0 -25
- package/dist/spec/catalogs/audiences/board.json +0 -24
- package/dist/spec/catalogs/audiences/candidates.json +0 -23
- package/dist/spec/catalogs/audiences/customer.json +0 -25
- package/dist/spec/catalogs/audiences/engineering-team.json +0 -23
- package/dist/spec/catalogs/audiences/executive.json +0 -24
- package/dist/spec/catalogs/audiences/general-public.json +0 -25
- package/dist/spec/catalogs/audiences/index.json +0 -105
- package/dist/spec/catalogs/audiences/internal-team.json +0 -25
- package/dist/spec/catalogs/audiences/investor.json +0 -25
- package/dist/spec/catalogs/audiences/marketing.json +0 -25
- package/dist/spec/catalogs/audiences/media.json +0 -24
- package/dist/spec/catalogs/audiences/partner.json +0 -25
- package/dist/spec/catalogs/audiences/regulatory.json +0 -25
- package/dist/spec/catalogs/audiences/sales.json +0 -25
- package/dist/spec/catalogs/audiences/technical.json +0 -25
- package/dist/spec/catalogs/chart-types/100pct-stacked-area.json +0 -21
- package/dist/spec/catalogs/chart-types/100pct-stacked-bar.json +0 -22
- package/dist/spec/catalogs/chart-types/100pct-stacked-column.json +0 -22
- package/dist/spec/catalogs/chart-types/area.json +0 -20
- package/dist/spec/catalogs/chart-types/bar.json +0 -22
- package/dist/spec/catalogs/chart-types/box-and-whisker.json +0 -21
- package/dist/spec/catalogs/chart-types/column.json +0 -22
- package/dist/spec/catalogs/chart-types/combo.json +0 -37
- package/dist/spec/catalogs/chart-types/doughnut.json +0 -20
- package/dist/spec/catalogs/chart-types/filled-radar.json +0 -21
- package/dist/spec/catalogs/chart-types/funnel.json +0 -21
- package/dist/spec/catalogs/chart-types/histogram.json +0 -21
- package/dist/spec/catalogs/chart-types/index.json +0 -171
- package/dist/spec/catalogs/chart-types/line-with-markers.json +0 -21
- package/dist/spec/catalogs/chart-types/line.json +0 -20
- package/dist/spec/catalogs/chart-types/pareto.json +0 -22
- package/dist/spec/catalogs/chart-types/pie.json +0 -20
- package/dist/spec/catalogs/chart-types/radar-with-markers.json +0 -21
- package/dist/spec/catalogs/chart-types/radar.json +0 -21
- package/dist/spec/catalogs/chart-types/scatter.json +0 -21
- package/dist/spec/catalogs/chart-types/stacked-area.json +0 -21
- package/dist/spec/catalogs/chart-types/stacked-bar.json +0 -22
- package/dist/spec/catalogs/chart-types/stacked-column.json +0 -22
- package/dist/spec/catalogs/chart-types/stacked-line-with-markers.json +0 -22
- package/dist/spec/catalogs/chart-types/stacked-line.json +0 -21
- package/dist/spec/catalogs/chart-types/treemap.json +0 -21
- package/dist/spec/catalogs/chart-types/waterfall.json +0 -21
- package/dist/spec/catalogs/chart-types/world.json +0 -21
- package/dist/spec/catalogs/color-schemes/black-and-white.json +0 -26
- package/dist/spec/catalogs/color-schemes/bold-red.json +0 -26
- package/dist/spec/catalogs/color-schemes/boost.json +0 -26
- package/dist/spec/catalogs/color-schemes/burnt-orange.json +0 -26
- package/dist/spec/catalogs/color-schemes/cool-horizon.json +0 -26
- package/dist/spec/catalogs/color-schemes/corporate-blue.json +0 -26
- package/dist/spec/catalogs/color-schemes/deep-purple.json +0 -26
- package/dist/spec/catalogs/color-schemes/forest-green.json +0 -26
- package/dist/spec/catalogs/color-schemes/golden-yellow.json +0 -26
- package/dist/spec/catalogs/color-schemes/index.json +0 -79
- package/dist/spec/catalogs/color-schemes/luxury.json +0 -26
- package/dist/spec/catalogs/color-schemes/pastel-red.json +0 -26
- package/dist/spec/catalogs/color-schemes/slate-gray.json +0 -26
- package/dist/spec/catalogs/color-schemes/steel-blue.json +0 -26
- package/dist/spec/catalogs/color-schemes/vibes.json +0 -26
- package/dist/spec/catalogs/font-schemes/angsana-new.json +0 -15
- package/dist/spec/catalogs/font-schemes/aparajita.json +0 -16
- package/dist/spec/catalogs/font-schemes/aptos.json +0 -13
- package/dist/spec/catalogs/font-schemes/arabic-typesetting.json +0 -15
- package/dist/spec/catalogs/font-schemes/arial.json +0 -13
- package/dist/spec/catalogs/font-schemes/batang.json +0 -15
- package/dist/spec/catalogs/font-schemes/bookman.json +0 -13
- package/dist/spec/catalogs/font-schemes/calibri.json +0 -13
- package/dist/spec/catalogs/font-schemes/century-schoolbook.json +0 -13
- package/dist/spec/catalogs/font-schemes/consolas.json +0 -14
- package/dist/spec/catalogs/font-schemes/constantia.json +0 -13
- package/dist/spec/catalogs/font-schemes/courier-new.json +0 -14
- package/dist/spec/catalogs/font-schemes/daunpenh.json +0 -15
- package/dist/spec/catalogs/font-schemes/david.json +0 -15
- package/dist/spec/catalogs/font-schemes/dilleniaupc.json +0 -15
- package/dist/spec/catalogs/font-schemes/fangsong.json +0 -15
- package/dist/spec/catalogs/font-schemes/garamond.json +0 -13
- package/dist/spec/catalogs/font-schemes/gautami.json +0 -15
- package/dist/spec/catalogs/font-schemes/georgia.json +0 -13
- package/dist/spec/catalogs/font-schemes/gisha.json +0 -16
- package/dist/spec/catalogs/font-schemes/grandview.json +0 -13
- package/dist/spec/catalogs/font-schemes/gungsuh.json +0 -15
- package/dist/spec/catalogs/font-schemes/impact.json +0 -13
- package/dist/spec/catalogs/font-schemes/index.json +0 -454
- package/dist/spec/catalogs/font-schemes/kalinga.json +0 -15
- package/dist/spec/catalogs/font-schemes/kartika.json +0 -15
- package/dist/spec/catalogs/font-schemes/khmer-ui.json +0 -15
- package/dist/spec/catalogs/font-schemes/latha.json +0 -15
- package/dist/spec/catalogs/font-schemes/lucida-sans.json +0 -13
- package/dist/spec/catalogs/font-schemes/malgun-gothic.json +0 -15
- package/dist/spec/catalogs/font-schemes/mangal.json +0 -17
- package/dist/spec/catalogs/font-schemes/meiryo.json +0 -15
- package/dist/spec/catalogs/font-schemes/microsoft-jhenghei.json +0 -15
- package/dist/spec/catalogs/font-schemes/microsoft-yahei.json +0 -18
- package/dist/spec/catalogs/font-schemes/mingliu.json +0 -15
- package/dist/spec/catalogs/font-schemes/miriam.json +0 -15
- package/dist/spec/catalogs/font-schemes/montserrat.json +0 -13
- package/dist/spec/catalogs/font-schemes/ms-mincho.json +0 -15
- package/dist/spec/catalogs/font-schemes/nirmala-ui.json +0 -15
- package/dist/spec/catalogs/font-schemes/noto-naksh-arabic.json +0 -15
- package/dist/spec/catalogs/font-schemes/noto-nastaliq-urdu.json +0 -16
- package/dist/spec/catalogs/font-schemes/noto-sans-arabic.json +0 -17
- package/dist/spec/catalogs/font-schemes/noto-sans-armenian.json +0 -15
- package/dist/spec/catalogs/font-schemes/noto-sans-bengali.json +0 -16
- package/dist/spec/catalogs/font-schemes/noto-sans-devangari.json +0 -16
- package/dist/spec/catalogs/font-schemes/noto-sans-ethiopic.json +0 -15
- package/dist/spec/catalogs/font-schemes/noto-sans-georgian.json +0 -15
- package/dist/spec/catalogs/font-schemes/noto-sans-gujarati.json +0 -15
- package/dist/spec/catalogs/font-schemes/noto-sans-gurmukhi.json +0 -15
- package/dist/spec/catalogs/font-schemes/noto-sans-hebrew.json +0 -15
- package/dist/spec/catalogs/font-schemes/noto-sans-jp.json +0 -15
- package/dist/spec/catalogs/font-schemes/noto-sans-kannada.json +0 -15
- package/dist/spec/catalogs/font-schemes/noto-sans-khmer.json +0 -15
- package/dist/spec/catalogs/font-schemes/noto-sans-kr.json +0 -15
- package/dist/spec/catalogs/font-schemes/noto-sans-malayalam.json +0 -15
- package/dist/spec/catalogs/font-schemes/noto-sans-mongolian.json +0 -15
- package/dist/spec/catalogs/font-schemes/noto-sans-oriya.json +0 -15
- package/dist/spec/catalogs/font-schemes/noto-sans-sc.json +0 -18
- package/dist/spec/catalogs/font-schemes/noto-sans-tamil.json +0 -15
- package/dist/spec/catalogs/font-schemes/noto-sans-tc.json +0 -15
- package/dist/spec/catalogs/font-schemes/noto-sans-telugu.json +0 -15
- package/dist/spec/catalogs/font-schemes/noto-sans-thai.json +0 -15
- package/dist/spec/catalogs/font-schemes/noto-sans.json +0 -18
- package/dist/spec/catalogs/font-schemes/nyala.json +0 -15
- package/dist/spec/catalogs/font-schemes/open-sans.json +0 -13
- package/dist/spec/catalogs/font-schemes/pmingliu.json +0 -15
- package/dist/spec/catalogs/font-schemes/poppins.json +0 -13
- package/dist/spec/catalogs/font-schemes/pt-serif.json +0 -13
- package/dist/spec/catalogs/font-schemes/raavi.json +0 -15
- package/dist/spec/catalogs/font-schemes/raleway.json +0 -13
- package/dist/spec/catalogs/font-schemes/roboto.json +0 -13
- package/dist/spec/catalogs/font-schemes/rockwell.json +0 -13
- package/dist/spec/catalogs/font-schemes/sakkal-majalla.json +0 -17
- package/dist/spec/catalogs/font-schemes/seaford.json +0 -13
- package/dist/spec/catalogs/font-schemes/segoe-ui-light.json +0 -13
- package/dist/spec/catalogs/font-schemes/segoe-ui.json +0 -13
- package/dist/spec/catalogs/font-schemes/shonar-bangla.json +0 -16
- package/dist/spec/catalogs/font-schemes/shruti.json +0 -15
- package/dist/spec/catalogs/font-schemes/simsun.json +0 -15
- package/dist/spec/catalogs/font-schemes/skeena.json +0 -13
- package/dist/spec/catalogs/font-schemes/sylfaen.json +0 -16
- package/dist/spec/catalogs/font-schemes/tahoma.json +0 -13
- package/dist/spec/catalogs/font-schemes/tenorite.json +0 -13
- package/dist/spec/catalogs/font-schemes/times-new-roman.json +0 -13
- package/dist/spec/catalogs/font-schemes/traditional-arabic.json +0 -17
- package/dist/spec/catalogs/font-schemes/trebuchet-ms.json +0 -13
- package/dist/spec/catalogs/font-schemes/tunga.json +0 -15
- package/dist/spec/catalogs/font-schemes/verdana.json +0 -13
- package/dist/spec/catalogs/font-schemes/vrinda.json +0 -15
- package/dist/spec/catalogs/font-schemes/yu-gothic.json +0 -15
- package/dist/spec/catalogs/languages/afrikaans.json +0 -12
- package/dist/spec/catalogs/languages/albanian.json +0 -12
- package/dist/spec/catalogs/languages/amharic.json +0 -12
- package/dist/spec/catalogs/languages/arabic.json +0 -12
- package/dist/spec/catalogs/languages/armenian.json +0 -12
- package/dist/spec/catalogs/languages/aymara.json +0 -12
- package/dist/spec/catalogs/languages/azerbaijani.json +0 -12
- package/dist/spec/catalogs/languages/bengali.json +0 -12
- package/dist/spec/catalogs/languages/berber-latin.json +0 -12
- package/dist/spec/catalogs/languages/bosnian-latin.json +0 -12
- package/dist/spec/catalogs/languages/bulgarian.json +0 -12
- package/dist/spec/catalogs/languages/catalan.json +0 -12
- package/dist/spec/catalogs/languages/cebuano.json +0 -12
- package/dist/spec/catalogs/languages/chinese-simplified.json +0 -12
- package/dist/spec/catalogs/languages/chinese-traditional.json +0 -12
- package/dist/spec/catalogs/languages/chittagonian.json +0 -12
- package/dist/spec/catalogs/languages/croatian.json +0 -12
- package/dist/spec/catalogs/languages/czech.json +0 -12
- package/dist/spec/catalogs/languages/danish.json +0 -12
- package/dist/spec/catalogs/languages/dutch.json +0 -12
- package/dist/spec/catalogs/languages/english-au.json +0 -12
- package/dist/spec/catalogs/languages/english-ca.json +0 -12
- package/dist/spec/catalogs/languages/english-gb.json +0 -12
- package/dist/spec/catalogs/languages/english-in.json +0 -12
- package/dist/spec/catalogs/languages/english-us.json +0 -12
- package/dist/spec/catalogs/languages/english.json +0 -12
- package/dist/spec/catalogs/languages/estonian.json +0 -12
- package/dist/spec/catalogs/languages/filipino.json +0 -12
- package/dist/spec/catalogs/languages/finnish.json +0 -12
- package/dist/spec/catalogs/languages/french.json +0 -12
- package/dist/spec/catalogs/languages/fulfulde.json +0 -12
- package/dist/spec/catalogs/languages/galician.json +0 -12
- package/dist/spec/catalogs/languages/georgian.json +0 -12
- package/dist/spec/catalogs/languages/german.json +0 -12
- package/dist/spec/catalogs/languages/greek.json +0 -12
- package/dist/spec/catalogs/languages/gujarati.json +0 -12
- package/dist/spec/catalogs/languages/hausa.json +0 -12
- package/dist/spec/catalogs/languages/hebrew.json +0 -12
- package/dist/spec/catalogs/languages/hindi.json +0 -12
- package/dist/spec/catalogs/languages/hungarian.json +0 -12
- package/dist/spec/catalogs/languages/igbo.json +0 -12
- package/dist/spec/catalogs/languages/index.json +0 -567
- package/dist/spec/catalogs/languages/indonesian.json +0 -12
- package/dist/spec/catalogs/languages/italian.json +0 -12
- package/dist/spec/catalogs/languages/japanese.json +0 -12
- package/dist/spec/catalogs/languages/kannada.json +0 -12
- package/dist/spec/catalogs/languages/kazakh.json +0 -12
- package/dist/spec/catalogs/languages/khmer.json +0 -12
- package/dist/spec/catalogs/languages/kinyarwanda.json +0 -12
- package/dist/spec/catalogs/languages/korean.json +0 -12
- package/dist/spec/catalogs/languages/kurmanji.json +0 -12
- package/dist/spec/catalogs/languages/latvian.json +0 -12
- package/dist/spec/catalogs/languages/lithuanian.json +0 -12
- package/dist/spec/catalogs/languages/macedonian.json +0 -12
- package/dist/spec/catalogs/languages/malagasy.json +0 -12
- package/dist/spec/catalogs/languages/malay.json +0 -12
- package/dist/spec/catalogs/languages/malayalam.json +0 -12
- package/dist/spec/catalogs/languages/maori.json +0 -12
- package/dist/spec/catalogs/languages/marathi.json +0 -12
- package/dist/spec/catalogs/languages/mongolian.json +0 -12
- package/dist/spec/catalogs/languages/nepali.json +0 -12
- package/dist/spec/catalogs/languages/norwegian.json +0 -12
- package/dist/spec/catalogs/languages/odia.json +0 -12
- package/dist/spec/catalogs/languages/oromo.json +0 -12
- package/dist/spec/catalogs/languages/pashto.json +0 -12
- package/dist/spec/catalogs/languages/persian.json +0 -12
- package/dist/spec/catalogs/languages/polish.json +0 -12
- package/dist/spec/catalogs/languages/portuguese.json +0 -12
- package/dist/spec/catalogs/languages/punjabi-gurmukhi.json +0 -12
- package/dist/spec/catalogs/languages/punjabi-shahmukhi.json +0 -12
- package/dist/spec/catalogs/languages/romanian.json +0 -12
- package/dist/spec/catalogs/languages/russian.json +0 -12
- package/dist/spec/catalogs/languages/serbian-cyrillic.json +0 -12
- package/dist/spec/catalogs/languages/serbian-latin.json +0 -12
- package/dist/spec/catalogs/languages/shona.json +0 -12
- package/dist/spec/catalogs/languages/slovak.json +0 -12
- package/dist/spec/catalogs/languages/slovenian.json +0 -12
- package/dist/spec/catalogs/languages/somali.json +0 -12
- package/dist/spec/catalogs/languages/spanish.json +0 -12
- package/dist/spec/catalogs/languages/swahili.json +0 -12
- package/dist/spec/catalogs/languages/swedish.json +0 -12
- package/dist/spec/catalogs/languages/tagalog.json +0 -12
- package/dist/spec/catalogs/languages/tajik.json +0 -12
- package/dist/spec/catalogs/languages/tamil.json +0 -12
- package/dist/spec/catalogs/languages/telugu.json +0 -12
- package/dist/spec/catalogs/languages/thai.json +0 -12
- package/dist/spec/catalogs/languages/turkish.json +0 -12
- package/dist/spec/catalogs/languages/ukrainian.json +0 -12
- package/dist/spec/catalogs/languages/urdu.json +0 -12
- package/dist/spec/catalogs/languages/uzbek-latin.json +0 -12
- package/dist/spec/catalogs/languages/vietnamese-quoc-ngu.json +0 -12
- package/dist/spec/catalogs/languages/xhosa.json +0 -12
- package/dist/spec/catalogs/languages/yoruba.json +0 -12
- package/dist/spec/catalogs/languages/zulu.json +0 -12
- package/dist/spec/catalogs/layouts/action-plan.json +0 -29
- package/dist/spec/catalogs/layouts/agenda.json +0 -28
- package/dist/spec/catalogs/layouts/appendix-index.json +0 -30
- package/dist/spec/catalogs/layouts/architecture-stack.json +0 -29
- package/dist/spec/catalogs/layouts/assumptions-dependencies.json +0 -29
- package/dist/spec/catalogs/layouts/before-after.json +0 -35
- package/dist/spec/catalogs/layouts/benchmark-target-table.json +0 -29
- package/dist/spec/catalogs/layouts/blank.json +0 -16
- package/dist/spec/catalogs/layouts/bullet-list.json +0 -32
- package/dist/spec/catalogs/layouts/business-model-canvas.json +0 -94
- package/dist/spec/catalogs/layouts/capability-map.json +0 -80
- package/dist/spec/catalogs/layouts/case-study.json +0 -29
- package/dist/spec/catalogs/layouts/chapter-recap.json +0 -28
- package/dist/spec/catalogs/layouts/chart-1x-title-center.json +0 -30
- package/dist/spec/catalogs/layouts/chart-1x.json +0 -34
- package/dist/spec/catalogs/layouts/chart-2x-title-center.json +0 -36
- package/dist/spec/catalogs/layouts/chart-2x-vertical-title-left.json +0 -37
- package/dist/spec/catalogs/layouts/chart-2x.json +0 -65
- package/dist/spec/catalogs/layouts/chart-3x-bottom-vertical-title-left.json +0 -52
- package/dist/spec/catalogs/layouts/chart-3x-left-title-center.json +0 -51
- package/dist/spec/catalogs/layouts/chart-3x-left.json +0 -46
- package/dist/spec/catalogs/layouts/chart-3x-right-title-center.json +0 -51
- package/dist/spec/catalogs/layouts/chart-3x-right.json +0 -46
- package/dist/spec/catalogs/layouts/chart-3x-title-center.json +0 -39
- package/dist/spec/catalogs/layouts/chart-3x-top-vertical-title-left.json +0 -52
- package/dist/spec/catalogs/layouts/chart-3x.json +0 -83
- package/dist/spec/catalogs/layouts/circular-lifecycle.json +0 -29
- package/dist/spec/catalogs/layouts/code-1x.json +0 -29
- package/dist/spec/catalogs/layouts/comparison.json +0 -35
- package/dist/spec/catalogs/layouts/competitive-landscape.json +0 -30
- package/dist/spec/catalogs/layouts/customer-journey.json +0 -30
- package/dist/spec/catalogs/layouts/customer-logos.json +0 -32
- package/dist/spec/catalogs/layouts/dashboard.json +0 -67
- package/dist/spec/catalogs/layouts/data-visualization.json +0 -39
- package/dist/spec/catalogs/layouts/decision-tree.json +0 -30
- package/dist/spec/catalogs/layouts/detailed-data-table.json +0 -35
- package/dist/spec/catalogs/layouts/ecosystem-map.json +0 -30
- package/dist/spec/catalogs/layouts/executive-decision.json +0 -32
- package/dist/spec/catalogs/layouts/executive-summary.json +0 -32
- package/dist/spec/catalogs/layouts/extract/canonical.json +0 -575
- package/dist/spec/catalogs/layouts/faq.json +0 -29
- package/dist/spec/catalogs/layouts/feature-comparison-matrix.json +0 -29
- package/dist/spec/catalogs/layouts/forecast-scenario.json +0 -39
- package/dist/spec/catalogs/layouts/funnel-pyramid.json +0 -32
- package/dist/spec/catalogs/layouts/gantt-project-plan.json +0 -32
- package/dist/spec/catalogs/layouts/geographic-map.json +0 -30
- package/dist/spec/catalogs/layouts/heatmap-cohort.json +0 -32
- package/dist/spec/catalogs/layouts/hub-and-spoke.json +0 -29
- package/dist/spec/catalogs/layouts/icon-grid.json +0 -30
- package/dist/spec/catalogs/layouts/image-1x-crop-title-center.json +0 -32
- package/dist/spec/catalogs/layouts/image-1x-crop-title-left.json +0 -32
- package/dist/spec/catalogs/layouts/image-1x-crop.json +0 -27
- package/dist/spec/catalogs/layouts/image-1x-fit-title-center.json +0 -32
- package/dist/spec/catalogs/layouts/image-1x.json +0 -32
- package/dist/spec/catalogs/layouts/image-2x-crop-title-center.json +0 -38
- package/dist/spec/catalogs/layouts/image-2x-crop-vertical-title-left.json +0 -39
- package/dist/spec/catalogs/layouts/image-2x-crop-vertical.json +0 -34
- package/dist/spec/catalogs/layouts/image-2x-crop.json +0 -33
- package/dist/spec/catalogs/layouts/image-2x-fit-title-center.json +0 -38
- package/dist/spec/catalogs/layouts/image-2x-fit-vertical-title-left.json +0 -39
- package/dist/spec/catalogs/layouts/image-2x-fit-vertical.json +0 -34
- package/dist/spec/catalogs/layouts/image-2x.json +0 -63
- package/dist/spec/catalogs/layouts/image-3x-crop-title-center.json +0 -41
- package/dist/spec/catalogs/layouts/image-3x-crop-vertical-title-left.json +0 -42
- package/dist/spec/catalogs/layouts/image-3x-crop-vertical.json +0 -37
- package/dist/spec/catalogs/layouts/image-3x-crop.json +0 -36
- package/dist/spec/catalogs/layouts/image-3x-fit-title-center.json +0 -41
- package/dist/spec/catalogs/layouts/image-3x-fit-vertical-title-left.json +0 -42
- package/dist/spec/catalogs/layouts/image-3x-fit-vertical.json +0 -37
- package/dist/spec/catalogs/layouts/image-3x-fit.json +0 -36
- package/dist/spec/catalogs/layouts/image-3x.json +0 -81
- package/dist/spec/catalogs/layouts/image-focus.json +0 -30
- package/dist/spec/catalogs/layouts/image-only-1x-crop-title-center.json +0 -31
- package/dist/spec/catalogs/layouts/image-only-1x-fit-title-center.json +0 -31
- package/dist/spec/catalogs/layouts/image-only-2x-crop-title-center.json +0 -37
- package/dist/spec/catalogs/layouts/image-only-2x-crop-vertical-title-left.json +0 -38
- package/dist/spec/catalogs/layouts/image-only-2x-crop-vertical.json +0 -33
- package/dist/spec/catalogs/layouts/image-only-2x-fit-title-center.json +0 -37
- package/dist/spec/catalogs/layouts/image-only-2x-fit-vertical-title-left.json +0 -38
- package/dist/spec/catalogs/layouts/image-only-2x-fit-vertical.json +0 -33
- package/dist/spec/catalogs/layouts/image-only-3x-crop-title-center.json +0 -40
- package/dist/spec/catalogs/layouts/image-only-3x-crop-vertical-title-left.json +0 -41
- package/dist/spec/catalogs/layouts/image-only-3x-crop-vertical.json +0 -36
- package/dist/spec/catalogs/layouts/image-only-3x-crop.json +0 -35
- package/dist/spec/catalogs/layouts/image-only-3x-fit-title-center.json +0 -40
- package/dist/spec/catalogs/layouts/image-only-3x-fit-vertical-title-left.json +0 -41
- package/dist/spec/catalogs/layouts/image-only-3x-fit-vertical.json +0 -36
- package/dist/spec/catalogs/layouts/image-only-3x-fit.json +0 -35
- package/dist/spec/catalogs/layouts/index.json +0 -1399
- package/dist/spec/catalogs/layouts/key-takeaway.json +0 -25
- package/dist/spec/catalogs/layouts/kpi-scorecard.json +0 -83
- package/dist/spec/catalogs/layouts/list-1x-box-title-center.json +0 -32
- package/dist/spec/catalogs/layouts/list-1x-box-vertical-title-center.json +0 -33
- package/dist/spec/catalogs/layouts/list-1x-box-vertical-title-left.json +0 -33
- package/dist/spec/catalogs/layouts/list-1x-box-vertical.json +0 -28
- package/dist/spec/catalogs/layouts/list-1x-box.json +0 -27
- package/dist/spec/catalogs/layouts/list-1x-itemimage-title-center.json +0 -32
- package/dist/spec/catalogs/layouts/list-1x-itemimage-vertical-title-center.json +0 -33
- package/dist/spec/catalogs/layouts/list-1x-title-center.json +0 -31
- package/dist/spec/catalogs/layouts/list-1x-vertical-title-center.json +0 -32
- package/dist/spec/catalogs/layouts/list-1x.json +0 -29
- package/dist/spec/catalogs/layouts/list-2x-box-title-center.json +0 -38
- package/dist/spec/catalogs/layouts/list-2x-box-vertical-title-center.json +0 -39
- package/dist/spec/catalogs/layouts/list-2x-box-vertical-title-left.json +0 -39
- package/dist/spec/catalogs/layouts/list-2x-box-vertical.json +0 -34
- package/dist/spec/catalogs/layouts/list-2x-box.json +0 -33
- package/dist/spec/catalogs/layouts/list-2x-itemimage-title-center.json +0 -38
- package/dist/spec/catalogs/layouts/list-2x-itemimage-vertical-title-center.json +0 -39
- package/dist/spec/catalogs/layouts/list-2x-itemimage-vertical-title-left.json +0 -39
- package/dist/spec/catalogs/layouts/list-2x-itemimage-vertical.json +0 -34
- package/dist/spec/catalogs/layouts/list-2x-title-center.json +0 -37
- package/dist/spec/catalogs/layouts/list-2x-vertical-title-center.json +0 -38
- package/dist/spec/catalogs/layouts/list-2x-vertical-title-left.json +0 -38
- package/dist/spec/catalogs/layouts/list-2x-vertical.json +0 -33
- package/dist/spec/catalogs/layouts/list-2x.json +0 -35
- package/dist/spec/catalogs/layouts/list-3x-box-title-center.json +0 -41
- package/dist/spec/catalogs/layouts/list-3x-box-vertical-title-center.json +0 -42
- package/dist/spec/catalogs/layouts/list-3x-box-vertical-title-left.json +0 -42
- package/dist/spec/catalogs/layouts/list-3x-box-vertical.json +0 -37
- package/dist/spec/catalogs/layouts/list-3x-box.json +0 -36
- package/dist/spec/catalogs/layouts/list-3x-itemimage-title-center.json +0 -41
- package/dist/spec/catalogs/layouts/list-3x-itemimage-vertical-title-center.json +0 -42
- package/dist/spec/catalogs/layouts/list-3x-itemimage-vertical-title-left.json +0 -42
- package/dist/spec/catalogs/layouts/list-3x-itemimage-vertical.json +0 -37
- package/dist/spec/catalogs/layouts/list-3x-itemimage.json +0 -36
- package/dist/spec/catalogs/layouts/list-3x-title-center.json +0 -40
- package/dist/spec/catalogs/layouts/list-3x-vertical-title-center.json +0 -41
- package/dist/spec/catalogs/layouts/list-3x-vertical-title-left.json +0 -41
- package/dist/spec/catalogs/layouts/list-3x-vertical.json +0 -36
- package/dist/spec/catalogs/layouts/list-3x.json +0 -38
- package/dist/spec/catalogs/layouts/list-4x-box-title-center.json +0 -45
- package/dist/spec/catalogs/layouts/list-4x-box-vertical-title-center.json +0 -45
- package/dist/spec/catalogs/layouts/list-4x-box-vertical-title-left.json +0 -45
- package/dist/spec/catalogs/layouts/list-4x-box-vertical.json +0 -40
- package/dist/spec/catalogs/layouts/list-4x-box.json +0 -40
- package/dist/spec/catalogs/layouts/list-4x-itemimage-title-center.json +0 -45
- package/dist/spec/catalogs/layouts/list-4x-itemimage-vertical-title-center.json +0 -45
- package/dist/spec/catalogs/layouts/list-4x-itemimage-vertical-title-left.json +0 -45
- package/dist/spec/catalogs/layouts/list-4x-itemimage-vertical.json +0 -40
- package/dist/spec/catalogs/layouts/list-4x-title-center.json +0 -44
- package/dist/spec/catalogs/layouts/list-4x-vertical-title-center.json +0 -44
- package/dist/spec/catalogs/layouts/list-4x-vertical-title-left.json +0 -44
- package/dist/spec/catalogs/layouts/list-4x-vertical.json +0 -39
- package/dist/spec/catalogs/layouts/list-4x.json +0 -42
- package/dist/spec/catalogs/layouts/list-5x-box-title-center.json +0 -48
- package/dist/spec/catalogs/layouts/list-5x-box-vertical-title-center.json +0 -50
- package/dist/spec/catalogs/layouts/list-5x-box-vertical-title-left.json +0 -50
- package/dist/spec/catalogs/layouts/list-5x-box-vertical.json +0 -45
- package/dist/spec/catalogs/layouts/list-5x-box.json +0 -43
- package/dist/spec/catalogs/layouts/list-5x-itemimage-title-center.json +0 -48
- package/dist/spec/catalogs/layouts/list-5x-itemimage-vertical-title-center.json +0 -48
- package/dist/spec/catalogs/layouts/list-5x-itemimage-vertical-title-left.json +0 -48
- package/dist/spec/catalogs/layouts/list-5x-itemimage-vertical.json +0 -43
- package/dist/spec/catalogs/layouts/list-5x-title-center.json +0 -47
- package/dist/spec/catalogs/layouts/list-5x-vertical-title-center.json +0 -47
- package/dist/spec/catalogs/layouts/list-5x-vertical-title-left.json +0 -47
- package/dist/spec/catalogs/layouts/list-5x-vertical.json +0 -42
- package/dist/spec/catalogs/layouts/list-5x.json +0 -45
- package/dist/spec/catalogs/layouts/list-6x-box-title-center.json +0 -51
- package/dist/spec/catalogs/layouts/list-6x-box-vertical-title-center.json +0 -53
- package/dist/spec/catalogs/layouts/list-6x-box-vertical-title-left.json +0 -53
- package/dist/spec/catalogs/layouts/list-6x-box-vertical.json +0 -48
- package/dist/spec/catalogs/layouts/list-6x-box.json +0 -46
- package/dist/spec/catalogs/layouts/list-6x-itemimage-title-center.json +0 -51
- package/dist/spec/catalogs/layouts/list-6x-itemimage-vertical-title-center.json +0 -51
- package/dist/spec/catalogs/layouts/list-6x-itemimage-vertical-title-left.json +0 -51
- package/dist/spec/catalogs/layouts/list-6x-itemimage-vertical.json +0 -46
- package/dist/spec/catalogs/layouts/list-6x-title-center.json +0 -50
- package/dist/spec/catalogs/layouts/list-6x-vertical-title-center.json +0 -50
- package/dist/spec/catalogs/layouts/list-6x-vertical-title-left.json +0 -50
- package/dist/spec/catalogs/layouts/list-6x-vertical.json +0 -45
- package/dist/spec/catalogs/layouts/list-6x.json +0 -48
- package/dist/spec/catalogs/layouts/logic-tree.json +0 -98
- package/dist/spec/catalogs/layouts/market-size.json +0 -53
- package/dist/spec/catalogs/layouts/matrix-quadrant.json +0 -42
- package/dist/spec/catalogs/layouts/media-1x.json +0 -29
- package/dist/spec/catalogs/layouts/network-dependency-map.json +0 -30
- package/dist/spec/catalogs/layouts/number-1x-box-title-center.json +0 -30
- package/dist/spec/catalogs/layouts/number-1x-box.json +0 -25
- package/dist/spec/catalogs/layouts/number-1x-title-center.json +0 -29
- package/dist/spec/catalogs/layouts/number-1x.json +0 -28
- package/dist/spec/catalogs/layouts/number-2x-box-title-center.json +0 -36
- package/dist/spec/catalogs/layouts/number-2x-box.json +0 -31
- package/dist/spec/catalogs/layouts/number-2x-title-center.json +0 -35
- package/dist/spec/catalogs/layouts/number-2x.json +0 -34
- package/dist/spec/catalogs/layouts/number-3x-box-title-center.json +0 -39
- package/dist/spec/catalogs/layouts/number-3x-box.json +0 -34
- package/dist/spec/catalogs/layouts/number-3x-title-center.json +0 -38
- package/dist/spec/catalogs/layouts/number-3x.json +0 -37
- package/dist/spec/catalogs/layouts/number-4x-box-title-center.json +0 -43
- package/dist/spec/catalogs/layouts/number-4x-box.json +0 -38
- package/dist/spec/catalogs/layouts/number-4x-title-center.json +0 -42
- package/dist/spec/catalogs/layouts/number-4x.json +0 -41
- package/dist/spec/catalogs/layouts/number-5x-box-title-center.json +0 -46
- package/dist/spec/catalogs/layouts/number-5x-box.json +0 -41
- package/dist/spec/catalogs/layouts/number-5x-title-center.json +0 -45
- package/dist/spec/catalogs/layouts/number-5x.json +0 -44
- package/dist/spec/catalogs/layouts/number-6x-box-title-center.json +0 -49
- package/dist/spec/catalogs/layouts/number-6x-box.json +0 -44
- package/dist/spec/catalogs/layouts/number-6x-title-center.json +0 -48
- package/dist/spec/catalogs/layouts/number-6x.json +0 -47
- package/dist/spec/catalogs/layouts/one-column-explainer.json +0 -29
- package/dist/spec/catalogs/layouts/org-chart.json +0 -86
- package/dist/spec/catalogs/layouts/persona-grid.json +0 -30
- package/dist/spec/catalogs/layouts/photo-grid.json +0 -43
- package/dist/spec/catalogs/layouts/pricing-table.json +0 -29
- package/dist/spec/catalogs/layouts/process-flow.json +0 -29
- package/dist/spec/catalogs/layouts/product-feature.json +0 -30
- package/dist/spec/catalogs/layouts/pros-cons.json +0 -35
- package/dist/spec/catalogs/layouts/qa-discussion.json +0 -30
- package/dist/spec/catalogs/layouts/quote-1x.json +0 -23
- package/dist/spec/catalogs/layouts/quote-highlight.json +0 -29
- package/dist/spec/catalogs/layouts/raci-matrix.json +0 -29
- package/dist/spec/catalogs/layouts/risk-heatmap.json +0 -29
- package/dist/spec/catalogs/layouts/roadmap.json +0 -29
- package/dist/spec/catalogs/layouts/screenshot-walkthrough.json +0 -30
- package/dist/spec/catalogs/layouts/section-divider.json +0 -28
- package/dist/spec/catalogs/layouts/single-message-statement.json +0 -25
- package/dist/spec/catalogs/layouts/stats-metrics.json +0 -39
- package/dist/spec/catalogs/layouts/status-rag.json +0 -29
- package/dist/spec/catalogs/layouts/swimlane-process.json +0 -30
- package/dist/spec/catalogs/layouts/swot-analysis.json +0 -42
- package/dist/spec/catalogs/layouts/table-1x.json +0 -29
- package/dist/spec/catalogs/layouts/team-bio.json +0 -30
- package/dist/spec/catalogs/layouts/testimonial-grid.json +0 -38
- package/dist/spec/catalogs/layouts/text-1x-box-title-center.json +0 -31
- package/dist/spec/catalogs/layouts/text-1x-box-title-left.json +0 -31
- package/dist/spec/catalogs/layouts/text-1x-center-box-title-center.json +0 -31
- package/dist/spec/catalogs/layouts/text-1x-center-box-title-left.json +0 -31
- package/dist/spec/catalogs/layouts/text-1x-center-box.json +0 -26
- package/dist/spec/catalogs/layouts/text-1x-center-title-center.json +0 -30
- package/dist/spec/catalogs/layouts/text-1x-center-title-left.json +0 -30
- package/dist/spec/catalogs/layouts/text-1x-center.json +0 -25
- package/dist/spec/catalogs/layouts/text-1x-left-box.json +0 -26
- package/dist/spec/catalogs/layouts/text-1x-title-center.json +0 -30
- package/dist/spec/catalogs/layouts/text-1x.json +0 -23
- package/dist/spec/catalogs/layouts/text-2x-box-title-center.json +0 -37
- package/dist/spec/catalogs/layouts/text-2x-box-vertical-title-left.json +0 -37
- package/dist/spec/catalogs/layouts/text-2x-center-box-title-center.json +0 -37
- package/dist/spec/catalogs/layouts/text-2x-center-box-vertical-title-left.json +0 -37
- package/dist/spec/catalogs/layouts/text-2x-center-box.json +0 -32
- package/dist/spec/catalogs/layouts/text-2x-center-title-center.json +0 -36
- package/dist/spec/catalogs/layouts/text-2x-center-vertical-title-left.json +0 -36
- package/dist/spec/catalogs/layouts/text-2x-center.json +0 -31
- package/dist/spec/catalogs/layouts/text-2x-left-box.json +0 -32
- package/dist/spec/catalogs/layouts/text-2x-title-center.json +0 -36
- package/dist/spec/catalogs/layouts/text-2x-vertical-title-left.json +0 -36
- package/dist/spec/catalogs/layouts/text-2x.json +0 -29
- package/dist/spec/catalogs/layouts/text-3x-box-title-center.json +0 -40
- package/dist/spec/catalogs/layouts/text-3x-box-vertical-title-left.json +0 -41
- package/dist/spec/catalogs/layouts/text-3x-center-box-title-center.json +0 -40
- package/dist/spec/catalogs/layouts/text-3x-center-box-vertical-title-left.json +0 -41
- package/dist/spec/catalogs/layouts/text-3x-center-box.json +0 -35
- package/dist/spec/catalogs/layouts/text-3x-center-title-center.json +0 -39
- package/dist/spec/catalogs/layouts/text-3x-center-vertical-title-left.json +0 -40
- package/dist/spec/catalogs/layouts/text-3x-center.json +0 -34
- package/dist/spec/catalogs/layouts/text-3x-left-box.json +0 -35
- package/dist/spec/catalogs/layouts/text-3x-left.json +0 -34
- package/dist/spec/catalogs/layouts/text-3x-title-center.json +0 -39
- package/dist/spec/catalogs/layouts/text-3x-vertical-title-left.json +0 -40
- package/dist/spec/catalogs/layouts/text-3x.json +0 -32
- package/dist/spec/catalogs/layouts/thank-you-cta.json +0 -28
- package/dist/spec/catalogs/layouts/three-column.json +0 -39
- package/dist/spec/catalogs/layouts/timeline-1x.json +0 -23
- package/dist/spec/catalogs/layouts/timeline.json +0 -32
- package/dist/spec/catalogs/layouts/title-center-box.json +0 -27
- package/dist/spec/catalogs/layouts/title-center-image-bottom.json +0 -34
- package/dist/spec/catalogs/layouts/title-center-image-top.json +0 -34
- package/dist/spec/catalogs/layouts/title-center.json +0 -26
- package/dist/spec/catalogs/layouts/title-left-image-bottom.json +0 -34
- package/dist/spec/catalogs/layouts/title-left-image-left.json +0 -34
- package/dist/spec/catalogs/layouts/title-left-image-right.json +0 -34
- package/dist/spec/catalogs/layouts/title-left-image-top.json +0 -34
- package/dist/spec/catalogs/layouts/title-slide.json +0 -28
- package/dist/spec/catalogs/layouts/title-subtitle.json +0 -23
- package/dist/spec/catalogs/layouts/title.json +0 -20
- package/dist/spec/catalogs/layouts/two-column.json +0 -36
- package/dist/spec/catalogs/layouts/venn-overlap.json +0 -29
- package/dist/spec/catalogs/layouts/waterfall-bridge.json +0 -39
- package/dist/spec/catalogs/layouts/wheel-radial.json +0 -29
- package/dist/spec/catalogs/manifest.json +0 -111
- package/dist/spec/catalogs/narratives/board-meeting.json +0 -192
- package/dist/spec/catalogs/narratives/business-narrative.json +0 -87
- package/dist/spec/catalogs/narratives/business-review.json +0 -119
- package/dist/spec/catalogs/narratives/capacity-planning.json +0 -88
- package/dist/spec/catalogs/narratives/challenge-resolution.json +0 -80
- package/dist/spec/catalogs/narratives/change-story.json +0 -64
- package/dist/spec/catalogs/narratives/classic-story.json +0 -78
- package/dist/spec/catalogs/narratives/company-intro.json +0 -96
- package/dist/spec/catalogs/narratives/conference-talk.json +0 -54
- package/dist/spec/catalogs/narratives/data-story.json +0 -65
- package/dist/spec/catalogs/narratives/early-startup-pitch.json +0 -119
- package/dist/spec/catalogs/narratives/educate.json +0 -95
- package/dist/spec/catalogs/narratives/employee-review.json +0 -87
- package/dist/spec/catalogs/narratives/failure-analysis.json +0 -104
- package/dist/spec/catalogs/narratives/focus.json +0 -120
- package/dist/spec/catalogs/narratives/golden-circle.json +0 -50
- package/dist/spec/catalogs/narratives/heros-journey.json +0 -64
- package/dist/spec/catalogs/narratives/index.json +0 -1041
- package/dist/spec/catalogs/narratives/innovation.json +0 -96
- package/dist/spec/catalogs/narratives/justice.json +0 -112
- package/dist/spec/catalogs/narratives/marketing-strategy.json +0 -111
- package/dist/spec/catalogs/narratives/performance-improvement-plan.json +0 -87
- package/dist/spec/catalogs/narratives/performance-review.json +0 -111
- package/dist/spec/catalogs/narratives/persuade.json +0 -94
- package/dist/spec/catalogs/narratives/persuasive-sales.json +0 -87
- package/dist/spec/catalogs/narratives/pitch-deck.json +0 -107
- package/dist/spec/catalogs/narratives/problem-solution.json +0 -61
- package/dist/spec/catalogs/narratives/product-launch.json +0 -104
- package/dist/spec/catalogs/narratives/project-proposal.json +0 -104
- package/dist/spec/catalogs/narratives/pyramid-principle.json +0 -48
- package/dist/spec/catalogs/narratives/qbr.json +0 -85
- package/dist/spec/catalogs/narratives/rags-to-riches.json +0 -80
- package/dist/spec/catalogs/narratives/reveal.json +0 -87
- package/dist/spec/catalogs/narratives/scqa.json +0 -55
- package/dist/spec/catalogs/narratives/situation-complication-resolution.json +0 -56
- package/dist/spec/catalogs/narratives/sparkline.json +0 -56
- package/dist/spec/catalogs/narratives/star-method.json +0 -56
- package/dist/spec/catalogs/narratives/status-update.json +0 -72
- package/dist/spec/catalogs/narratives/strategic-advisory.json +0 -85
- package/dist/spec/catalogs/narratives/strategic-narrative.json +0 -61
- package/dist/spec/catalogs/narratives/survey-analysis.json +0 -104
- package/dist/spec/catalogs/narratives/survival-story.json +0 -103
- package/dist/spec/catalogs/narratives/transformation-arc.json +0 -50
- package/dist/spec/catalogs/narratives/trend-analysis.json +0 -79
- package/dist/spec/catalogs/narratives/underdog-victory.json +0 -87
- package/dist/spec/catalogs/narratives/venture-pitch.json +0 -109
- package/dist/spec/catalogs/narratives/vision-roadmap.json +0 -65
- package/dist/spec/catalogs/narratives/weekly-progress.json +0 -103
- package/dist/spec/catalogs/narratives/what-so-what-now-what.json +0 -48
- package/dist/spec/catalogs/purposes/align.json +0 -16
- package/dist/spec/catalogs/purposes/decide.json +0 -16
- package/dist/spec/catalogs/purposes/educate.json +0 -16
- package/dist/spec/catalogs/purposes/index.json +0 -63
- package/dist/spec/catalogs/purposes/inform.json +0 -16
- package/dist/spec/catalogs/purposes/persuade.json +0 -16
- package/dist/spec/catalogs/purposes/pitch.json +0 -16
- package/dist/spec/catalogs/purposes/plan.json +0 -16
- package/dist/spec/catalogs/purposes/report.json +0 -16
- package/dist/spec/catalogs/purposes/sell.json +0 -16
- package/dist/spec/catalogs/social-platforms/bluesky.json +0 -14
- package/dist/spec/catalogs/social-platforms/facebook.json +0 -14
- package/dist/spec/catalogs/social-platforms/github.json +0 -15
- package/dist/spec/catalogs/social-platforms/index.json +0 -69
- package/dist/spec/catalogs/social-platforms/instagram.json +0 -13
- package/dist/spec/catalogs/social-platforms/linkedin.json +0 -15
- package/dist/spec/catalogs/social-platforms/mastodon.json +0 -14
- package/dist/spec/catalogs/social-platforms/threads.json +0 -13
- package/dist/spec/catalogs/social-platforms/tiktok.json +0 -14
- package/dist/spec/catalogs/social-platforms/x.json +0 -14
- package/dist/spec/catalogs/social-platforms/youtube.json +0 -14
- package/dist/spec/catalogs/themes/bold.json +0 -13
- package/dist/spec/catalogs/themes/classic.json +0 -13
- package/dist/spec/catalogs/themes/dark.json +0 -13
- package/dist/spec/catalogs/themes/index.json +0 -33
- package/dist/spec/catalogs/themes/minimal.json +0 -13
- package/dist/spec/catalogs/tones/authoritative.json +0 -31
- package/dist/spec/catalogs/tones/casual.json +0 -31
- package/dist/spec/catalogs/tones/conversational.json +0 -31
- package/dist/spec/catalogs/tones/formal.json +0 -31
- package/dist/spec/catalogs/tones/index.json +0 -51
- package/dist/spec/catalogs/tones/inspirational.json +0 -31
- package/dist/spec/catalogs/tones/persuasive.json +0 -32
- package/dist/spec/catalogs/tones/technical.json +0 -31
- package/dist/spec/previews/layouts/action-plan.html +0 -1
- package/dist/spec/previews/layouts/agenda.html +0 -1
- package/dist/spec/previews/layouts/appendix-index.html +0 -1
- package/dist/spec/previews/layouts/architecture-stack.html +0 -1
- package/dist/spec/previews/layouts/assumptions-dependencies.html +0 -1
- package/dist/spec/previews/layouts/before-after.html +0 -1
- package/dist/spec/previews/layouts/benchmark-target-table.html +0 -1
- package/dist/spec/previews/layouts/bullet-list.html +0 -1
- package/dist/spec/previews/layouts/business-model-canvas.html +0 -1
- package/dist/spec/previews/layouts/capability-map.html +0 -1
- package/dist/spec/previews/layouts/case-study.html +0 -1
- package/dist/spec/previews/layouts/chapter-recap.html +0 -1
- package/dist/spec/previews/layouts/circular-lifecycle.html +0 -1
- package/dist/spec/previews/layouts/comparison.html +0 -1
- package/dist/spec/previews/layouts/competitive-landscape.html +0 -1
- package/dist/spec/previews/layouts/customer-journey.html +0 -1
- package/dist/spec/previews/layouts/customer-logos.html +0 -1
- package/dist/spec/previews/layouts/dashboard.html +0 -1
- package/dist/spec/previews/layouts/data-visualization.html +0 -1
- package/dist/spec/previews/layouts/decision-tree.html +0 -1
- package/dist/spec/previews/layouts/detailed-data-table.html +0 -1
- package/dist/spec/previews/layouts/ecosystem-map.html +0 -1
- package/dist/spec/previews/layouts/executive-decision.html +0 -1
- package/dist/spec/previews/layouts/executive-summary.html +0 -1
- package/dist/spec/previews/layouts/faq.html +0 -1
- package/dist/spec/previews/layouts/feature-comparison-matrix.html +0 -1
- package/dist/spec/previews/layouts/forecast-scenario.html +0 -1
- package/dist/spec/previews/layouts/funnel-pyramid.html +0 -1
- package/dist/spec/previews/layouts/gantt-project-plan.html +0 -1
- package/dist/spec/previews/layouts/geographic-map.html +0 -1
- package/dist/spec/previews/layouts/heatmap-cohort.html +0 -1
- package/dist/spec/previews/layouts/hub-and-spoke.html +0 -1
- package/dist/spec/previews/layouts/icon-grid.html +0 -1
- package/dist/spec/previews/layouts/image-focus.html +0 -1
- package/dist/spec/previews/layouts/index.json +0 -357
- package/dist/spec/previews/layouts/key-takeaway.html +0 -1
- package/dist/spec/previews/layouts/kpi-scorecard.html +0 -1
- package/dist/spec/previews/layouts/logic-tree.html +0 -1
- package/dist/spec/previews/layouts/market-size.html +0 -1
- package/dist/spec/previews/layouts/matrix-quadrant.html +0 -1
- package/dist/spec/previews/layouts/network-dependency-map.html +0 -1
- package/dist/spec/previews/layouts/one-column-explainer.html +0 -1
- package/dist/spec/previews/layouts/org-chart.html +0 -1
- package/dist/spec/previews/layouts/persona-grid.html +0 -1
- package/dist/spec/previews/layouts/photo-grid.html +0 -1
- package/dist/spec/previews/layouts/pricing-table.html +0 -1
- package/dist/spec/previews/layouts/process-flow.html +0 -1
- package/dist/spec/previews/layouts/product-feature.html +0 -1
- package/dist/spec/previews/layouts/pros-cons.html +0 -1
- package/dist/spec/previews/layouts/qa-discussion.html +0 -1
- package/dist/spec/previews/layouts/quote-highlight.html +0 -1
- package/dist/spec/previews/layouts/raci-matrix.html +0 -1
- package/dist/spec/previews/layouts/risk-heatmap.html +0 -1
- package/dist/spec/previews/layouts/roadmap.html +0 -1
- package/dist/spec/previews/layouts/screenshot-walkthrough.html +0 -1
- package/dist/spec/previews/layouts/section-divider.html +0 -1
- package/dist/spec/previews/layouts/single-message-statement.html +0 -1
- package/dist/spec/previews/layouts/stats-metrics.html +0 -1
- package/dist/spec/previews/layouts/status-rag.html +0 -1
- package/dist/spec/previews/layouts/swimlane-process.html +0 -1
- package/dist/spec/previews/layouts/swot-analysis.html +0 -1
- package/dist/spec/previews/layouts/team-bio.html +0 -1
- package/dist/spec/previews/layouts/testimonial-grid.html +0 -1
- package/dist/spec/previews/layouts/thank-you-cta.html +0 -1
- package/dist/spec/previews/layouts/three-column.html +0 -1
- package/dist/spec/previews/layouts/timeline.html +0 -1
- package/dist/spec/previews/layouts/title-slide.html +0 -1
- package/dist/spec/previews/layouts/two-column.html +0 -1
- package/dist/spec/previews/layouts/venn-overlap.html +0 -1
- package/dist/spec/previews/layouts/waterfall-bridge.html +0 -1
- package/dist/spec/previews/layouts/wheel-radial.html +0 -1
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { checkCatalogsOption, resolveReference, unresolvedReference, provenanceOf } from './chunk-SPFV27O5.js';
|
|
2
|
-
|
|
3
1
|
// src/table.ts
|
|
4
2
|
var record = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
5
3
|
function tableGrid(value, path = "table") {
|
|
@@ -1187,10 +1185,10 @@ function slideSectionDiagnostics(presentation, uses) {
|
|
|
1187
1185
|
const out = [];
|
|
1188
1186
|
presentation.slides.forEach((slide, index) => {
|
|
1189
1187
|
if (!isRecord(slide) || typeof slide.section === "string" && slide.section !== "") return;
|
|
1190
|
-
const
|
|
1188
|
+
const own3 = `/slides/${index}/`;
|
|
1191
1189
|
const design = isRecord(slide.design) ? slide.design : {};
|
|
1192
1190
|
const inherited = ["header", "footer"].filter((kind2) => design[kind2] === void 0).map((kind2) => `/design/${kind2}/`);
|
|
1193
|
-
const where = paths.find((path) => path.startsWith(
|
|
1191
|
+
const where = paths.find((path) => path.startsWith(own3) || inherited.some((prefix) => path.startsWith(prefix)));
|
|
1194
1192
|
if (where === void 0) return;
|
|
1195
1193
|
out.push({ code: "variable-builtin-missing", severity: "warning", path: `/slides/${index}`, id: "slide.section", message: `Slide ${index + 1} has no section, so '{{slide.section}}' (used at ${where}) resolves to nothing on it; give the slide a section or remove the token.` });
|
|
1196
1194
|
});
|
|
@@ -1989,7 +1987,8 @@ function intrinsicImageAspect(value, assets) {
|
|
|
1989
1987
|
}
|
|
1990
1988
|
|
|
1991
1989
|
// src/design-hints.ts
|
|
1992
|
-
var DESIGN_HINT_KEYS = ["titleAlignment", "contentAlignment", "contentBox", "contentDirection", "chartPrimary", "imageFit", "listBullet"];
|
|
1990
|
+
var DESIGN_HINT_KEYS = ["titleAlignment", "contentAlignment", "contentBox", "contentDirection", "chartPrimary", "imageFit", "listBullet", "mirror"];
|
|
1991
|
+
var THEME_DESIGN_KEYS = ["titleAlignment", "contentAlignment", "contentBox", "contentDirection", "imageFit", "listBullet"];
|
|
1993
1992
|
var ALIGNMENTS = ["left", "center", "right"];
|
|
1994
1993
|
var VALUES = {
|
|
1995
1994
|
titleAlignment: ALIGNMENTS,
|
|
@@ -1998,12 +1997,14 @@ var VALUES = {
|
|
|
1998
1997
|
contentDirection: ["horizontal", "vertical"],
|
|
1999
1998
|
chartPrimary: ["none", "top", "bottom", "left", "right"],
|
|
2000
1999
|
imageFit: ["cover", "contain", "stretch"],
|
|
2001
|
-
listBullet: ["character", "image"]
|
|
2000
|
+
listBullet: ["character", "image"],
|
|
2001
|
+
mirror: "boolean"
|
|
2002
2002
|
};
|
|
2003
|
+
var themeKeys = new Set(THEME_DESIGN_KEYS);
|
|
2003
2004
|
var accepts = (key, value) => VALUES[key] === "boolean" ? typeof value === "boolean" : VALUES[key].includes(value);
|
|
2004
2005
|
var object = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
2005
2006
|
function resolveDesignHints(options = {}) {
|
|
2006
|
-
const slide = object(object(options.slide).design), host = object(options.deck), deck = object(object(options.presentation).design), layout = object(object(options.layout).design);
|
|
2007
|
+
const slide = object(object(options.slide).design), host = object(options.deck), deck = object(object(options.presentation).design), theme = object(object(options.theme).design), layout = object(object(options.layout).design);
|
|
2007
2008
|
const index = options.slideIndex ?? 0;
|
|
2008
2009
|
const result = { sources: {}, paths: {} };
|
|
2009
2010
|
const set2 = (key, value, source, path) => {
|
|
@@ -2015,6 +2016,7 @@ function resolveDesignHints(options = {}) {
|
|
|
2015
2016
|
if (accepts(key, slide[key])) set2(key, slide[key], "slide", `slides.${index}.design.${key}`);
|
|
2016
2017
|
else if (accepts(key, host[key])) set2(key, host[key], "deck", `design.${key}`);
|
|
2017
2018
|
else if (accepts(key, deck[key])) set2(key, deck[key], "deck", `design.${key}`);
|
|
2019
|
+
else if (themeKeys.has(key) && accepts(key, theme[key])) set2(key, theme[key], "theme", slide.theme !== void 0 ? `slides.${index}.design.theme` : "design.theme");
|
|
2018
2020
|
else if (accepts(key, layout[key])) set2(key, layout[key], "layout", `slides.${index}.layout`);
|
|
2019
2021
|
}
|
|
2020
2022
|
return result;
|
|
@@ -2043,73 +2045,447 @@ function readingRows(items) {
|
|
|
2043
2045
|
return rows3.map((row) => row.items.sort((a, b) => index.get(a) - index.get(b)));
|
|
2044
2046
|
}
|
|
2045
2047
|
|
|
2046
|
-
// src/layout-
|
|
2047
|
-
var
|
|
2048
|
-
var
|
|
2049
|
-
var
|
|
2048
|
+
// src/layout-template.ts
|
|
2049
|
+
var REGION_KINDS = ["text", "list", "image", "video", "chart", "table", "code", "metric", "quote", "timeline", "group"];
|
|
2050
|
+
var REGION_ROLES = ["primary", "secondary", "media", "supporting"];
|
|
2051
|
+
var REGION_FLOWS = ["none", "grid", "column", "auto"];
|
|
2052
|
+
var REGION_ANCHORS = ["top", "middle", "bottom"];
|
|
2053
|
+
var HEADING_AREAS = ["title", "subtitle"];
|
|
2054
|
+
var RESERVED_REGION_NAMES = ["title", "subtitle", "tag", "auto", "left", "center", "right", "top", "middle", "bottom"];
|
|
2055
|
+
var MAX_TEMPLATE_TRACKS = 12;
|
|
2056
|
+
var MAX_REGION_BLOCKS = 12;
|
|
2057
|
+
var AUTO_LAYOUT = "auto";
|
|
2058
|
+
var OPFLayoutTemplateError = class extends RangeError {
|
|
2059
|
+
constructor(issues) {
|
|
2060
|
+
super(`The layout template is invalid: ${issues.map((issue) => `${issue.path || "/"}: ${issue.message}`).join("; ")}`);
|
|
2061
|
+
this.issues = issues;
|
|
2062
|
+
this.name = "OPFLayoutTemplateError";
|
|
2063
|
+
}
|
|
2064
|
+
issues;
|
|
2065
|
+
code = "layout-template";
|
|
2066
|
+
};
|
|
2067
|
+
var NAME = /^[a-z][a-z0-9-]*$/;
|
|
2050
2068
|
var record4 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2069
|
+
var pointerSegment = (segment2) => segment2.replaceAll("~", "~0").replaceAll("/", "~1");
|
|
2070
|
+
var reserved = new Set(RESERVED_REGION_NAMES);
|
|
2071
|
+
var headingNames = new Set(HEADING_AREAS);
|
|
2072
|
+
var positive = (value) => typeof value === "number" && Number.isFinite(value) && value > 0;
|
|
2073
|
+
function isLayoutTemplate(layout) {
|
|
2074
|
+
return Object.hasOwn(record4(layout), "areas");
|
|
2075
|
+
}
|
|
2076
|
+
function layoutRegion(name, value) {
|
|
2077
|
+
const entry = record4(value);
|
|
2078
|
+
const accepts2 = Array.isArray(entry.accepts) ? [...new Set(entry.accepts.filter((kind2) => REGION_KINDS.includes(kind2)))] : [];
|
|
2079
|
+
const flow = REGION_FLOWS.includes(entry.flow) ? entry.flow : "auto";
|
|
2080
|
+
const max = Number.isInteger(entry.max) && entry.max >= 1 && entry.max <= MAX_REGION_BLOCKS ? entry.max : flow === "none" ? 1 : 6;
|
|
2081
|
+
return {
|
|
2082
|
+
name,
|
|
2083
|
+
accepts: accepts2,
|
|
2084
|
+
role: REGION_ROLES.includes(entry.role) ? entry.role : "primary",
|
|
2085
|
+
flow,
|
|
2086
|
+
max,
|
|
2087
|
+
bleed: entry.bleed === true,
|
|
2088
|
+
listColumns: entry.listColumns === "auto" ? "auto" : 1,
|
|
2089
|
+
anchor: REGION_ANCHORS.includes(entry.anchor) ? entry.anchor : "top",
|
|
2090
|
+
empty: entry.empty === "keep" ? "keep" : "collapse"
|
|
2091
|
+
};
|
|
2067
2092
|
}
|
|
2068
|
-
function
|
|
2069
|
-
const
|
|
2070
|
-
const
|
|
2071
|
-
|
|
2093
|
+
function parse(layout) {
|
|
2094
|
+
const value = record4(layout);
|
|
2095
|
+
const issues = [];
|
|
2096
|
+
const grid = (code, path, message) => issues.push({ code, path, message });
|
|
2097
|
+
const areas = value.areas;
|
|
2098
|
+
if (!Array.isArray(areas) || !areas.length) {
|
|
2099
|
+
grid("layout-template", "/areas", "a template needs 1 to 12 rows of area names");
|
|
2100
|
+
return { issues };
|
|
2101
|
+
}
|
|
2102
|
+
if (areas.length > MAX_TEMPLATE_TRACKS) grid("layout-template", "/areas", `a template has at most ${MAX_TEMPLATE_TRACKS} rows; this one has ${areas.length}`);
|
|
2103
|
+
const cells = areas.map((row, index) => {
|
|
2104
|
+
if (!Array.isArray(row)) {
|
|
2105
|
+
grid("layout-template", `/areas/${index}`, "each row is an array of area names; use nested arrays instead of space-separated strings");
|
|
2106
|
+
return [];
|
|
2107
|
+
}
|
|
2108
|
+
const words = [];
|
|
2109
|
+
if (!row.length) grid("layout-template", `/areas/${index}`, 'a row needs at least one area name or "."');
|
|
2110
|
+
row.forEach((cell, column) => {
|
|
2111
|
+
if (typeof cell !== "string") grid("layout-template", `/areas/${index}/${column}`, 'each cell is one area name or "."');
|
|
2112
|
+
else {
|
|
2113
|
+
words.push(cell);
|
|
2114
|
+
if (cell !== "." && !NAME.test(cell)) grid("layout-template", `/areas/${index}/${column}`, `'${cell}' is not an area name (lowercase letters, digits and hyphens, starting with a letter) or "."`);
|
|
2115
|
+
}
|
|
2116
|
+
});
|
|
2117
|
+
return words;
|
|
2118
|
+
});
|
|
2119
|
+
const width = cells[0]?.length ?? 0;
|
|
2120
|
+
cells.forEach((row, index) => {
|
|
2121
|
+
if (index > 0 && row.length !== width && row.length) grid("layout-template", `/areas/${index}`, `every row has the same number of cells; row ${index + 1} has ${row.length}, row 1 has ${width}`);
|
|
2122
|
+
});
|
|
2123
|
+
if (width > MAX_TEMPLATE_TRACKS) grid("layout-template", "/areas", `a template has at most ${MAX_TEMPLATE_TRACKS} columns; this one has ${width}`);
|
|
2124
|
+
const columns2 = value.columns === void 0 ? Array.from({ length: width }, () => 1) : value.columns;
|
|
2125
|
+
const rows3 = value.rows === void 0 ? Array.from({ length: cells.length }, () => 1) : value.rows;
|
|
2126
|
+
if (!Array.isArray(columns2) || columns2.length !== width || !columns2.every(positive)) grid("layout-template", "/columns", `columns needs one positive number per cell of a row (${width})`);
|
|
2127
|
+
if (!Array.isArray(rows3) || rows3.length !== cells.length || !rows3.every((size) => size === "auto" || positive(size))) grid("layout-template", "/rows", `rows needs one positive number or "auto" per row (${cells.length})`);
|
|
2128
|
+
if (issues.length) return { issues };
|
|
2129
|
+
const bounds = /* @__PURE__ */ new Map();
|
|
2130
|
+
cells.forEach((row, r) => {
|
|
2131
|
+
row.forEach((name, c) => {
|
|
2132
|
+
if (name === ".") return;
|
|
2133
|
+
const found = bounds.get(name);
|
|
2134
|
+
if (!found) bounds.set(name, { top: r, left: c, bottom: r, right: c, count: 1 });
|
|
2135
|
+
else {
|
|
2136
|
+
found.top = Math.min(found.top, r);
|
|
2137
|
+
found.left = Math.min(found.left, c);
|
|
2138
|
+
found.bottom = Math.max(found.bottom, r);
|
|
2139
|
+
found.right = Math.max(found.right, c);
|
|
2140
|
+
found.count++;
|
|
2141
|
+
}
|
|
2142
|
+
});
|
|
2143
|
+
});
|
|
2144
|
+
const list = [];
|
|
2145
|
+
for (const [name, box] of bounds) {
|
|
2146
|
+
const filled = (box.bottom - box.top + 1) * (box.right - box.left + 1);
|
|
2147
|
+
let rectangle = filled === box.count;
|
|
2148
|
+
for (let r = box.top; rectangle && r <= box.bottom; r++) for (let c = box.left; c <= box.right; c++) if (cells[r][c] !== name) {
|
|
2149
|
+
rectangle = false;
|
|
2150
|
+
break;
|
|
2151
|
+
}
|
|
2152
|
+
if (!rectangle) {
|
|
2153
|
+
grid("layout-template", "/areas", `the cells of '${name}' do not form one filled rectangle`);
|
|
2154
|
+
continue;
|
|
2155
|
+
}
|
|
2156
|
+
list.push({ name, row: box.top, column: box.left, rowSpan: box.bottom - box.top + 1, columnSpan: box.right - box.left + 1, heading: headingNames.has(name) });
|
|
2157
|
+
}
|
|
2158
|
+
if (issues.length) return { issues };
|
|
2159
|
+
list.sort((a, b) => a.row - b.row || a.column - b.column);
|
|
2160
|
+
const entries = record4(value.regions);
|
|
2161
|
+
const region = (path, message) => grid("layout-region", path, message);
|
|
2162
|
+
if (value.regions !== void 0 && (value.regions === null || typeof value.regions !== "object" || Array.isArray(value.regions))) region("/regions", "regions is an object keyed by region name");
|
|
2163
|
+
for (const name of Object.keys(entries)) {
|
|
2164
|
+
if (reserved.has(name)) region(`/regions/${pointerSegment(name)}`, `'${name}' is reserved and cannot name a region (reserved: ${RESERVED_REGION_NAMES.join(", ")})`);
|
|
2165
|
+
else if (!bounds.has(name)) region(`/regions/${pointerSegment(name)}`, `region '${name}' has no area in areas`);
|
|
2166
|
+
}
|
|
2167
|
+
for (const area of list) {
|
|
2168
|
+
if (area.heading) continue;
|
|
2169
|
+
if (reserved.has(area.name)) {
|
|
2170
|
+
if (!Object.hasOwn(entries, area.name)) region("/areas", `'${area.name}' is reserved and cannot name a body area (reserved: ${RESERVED_REGION_NAMES.join(", ")})`);
|
|
2171
|
+
continue;
|
|
2172
|
+
}
|
|
2173
|
+
if (!Object.hasOwn(entries, area.name)) region("/regions", `body area '${area.name}' has no entry in regions`);
|
|
2174
|
+
}
|
|
2175
|
+
if (bounds.has("subtitle") && !bounds.has("title")) region("/areas", "a 'subtitle' area needs a 'title' area");
|
|
2176
|
+
for (const [name, entry] of Object.entries(entries)) {
|
|
2177
|
+
const raw = record4(entry);
|
|
2178
|
+
if (raw.flow === "none" && raw.max !== void 0 && raw.max !== 1) region(`/regions/${pointerSegment(name)}/max`, `a region with flow "none" holds one block; max must be 1, not ${JSON.stringify(raw.max)}`);
|
|
2179
|
+
}
|
|
2180
|
+
const regions = list.filter((area) => !area.heading && !reserved.has(area.name) && Object.hasOwn(entries, area.name)).map((area) => layoutRegion(area.name, entries[area.name]));
|
|
2181
|
+
for (const entry of regions) if (!entry.accepts.length) region(`/regions/${pointerSegment(entry.name)}/accepts`, `region '${entry.name}' accepts no content kind`);
|
|
2182
|
+
if (value.overflowRegion !== void 0 && !regions.some((entry) => entry.name === value.overflowRegion)) region("/overflowRegion", `overflowRegion ${JSON.stringify(value.overflowRegion)} is not a region of this layout`);
|
|
2183
|
+
if (issues.length) return { issues };
|
|
2184
|
+
const overflowRegion = typeof value.overflowRegion === "string" ? value.overflowRegion : regions.find((entry) => entry.role === "primary" && entry.flow !== "none")?.name;
|
|
2185
|
+
return {
|
|
2186
|
+
issues,
|
|
2187
|
+
template: {
|
|
2188
|
+
rows: rows3.slice(),
|
|
2189
|
+
columns: columns2.slice(),
|
|
2190
|
+
grid: cells,
|
|
2191
|
+
areas: list,
|
|
2192
|
+
regions,
|
|
2193
|
+
...overflowRegion !== void 0 ? { overflowRegion } : {},
|
|
2194
|
+
title: bounds.has("title"),
|
|
2195
|
+
subtitle: bounds.has("subtitle")
|
|
2196
|
+
}
|
|
2072
2197
|
};
|
|
2073
|
-
visit(layoutSlots(layout));
|
|
2074
|
-
return leaves;
|
|
2075
2198
|
}
|
|
2076
|
-
function
|
|
2077
|
-
|
|
2078
|
-
if (!slot.children) return slot.type;
|
|
2079
|
-
const mode = record4(slot.placeholder.composition).mode;
|
|
2080
|
-
return `${typeof mode === "string" && mode !== "auto" ? mode : "group"} (${describe(slot.children)})`;
|
|
2081
|
-
}).join(", ");
|
|
2082
|
-
return describe(layoutSlots(layout));
|
|
2199
|
+
function layoutTemplateIssues(layout) {
|
|
2200
|
+
return isLayoutTemplate(layout) ? parse(layout).issues : [];
|
|
2083
2201
|
}
|
|
2084
|
-
function
|
|
2085
|
-
|
|
2202
|
+
function layoutTemplate(layout) {
|
|
2203
|
+
const parsed = parse(layout);
|
|
2204
|
+
if (!parsed.template) throw new OPFLayoutTemplateError(parsed.issues);
|
|
2205
|
+
return parsed.template;
|
|
2086
2206
|
}
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2207
|
+
|
|
2208
|
+
// src/bind-regions.ts
|
|
2209
|
+
var FIELDS = ["text", "items", "bullets", "image", "video", "chart", "table", "code", "metric", "quote", "timeline"];
|
|
2210
|
+
var FIELD_KINDS = { text: "text", bullets: "text", items: "list", image: "image", video: "video", chart: "chart", table: "table", code: "code", metric: "metric", quote: "quote", timeline: "timeline" };
|
|
2211
|
+
var IMAGE_EDGES = ["left", "right", "top", "bottom"];
|
|
2212
|
+
var PROMOTED_REGION_KEY = /^(top|middle|bottom)(\+(top|middle|bottom))*(:(left|center|right)(\+(left|center|right))*)?$|^(left|center|right)(\+(left|center|right))*$/;
|
|
2213
|
+
var record5 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
2214
|
+
var empty = (value) => value === void 0 || value === null || value === "" || Array.isArray(value) && value.length === 0;
|
|
2215
|
+
function blockKind(block) {
|
|
2216
|
+
const value = record5(block);
|
|
2217
|
+
if (Array.isArray(value.blocks)) return "group";
|
|
2218
|
+
if (typeof value.type === "string" && value.type !== "group" && Object.values(FIELD_KINDS).includes(value.type)) return value.type;
|
|
2219
|
+
const field = FIELDS.find((name) => value[name] !== void 0);
|
|
2220
|
+
return field ? FIELD_KINDS[field] : "text";
|
|
2221
|
+
}
|
|
2222
|
+
function leafKinds(block, into = /* @__PURE__ */ new Set(), depth = 0) {
|
|
2223
|
+
if (depth > 32) return into;
|
|
2224
|
+
for (const child of Array.isArray(block.blocks) ? block.blocks : []) {
|
|
2225
|
+
const value = record5(child);
|
|
2226
|
+
if (Array.isArray(value.blocks)) leafKinds(value, into, depth + 1);
|
|
2227
|
+
else into.add(blockKind(value));
|
|
2228
|
+
}
|
|
2229
|
+
return into;
|
|
2230
|
+
}
|
|
2231
|
+
function regionAccepts(region, block) {
|
|
2232
|
+
const kind2 = blockKind(block);
|
|
2233
|
+
if (region.accepts.includes(kind2)) return true;
|
|
2234
|
+
if (kind2 !== "group") return false;
|
|
2235
|
+
const kinds = leafKinds(record5(block));
|
|
2236
|
+
return kinds.size > 0 && [...kinds].every((leaf) => region.accepts.includes(leaf));
|
|
2237
|
+
}
|
|
2238
|
+
function placedImageBlocks(slide) {
|
|
2239
|
+
const value = record5(slide);
|
|
2240
|
+
const placed = /* @__PURE__ */ new Set();
|
|
2241
|
+
if (!Array.isArray(value.blocks) || Object.keys(value).some((key) => PROMOTED_REGION_KEY.test(key))) return placed;
|
|
2242
|
+
const used = /* @__PURE__ */ new Set();
|
|
2243
|
+
value.blocks.forEach((block, index) => {
|
|
2244
|
+
const host = record5(block);
|
|
2245
|
+
if (Array.isArray(host.blocks) || host.image === void 0 || host.placement === void 0) return;
|
|
2246
|
+
const edge = record5(host.placement).edge;
|
|
2247
|
+
if (!IMAGE_EDGES.includes(edge) || used.has(edge)) return;
|
|
2248
|
+
used.add(edge);
|
|
2249
|
+
placed.add(index);
|
|
2250
|
+
});
|
|
2251
|
+
return placed;
|
|
2252
|
+
}
|
|
2253
|
+
function rootNodes(slide, slideIndex = 0) {
|
|
2254
|
+
const value = record5(slide), base = `slides.${slideIndex}`;
|
|
2255
|
+
if (Array.isArray(value.blocks)) {
|
|
2256
|
+
const placed = placedImageBlocks(value);
|
|
2257
|
+
return value.blocks.flatMap((block, index) => {
|
|
2258
|
+
const host = record5(block);
|
|
2259
|
+
if (placed.has(index)) return [];
|
|
2260
|
+
if (!Array.isArray(host.blocks) && FIELDS.every((field) => empty(host[field]))) return [];
|
|
2261
|
+
if (Array.isArray(host.blocks) && !host.blocks.length) return [];
|
|
2262
|
+
return [{ path: `${base}.blocks.${index}`, kind: blockKind(host), block: index, value: host }];
|
|
2263
|
+
});
|
|
2264
|
+
}
|
|
2265
|
+
const nodes = [];
|
|
2266
|
+
for (const field of FIELDS) {
|
|
2267
|
+
if (empty(value[field]) || field === "bullets" && !empty(value.text)) continue;
|
|
2268
|
+
const fields2 = field === "text" && !empty(value.bullets) ? ["text", "bullets"] : [field];
|
|
2269
|
+
nodes.push({ path: `${base}.${field}`, kind: FIELD_KINDS[field], fields: fields2, value: Object.fromEntries(fields2.map((name) => [name, value[name]])) });
|
|
2270
|
+
}
|
|
2271
|
+
return nodes;
|
|
2272
|
+
}
|
|
2273
|
+
function regionRoleRank(role, kind2) {
|
|
2274
|
+
const media = kind2 === "image" || kind2 === "video";
|
|
2275
|
+
return media ? { media: 0, primary: 1, secondary: 2, supporting: 3 }[role] : { primary: 0, secondary: 1, supporting: 2, media: 3 }[role];
|
|
2276
|
+
}
|
|
2277
|
+
function bindRegions(slide, layout, options = {}) {
|
|
2278
|
+
const template = layoutTemplate(layout);
|
|
2279
|
+
const value = record5(slide), index = options.slideIndex ?? 0;
|
|
2280
|
+
const regions = template.regions.map((region) => ({ name: region.name, blocks: [], overflow: [] }));
|
|
2281
|
+
const result = { regions, below: [], diagnostics: [] };
|
|
2282
|
+
if (Object.keys(value).some((key) => PROMOTED_REGION_KEY.test(key))) return result;
|
|
2283
|
+
const byName = new Map(template.regions.map((region, order2) => [region.name, { region, binding: regions[order2], order: order2 }]));
|
|
2284
|
+
const room = (name) => {
|
|
2285
|
+
const entry = byName.get(name);
|
|
2286
|
+
return entry.binding.blocks.length < entry.region.max;
|
|
2287
|
+
};
|
|
2288
|
+
const nodes = rootNodes(value, index);
|
|
2289
|
+
const rest = [];
|
|
2290
|
+
for (const node of nodes) {
|
|
2291
|
+
const pin = node.block !== void 0 ? node.value.region : void 0;
|
|
2292
|
+
if (typeof pin !== "string") {
|
|
2293
|
+
rest.push(node);
|
|
2294
|
+
continue;
|
|
2104
2295
|
}
|
|
2296
|
+
const target = byName.get(pin), pinPath = `${node.path}.region`;
|
|
2297
|
+
if (!target) result.diagnostics.push({ code: "region-unknown", path: pinPath, region: pin, message: `The layout has no region '${pin}'; the block is placed by its kind instead.` });
|
|
2298
|
+
else if (!regionAccepts(target.region, node.value)) result.diagnostics.push({ code: "region-kind", path: pinPath, region: pin, message: `Region '${pin}' does not accept ${node.kind} content (it accepts ${target.region.accepts.join(", ")}); the block is placed by its kind instead.` });
|
|
2299
|
+
else if (!room(pin)) result.diagnostics.push({ code: "region-full", path: pinPath, region: pin, message: `Region '${pin}' already holds its ${target.region.max} block${target.region.max === 1 ? "" : "s"}; the block is placed by its kind instead.` });
|
|
2300
|
+
else {
|
|
2301
|
+
target.binding.blocks.push({ path: node.path, kind: node.kind, block: node.block, pinned: true });
|
|
2302
|
+
continue;
|
|
2303
|
+
}
|
|
2304
|
+
rest.push(node);
|
|
2305
|
+
}
|
|
2306
|
+
const overflowName = template.overflowRegion;
|
|
2307
|
+
for (const node of rest) {
|
|
2308
|
+
const bound = { path: node.path, kind: node.kind, ...node.block !== void 0 ? { block: node.block } : {}, ...node.fields ? { fields: node.fields } : {} };
|
|
2309
|
+
let best;
|
|
2310
|
+
for (const [name, entry] of byName) {
|
|
2311
|
+
if (!regionAccepts(entry.region, node.value) || !room(name)) continue;
|
|
2312
|
+
const rank = regionRoleRank(entry.region.role, node.kind);
|
|
2313
|
+
if (!best || rank < best.rank || rank === best.rank && entry.order < best.order) best = { rank, order: entry.order, name };
|
|
2314
|
+
}
|
|
2315
|
+
if (best) {
|
|
2316
|
+
byName.get(best.name).binding.blocks.push(bound);
|
|
2317
|
+
continue;
|
|
2318
|
+
}
|
|
2319
|
+
if (overflowName === void 0) {
|
|
2320
|
+
result.below.push(bound);
|
|
2321
|
+
result.diagnostics.push({ code: "layout-unplaced", path: node.path, message: "No region of the layout takes this block; it is drawn below the layout's grid. Choose another layout, pin it to a region, or paginate." });
|
|
2322
|
+
continue;
|
|
2323
|
+
}
|
|
2324
|
+
const overflow = byName.get(overflowName);
|
|
2325
|
+
if (room(overflowName)) {
|
|
2326
|
+
overflow.binding.blocks.push(bound);
|
|
2327
|
+
continue;
|
|
2328
|
+
}
|
|
2329
|
+
overflow.binding.overflow.push(bound);
|
|
2330
|
+
result.diagnostics.push({ code: "layout-unplaced", path: node.path, region: overflowName, message: `No region of the layout has room for this block; it is drawn in '${overflowName}' beyond its ${overflow.region.max} block${overflow.region.max === 1 ? "" : "s"}. Paginate to move it to a continuation slide, choose another layout, or remove a block.` });
|
|
2331
|
+
}
|
|
2332
|
+
const order = new Map(nodes.map((node, position) => [node.path, position]));
|
|
2333
|
+
for (const binding of regions) binding.blocks.sort((a, b) => order.get(a.path) - order.get(b.path));
|
|
2334
|
+
return result;
|
|
2335
|
+
}
|
|
2336
|
+
|
|
2337
|
+
// src/template-geometry.ts
|
|
2338
|
+
function gridFlowShape(count, landscape) {
|
|
2339
|
+
if (!Number.isInteger(count) || count < 1) return { columns: 1, rows: 0, perRow: [] };
|
|
2340
|
+
let columns2;
|
|
2341
|
+
if (landscape) columns2 = count <= 3 ? count : count === 4 ? 2 : count <= 6 ? 3 : 4;
|
|
2342
|
+
else columns2 = count <= 3 ? 1 : count <= 6 ? 2 : Math.ceil(count / 3);
|
|
2343
|
+
const rows3 = Math.ceil(count / columns2);
|
|
2344
|
+
const perRow = Array.from({ length: rows3 }, (_, row) => Math.min(columns2, count - row * columns2));
|
|
2345
|
+
return { columns: columns2, rows: rows3, perRow };
|
|
2346
|
+
}
|
|
2347
|
+
function flowShape(arrangement, count, landscape) {
|
|
2348
|
+
if (count < 1) return { columns: 1, rows: 0, perRow: [] };
|
|
2349
|
+
if (arrangement === "row") return { columns: count, rows: 1, perRow: [count] };
|
|
2350
|
+
if (arrangement === "column") return { columns: 1, rows: count, perRow: Array.from({ length: count }, () => 1) };
|
|
2351
|
+
return gridFlowShape(count, landscape);
|
|
2352
|
+
}
|
|
2353
|
+
function flowCells(shape, box, requestedGap) {
|
|
2354
|
+
if (!shape.rows) return { cells: [], gap: requestedGap };
|
|
2355
|
+
const gap = Math.max(0, Math.min(requestedGap, box.width / (shape.columns * 2), box.height / (shape.rows * 2)));
|
|
2356
|
+
const width = (box.width - gap * (shape.columns - 1)) / shape.columns;
|
|
2357
|
+
const height = (box.height - gap * (shape.rows - 1)) / shape.rows;
|
|
2358
|
+
const cells = [];
|
|
2359
|
+
shape.perRow.forEach((count, row) => {
|
|
2360
|
+
const used = count * width + (count - 1) * gap, start = box.x + (box.width - used) / 2;
|
|
2361
|
+
for (let column = 0; column < count; column++) cells.push({ x: count === shape.columns ? box.x + column * (width + gap) : start + column * (width + gap), y: box.y + row * (height + gap), width, height });
|
|
2362
|
+
});
|
|
2363
|
+
return { cells, gap };
|
|
2364
|
+
}
|
|
2365
|
+
function columnWidths(sizes, total, gap) {
|
|
2366
|
+
const sum = sizes.reduce((a, b) => a + b, 0);
|
|
2367
|
+
const rest = Math.max(0, total - Math.max(0, sizes.length - 1) * gap);
|
|
2368
|
+
return sizes.map((size) => sum > 0 ? rest * size / sum : 0);
|
|
2369
|
+
}
|
|
2370
|
+
function collapseAreas(grid, empty2, heading, absorbs = () => true) {
|
|
2371
|
+
const owner = grid.map((row) => [...row]);
|
|
2372
|
+
const joined = /* @__PURE__ */ new Map();
|
|
2373
|
+
const rect = (name) => {
|
|
2374
|
+
let top = Infinity, left = Infinity, bottom = -1, right = -1;
|
|
2375
|
+
owner.forEach((row, r) => {
|
|
2376
|
+
row.forEach((cell, c) => {
|
|
2377
|
+
if (cell === name) {
|
|
2378
|
+
top = Math.min(top, r);
|
|
2379
|
+
left = Math.min(left, c);
|
|
2380
|
+
bottom = Math.max(bottom, r);
|
|
2381
|
+
right = Math.max(right, c);
|
|
2382
|
+
}
|
|
2383
|
+
});
|
|
2384
|
+
});
|
|
2385
|
+
return bottom < 0 ? void 0 : { row: top, column: left, rowSpan: bottom - top + 1, columnSpan: right - left + 1 };
|
|
2105
2386
|
};
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2387
|
+
const order = [];
|
|
2388
|
+
for (const row of owner) for (const cell of row) if (cell !== "." && !order.includes(cell)) order.push(cell);
|
|
2389
|
+
const pending = order.filter((name) => empty2.has(name));
|
|
2390
|
+
let changed = true;
|
|
2391
|
+
while (changed) {
|
|
2392
|
+
changed = false;
|
|
2393
|
+
for (const name of pending) {
|
|
2394
|
+
if (joined.has(name)) continue;
|
|
2395
|
+
const own3 = rect(name);
|
|
2396
|
+
if (!own3) continue;
|
|
2397
|
+
const neighbour = (side) => {
|
|
2398
|
+
const cells = [];
|
|
2399
|
+
if (side === "start" || side === "end") {
|
|
2400
|
+
const column = side === "start" ? own3.column - 1 : own3.column + own3.columnSpan;
|
|
2401
|
+
if (column < 0 || column >= (owner[0]?.length ?? 0)) return void 0;
|
|
2402
|
+
for (let r = own3.row; r < own3.row + own3.rowSpan; r++) cells.push(owner[r][column]);
|
|
2403
|
+
} else {
|
|
2404
|
+
const row = side === "above" ? own3.row - 1 : own3.row + own3.rowSpan;
|
|
2405
|
+
if (row < 0 || row >= owner.length) return void 0;
|
|
2406
|
+
for (let c = own3.column; c < own3.column + own3.columnSpan; c++) cells.push(owner[row][c]);
|
|
2407
|
+
}
|
|
2408
|
+
const candidate = cells[0];
|
|
2409
|
+
if (candidate === void 0 || candidate === "." || candidate === name || cells.some((cell) => cell !== candidate)) return void 0;
|
|
2410
|
+
if (empty2.has(candidate) || !absorbs(candidate)) return void 0;
|
|
2411
|
+
const other = rect(candidate);
|
|
2412
|
+
const fits = side === "start" || side === "end" ? other.row === own3.row && other.rowSpan === own3.rowSpan : other.column === own3.column && other.columnSpan === own3.columnSpan;
|
|
2413
|
+
return fits ? candidate : void 0;
|
|
2414
|
+
};
|
|
2415
|
+
const sides = ["start", "end", "below", "above"];
|
|
2416
|
+
let target;
|
|
2417
|
+
for (const body of [true, false]) {
|
|
2418
|
+
for (const side of sides) {
|
|
2419
|
+
const candidate = neighbour(side);
|
|
2420
|
+
if (candidate !== void 0 && heading(candidate) !== body) {
|
|
2421
|
+
target = candidate;
|
|
2422
|
+
break;
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2425
|
+
if (target !== void 0) break;
|
|
2426
|
+
}
|
|
2427
|
+
if (target === void 0) continue;
|
|
2428
|
+
for (const row of owner) row.forEach((cell, c) => {
|
|
2429
|
+
if (cell === name) row[c] = target;
|
|
2430
|
+
});
|
|
2431
|
+
joined.set(name, target);
|
|
2432
|
+
changed = true;
|
|
2433
|
+
}
|
|
2111
2434
|
}
|
|
2112
|
-
return {
|
|
2435
|
+
return { grid: owner, joined };
|
|
2436
|
+
}
|
|
2437
|
+
function areaRects(grid) {
|
|
2438
|
+
const rects = /* @__PURE__ */ new Map();
|
|
2439
|
+
grid.forEach((row, r) => {
|
|
2440
|
+
row.forEach((name, c) => {
|
|
2441
|
+
if (name === ".") return;
|
|
2442
|
+
const found = rects.get(name);
|
|
2443
|
+
if (!found) rects.set(name, { row: r, column: c, rowSpan: 1, columnSpan: 1 });
|
|
2444
|
+
else {
|
|
2445
|
+
found.rowSpan = Math.max(found.rowSpan, r - found.row + 1);
|
|
2446
|
+
found.columnSpan = Math.max(found.columnSpan, c - found.column + 1);
|
|
2447
|
+
}
|
|
2448
|
+
});
|
|
2449
|
+
});
|
|
2450
|
+
return rects;
|
|
2451
|
+
}
|
|
2452
|
+
function listColumnBreaks(heights, levels, count) {
|
|
2453
|
+
const n = heights.length;
|
|
2454
|
+
if (count <= 1 || n < 2) return [];
|
|
2455
|
+
const allowed = Array.from({ length: n }, (_, index) => index > 0 && (levels[index] ?? 0) === 0);
|
|
2456
|
+
const prefix = [0];
|
|
2457
|
+
for (const height of heights) prefix.push(prefix.at(-1) + height);
|
|
2458
|
+
const span = (from, to) => prefix[to] - prefix[from];
|
|
2459
|
+
const memo = /* @__PURE__ */ new Map();
|
|
2460
|
+
const solve = (start, columns2) => {
|
|
2461
|
+
const key = `${start}:${columns2}`;
|
|
2462
|
+
const found = memo.get(key);
|
|
2463
|
+
if (found) return found;
|
|
2464
|
+
let best = { cost: span(start, n), breaks: [] };
|
|
2465
|
+
if (columns2 > 1) for (let next = start + 1; next < n; next++) {
|
|
2466
|
+
if (!allowed[next]) continue;
|
|
2467
|
+
const rest = solve(next, columns2 - 1);
|
|
2468
|
+
const cost = Math.max(span(start, next), rest.cost);
|
|
2469
|
+
if (cost < best.cost - 1e-9) best = { cost, breaks: [next, ...rest.breaks] };
|
|
2470
|
+
}
|
|
2471
|
+
memo.set(key, best);
|
|
2472
|
+
return best;
|
|
2473
|
+
};
|
|
2474
|
+
return solve(0, count).breaks;
|
|
2475
|
+
}
|
|
2476
|
+
function allocateRows(rows3, total, gap) {
|
|
2477
|
+
const auto = rows3.map((row) => row.size === "auto" ? Math.max(0, Math.min(row.need, row.kind === "below" ? total : total / 2)) : 0);
|
|
2478
|
+
const visible = rows3.filter((row, index) => row.size !== "auto" || auto[index] > 0).length;
|
|
2479
|
+
const headings2 = rows3.reduce((sum, row, index) => sum + (row.kind === "heading" ? auto[index] : 0), 0);
|
|
2480
|
+
const space = Math.max(0, total - headings2 - Math.max(0, visible - 1) * gap);
|
|
2481
|
+
const numeric = rows3.reduce((sum, row) => sum + (row.size === "auto" ? 0 : row.size), 0);
|
|
2482
|
+
const numericNeed = rows3.reduce((sum, row) => sum + (row.size === "auto" ? 0 : Math.max(0, row.need)), 0);
|
|
2483
|
+
const reserve = numeric > 0 ? Math.min(numericNeed, space / 2) : 0;
|
|
2484
|
+
const body = rows3.reduce((sum, row, index) => sum + (row.size === "auto" && row.kind !== "heading" ? auto[index] : 0), 0);
|
|
2485
|
+
const factor = body > space - reserve && body > 0 ? Math.max(0, space - reserve) / body : 1;
|
|
2486
|
+
const heights = rows3.map((row, index) => row.size === "auto" ? row.kind === "heading" ? auto[index] : auto[index] * factor : 0);
|
|
2487
|
+
const rest = Math.max(0, space - heights.reduce((sum, height, index) => sum + (rows3[index].kind === "heading" ? 0 : height), 0));
|
|
2488
|
+
return rows3.map((row, index) => row.size === "auto" ? heights[index] : numeric > 0 ? rest * row.size / numeric : 0);
|
|
2113
2489
|
}
|
|
2114
2490
|
|
|
2115
2491
|
// src/direction.ts
|
|
@@ -2152,6 +2528,215 @@ function paragraphDirectionAt(text2, deckDirection) {
|
|
|
2152
2528
|
};
|
|
2153
2529
|
}
|
|
2154
2530
|
|
|
2531
|
+
// src/catalog-refs.ts
|
|
2532
|
+
var catalogKinds = ["layouts", "themes", "colorSchemes", "fontSchemes", "narratives", "audiences", "purposes", "tones"];
|
|
2533
|
+
var CATALOG_REFERENCE_PATTERN = /^(?:([a-z][a-z0-9-]*):)?([a-z][a-z0-9-]*)$/;
|
|
2534
|
+
var CATALOG_GROUP_PATTERN = /^[a-z][a-z0-9-]*$/;
|
|
2535
|
+
function provenanceOf(found) {
|
|
2536
|
+
const { record: _record, ...provenance } = found;
|
|
2537
|
+
return provenance;
|
|
2538
|
+
}
|
|
2539
|
+
var OPFCatalogsOptionError = class extends TypeError {
|
|
2540
|
+
code = "invalid-catalogs";
|
|
2541
|
+
constructor(entry, detail) {
|
|
2542
|
+
super(`${entry}: the catalogs option must be an array of registered catalogs ({ source, <kind>: { <id>: record } } with known catalog kinds); ${detail}.`);
|
|
2543
|
+
this.name = "OPFCatalogsOptionError";
|
|
2544
|
+
}
|
|
2545
|
+
};
|
|
2546
|
+
function checkCatalogsOption(catalogs, entry) {
|
|
2547
|
+
if (catalogs === void 0) return [];
|
|
2548
|
+
if (!Array.isArray(catalogs)) throw new OPFCatalogsOptionError(entry, `got ${catalogs === null ? "null" : typeof catalogs}`);
|
|
2549
|
+
catalogs.forEach((catalog, index) => {
|
|
2550
|
+
if (!isRec(catalog) || typeof catalog.source !== "string") throw new OPFCatalogsOptionError(entry, `catalogs[${index}] is not an object with a string source`);
|
|
2551
|
+
for (const [kind2, records] of Object.entries(catalog)) {
|
|
2552
|
+
if (kind2 === "source") continue;
|
|
2553
|
+
if (!catalogKinds.includes(kind2)) throw new OPFCatalogsOptionError(entry, `catalogs[${index}].${kind2} is not a catalog kind`);
|
|
2554
|
+
if (!isRec(records)) throw new OPFCatalogsOptionError(entry, `catalogs[${index}].${kind2} is not an object of records keyed by id`);
|
|
2555
|
+
}
|
|
2556
|
+
});
|
|
2557
|
+
return catalogs;
|
|
2558
|
+
}
|
|
2559
|
+
var OPFUnresolvedReferenceError = class extends Error {
|
|
2560
|
+
diagnostics;
|
|
2561
|
+
constructor(diagnostics) {
|
|
2562
|
+
super(diagnostics.map((diagnostic) => diagnostic.message).join(" "));
|
|
2563
|
+
this.name = "OPFUnresolvedReferenceError";
|
|
2564
|
+
this.diagnostics = diagnostics;
|
|
2565
|
+
}
|
|
2566
|
+
};
|
|
2567
|
+
var isRec = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2568
|
+
var rec = (value) => isRec(value) ? value : {};
|
|
2569
|
+
var own2 = (value, key) => Object.hasOwn(value, key);
|
|
2570
|
+
function parseReference(reference) {
|
|
2571
|
+
if (typeof reference !== "string") return void 0;
|
|
2572
|
+
const match = CATALOG_REFERENCE_PATTERN.exec(reference);
|
|
2573
|
+
if (!match) return void 0;
|
|
2574
|
+
const [, group, id] = match;
|
|
2575
|
+
return group === void 0 ? { id } : { group, id };
|
|
2576
|
+
}
|
|
2577
|
+
function groupsOf(document) {
|
|
2578
|
+
return rec(rec(document).catalogs);
|
|
2579
|
+
}
|
|
2580
|
+
function catalogGroupDeclared(document, name) {
|
|
2581
|
+
const groups = groupsOf(document);
|
|
2582
|
+
return own2(groups, name) && (isRec(groups[name]) || name === "default" && groups[name] === false);
|
|
2583
|
+
}
|
|
2584
|
+
function catalogGroupSource(document, name, options = {}) {
|
|
2585
|
+
if (name === "custom") return void 0;
|
|
2586
|
+
const group = groupsOf(document)[name];
|
|
2587
|
+
if (name === "default") {
|
|
2588
|
+
if (group === false) return void 0;
|
|
2589
|
+
const source2 = rec(group).source;
|
|
2590
|
+
return typeof source2 === "string" ? source2 : options.catalogs?.[0]?.source;
|
|
2591
|
+
}
|
|
2592
|
+
const source = rec(group).source;
|
|
2593
|
+
return typeof source === "string" ? source : void 0;
|
|
2594
|
+
}
|
|
2595
|
+
function registeredCatalog(source, options = {}) {
|
|
2596
|
+
if (source === void 0) return void 0;
|
|
2597
|
+
return options.catalogs?.find((catalog) => catalog?.source === source);
|
|
2598
|
+
}
|
|
2599
|
+
function lookupInGroup(document, kind2, group, id, reference, options = {}) {
|
|
2600
|
+
const groups = groupsOf(document);
|
|
2601
|
+
if (group === "default" && groups.default === false) return void 0;
|
|
2602
|
+
if (group !== "default" && group !== "custom" && !isRec(groups[group])) return void 0;
|
|
2603
|
+
const source = catalogGroupSource(document, group, options);
|
|
2604
|
+
const embedded = rec(rec(groups[group])[kind2]);
|
|
2605
|
+
if (own2(embedded, id) && isRec(embedded[id])) {
|
|
2606
|
+
return { kind: kind2, reference, id, group, ...source !== void 0 ? { source } : {}, origin: "document", record: embedded[id] };
|
|
2607
|
+
}
|
|
2608
|
+
if (group === "custom") return void 0;
|
|
2609
|
+
const hosted = registeredCatalog(source, options)?.[kind2];
|
|
2610
|
+
if (hosted && own2(hosted, id) && isRec(hosted[id])) {
|
|
2611
|
+
return { kind: kind2, reference, id, group, ...source !== void 0 ? { source } : {}, origin: "host", record: hosted[id] };
|
|
2612
|
+
}
|
|
2613
|
+
return void 0;
|
|
2614
|
+
}
|
|
2615
|
+
function resolveReference(document, kind2, reference, options = {}) {
|
|
2616
|
+
checkCatalogsOption(options.catalogs, "resolveReference");
|
|
2617
|
+
const parsed = parseReference(reference);
|
|
2618
|
+
if (!parsed) return void 0;
|
|
2619
|
+
const written = reference;
|
|
2620
|
+
if (parsed.group !== void 0) return lookupInGroup(document, kind2, parsed.group, parsed.id, written, options);
|
|
2621
|
+
const order = [...new Set([options.group, "custom", "default"].filter((group) => typeof group === "string"))];
|
|
2622
|
+
for (const group of order) {
|
|
2623
|
+
const found = lookupInGroup(document, kind2, group, parsed.id, written, options);
|
|
2624
|
+
if (found) return found;
|
|
2625
|
+
}
|
|
2626
|
+
return void 0;
|
|
2627
|
+
}
|
|
2628
|
+
var KIND_NOUNS = {
|
|
2629
|
+
layouts: "Layout",
|
|
2630
|
+
themes: "Theme",
|
|
2631
|
+
colorSchemes: "Colour scheme",
|
|
2632
|
+
fontSchemes: "Font scheme",
|
|
2633
|
+
narratives: "Narrative",
|
|
2634
|
+
audiences: "Audience",
|
|
2635
|
+
purposes: "Purpose",
|
|
2636
|
+
tones: "Tone"
|
|
2637
|
+
};
|
|
2638
|
+
function unresolvedReference(document, kind2, reference, path, options = {}) {
|
|
2639
|
+
const parsed = parseReference(reference);
|
|
2640
|
+
const group = parsed?.group ?? "default";
|
|
2641
|
+
const source = catalogGroupSource(document, group, options);
|
|
2642
|
+
const noun = KIND_NOUNS[kind2];
|
|
2643
|
+
const where = parsed?.group !== void 0 && !catalogGroupDeclared(document, parsed.group) ? `the document declares no catalogs.${parsed.group} group` : group === "custom" ? "it is not in catalogs.custom" : group === "default" && groupsOf(document).default === false ? "it is not in catalogs.custom and catalogs.default is false" : source === void 0 ? `it is not embedded in catalogs.${group === "default" ? "custom or catalogs.default" : group} and no catalog is registered for it` : `it is not embedded in catalogs.${group === "default" ? "custom or catalogs.default" : group} and the catalog registered for ${source} ${registeredCatalog(source, options) ? "has no such record" : "is not registered"}`;
|
|
2644
|
+
const fallback = kind2 === "layouts" ? "automatic" : "engine-default";
|
|
2645
|
+
return {
|
|
2646
|
+
code: "unresolved-reference",
|
|
2647
|
+
kind: kind2,
|
|
2648
|
+
reference,
|
|
2649
|
+
path,
|
|
2650
|
+
group,
|
|
2651
|
+
...source !== void 0 ? { source } : {},
|
|
2652
|
+
fallback,
|
|
2653
|
+
message: `${noun} '${reference}' resolves nowhere: ${where}; ${fallback === "automatic" ? "the slide composes automatically" : "the engine default is used"}.`
|
|
2654
|
+
};
|
|
2655
|
+
}
|
|
2656
|
+
var pushReference = (sites, kind2, value, path, group) => {
|
|
2657
|
+
if (typeof value === "string" && parseReference(value)) sites.push({ kind: kind2, reference: value, path, ...group !== void 0 ? { group } : {} });
|
|
2658
|
+
};
|
|
2659
|
+
var pushObjectReference = (sites, kind2, value, path, group) => {
|
|
2660
|
+
if (typeof value === "string") pushReference(sites, kind2, value, path, group);
|
|
2661
|
+
else if (isRec(value)) pushReference(sites, kind2, value.id, [...path, "id"], group);
|
|
2662
|
+
};
|
|
2663
|
+
function designSites(sites, design, path) {
|
|
2664
|
+
if (!isRec(design)) return;
|
|
2665
|
+
pushReference(sites, "themes", design.theme, [...path, "theme"]);
|
|
2666
|
+
pushObjectReference(sites, "colorSchemes", design.colorScheme, [...path, "colorScheme"]);
|
|
2667
|
+
pushObjectReference(sites, "fontSchemes", design.fontScheme, [...path, "fontScheme"]);
|
|
2668
|
+
}
|
|
2669
|
+
function recordReferenceSites(kind2, record9, path, group) {
|
|
2670
|
+
const sites = [];
|
|
2671
|
+
if (kind2 === "themes" && isRec(record9)) {
|
|
2672
|
+
pushObjectReference(sites, "colorSchemes", record9.colorScheme, [...path, "colorScheme"], group);
|
|
2673
|
+
pushObjectReference(sites, "fontSchemes", record9.fontScheme, [...path, "fontScheme"], group);
|
|
2674
|
+
}
|
|
2675
|
+
return sites;
|
|
2676
|
+
}
|
|
2677
|
+
function catalogReferenceSites(document, options = {}) {
|
|
2678
|
+
const deck = rec(document);
|
|
2679
|
+
const sites = [];
|
|
2680
|
+
pushReference(sites, "narratives", deck.narrative, ["narrative"]);
|
|
2681
|
+
if (Array.isArray(deck.audience)) deck.audience.forEach((entry, index) => {
|
|
2682
|
+
pushObjectReference(sites, "audiences", entry, ["audience", index]);
|
|
2683
|
+
});
|
|
2684
|
+
else pushObjectReference(sites, "audiences", deck.audience, ["audience"]);
|
|
2685
|
+
pushObjectReference(sites, "purposes", deck.purpose, ["purpose"]);
|
|
2686
|
+
pushObjectReference(sites, "tones", deck.tone, ["tone"]);
|
|
2687
|
+
if (isRec(deck.language)) {
|
|
2688
|
+
pushReference(sites, "fontSchemes", deck.language.fontScheme, ["language", "fontScheme"]);
|
|
2689
|
+
pushReference(sites, "fontSchemes", deck.language.googleFontScheme, ["language", "googleFontScheme"]);
|
|
2690
|
+
}
|
|
2691
|
+
designSites(sites, deck.design, ["design"]);
|
|
2692
|
+
if (options.slides !== false && Array.isArray(deck.slides))
|
|
2693
|
+
deck.slides.forEach((slide, index) => {
|
|
2694
|
+
if (!isRec(slide)) return;
|
|
2695
|
+
if (slide.layout !== "auto") pushReference(sites, "layouts", slide.layout, ["slides", index, "layout"]);
|
|
2696
|
+
designSites(sites, slide.design, ["slides", index, "design"]);
|
|
2697
|
+
});
|
|
2698
|
+
if (options.records !== false)
|
|
2699
|
+
for (const [group, value] of Object.entries(groupsOf(document))) {
|
|
2700
|
+
if (!isRec(value)) continue;
|
|
2701
|
+
for (const kind2 of catalogKinds)
|
|
2702
|
+
for (const [id, record9] of Object.entries(rec(value[kind2]))) sites.push(...recordReferenceSites(kind2, record9, ["catalogs", group, kind2, id], group));
|
|
2703
|
+
}
|
|
2704
|
+
return sites;
|
|
2705
|
+
}
|
|
2706
|
+
var dottedPath = (path) => path.join(".");
|
|
2707
|
+
var pointerPath = (path) => path.length ? `/${path.map((part) => String(part).replaceAll("~", "~0").replaceAll("/", "~1")).join("/")}` : "";
|
|
2708
|
+
function catalogRecords(document, kind2, options = {}) {
|
|
2709
|
+
checkCatalogsOption(options.catalogs, "catalogRecords");
|
|
2710
|
+
const result = [];
|
|
2711
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2712
|
+
const add = (entry) => {
|
|
2713
|
+
if (seen.has(entry.reference)) return;
|
|
2714
|
+
seen.add(entry.reference);
|
|
2715
|
+
result.push(entry);
|
|
2716
|
+
};
|
|
2717
|
+
const groups = groupsOf(document);
|
|
2718
|
+
const names = [.../* @__PURE__ */ new Set(["custom", "default", ...Object.keys(groups)])];
|
|
2719
|
+
for (const group of names) {
|
|
2720
|
+
if (group === "default" && groups.default === false) continue;
|
|
2721
|
+
if (group !== "custom" && group !== "default" && !isRec(groups[group])) continue;
|
|
2722
|
+
const prefix = group === "custom" || group === "default" ? "" : `${group}:`;
|
|
2723
|
+
for (const id of Object.keys(rec(rec(groups[group])[kind2]))) {
|
|
2724
|
+
const found = lookupInGroup(document, kind2, group, id, `${prefix}${id}`, options);
|
|
2725
|
+
if (found) add(found);
|
|
2726
|
+
}
|
|
2727
|
+
if (group === "custom") continue;
|
|
2728
|
+
const hosted = registeredCatalog(catalogGroupSource(document, group, options), options)?.[kind2];
|
|
2729
|
+
for (const id of Object.keys(hosted ?? {})) {
|
|
2730
|
+
const found = lookupInGroup(document, kind2, group, id, `${prefix}${id}`, options);
|
|
2731
|
+
if (found) add(found);
|
|
2732
|
+
}
|
|
2733
|
+
}
|
|
2734
|
+
return result;
|
|
2735
|
+
}
|
|
2736
|
+
function embeddedCopy(record9) {
|
|
2737
|
+
return Object.fromEntries(Object.entries(rec(record9)).filter(([key]) => key !== "$schema" && key !== "id" && !key.startsWith("x-")).map(([key, value]) => [key, structuredClone(value)]));
|
|
2738
|
+
}
|
|
2739
|
+
|
|
2155
2740
|
// src/generated/engine-data.ts
|
|
2156
2741
|
var engineDefaultsSource = {
|
|
2157
2742
|
"theme": {
|
|
@@ -2198,10 +2783,10 @@ var SOCIAL_PLATFORMS = engineVocabulariesSource.socialPlatforms;
|
|
|
2198
2783
|
var LANGUAGES = engineVocabulariesSource.languages;
|
|
2199
2784
|
|
|
2200
2785
|
// src/design-records.ts
|
|
2201
|
-
var
|
|
2202
|
-
var
|
|
2786
|
+
var isRec2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2787
|
+
var rec2 = (value) => isRec2(value) ? value : {};
|
|
2203
2788
|
function resolveRecordReference(document, kind2, reference, path, fallback, options, diagnostics) {
|
|
2204
|
-
const object2 =
|
|
2789
|
+
const object2 = isRec2(reference) ? reference : void 0;
|
|
2205
2790
|
const id = typeof reference === "string" ? reference : typeof object2?.id === "string" ? object2.id : void 0;
|
|
2206
2791
|
if (id === void 0) return { record: { ...fallback, ...object2 } };
|
|
2207
2792
|
const found = resolveReference(document, kind2, id, options);
|
|
@@ -2210,27 +2795,27 @@ function resolveRecordReference(document, kind2, reference, path, fallback, opti
|
|
|
2210
2795
|
}
|
|
2211
2796
|
function resolveDesignRecords(document, slideIndex, options = {}) {
|
|
2212
2797
|
checkCatalogsOption(options.catalogs, "resolveDesignRecords");
|
|
2213
|
-
const deck =
|
|
2798
|
+
const deck = rec2(document);
|
|
2214
2799
|
const slides = Array.isArray(deck.slides) ? deck.slides : [];
|
|
2215
|
-
const
|
|
2216
|
-
const shared =
|
|
2217
|
-
const design = { ...shared, ...
|
|
2800
|
+
const own3 = slideIndex === void 0 ? {} : rec2(rec2(slides[slideIndex]).design);
|
|
2801
|
+
const shared = rec2(deck.design);
|
|
2802
|
+
const design = { ...shared, ...own3 };
|
|
2218
2803
|
const slidePath = `slides.${slideIndex}.design`;
|
|
2219
2804
|
const diagnostics = [];
|
|
2220
|
-
const themePath =
|
|
2805
|
+
const themePath = own3.theme !== void 0 ? `${slidePath}.theme` : "design.theme";
|
|
2221
2806
|
const themeFound = typeof design.theme === "string" ? resolveReference(document, "themes", design.theme, options) : void 0;
|
|
2222
2807
|
if (typeof design.theme === "string" && !themeFound) diagnostics.push(unresolvedReference(document, "themes", design.theme, themePath, options));
|
|
2223
2808
|
const theme = themeFound ? { ...themeFound.record } : { ...ENGINE_DEFAULT_THEME };
|
|
2224
2809
|
const inTheme = { ...options, ...themeFound ? { group: themeFound.group } : {} };
|
|
2225
2810
|
const inThemePath = (key) => themeFound?.origin === "document" ? `catalogs.${themeFound.group}.themes.${themeFound.id}.${key}` : themePath;
|
|
2226
2811
|
const colorFromDesign = design.colorScheme !== void 0;
|
|
2227
|
-
const colorSchemePath =
|
|
2812
|
+
const colorSchemePath = own3.colorScheme !== void 0 ? `${slidePath}.colorScheme` : shared.colorScheme !== void 0 ? "design.colorScheme" : inThemePath("colorScheme");
|
|
2228
2813
|
const color = resolveRecordReference(document, "colorSchemes", colorFromDesign ? design.colorScheme : theme.colorScheme, colorFromDesign ? colorSchemePath : inThemePath("colorScheme"), ENGINE_DEFAULT_COLOR_SCHEME, colorFromDesign ? options : inTheme, diagnostics);
|
|
2229
2814
|
const fontFromDesign = design.fontScheme !== void 0;
|
|
2230
|
-
const fontSchemePath =
|
|
2815
|
+
const fontSchemePath = own3.fontScheme !== void 0 ? `${slidePath}.fontScheme` : shared.fontScheme !== void 0 ? "design.fontScheme" : inThemePath("fontScheme");
|
|
2231
2816
|
const font = resolveRecordReference(document, "fontSchemes", fontFromDesign ? design.fontScheme : theme.fontScheme, fontSchemePath, ENGINE_DEFAULT_FONT_SCHEME, fontFromDesign ? options : inTheme, diagnostics);
|
|
2232
2817
|
const fontReference = fontFromDesign ? design.fontScheme : theme.fontScheme;
|
|
2233
|
-
const fontSchemeReference = typeof fontReference === "string" ? fontReference :
|
|
2818
|
+
const fontSchemeReference = typeof fontReference === "string" ? fontReference : isRec2(fontReference) && typeof fontReference.id === "string" ? fontReference.id : void 0;
|
|
2234
2819
|
const provenance = {
|
|
2235
2820
|
...themeFound ? { theme: provenanceOf(themeFound) } : {},
|
|
2236
2821
|
...color.provenance ? { colorScheme: color.provenance } : {},
|
|
@@ -2551,11 +3136,11 @@ function listNumbers(items, numbering) {
|
|
|
2551
3136
|
const object2 = isObject(item) ? item : void 0;
|
|
2552
3137
|
const level = object2?.level === void 0 ? 0 : object2.level;
|
|
2553
3138
|
if (typeof level !== "number" || !Number.isInteger(level) || level < 0) throw new RangeError("List levels must be nonnegative integers.");
|
|
2554
|
-
const
|
|
2555
|
-
if (
|
|
3139
|
+
const own3 = object2?.start;
|
|
3140
|
+
if (own3 !== void 0 && (typeof own3 !== "number" || !Number.isInteger(own3) || own3 < 1 || own3 > MAX_NUMBERING_VALUE)) throw new RangeError(`A list item start must be an integer from 1 to ${MAX_NUMBERING_VALUE}.`);
|
|
2556
3141
|
const { style: authored, start, suffix } = numberingAtLevel(levels, level);
|
|
2557
3142
|
const previous = counters[level];
|
|
2558
|
-
const value =
|
|
3143
|
+
const value = own3 ?? (previous === void 0 ? start : previous + 1);
|
|
2559
3144
|
counters[level] = value;
|
|
2560
3145
|
counters.length = level + 1;
|
|
2561
3146
|
const adapted = !numberingStyleDraws(authored, value);
|
|
@@ -2720,6 +3305,7 @@ function resolveColorRoles(colorScheme, options = {}) {
|
|
|
2720
3305
|
background,
|
|
2721
3306
|
surface,
|
|
2722
3307
|
surfaceAlt: surfaceAltColor(surface, text2),
|
|
3308
|
+
border: dark ? "#475569" : "#CBD5E1",
|
|
2723
3309
|
text: text2,
|
|
2724
3310
|
textSecondary: keepAlpha(colorScheme.textSecondary) ?? (dark ? slot("light2", "#E2E8F0") : slot("dark2", "#334155")),
|
|
2725
3311
|
hyperlink: readableLink(slot("hyperlink", DEFAULT_HYPERLINK), background, text2),
|
|
@@ -3624,8 +4210,8 @@ function codeSyntaxPalette(theme = {}, options = {}) {
|
|
|
3624
4210
|
return palette;
|
|
3625
4211
|
}
|
|
3626
4212
|
function codeSyntaxPaletteForScheme(scheme, options = {}) {
|
|
3627
|
-
const
|
|
3628
|
-
const pick = (role, slot, fallback) => normalize(
|
|
4213
|
+
const record9 = scheme && typeof scheme === "object" ? scheme : {};
|
|
4214
|
+
const pick = (role, slot, fallback) => normalize(record9[role]) ?? normalize(record9[slot]) ?? fallback;
|
|
3629
4215
|
return codeSyntaxPalette({ primary: pick("primary", "accent1", "#2563EB"), secondary: pick("secondary", "accent2", "#0F766E"), accent: pick("accent", "accent3", "#F59E0B") }, options);
|
|
3630
4216
|
}
|
|
3631
4217
|
|
|
@@ -3777,8 +4363,8 @@ var blend = (from, to, amount) => {
|
|
|
3777
4363
|
return toHex(a.map((value, index) => value + (b[index] - value) * amount));
|
|
3778
4364
|
};
|
|
3779
4365
|
function codeHighlightColors(scheme, palette = codeSyntaxPaletteForScheme(scheme)) {
|
|
3780
|
-
const
|
|
3781
|
-
const primary = normalize(
|
|
4366
|
+
const record9 = scheme && typeof scheme === "object" ? scheme : {};
|
|
4367
|
+
const primary = normalize(record9.primary) ?? normalize(record9.accent1) ?? "#2563EB";
|
|
3782
4368
|
const [hue, saturation] = toHsl(primary);
|
|
3783
4369
|
const tint = fromHsl(hue, Math.min(saturation, 0.7), 0.45);
|
|
3784
4370
|
const band = blend(CODE_PANEL_BACKGROUND, tint, CODE_HIGHLIGHT_BAND_TINT);
|
|
@@ -3975,7 +4561,7 @@ var CAPTION_FONT_RATIO = 0.6;
|
|
|
3975
4561
|
var CAPTION_MAX_RATIO = 0.35;
|
|
3976
4562
|
var FOOTNOTE_MAX_RATIO = 0.35;
|
|
3977
4563
|
var CAPTIONABLE_FIELDS = Object.freeze(["image", "chart", "table", "video"]);
|
|
3978
|
-
var
|
|
4564
|
+
var record6 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
3979
4565
|
var isRecord3 = (value) => !!value && typeof value === "object" && !Array.isArray(value);
|
|
3980
4566
|
var round = (value) => Math.round(value * 1e6) / 1e6 || value;
|
|
3981
4567
|
var regionKey = /^(top|middle|bottom|left|center|right)([+:]|$)/;
|
|
@@ -3983,7 +4569,7 @@ var TEXT_FIELDS = ["text", "items", "bullets"];
|
|
|
3983
4569
|
var HEADING_FIELDS = ["tag", "title", "subtitle"];
|
|
3984
4570
|
function annotationText(value) {
|
|
3985
4571
|
if (typeof value === "string") return value;
|
|
3986
|
-
if (Array.isArray(value)) return value.map((run) => typeof run === "string" ? run :
|
|
4572
|
+
if (Array.isArray(value)) return value.map((run) => typeof run === "string" ? run : record6(run).text ?? "").join("");
|
|
3987
4573
|
if (isRecord3(value) && value.text !== void 0) return annotationText(value.text);
|
|
3988
4574
|
return value === void 0 || value === null ? "" : String(value);
|
|
3989
4575
|
}
|
|
@@ -4015,7 +4601,7 @@ function walkCitationRuns(slide, basePath, visit) {
|
|
|
4015
4601
|
});
|
|
4016
4602
|
};
|
|
4017
4603
|
const host = (node, path, depth) => {
|
|
4018
|
-
const payload =
|
|
4604
|
+
const payload = record6(node);
|
|
4019
4605
|
if (Array.isArray(payload.blocks)) {
|
|
4020
4606
|
if (depth > 32) return;
|
|
4021
4607
|
payload.blocks.forEach((block, index) => {
|
|
@@ -4030,7 +4616,7 @@ function walkCitationRuns(slide, basePath, visit) {
|
|
|
4030
4616
|
}
|
|
4031
4617
|
if (isRecord3(payload.quote)) runs(payload.quote.text, `${path}.quote.text`);
|
|
4032
4618
|
};
|
|
4033
|
-
const value =
|
|
4619
|
+
const value = record6(slide);
|
|
4034
4620
|
for (const field of HEADING_FIELDS) runs(value[field], `${basePath}.${field}`);
|
|
4035
4621
|
const regions = Object.keys(value).filter((key) => regionKey.test(key)).sort();
|
|
4036
4622
|
if (regions.length) {
|
|
@@ -4047,7 +4633,7 @@ function walkCitationRuns(slide, basePath, visit) {
|
|
|
4047
4633
|
}
|
|
4048
4634
|
var citationMarkerText = (numbers) => numbers.join(",");
|
|
4049
4635
|
function referenceList(presentation) {
|
|
4050
|
-
const list =
|
|
4636
|
+
const list = record6(presentation).references;
|
|
4051
4637
|
return Array.isArray(list) ? list.filter((item) => isRecord3(item) && typeof item.id === "string") : [];
|
|
4052
4638
|
}
|
|
4053
4639
|
function numberSlide(slide, slideIndex, references, numbering) {
|
|
@@ -4080,7 +4666,7 @@ function numberSlide(slide, slideIndex, references, numbering) {
|
|
|
4080
4666
|
}
|
|
4081
4667
|
function collectCitations(presentation) {
|
|
4082
4668
|
const references = referenceList(presentation), numbering = { notes: [], byId: /* @__PURE__ */ new Map() }, slides = /* @__PURE__ */ new Map();
|
|
4083
|
-
const list =
|
|
4669
|
+
const list = record6(presentation).slides;
|
|
4084
4670
|
if (Array.isArray(list)) list.forEach((slide, index) => {
|
|
4085
4671
|
const result = numberSlide(slide, index, references, numbering);
|
|
4086
4672
|
if (result) slides.set(index, result);
|
|
@@ -4090,7 +4676,7 @@ function collectCitations(presentation) {
|
|
|
4090
4676
|
}
|
|
4091
4677
|
function slideCitations(slide, slideIndex, presentation) {
|
|
4092
4678
|
const references = referenceList(presentation), numbering = { notes: [], byId: /* @__PURE__ */ new Map() };
|
|
4093
|
-
const list =
|
|
4679
|
+
const list = record6(presentation).slides;
|
|
4094
4680
|
if (Array.isArray(list)) for (let index = 0; index < Math.min(slideIndex, list.length); index += 1) numberSlide(list[index], index, references, numbering);
|
|
4095
4681
|
return numberSlide(slide, slideIndex, references, numbering);
|
|
4096
4682
|
}
|
|
@@ -4153,12 +4739,39 @@ function referencesSlide(presentation, options = {}) {
|
|
|
4153
4739
|
return { title, items };
|
|
4154
4740
|
}
|
|
4155
4741
|
|
|
4742
|
+
// src/layout-content.ts
|
|
4743
|
+
var LAYOUT_BODY_KINDS = ["text", "list", "image", "video", "chart", "table", "code", "metric", "quote", "timeline"];
|
|
4744
|
+
var record7 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
4745
|
+
function layoutStructure(layout) {
|
|
4746
|
+
if (!isLayoutTemplate(layout)) return "";
|
|
4747
|
+
return templateAreas(layout).map((entry) => entry.region ? `${entry.name} (${entry.region.flow}: ${entry.region.accepts.join(", ")})` : entry.name).join(", ");
|
|
4748
|
+
}
|
|
4749
|
+
function layoutContent(layout) {
|
|
4750
|
+
const areas = isLayoutTemplate(layout) ? templateAreas(layout) : [];
|
|
4751
|
+
const regions = areas.flatMap((entry) => entry.region ? [entry.region] : []);
|
|
4752
|
+
const lead = regions.find((region) => region.role === "primary") ?? regions[0];
|
|
4753
|
+
const leadKind = lead?.accepts.find((kind2) => kind2 !== "group");
|
|
4754
|
+
const title = areas.some((entry) => entry.name === "title");
|
|
4755
|
+
return { kind: leadKind ?? "title", count: regions.length, heading: { title, subtitle: title || areas.some((entry) => entry.name === "subtitle"), tag: title } };
|
|
4756
|
+
}
|
|
4757
|
+
function templateAreas(layout) {
|
|
4758
|
+
const value = record7(layout), regions = record7(value.regions);
|
|
4759
|
+
const rows3 = Array.isArray(value.areas) ? value.areas.filter((row) => Array.isArray(row) && row.every((cell) => typeof cell === "string")) : [];
|
|
4760
|
+
const seen = /* @__PURE__ */ new Set(), out = [];
|
|
4761
|
+
for (const row of rows3) for (const name of row) {
|
|
4762
|
+
if (!name || name === "." || seen.has(name)) continue;
|
|
4763
|
+
seen.add(name);
|
|
4764
|
+
out.push(name === "title" || name === "subtitle" || !Object.hasOwn(regions, name) ? { name } : { name, region: layoutRegion(name, regions[name]) });
|
|
4765
|
+
}
|
|
4766
|
+
return out;
|
|
4767
|
+
}
|
|
4768
|
+
|
|
4156
4769
|
// src/composition.ts
|
|
4157
4770
|
var MAX_COMPOSITION_DEPTH = 32;
|
|
4158
4771
|
var FALLBACK_CODE_FAMILY = "Roboto Mono";
|
|
4159
4772
|
var DEFAULT_FONT_FAMILIES = { heading: String(ENGINE_DEFAULT_FONT_SCHEME.major), body: String(ENGINE_DEFAULT_FONT_SCHEME.minor) };
|
|
4160
4773
|
function resolveFontFamilies(input) {
|
|
4161
|
-
const scheme =
|
|
4774
|
+
const scheme = record8(input);
|
|
4162
4775
|
const family = (value) => typeof value === "string" && value ? value : void 0;
|
|
4163
4776
|
const accent = family(scheme.accent);
|
|
4164
4777
|
return {
|
|
@@ -4229,12 +4842,6 @@ function translateTextFit(fit, dy) {
|
|
|
4229
4842
|
}
|
|
4230
4843
|
};
|
|
4231
4844
|
}
|
|
4232
|
-
var FIELD_KINDS = { text: "text", bullets: "text", items: "list", image: "image", video: "video", chart: "chart", table: "table", code: "code", metric: "metric", quote: "quote", timeline: "timeline" };
|
|
4233
|
-
function chartPrimaryLayout(side, kinds) {
|
|
4234
|
-
const first = side === "left" || side === "top";
|
|
4235
|
-
const group = { type: "group", composition: {}, placeholders: kinds.map((type) => ({ type })) };
|
|
4236
|
-
return { composition: { mode: side === "left" || side === "right" ? "row" : "column", weights: first ? [3, 2] : [2, 3] }, placeholders: first ? [{ type: "chart" }, group] : [group, { type: "chart" }] };
|
|
4237
|
-
}
|
|
4238
4845
|
var OPFCompositionError = class extends Error {
|
|
4239
4846
|
constructor(diagnostics, explanation) {
|
|
4240
4847
|
super("Slide content does not fit its composition.");
|
|
@@ -4250,11 +4857,11 @@ var fields = ["text", "items", "bullets", "image", "video", "chart", "table", "c
|
|
|
4250
4857
|
var headings = /* @__PURE__ */ new Set(["title", "subtitle", "tag"]);
|
|
4251
4858
|
var rows2 = ["top", "middle", "bottom"];
|
|
4252
4859
|
var columns = ["left", "center", "right"];
|
|
4253
|
-
var
|
|
4860
|
+
var record8 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
4254
4861
|
var kind = (field) => field === "items" ? "list" : field === "bullets" ? "text" : field;
|
|
4255
4862
|
var round2 = (value) => Math.round(value * 1e6) / 1e6 || value;
|
|
4256
4863
|
var PLACEMENT_BAND = 0.5;
|
|
4257
|
-
var
|
|
4864
|
+
var IMAGE_EDGES2 = ["left", "right", "top", "bottom"];
|
|
4258
4865
|
var IMAGE_FITS = ["cover", "contain", "stretch"];
|
|
4259
4866
|
var BACKGROUND_FITS = ["cover", "contain", "stretch", "tile"];
|
|
4260
4867
|
var IMAGE_SOURCE = /^(asset:|https:\/\/|data:|\.\/|\.\.\/)/;
|
|
@@ -4269,7 +4876,7 @@ var pathNumber = (value) => String(round2(value));
|
|
|
4269
4876
|
var IMAGE_SHAPES = { rectangle: "rect", rounded: "roundRect", circle: "ellipse", hexagon: "hexagon" };
|
|
4270
4877
|
var roundBox = (box) => ({ x: round2(box.x), y: round2(box.y), width: round2(box.width), height: round2(box.height) });
|
|
4271
4878
|
var imageFocus = (value) => {
|
|
4272
|
-
const focus =
|
|
4879
|
+
const focus = record8(value), x = finite(focus.x, 0, 1), y = finite(focus.y, 0, 1);
|
|
4273
4880
|
return x !== void 0 && y !== void 0 ? { x, y } : { x: 0.5, y: 0.5 };
|
|
4274
4881
|
};
|
|
4275
4882
|
function imageShape(kind2, box, cornerRadius = 1 / 6) {
|
|
@@ -4310,7 +4917,7 @@ function fitImage(frame, fit, aspect, focus = { x: 0.5, y: 0.5 }) {
|
|
|
4310
4917
|
}
|
|
4311
4918
|
function imageBackground(value) {
|
|
4312
4919
|
if (typeof value === "string") return IMAGE_SOURCE.test(value) ? { src: value, fit: "cover", focus: { x: 0.5, y: 0.5 } } : void 0;
|
|
4313
|
-
const background =
|
|
4920
|
+
const background = record8(value);
|
|
4314
4921
|
if (background.type !== "image" || typeof background.src !== "string" || !background.src) return void 0;
|
|
4315
4922
|
const opacity = finite(background.opacity, 0, 1);
|
|
4316
4923
|
return {
|
|
@@ -4325,13 +4932,13 @@ function imageBackground(value) {
|
|
|
4325
4932
|
}
|
|
4326
4933
|
function composeRecolor(value) {
|
|
4327
4934
|
if (value === "grayscale") return { type: "grayscale" };
|
|
4328
|
-
const duotone =
|
|
4935
|
+
const duotone = record8(value);
|
|
4329
4936
|
return duotone.dark !== void 0 && duotone.light !== void 0 ? { type: "duotone", dark: duotone.dark, light: duotone.light } : void 0;
|
|
4330
4937
|
}
|
|
4331
4938
|
function composeOverlay(value, frame, shape, path, mirrorSide, diagnostics) {
|
|
4332
|
-
const overlay =
|
|
4939
|
+
const overlay = record8(value), opacity = finite(overlay.opacity, 0, 1);
|
|
4333
4940
|
if (overlay.color === void 0 || opacity === void 0) return void 0;
|
|
4334
|
-
const edge =
|
|
4941
|
+
const edge = IMAGE_EDGES2.includes(overlay.edge) ? mirrorSide(overlay.edge) : void 0;
|
|
4335
4942
|
if (edge && shape.kind !== "rectangle") {
|
|
4336
4943
|
diagnostics.push({ code: "unsupported-image-treatment", path: `${path}.edge`, message: "An edge overlay needs a rectangle frame; a band cannot follow a rounded, circular or hexagonal mask as one native shape. Remove edge or use shape rectangle." });
|
|
4337
4944
|
return void 0;
|
|
@@ -4354,7 +4961,7 @@ function composeImage(host, hostPath, region, frameArea, context) {
|
|
|
4354
4961
|
const focus = imageFocus(host.focus);
|
|
4355
4962
|
const shape = imageShape(kindName, box, finite(host.cornerRadius, 0, 0.5));
|
|
4356
4963
|
const result = { region: roundBox(region), box, fit, focus, shape };
|
|
4357
|
-
const border =
|
|
4964
|
+
const border = record8(host.border), borderWidth = finite(border.width, 0, 64);
|
|
4358
4965
|
if (border.color !== void 0 && borderWidth) result.border = { color: border.color, width: round2(borderWidth * scale) };
|
|
4359
4966
|
const opacity = finite(host.opacity, 0, 1);
|
|
4360
4967
|
if (opacity !== void 0 && opacity < 1) result.opacity = opacity;
|
|
@@ -4368,8 +4975,8 @@ function composeImage(host, hostPath, region, frameArea, context) {
|
|
|
4368
4975
|
return result;
|
|
4369
4976
|
}
|
|
4370
4977
|
function resolveBackgroundImage(slide, presentation, themeBackground, width, height, path, mirrorSide, diagnostics) {
|
|
4371
|
-
const
|
|
4372
|
-
const [value, at3] =
|
|
4978
|
+
const own3 = record8(slide.design), deck = record8(record8(presentation).design);
|
|
4979
|
+
const [value, at3] = own3.background !== void 0 ? [own3.background, `${path}.design.background`] : deck.background !== void 0 ? [deck.background, "design.background"] : [themeBackground, "theme"];
|
|
4373
4980
|
const background = imageBackground(value);
|
|
4374
4981
|
if (!background) return void 0;
|
|
4375
4982
|
const box = { x: 0, y: 0, width, height };
|
|
@@ -4379,7 +4986,7 @@ function resolveBackgroundImage(slide, presentation, themeBackground, width, hei
|
|
|
4379
4986
|
if (recolor) result.recolor = recolor;
|
|
4380
4987
|
const overlay = composeOverlay(background.overlay, box, imageShape("rectangle", box), `${at3}.overlay`, mirrorSide, diagnostics);
|
|
4381
4988
|
if (overlay) result.overlay = overlay;
|
|
4382
|
-
const aspect = background.fit === "tile" ? void 0 : intrinsicImageAspect(background.src,
|
|
4989
|
+
const aspect = background.fit === "tile" ? void 0 : intrinsicImageAspect(background.src, record8(presentation).assets);
|
|
4383
4990
|
if (aspect) result.picture = fitImage(box, background.fit, aspect, background.focus);
|
|
4384
4991
|
return result;
|
|
4385
4992
|
}
|
|
@@ -4410,8 +5017,8 @@ function breaksInsideWord(text2, fit) {
|
|
|
4410
5017
|
});
|
|
4411
5018
|
}
|
|
4412
5019
|
function layoutFurniture(input, options = {}) {
|
|
4413
|
-
const slide =
|
|
4414
|
-
const settings = { ...
|
|
5020
|
+
const slide = record8(input), width = options.width ?? 1280, height = options.height ?? 720, scale = Math.min(width, height) / 720;
|
|
5021
|
+
const settings = { ...record8(record8(options.layout).composition), ...record8(slide.composition) };
|
|
4415
5022
|
assertComposition(settings);
|
|
4416
5023
|
const furnitureRtl = (options.direction ?? resolveSlideDirection(options.presentation, options.slideIndex)) === "rtl";
|
|
4417
5024
|
const minimum = snapFontSizeUp((settings.minFontSize ?? 16) * scale), size = gridFontSize(13 * scale, minimum), padding = (options.textRasterPadding ?? 2) * scale;
|
|
@@ -4423,13 +5030,13 @@ function layoutFurniture(input, options = {}) {
|
|
|
4423
5030
|
if (options.date !== void 0 && (typeof options.date !== "string" || !parseIsoDate(options.date))) throw new RangeError("The furniture date option must be an ISO YYYY-MM-DD calendar date.");
|
|
4424
5031
|
const outlines = options.textMeasurement?.outlineBounds !== void 0, parts = [], diagnostics = [];
|
|
4425
5032
|
const sourceRoot = `slides.${options.slideIndex ?? 0}`, organizations = Array.isArray(options.presentation?.organization) ? options.presentation.organization : [options.presentation?.organization];
|
|
4426
|
-
const primaryIndex = organizations.findIndex((item) =>
|
|
4427
|
-
const organization =
|
|
5033
|
+
const primaryIndex = organizations.findIndex((item) => record8(item).role === "primary"), organizationIndex2 = primaryIndex >= 0 ? primaryIndex : organizations.findIndex(Boolean);
|
|
5034
|
+
const organization = record8(organizations[organizationIndex2]), organizationRoot = Array.isArray(options.presentation?.organization) ? `organization.${organizationIndex2}` : "organization";
|
|
4428
5035
|
const fontFamily = options.fontFamilies?.body ?? "sans-serif";
|
|
4429
5036
|
let headerBottom = 0, footerTop = height, configured = false;
|
|
4430
5037
|
const error = (path, message, code = "text-overflow") => diagnostics.push({ code, path, message });
|
|
4431
5038
|
for (const kind2 of ["header", "footer"]) {
|
|
4432
|
-
const local =
|
|
5039
|
+
const local = record8(slide.design)[kind2] !== void 0, value = local ? record8(slide.design)[kind2] : options.presentation?.design?.[kind2];
|
|
4433
5040
|
if (value === void 0 || value === false) continue;
|
|
4434
5041
|
const root = local ? `${sourceRoot}.design.${kind2}` : `design.${kind2}`;
|
|
4435
5042
|
if (!value || typeof value !== "object" || Array.isArray(value)) throw new TypeError("Header/footer content must be an object or false.");
|
|
@@ -4437,7 +5044,7 @@ function layoutFurniture(input, options = {}) {
|
|
|
4437
5044
|
const zones = [];
|
|
4438
5045
|
for (const [index, zone] of ["left", "center", "right"].entries()) {
|
|
4439
5046
|
const side = furnitureRtl && zone !== "center" ? zone === "left" ? "right" : "left" : zone;
|
|
4440
|
-
const content =
|
|
5047
|
+
const content = record8(record8(value)[zone]), path = `${root}.${zone}`, x = width * (0.07 + (furnitureRtl ? 2 - index : index) * 0.3), zoneWidth = width * 0.26;
|
|
4441
5048
|
const pending = [];
|
|
4442
5049
|
const add = (field, text2, generated = false, sourcePath, extras = {}) => {
|
|
4443
5050
|
if (text2 === void 0) return;
|
|
@@ -4446,7 +5053,7 @@ function layoutFurniture(input, options = {}) {
|
|
|
4446
5053
|
pending.push({ type: "text", field, text: text2, generated, sourcePath: sourcePath ?? (!generated ? partPath : void 0), extras, partPath, style: resolveTextStyle({ fontFamily, fontWeight: 400, italic: false, path: partPath }, options.textMeasurement) });
|
|
4447
5054
|
};
|
|
4448
5055
|
const addImage = (source, sourcePath, reference) => {
|
|
4449
|
-
const imageHeight = Math.max(32 * scale, Math.min(height * 0.05, 72 * scale)), imageWidth = Math.min(zoneWidth, imageHeight * (intrinsicImageAspect(source,
|
|
5056
|
+
const imageHeight = Math.max(32 * scale, Math.min(height * 0.05, 72 * scale)), imageWidth = Math.min(zoneWidth, imageHeight * (intrinsicImageAspect(source, record8(options.presentation).assets) ?? 1));
|
|
4450
5057
|
pending.push({ type: "image", sourcePath, image: source, ...reference !== void 0 ? { reference } : {}, width: imageWidth, height: imageHeight });
|
|
4451
5058
|
};
|
|
4452
5059
|
if (content.image !== void 0) {
|
|
@@ -4465,7 +5072,7 @@ function layoutFurniture(input, options = {}) {
|
|
|
4465
5072
|
add("text", resolved.text, false, void 0, { fields: resolved.fields });
|
|
4466
5073
|
} else add("text", content.text);
|
|
4467
5074
|
if (content.socials === true) {
|
|
4468
|
-
const links = Object.entries(
|
|
5075
|
+
const links = Object.entries(record8(organization.socials)).filter(([, value2]) => typeof value2 === "string" && value2.trim()).map(([platform, value2]) => ({ platform, sourcePath: `${organizationRoot}.socials.${platform}`, ...resolveSocialProfile(platform, value2, "organization") }));
|
|
4469
5076
|
if (links.length) add("socials", links.map((link) => link.text).join("\n"), true, `${organizationRoot}.socials`, { links });
|
|
4470
5077
|
else error(`${path}.socials`, "Generated social profiles need a primary organization with socials.", "unresolved-content");
|
|
4471
5078
|
}
|
|
@@ -4572,11 +5179,22 @@ function layoutFurniture(input, options = {}) {
|
|
|
4572
5179
|
var textSegments = new Intl.Segmenter("und", { granularity: "grapheme" });
|
|
4573
5180
|
var WRAP_TOLERANCE = 0.01;
|
|
4574
5181
|
var HANGING_SPACE = /[^\S\r\n\u00a0\u202f\ufeff]/u;
|
|
5182
|
+
var SCRIPT_WIDTH_FACTORS = [
|
|
5183
|
+
[/\p{Script=Tamil}/u, 1.53],
|
|
5184
|
+
[/\p{Script=Malayalam}/u, 1.76],
|
|
5185
|
+
[/\p{Script=Sinhala}/u, 1.44],
|
|
5186
|
+
[/\p{Script=Myanmar}/u, 1.18],
|
|
5187
|
+
[/\p{Script=Ethiopic}/u, 1.13],
|
|
5188
|
+
[/\p{Script=Georgian}/u, 1.28]
|
|
5189
|
+
];
|
|
4575
5190
|
function measureText(text2, fontSize) {
|
|
4576
5191
|
let units = 0;
|
|
4577
5192
|
for (const character of text2) {
|
|
4578
|
-
if (/\p{
|
|
4579
|
-
|
|
5193
|
+
if (/\p{Mn}|\p{Me}|\u200d|\ufe0f/u.test(character)) continue;
|
|
5194
|
+
if (/\p{Mc}/u.test(character) && /\p{Script=Latin}|\p{Script=Han}|\p{Script=Hangul}|\p{Script=Hiragana}|\p{Script=Katakana}/u.test(character)) continue;
|
|
5195
|
+
const base = character === " " ? 0.32 : /[A-Z0-9]/.test(character) ? 0.62 : character.codePointAt(0) > 11904 ? 1 : 0.54;
|
|
5196
|
+
const factor = SCRIPT_WIDTH_FACTORS.find(([script]) => script.test(character))?.[1] ?? 1;
|
|
5197
|
+
units += base * factor;
|
|
4580
5198
|
}
|
|
4581
5199
|
return units * fontSize;
|
|
4582
5200
|
}
|
|
@@ -4727,6 +5345,22 @@ function layoutQuote(value, box, options = {}) {
|
|
|
4727
5345
|
photoFits = selected.photoFits;
|
|
4728
5346
|
}
|
|
4729
5347
|
}
|
|
5348
|
+
if (body.fit && !body.fit.overflow && photoFits && (!attribution || attribution.fit && !attribution.fit.overflow)) {
|
|
5349
|
+
body.box.height = body.fit.placement?.height ?? heightOf(body.fit);
|
|
5350
|
+
const footerTop = body.box.y + body.box.height + 18;
|
|
5351
|
+
const previousTop = Math.min(attribution?.box.y ?? Infinity, photo?.box.y ?? Infinity);
|
|
5352
|
+
if (Number.isFinite(previousTop)) {
|
|
5353
|
+
const shift = footerTop - previousTop;
|
|
5354
|
+
if (attribution) {
|
|
5355
|
+
attribution.box.y += shift;
|
|
5356
|
+
attribution.fit = translateTextFit(attribution.fit, shift);
|
|
5357
|
+
}
|
|
5358
|
+
if (photo) {
|
|
5359
|
+
photo.box.y += shift;
|
|
5360
|
+
photo.shape = imageShape("circle", photo.box);
|
|
5361
|
+
}
|
|
5362
|
+
}
|
|
5363
|
+
}
|
|
4730
5364
|
if (hasPhoto && !photo) photoFits = false;
|
|
4731
5365
|
for (const part of parts) {
|
|
4732
5366
|
const area = part.box;
|
|
@@ -4746,7 +5380,11 @@ function layoutQuote(value, box, options = {}) {
|
|
|
4746
5380
|
report("part-overlap", path, ["body", "footer"], "Quote body and photo overlap; do not accept this layout without more space.");
|
|
4747
5381
|
}
|
|
4748
5382
|
if (diagnostics.length && options.overflow === "error") throw new OPFCompositionError(diagnostics);
|
|
4749
|
-
|
|
5383
|
+
const occupiedParts = parts.filter((part) => part.fit).map((part) => ({ ...part.box, height: part.fit.placement?.height ?? heightOf(part.fit) }));
|
|
5384
|
+
if (photo) occupiedParts.push(photo.box);
|
|
5385
|
+
const bottom = Math.max(box.y, ...occupiedParts.map((area) => area.y + area.height));
|
|
5386
|
+
const bounds = { x: box.x, y: box.y, width: box.width, height: bottom - box.y };
|
|
5387
|
+
return { bounds, algorithm: "quote-flow-v1", textMeasurement: options.textMeasurement ? "provided" : "estimated", parts, ...photo ? { photo } : {}, diagnostics, overflow: diagnostics.length > 0 };
|
|
4750
5388
|
}
|
|
4751
5389
|
function layoutMetric(value, box, options = {}) {
|
|
4752
5390
|
const scalar = typeof value === "string" || typeof value === "number";
|
|
@@ -4797,16 +5435,16 @@ function layoutMetric(value, box, options = {}) {
|
|
|
4797
5435
|
let outline = null;
|
|
4798
5436
|
for (const segment2 of line.segments) {
|
|
4799
5437
|
if (segment2.kind !== "text") continue;
|
|
4800
|
-
const
|
|
4801
|
-
if (!
|
|
4802
|
-
const next = { ...
|
|
5438
|
+
const bounds2 = measureTextOutline(part.text.slice(segment2.start, segment2.end), fit.fontSize, part.style, options.textMeasurement);
|
|
5439
|
+
if (!bounds2) continue;
|
|
5440
|
+
const next = { ...bounds2, x: segment2.x + bounds2.x };
|
|
4803
5441
|
if (!outline) outline = next;
|
|
4804
5442
|
else {
|
|
4805
|
-
const right = Math.max(outline.x + outline.width, next.x + next.width),
|
|
5443
|
+
const right = Math.max(outline.x + outline.width, next.x + next.width), bottom2 = Math.max(outline.y + outline.height, next.y + next.height);
|
|
4806
5444
|
outline.x = Math.min(outline.x, next.x);
|
|
4807
5445
|
outline.y = Math.min(outline.y, next.y);
|
|
4808
5446
|
outline.width = right - outline.x;
|
|
4809
|
-
outline.height =
|
|
5447
|
+
outline.height = bottom2 - outline.y;
|
|
4810
5448
|
}
|
|
4811
5449
|
}
|
|
4812
5450
|
return { width: line.width, y: index * fit.lineHeight, baseline: fit.fontSize + index * fit.lineHeight, height: fit.lineHeight, outline };
|
|
@@ -4916,7 +5554,9 @@ function layoutMetric(value, box, options = {}) {
|
|
|
4916
5554
|
}
|
|
4917
5555
|
}
|
|
4918
5556
|
if (diagnostics.length && options.overflow === "error") throw new OPFCompositionError(diagnostics);
|
|
4919
|
-
|
|
5557
|
+
const bottom = Math.max(box.y, ...visible.map((part) => part.box.y + occupied(part.fit)));
|
|
5558
|
+
const bounds = { x: box.x, y: box.y, width: box.width, height: bottom - box.y };
|
|
5559
|
+
return { bounds, algorithm: "metric-flow-v1", alignment, textMeasurement: options.textMeasurement ? "provided" : "estimated", arrangement: selected.arrangement, ...metric.sentiment === void 0 ? {} : { sentiment: metric.sentiment }, attempts, parts, diagnostics, overflow: diagnostics.length > 0 };
|
|
4920
5560
|
}
|
|
4921
5561
|
var TIMELINE_STATUS_VALUES = ["done", "current", "planned"];
|
|
4922
5562
|
var TIMELINE_RING_RATIO = 1.6;
|
|
@@ -4942,9 +5582,9 @@ function layoutTimeline(value, box, options = {}) {
|
|
|
4942
5582
|
add("name", timeline.name, `${path}.name`, 24, 700);
|
|
4943
5583
|
add("description", timeline.description, `${path}.description`, 18, 400);
|
|
4944
5584
|
timeline.events.forEach((event, index) => {
|
|
4945
|
-
add("when", event.when, `${eventPath(index)}.when`,
|
|
4946
|
-
add("what", event.what, `${eventPath(index)}.what`,
|
|
4947
|
-
add("event-description", event.description, `${eventPath(index)}.description`,
|
|
5585
|
+
add("when", event.when, `${eventPath(index)}.when`, 18, 500, index);
|
|
5586
|
+
add("what", event.what, `${eventPath(index)}.what`, 22, 600, index);
|
|
5587
|
+
add("event-description", event.description, `${eventPath(index)}.description`, 18, 400, index);
|
|
4948
5588
|
});
|
|
4949
5589
|
const metadata = [], events = timeline.events.map(() => []);
|
|
4950
5590
|
for (const part of source) if (part.eventIndex === void 0) metadata.push(part);
|
|
@@ -4998,6 +5638,7 @@ function layoutTimeline(value, box, options = {}) {
|
|
|
4998
5638
|
const accepted = { ...part, box: area, alignment, fit };
|
|
4999
5639
|
parts.push(accepted);
|
|
5000
5640
|
if (fit.overflow) report(accepted, "text-fit", "Timeline field exceeds its readable width; increase its space or split the timeline.");
|
|
5641
|
+
if (breaksInsideWord(part.text, fit)) report(accepted, "text-fit", "Timeline field would split a word; use a wider vertical arrangement or paginate events.");
|
|
5001
5642
|
if (area.x < box.x - 0.01 || area.y < box.y - 0.01 || area.x + area.width > box.x + box.width + 0.01 || area.y + area.height > box.y + box.height + 0.01) report(accepted, "part-outside-cell", "Timeline field extends outside its cell; increase the cell or paginate events.", Math.max(area.x + area.width - box.x - box.width, area.y + area.height - box.y - box.height));
|
|
5002
5643
|
return accepted;
|
|
5003
5644
|
};
|
|
@@ -5015,27 +5656,35 @@ function layoutTimeline(value, box, options = {}) {
|
|
|
5015
5656
|
};
|
|
5016
5657
|
if (arrangement === "alternating") {
|
|
5017
5658
|
const width = box.width / Math.max(2, count), step = (box.width - width) / Math.max(1, count - 1), start = count === 1 ? box.x + box.width / 2 : box.x + width / 2;
|
|
5018
|
-
const
|
|
5659
|
+
const fieldGap = 4 * scale, clearance = 24 * scale;
|
|
5660
|
+
const heights = events.map((fields2) => fields2.reduce((height, part) => height + measure(part, gridFontSize(part.requestedFontSize - reduction * scale, minimum), width, "center").height, 0) + Math.max(0, fields2.length - 1) * fieldGap);
|
|
5661
|
+
const markerExtent = hasRing ? ringRadius + strokeWidth / 2 : radius;
|
|
5662
|
+
const upper = Math.max(markerExtent, ...heights.filter((_, index) => index % 2 === 0).map((height) => height + clearance));
|
|
5663
|
+
const lower = Math.max(markerExtent, ...heights.filter((_, index) => index % 2 === 1).map((height) => height + clearance));
|
|
5664
|
+
const lineY = y + Math.max(0, (available - upper - lower) / 2) + upper;
|
|
5019
5665
|
events.forEach((fields2, index) => {
|
|
5020
|
-
const x = start + (rtl ? count - 1 - index : index) * step, top = index % 2 === 0 ?
|
|
5666
|
+
const x = start + (rtl ? count - 1 - index : index) * step, top = index % 2 === 0 ? lineY - clearance - heights[index] : lineY + clearance, bottom = index % 2 === 0 ? lineY - clearance : box.y + box.height;
|
|
5021
5667
|
markers.push(marker(index, x, lineY));
|
|
5022
5668
|
let cursor = top;
|
|
5023
|
-
for (const part of fields2) {
|
|
5669
|
+
for (const [fieldIndex, part] of fields2.entries()) {
|
|
5024
5670
|
const placed = place(part, x - width / 2, cursor, width, "center");
|
|
5025
5671
|
cursor += placed.box.height;
|
|
5026
5672
|
if (cursor > bottom + 0.01) report(placed, "event-space", "Timeline event labels exceed their side of the connector; change the arrangement or paginate events.", cursor - bottom);
|
|
5673
|
+
if (fieldIndex < fields2.length - 1) cursor += fieldGap;
|
|
5027
5674
|
}
|
|
5028
5675
|
});
|
|
5029
5676
|
} else {
|
|
5030
|
-
const
|
|
5677
|
+
const outlined = timeline.events.some((event) => event.status === "planned");
|
|
5678
|
+
const lead = hasRing ? ringRadius + strokeWidth / 2 : radius + (outlined ? strokeWidth / 2 : 0), gap = 2 * lead + 12 * scale;
|
|
5031
5679
|
const x = rtl ? box.x + box.width - lead : box.x + lead, textX = rtl ? box.x : box.x + gap, width = box.width - gap;
|
|
5032
5680
|
events.forEach((fields2, index) => {
|
|
5033
5681
|
const top = y;
|
|
5034
5682
|
let first2;
|
|
5035
|
-
for (const part of fields2) {
|
|
5683
|
+
for (const [fieldIndex, part] of fields2.entries()) {
|
|
5036
5684
|
const placed = place(part, textX, y, width, "left");
|
|
5037
5685
|
first2 ??= placed;
|
|
5038
5686
|
y += placed.box.height;
|
|
5687
|
+
if (fieldIndex < fields2.length - 1) y += 4 * scale;
|
|
5039
5688
|
}
|
|
5040
5689
|
markers.push(marker(index, x, top + Math.min(first2?.box.height ?? 2 * radius, 2 * radius) / 2));
|
|
5041
5690
|
y += 16 * scale;
|
|
@@ -5067,19 +5716,19 @@ function fitSourceText(text2, box, size, minimum, step, measure, prose = false,
|
|
|
5067
5716
|
const layout = (fontSize) => {
|
|
5068
5717
|
const tabWidth = measure(" ", fontSize) * 4;
|
|
5069
5718
|
if (!Number.isFinite(tabWidth) || text2.includes(" ") && tabWidth <= 0) throw new RangeError("Text tabs require a positive finite measured space advance.");
|
|
5070
|
-
const measureLine = (start2, end2,
|
|
5719
|
+
const measureLine = (start2, end2, record9 = false) => {
|
|
5071
5720
|
let x = 0, offset = start2;
|
|
5072
5721
|
const segments = [];
|
|
5073
5722
|
for (const [index, segment2] of text2.slice(start2, end2).split(" ").entries()) {
|
|
5074
5723
|
if (index) {
|
|
5075
5724
|
const next = (Math.floor(x / tabWidth + 1e-9) + 1) * tabWidth;
|
|
5076
|
-
if (
|
|
5725
|
+
if (record9) segments.push({ kind: "tab", start: offset, end: offset + 1, x, width: next - x });
|
|
5077
5726
|
x = next;
|
|
5078
5727
|
offset++;
|
|
5079
5728
|
}
|
|
5080
5729
|
if (segment2) {
|
|
5081
5730
|
const advance = measure(segment2, fontSize);
|
|
5082
|
-
if (
|
|
5731
|
+
if (record9) segments.push({ kind: "text", start: offset, end: offset + segment2.length, x, width: advance });
|
|
5083
5732
|
x += advance;
|
|
5084
5733
|
offset += segment2.length;
|
|
5085
5734
|
}
|
|
@@ -5358,7 +6007,10 @@ function richTextLayouter(input, box, requestedSize, options, minimum = 0) {
|
|
|
5358
6007
|
return layout;
|
|
5359
6008
|
}
|
|
5360
6009
|
var PICTURE_BULLET_SCALE = 0.65;
|
|
5361
|
-
function
|
|
6010
|
+
function contentNominalSize(field) {
|
|
6011
|
+
return field === "items" || field === "bullets" ? 32 : 25;
|
|
6012
|
+
}
|
|
6013
|
+
function fitList(input, box, requestedSize = contentNominalSize("items"), minFontSize = 16, options = { style: { fontFamily: "sans-serif", fontWeight: 400 } }) {
|
|
5362
6014
|
if (!Array.isArray(input) || ![box.width, box.height, requestedSize, minFontSize].every((value) => Number.isFinite(value) && value > 0)) throw new RangeError("List content, dimensions and font sizes must be valid.");
|
|
5363
6015
|
const source = input.map((value, index) => {
|
|
5364
6016
|
const object2 = typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
@@ -5436,12 +6088,12 @@ function fitList(input, box, requestedSize = 25, minFontSize = 16, options = { s
|
|
|
5436
6088
|
function contentText(field, value) {
|
|
5437
6089
|
if (field === "text" || headings.has(field)) return flatten(value);
|
|
5438
6090
|
if (field === "items" || field === "bullets") return (Array.isArray(value) ? value : [value]).map((item) => {
|
|
5439
|
-
const entry =
|
|
6091
|
+
const entry = record8(item);
|
|
5440
6092
|
return `\u2022 ${flatten(item)}${entry.description ? `
|
|
5441
6093
|
${flatten(entry.description)}` : ""}`;
|
|
5442
6094
|
}).join("\n");
|
|
5443
|
-
if (field === "code") return flatten(
|
|
5444
|
-
if (field === "quote") return flatten(
|
|
6095
|
+
if (field === "code") return flatten(record8(value).source ?? value);
|
|
6096
|
+
if (field === "quote") return flatten(record8(value).text ?? value);
|
|
5445
6097
|
return void 0;
|
|
5446
6098
|
}
|
|
5447
6099
|
function layoutTable(value, box, options = {}) {
|
|
@@ -5450,6 +6102,11 @@ function layoutTable(value, box, options = {}) {
|
|
|
5450
6102
|
const inline = inlineTableData(value, options.presentation);
|
|
5451
6103
|
const grid = tableGrid(inline, options.path ?? "table");
|
|
5452
6104
|
if (grid.issues.length) throw new RangeError(`${grid.issues[0].path}: ${grid.issues[0].message}`);
|
|
6105
|
+
const numeric = new Set(grid.rows.flat().filter((cell) => !cell.header && typeof cell.value === "number" && Number.isFinite(cell.value)));
|
|
6106
|
+
const numericColumns = new Set(Array.from({ length: grid.columnCount }, (_, column) => column).filter((column) => {
|
|
6107
|
+
const body = grid.rows.flat().filter((cell) => !cell.header && cell.column === column && cell.value !== null && cell.value !== void 0);
|
|
6108
|
+
return body.length > 0 && body.every((cell) => cell.colSpan === 1 && numeric.has(cell));
|
|
6109
|
+
}));
|
|
5453
6110
|
const formats = resolveTableData(inline).formats;
|
|
5454
6111
|
for (const row of grid.rows) for (const cell of row) {
|
|
5455
6112
|
if (cell.header) continue;
|
|
@@ -5461,7 +6118,9 @@ function layoutTable(value, box, options = {}) {
|
|
|
5461
6118
|
const padding = { top: 8, right: 10, bottom: 4, left: 10, ...cell.style.padding };
|
|
5462
6119
|
const width = cellWidth * cell.colSpan - (padding.left + padding.right) * scale;
|
|
5463
6120
|
const style = { fontFamily: options.fontFamily ?? "sans-serif", fontWeight: cell.header ? 700 : 400, italic: false, path: cell.valuePath };
|
|
5464
|
-
|
|
6121
|
+
const numericDefault = numeric.has(cell) || cell.header && cell.colSpan === 1 && numericColumns.has(cell.column);
|
|
6122
|
+
const alignment = cell.style.align ?? options.alignment ?? (numericDefault ? options.direction === "rtl" ? "left" : "right" : "left");
|
|
6123
|
+
return { ...cell, padding, width, textStyle: style, alignment };
|
|
5465
6124
|
});
|
|
5466
6125
|
const cellMinimum = (cell) => Array.isArray(cell.value) ? richMinimum(cell.value, requested, minimum) : minimum;
|
|
5467
6126
|
const fitCell = (cell, height, min) => {
|
|
@@ -5501,7 +6160,7 @@ function layoutTable(value, box, options = {}) {
|
|
|
5501
6160
|
const offset = cell.style.verticalAlign === "bottom" ? Math.max(0, available - height) : cell.style.verticalAlign === "middle" ? Math.max(0, (available - height) / 2) : 0;
|
|
5502
6161
|
const textBox = { x: cellBox.x + cell.padding.left * scale, y: cellBox.y + cell.padding.top * scale + offset, width: Math.max(scale, cell.width), height: Math.max(scale, available - offset) };
|
|
5503
6162
|
overflow ||= cell.width <= 0 || available <= 0 || fit.overflow;
|
|
5504
|
-
rows3[cell.row].cells.push({ value: cell.value, input: cell.input, path: cell.valuePath, sourcePath: cell.path, style: cell.style, row: cell.row, column: cell.column, rowSpan: cell.rowSpan, colSpan: cell.colSpan, header: cell.header, rich: Array.isArray(cell.value), box: cellBox, textBox, textStyle: resolveTextStyle(cell.textStyle, options.textMeasurement), fit, ...fit.directions ? { direction: fit.directions[0] } : {} });
|
|
6163
|
+
rows3[cell.row].cells.push({ value: cell.value, input: cell.input, path: cell.valuePath, sourcePath: cell.path, style: cell.style, alignment: cell.alignment, row: cell.row, column: cell.column, rowSpan: cell.rowSpan, colSpan: cell.colSpan, header: cell.header, rich: Array.isArray(cell.value), box: cellBox, textBox, textStyle: resolveTextStyle(cell.textStyle, options.textMeasurement), fit, ...fit.directions ? { direction: fit.directions[0] } : {} });
|
|
5505
6164
|
}
|
|
5506
6165
|
return { rows: rows3, columnCount, height: sum(heights), overflow };
|
|
5507
6166
|
}
|
|
@@ -5512,7 +6171,7 @@ function flatten(value) {
|
|
|
5512
6171
|
if (value == null) return "";
|
|
5513
6172
|
if (typeof value !== "object") return String(value);
|
|
5514
6173
|
if (Array.isArray(value)) return value.map(flatten).join("");
|
|
5515
|
-
const item =
|
|
6174
|
+
const item = record8(value);
|
|
5516
6175
|
return flatten(item.text ?? item.value ?? item.source ?? JSON.stringify(value));
|
|
5517
6176
|
}
|
|
5518
6177
|
function regionParts(key) {
|
|
@@ -5567,16 +6226,43 @@ function assertComposition(value) {
|
|
|
5567
6226
|
if (value.weights !== void 0 && (!Array.isArray(value.weights) || !value.weights.length || value.weights.length > 12 || value.weights.some((weight) => !Number.isFinite(weight) || weight <= 0 || weight > 100))) throw new RangeError("Invalid composition.weights.");
|
|
5568
6227
|
if (value.overflow !== void 0 && !["warn", "error"].includes(value.overflow)) throw new RangeError("Invalid composition.overflow.");
|
|
5569
6228
|
}
|
|
6229
|
+
var LAYOUT_MASTER = /* @__PURE__ */ Symbol("opf.layoutMaster");
|
|
6230
|
+
function mergeListColumns(columns2) {
|
|
6231
|
+
const fits = columns2.map((column) => column.text), first = fits[0];
|
|
6232
|
+
const directions = fits.flatMap((fit) => fit.directions ?? []);
|
|
6233
|
+
return { ...first, listEntries: fits.flatMap((fit) => fit.listEntries), lines: fits.flatMap((fit) => fit.lines), height: Math.max(...fits.map((fit) => fit.height)), overflow: fits.some((fit) => fit.overflow), ...first.directions ? { directions } : {} };
|
|
6234
|
+
}
|
|
6235
|
+
function composeLayoutAreas(layout, options = {}) {
|
|
6236
|
+
const template = layoutTemplate(layout), source = record8(layout);
|
|
6237
|
+
const kept = { ...source, regions: Object.fromEntries(Object.entries(record8(source.regions)).map(([name, value]) => [name, { ...record8(value), empty: "keep" }])) };
|
|
6238
|
+
const { mirror, bleed = true, placements = [], ...compose } = options;
|
|
6239
|
+
const slide = {
|
|
6240
|
+
...template.title ? { title: "Title", subtitle: "Subtitle" } : {},
|
|
6241
|
+
...placements.length ? { blocks: placements.map((placement) => ({ image: "https://example.invalid/placeholder.png", placement: { ...placement } })) } : {},
|
|
6242
|
+
...mirror !== void 0 ? { design: { mirror } } : {}
|
|
6243
|
+
};
|
|
6244
|
+
const result = composeSlide(slide, { ...compose, layout: kept, [LAYOUT_MASTER]: true });
|
|
6245
|
+
const areas = template.areas.map((area) => {
|
|
6246
|
+
if (area.heading) {
|
|
6247
|
+
const found = result.headingAreas?.find((entry) => entry.name === area.name);
|
|
6248
|
+
return { name: area.name, heading: true, box: found ? { ...found.box } : { x: 0, y: 0, width: 0, height: 0 }, ...found?.parts ? { parts: found.parts } : {} };
|
|
6249
|
+
}
|
|
6250
|
+
const region = result.regions.find((entry) => entry.name === area.name);
|
|
6251
|
+
return { name: area.name, heading: false, box: { ...!bleed && region.areaBox ? region.areaBox : region.box } };
|
|
6252
|
+
});
|
|
6253
|
+
return { contentBox: { ...result.contentBox }, areas };
|
|
6254
|
+
}
|
|
5570
6255
|
function composeSlide(input, options = {}) {
|
|
5571
|
-
const slide =
|
|
6256
|
+
const slide = record8(input), layout = record8(options.layout);
|
|
5572
6257
|
const width = options.width ?? 1280, height = options.height ?? 720;
|
|
5573
6258
|
if (![width, height].every((value) => Number.isFinite(value) && value > 0)) throw new RangeError("Canvas dimensions must be finite and positive.");
|
|
5574
6259
|
const scale = Math.min(width, height) / 720;
|
|
5575
6260
|
const deckDirection = options.direction ?? resolveSlideDirection(options.presentation, options.slideIndex);
|
|
5576
6261
|
const rtl = deckDirection === "rtl", textDirection = rtl ? "rtl" : void 0;
|
|
5577
|
-
const
|
|
6262
|
+
const template = isLayoutTemplate(layout) ? layoutTemplate(layout) : void 0;
|
|
6263
|
+
const hints = resolveDesignHints({ slide, layout, theme: { design: options.themeDesign }, presentation: options.presentation, slideIndex: options.slideIndex, deck: { titleAlignment: options.titleAlignment, contentAlignment: options.contentAlignment, contentBox: options.contentBox } });
|
|
5578
6264
|
const hasCards = hints.contentBox ?? false;
|
|
5579
|
-
const composition = { ...
|
|
6265
|
+
const composition = { ...record8(layout.composition), ...record8(slide.composition) };
|
|
5580
6266
|
assertComposition(composition);
|
|
5581
6267
|
const padding = (composition.padding ?? 0.08) * Math.min(width, height);
|
|
5582
6268
|
const gap = (composition.gap ?? 1 / 30) * Math.min(width, height);
|
|
@@ -5657,17 +6343,15 @@ function composeSlide(input, options = {}) {
|
|
|
5657
6343
|
const mirrorSide = (side) => !rtl ? side : side === "left" ? "right" : side === "right" ? "left" : side;
|
|
5658
6344
|
const backgroundImage = resolveBackgroundImage(slide, options.presentation, options.themeBackground, width, height, path, mirrorSide, imageDiagnostics);
|
|
5659
6345
|
const regions = Object.keys(slide).filter((key) => regionParts(key)).sort();
|
|
5660
|
-
const assets =
|
|
6346
|
+
const assets = record8(options.presentation).assets;
|
|
5661
6347
|
const imageContext = (placement) => ({ fit: hints.imageFit, scale, mirrorSide, diagnostics: imageDiagnostics, assets, ...placement ? { placement } : {} });
|
|
5662
6348
|
const area = { left: 0, top: 0, right: width, bottom: height };
|
|
5663
|
-
const
|
|
5664
|
-
const topImages = regions.length ? [] : Array.isArray(slide.blocks) ? slide.blocks.flatMap((block, index) => !Array.isArray(record6(block).blocks) && record6(block).image !== void 0 ? [{ host: record6(block), hostPath: `${path}.blocks.${index}`, block: index }] : []) : slide.image !== void 0 ? [{ host: { type: "image", image: slide.image }, hostPath: path }] : [];
|
|
6349
|
+
const topImages = regions.length ? [] : Array.isArray(slide.blocks) ? slide.blocks.flatMap((block, index) => !Array.isArray(record8(block).blocks) && record8(block).image !== void 0 ? [{ host: record8(block), hostPath: `${path}.blocks.${index}`, block: index }] : []) : slide.image !== void 0 ? [{ host: { type: "image", image: slide.image }, hostPath: path }] : [];
|
|
5665
6350
|
const placed = [], usedEdges = /* @__PURE__ */ new Set();
|
|
5666
|
-
topImages.forEach((node
|
|
5667
|
-
const
|
|
5668
|
-
const
|
|
5669
|
-
|
|
5670
|
-
if (!value || !IMAGE_EDGES.includes(value.edge)) return;
|
|
6351
|
+
topImages.forEach((node) => {
|
|
6352
|
+
const own3 = node.block !== void 0 && node.host.placement !== void 0 ? record8(node.host.placement) : void 0;
|
|
6353
|
+
const value = own3;
|
|
6354
|
+
if (!value || !IMAGE_EDGES2.includes(value.edge)) return;
|
|
5671
6355
|
const edge = mirrorSide(value.edge);
|
|
5672
6356
|
if (usedEdges.has(edge)) return;
|
|
5673
6357
|
usedEdges.add(edge);
|
|
@@ -5679,8 +6363,8 @@ function composeSlide(input, options = {}) {
|
|
|
5679
6363
|
else if (edge === "right") area.right = region.x;
|
|
5680
6364
|
else if (edge === "top") area.top += band;
|
|
5681
6365
|
else area.bottom = region.y;
|
|
5682
|
-
const placement = { edge, size, inset: value.inset === true, path:
|
|
5683
|
-
placed.push({ ...node, placement, region
|
|
6366
|
+
const placement = { edge, size, inset: value.inset === true, path: `${node.hostPath}.placement` };
|
|
6367
|
+
placed.push({ ...node, placement, region });
|
|
5684
6368
|
});
|
|
5685
6369
|
const placedBlocks = new Set(placed.flatMap((entry) => entry.block !== void 0 ? [entry.block] : []));
|
|
5686
6370
|
const placedRoot = placed.some((entry) => entry.block === void 0);
|
|
@@ -5696,17 +6380,16 @@ function composeSlide(input, options = {}) {
|
|
|
5696
6380
|
diagnostics.push(...footnotes.diagnostics);
|
|
5697
6381
|
bodyBottom = footnotes.box.y - gap * 0.5;
|
|
5698
6382
|
}
|
|
5699
|
-
const layoutPlaceholders = Array.isArray(layout.placeholders) ? layout.placeholders : [];
|
|
5700
6383
|
const hasLayoutRecord = options.layout !== void 0 && options.layout !== null && typeof options.layout === "object";
|
|
5701
|
-
const headingOnlyLayout = layoutPlaceholders.length > 0 && layoutPlaceholders.every((placeholder) => headings.has(placeholder.type ?? "") || placeholder.type === "image" && typeof placeholder.placement === "object" && placeholder.placement !== null);
|
|
5702
6384
|
const emptyPayload = (value) => value === void 0 || value === null || value === "" || Array.isArray(value) && value.length === 0;
|
|
5703
6385
|
const emptyHost = (host) => emptyPayload(host.blocks) && fields.every((field) => emptyPayload(host[field]));
|
|
5704
6386
|
const flowBlocks = Array.isArray(slide.blocks) ? slide.blocks.filter((_, index) => !placedBlocks.has(index)) : slide.blocks;
|
|
5705
|
-
const hasBodyPayload = regions.some((key) => !emptyHost(
|
|
5706
|
-
const
|
|
6387
|
+
const hasBodyPayload = regions.some((key) => !emptyHost(record8(slide[key]))) || !emptyPayload(flowBlocks) || fields.some((field) => !(placedRoot && field === "image") && !emptyPayload(slide[field]));
|
|
6388
|
+
const useTemplate = template !== void 0 && !regions.length;
|
|
6389
|
+
const isCover = !hasBodyPayload && (useTemplate || !hasLayoutRecord);
|
|
5707
6390
|
coverGroup = isCover;
|
|
5708
6391
|
let logo;
|
|
5709
|
-
if (isCover) {
|
|
6392
|
+
if (isCover && options[LAYOUT_MASTER] !== true) {
|
|
5710
6393
|
const resolved = resolveLogo(options.presentation, slide, { shape: "full", onDark: options.darkBackground, slideIndex: options.slideIndex });
|
|
5711
6394
|
if (resolved) {
|
|
5712
6395
|
const logoHeight = 56 * scale;
|
|
@@ -5717,7 +6400,7 @@ function composeSlide(input, options = {}) {
|
|
|
5717
6400
|
}
|
|
5718
6401
|
let y = logo ? logo.box.y + logo.box.height + gap : headingTop;
|
|
5719
6402
|
const headingItems = [];
|
|
5720
|
-
for (const field of ["tag", "title", "subtitle"]) {
|
|
6403
|
+
for (const field of useTemplate ? [] : ["tag", "title", "subtitle"]) {
|
|
5721
6404
|
if (!slide[field] || Array.isArray(slide[field]) && !annotationText(slide[field])) continue;
|
|
5722
6405
|
const requested = (field === "title" ? 54 : field === "tag" ? 16 : 25) * scale;
|
|
5723
6406
|
const maxHeight = Math.max(height * (field === "title" ? 0.26 : field === "subtitle" ? 0.12 : 0.045), minSize * 1.22 + 2 * rasterPadding);
|
|
@@ -5769,7 +6452,7 @@ function composeSlide(input, options = {}) {
|
|
|
5769
6452
|
const collect = (host, basePath, depth = 0, ancestors = []) => {
|
|
5770
6453
|
if (Array.isArray(host.blocks)) {
|
|
5771
6454
|
if (depth >= MAX_COMPOSITION_DEPTH || ancestors.includes(host)) throw new RangeError(`Content groups must be acyclic and nest at most ${MAX_COMPOSITION_DEPTH} levels.`);
|
|
5772
|
-
const settings =
|
|
6455
|
+
const settings = record8(host.composition);
|
|
5773
6456
|
assertComposition(settings);
|
|
5774
6457
|
return [{
|
|
5775
6458
|
field: "blocks",
|
|
@@ -5778,7 +6461,7 @@ function composeSlide(input, options = {}) {
|
|
|
5778
6461
|
path: basePath,
|
|
5779
6462
|
payload: host,
|
|
5780
6463
|
composition: settings,
|
|
5781
|
-
children: host.blocks.flatMap((block, index) => collect(
|
|
6464
|
+
children: host.blocks.flatMap((block, index) => collect(record8(block), `${basePath}.blocks.${index}`, depth + 1, [...ancestors, host]))
|
|
5782
6465
|
}];
|
|
5783
6466
|
}
|
|
5784
6467
|
const captioned = host.caption !== void 0 ? fields.filter((field) => host[field] !== void 0 && CAPTIONABLE_FIELDS.includes(field)) : [];
|
|
@@ -5788,27 +6471,27 @@ function composeSlide(input, options = {}) {
|
|
|
5788
6471
|
type: host.type ?? kind(field),
|
|
5789
6472
|
value: fieldValue(field),
|
|
5790
6473
|
path: `${basePath}.${field}`,
|
|
5791
|
-
payload: field === "image" ? imagePayload(host) : { type: host.type ?? kind(field), [field]: fieldValue(field), ...host.numbering !== void 0 && (field === "items" || field === "bullets") ? { numbering: host.numbering } : {} },
|
|
6474
|
+
payload: field === "image" ? imagePayload(host) : { type: host.type ?? kind(field), [field]: fieldValue(field), ...host.numbering !== void 0 && (field === "items" || field === "bullets") ? { numbering: host.numbering } : {}, ...host.columns !== void 0 && (field === "items" || field === "bullets") ? { columns: host.columns } : {} },
|
|
5792
6475
|
...field === "image" ? { host, hostPath: basePath } : {},
|
|
5793
6476
|
...captioned.length === 1 && captioned[0] === field ? { caption: host.caption, captionPath: `${basePath}.caption` } : {}
|
|
5794
6477
|
}));
|
|
5795
6478
|
};
|
|
5796
6479
|
const regionsInReadingOrder = visualReadingOrder(regions.map((key) => ({ key, box: regionBox(regionParts(key), contentBox, gap) }))).map((entry) => entry.key);
|
|
5797
|
-
const pending = regions.length ? regionsInReadingOrder.flatMap((key) => collect(
|
|
6480
|
+
const pending = regions.length ? regionsInReadingOrder.flatMap((key) => collect(record8(slide[key]), `${path}.${key}`).map((item) => ({ ...item, region: regionParts(key) }))) : Array.isArray(slide.blocks) ? slide.blocks.flatMap((block, index) => placedBlocks.has(index) ? [] : collect(record8(block), `${path}.blocks.${index}`)) : collect(placedRoot ? { ...slide, image: void 0 } : slide, path);
|
|
5798
6481
|
const groups = [], flows = [];
|
|
5799
6482
|
const decisions = options.explain ? [] : void 0;
|
|
5800
|
-
const inheritedSettings = (parent,
|
|
6483
|
+
const inheritedSettings = (parent, own3 = {}) => ({
|
|
5801
6484
|
minFontSize: parent.minFontSize,
|
|
5802
|
-
...
|
|
5803
|
-
overflow: parent.overflow === "error" ? "error" :
|
|
6485
|
+
...own3,
|
|
6486
|
+
overflow: parent.overflow === "error" ? "error" : own3.overflow ?? parent.overflow
|
|
5804
6487
|
});
|
|
5805
6488
|
const inset = (box, settings) => {
|
|
5806
6489
|
const amount = (settings.padding ?? 0) * Math.min(box.width, box.height);
|
|
5807
6490
|
return { x: box.x + amount, y: box.y + amount, width: box.width - amount * 2, height: box.height - amount * 2 };
|
|
5808
6491
|
};
|
|
5809
6492
|
const acceptedBox = (box) => ({ x: round2(box.x), y: round2(box.y), width: round2(box.width), height: round2(box.height) });
|
|
5810
|
-
const payloadBox = (box) => {
|
|
5811
|
-
if (!
|
|
6493
|
+
const payloadBox = (box, cards = hasCards) => {
|
|
6494
|
+
if (!cards) return box;
|
|
5812
6495
|
const frame = acceptedBox(box), padding2 = Math.min(12 * scale, frame.width / 4, frame.height / 4);
|
|
5813
6496
|
return acceptedBox({ x: frame.x + padding2, y: frame.y + padding2, width: frame.width - 2 * padding2, height: frame.height - 2 * padding2 });
|
|
5814
6497
|
};
|
|
@@ -5867,8 +6550,8 @@ function composeSlide(input, options = {}) {
|
|
|
5867
6550
|
penalties.textOverflow += internal.overflow ? 1e3 : 0;
|
|
5868
6551
|
}
|
|
5869
6552
|
} else if (text2) {
|
|
5870
|
-
const fit = fitContent(node.field, node.value, text2, box,
|
|
5871
|
-
const reduction = Math.max(0, snapFontSizeDown(
|
|
6553
|
+
const fit = fitContent(node.field, node.value, text2, box, contentNominalSize(node.field) * scale, snapFontSizeUp((settings.minFontSize ?? 16) * scale), node.path, node.payload.numbering);
|
|
6554
|
+
const reduction = Math.max(0, snapFontSizeDown(contentNominalSize(node.field) * scale) - fit.fontSize) / scale;
|
|
5872
6555
|
score += reduction + (fit.overflow ? 1e3 : 0);
|
|
5873
6556
|
if (penalties) {
|
|
5874
6557
|
penalties.fontReduction += reduction;
|
|
@@ -5892,24 +6575,13 @@ function composeSlide(input, options = {}) {
|
|
|
5892
6575
|
};
|
|
5893
6576
|
const scoreNode = (node, box, settings, penalties) => {
|
|
5894
6577
|
if (!node.children) return leafScore(node, box, settings, penalties);
|
|
5895
|
-
const
|
|
5896
|
-
const cols = defaultColumns(slotCount, area2,
|
|
5897
|
-
const boxes = gridBoxes(slotCount, area2, cols, (
|
|
5898
|
-
return node.children.reduce((score, child, index) => score + scoreNode(child, boxes[index],
|
|
6578
|
+
const own3 = inheritedSettings(settings, node.composition), area2 = inset(box, own3), slotCount = Math.max(node.children.length, 0);
|
|
6579
|
+
const cols = defaultColumns(slotCount, area2, own3);
|
|
6580
|
+
const boxes = gridBoxes(slotCount, area2, cols, (own3.gap ?? 1 / 30) * Math.min(box.width, box.height), own3.weights ?? [], modeFor(own3) === "column");
|
|
6581
|
+
return node.children.reduce((score, child, index) => score + scoreNode(child, boxes[index], own3, penalties), 0);
|
|
5899
6582
|
};
|
|
5900
|
-
const
|
|
5901
|
-
|
|
5902
|
-
const box = boxes[index];
|
|
5903
|
-
if (!box) return;
|
|
5904
|
-
slots.push({ path: entry.path, type: entry.type, depth: entry.depth, box: acceptedBox(box) });
|
|
5905
|
-
if (!entry.children) return;
|
|
5906
|
-
const own2 = inheritedSettings(settings, record6(entry.placeholder.composition)), inner = inset(box, own2);
|
|
5907
|
-
const cols = defaultColumns(entry.children.length, inner, own2);
|
|
5908
|
-
const mirror = (cell) => rtl ? { ...cell, x: inner.x + inner.width - (cell.x - inner.x) - cell.width } : cell;
|
|
5909
|
-
emptySlots(entry.children, gridBoxes(entry.children.length, inner, cols, (own2.gap ?? 1 / 30) * Math.min(box.width, box.height), own2.weights ?? [], modeFor(own2) === "column").map(mirror), own2);
|
|
5910
|
-
});
|
|
5911
|
-
const arrange = (nodes, area2, settings, reserved = 0, gapOverride, containerPath = path, recorded = true, template) => {
|
|
5912
|
-
const count = Math.max(nodes.length, reserved);
|
|
6583
|
+
const arrange = (nodes, area2, settings, reserved2 = 0, gapOverride, containerPath = path, recorded = true) => {
|
|
6584
|
+
const count = Math.max(nodes.length, reserved2);
|
|
5913
6585
|
if (!count) return;
|
|
5914
6586
|
const mode = modeFor(settings), localGap = (settings.gap ?? 1 / 30) * Math.min(area2.width, area2.height);
|
|
5915
6587
|
const actualGap = gapOverride ?? (settings === rootSettings ? gap : localGap);
|
|
@@ -5920,9 +6592,9 @@ function composeSlide(input, options = {}) {
|
|
|
5920
6592
|
let best = Infinity;
|
|
5921
6593
|
for (let candidate = 1; candidate <= Math.min(count, settings.columns ?? 6); candidate++) {
|
|
5922
6594
|
const boxes2 = gridBoxes(count, area2, candidate, actualGap, settings.weights ?? [], false);
|
|
5923
|
-
const
|
|
5924
|
-
const penalties = candidates ? { cellProportions: 0, fontReduction: 0, textOverflow: 0, tableOverflow: 0, smallCells: 0, emptySlots
|
|
5925
|
-
const score = nodes.reduce((sum, node, i) => sum + scoreNode(node, boxes2[i], settings, penalties), 0) +
|
|
6595
|
+
const emptySlots = (Math.ceil(count / candidate) * candidate - count) * 2;
|
|
6596
|
+
const penalties = candidates ? { cellProportions: 0, fontReduction: 0, textOverflow: 0, tableOverflow: 0, smallCells: 0, emptySlots } : void 0;
|
|
6597
|
+
const score = nodes.reduce((sum, node, i) => sum + scoreNode(node, boxes2[i], settings, penalties), 0) + emptySlots;
|
|
5926
6598
|
if (penalties && candidates) candidates.push({ columns: candidate, rows: Math.ceil(count / candidate), score, penalties });
|
|
5927
6599
|
if (score < best) {
|
|
5928
6600
|
best = score;
|
|
@@ -5940,114 +6612,387 @@ function composeSlide(input, options = {}) {
|
|
|
5940
6612
|
const grid = gridGeometry(count, area2, cols, actualGap, settings.weights ?? [], mode === "column");
|
|
5941
6613
|
const mirrored = (box) => rtl ? { ...box, x: area2.x + area2.width - (box.x - area2.x) - box.width } : box;
|
|
5942
6614
|
const boxes = grid.boxes.map(mirrored);
|
|
5943
|
-
if (template) emptySlots(template.slice(nodes.length), boxes.slice(nodes.length), settings);
|
|
5944
6615
|
if (recorded && !hasRegions) flows.push({ path: containerPath, box: { ...area2 }, composition: { ...settings }, columns: rtl ? grid.columns.map((track) => ({ offset: area2.width - track.offset - track.size, size: track.size })) : grid.columns, rows: grid.rows, gap: grid.gap, itemCount: nodes.length, slotCount: count });
|
|
5945
6616
|
nodes.forEach((node, index) => {
|
|
5946
|
-
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
|
|
5950
|
-
|
|
5951
|
-
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
5957
|
-
|
|
5958
|
-
|
|
6617
|
+
const box = node.region ? mirrored(regionBox(node.region, area2, actualGap)) : boxes[index];
|
|
6618
|
+
placeNode(node, box, settings);
|
|
6619
|
+
});
|
|
6620
|
+
};
|
|
6621
|
+
let regionTag, templateCell = false;
|
|
6622
|
+
const placeNode = (node, box, settings, cards = hasCards, listColumns, metricReferenceHeight) => {
|
|
6623
|
+
if (node.children) {
|
|
6624
|
+
const own3 = inheritedSettings(settings, node.composition), inner = inset(box, own3);
|
|
6625
|
+
if (!node.synthetic) groups.push({ path: node.path, box, contentBox: inner, composition: own3 });
|
|
6626
|
+
arrange(node.children, inner, own3, 0, (own3.gap ?? 1 / 30) * Math.min(box.width, box.height), node.path, !node.synthetic);
|
|
6627
|
+
return;
|
|
6628
|
+
}
|
|
6629
|
+
const frameBox = cards ? acceptedBox(box) : void 0;
|
|
6630
|
+
const metricHeight = metricReferenceHeight === void 0 ? void 0 : payloadBox({ ...box, height: metricReferenceHeight }, cards).height;
|
|
6631
|
+
box = payloadBox(box, cards);
|
|
6632
|
+
const caption = captionOf(node, box);
|
|
6633
|
+
if (caption) {
|
|
6634
|
+
box = caption.mediaBox;
|
|
6635
|
+
diagnostics.push(...caption.diagnostics);
|
|
6636
|
+
}
|
|
6637
|
+
const textValue = contentText(node.field, node.value);
|
|
6638
|
+
const quoteLayout = node.field === "quote" ? measureQuote(node, box, settings) : void 0;
|
|
6639
|
+
const codeLayout = node.field === "code" ? measureCode(node, box, settings) : void 0;
|
|
6640
|
+
const metricLayout = node.field === "metric" ? measureMetric(node, { ...box, height: metricHeight ?? box.height }, settings) : void 0;
|
|
6641
|
+
const timelineLayout = node.field === "timeline" ? measureTimeline(node, box, settings) : void 0;
|
|
6642
|
+
const internal = quoteLayout ?? codeLayout ?? metricLayout ?? timelineLayout, body = internal?.parts.find((part) => part.role === "body" || part.role === "value");
|
|
6643
|
+
const columns2 = textValue !== void 0 && !internal ? listColumnsFor(node, box, settings, listColumns) : void 0;
|
|
6644
|
+
const text2 = internal ? body?.fit : columns2 ? columns2.length > 1 ? mergeListColumns(columns2) : columns2[0].text : textValue !== void 0 ? fitContent(node.field, node.value, textValue, box, contentNominalSize(node.field) * scale, snapFontSizeUp((settings.minFontSize ?? 16) * scale), node.path, node.payload.numbering) : void 0;
|
|
6645
|
+
const image = node.field === "image" ? composeImage(node.host ?? {}, node.hostPath ?? node.path, box, box, imageContext()) : void 0;
|
|
6646
|
+
items.push({
|
|
6647
|
+
path: node.path,
|
|
6648
|
+
field: node.field,
|
|
6649
|
+
type: node.type,
|
|
6650
|
+
value: node.value,
|
|
6651
|
+
payload: node.payload,
|
|
6652
|
+
box: internal ? acceptedBox(box) : box,
|
|
6653
|
+
...image ? { image } : {},
|
|
6654
|
+
...frameBox ? { frameBox } : {},
|
|
6655
|
+
text: text2,
|
|
6656
|
+
textStyle: body?.style ?? styleFor(node.field, node.path),
|
|
6657
|
+
composition: settings,
|
|
6658
|
+
alignment: alignmentFor(node.field),
|
|
6659
|
+
...quoteLayout ? { quoteLayout } : {},
|
|
6660
|
+
...codeLayout ? { codeLayout } : {},
|
|
6661
|
+
...metricLayout ? { metricLayout } : {},
|
|
6662
|
+
...timelineLayout ? { timelineLayout } : {},
|
|
6663
|
+
...bulletImage && node.payload.numbering === void 0 && (node.field === "items" || node.field === "bullets") ? { bulletImage } : {},
|
|
6664
|
+
...caption ? { caption } : {},
|
|
6665
|
+
...regionTag !== void 0 ? { region: regionTag } : {},
|
|
6666
|
+
...columns2 && columns2.length > 1 ? { listColumns: columns2 } : {}
|
|
6667
|
+
});
|
|
6668
|
+
if (box.width < 100 * scale || !templateCell && box.height < 60 * scale) diagnostics.push({ code: "small-cell", path: node.path, message: "Content cell is too small for comfortable reading; use fewer blocks or a different composition." });
|
|
6669
|
+
};
|
|
6670
|
+
const listColumnsFor = (node, box, settings, regionMode) => {
|
|
6671
|
+
if (node.field !== "items" && node.field !== "bullets") return void 0;
|
|
6672
|
+
const values = node.value;
|
|
6673
|
+
if (!Array.isArray(values) || values.length < 2) return void 0;
|
|
6674
|
+
const own3 = node.payload.columns;
|
|
6675
|
+
const mode = own3 === "auto" || own3 === 1 || own3 === 2 || own3 === 3 ? own3 : regionMode;
|
|
6676
|
+
if (mode === void 0 || mode === 1) return void 0;
|
|
6677
|
+
const start = contentNominalSize(node.field) * scale, floor = snapFontSizeUp((settings.minFontSize ?? 16) * scale);
|
|
6678
|
+
const numbering = node.payload.numbering;
|
|
6679
|
+
const listOptions = { ...richOptions(styleFor(node.field, node.path)), ...numbering !== void 0 ? { numbering } : bulletImage ? { bulletImage } : {} };
|
|
6680
|
+
const columnGap = (count2) => Math.min(gap, box.width / (count2 * 2));
|
|
6681
|
+
const columnBoxes = (count2) => {
|
|
6682
|
+
const between = columnGap(count2), columnWidth = (box.width - between * (count2 - 1)) / count2;
|
|
6683
|
+
const ordered = Array.from({ length: count2 }, (_, index) => ({ x: box.x + index * (columnWidth + between), y: box.y, width: columnWidth, height: box.height }));
|
|
6684
|
+
return rtl ? ordered.map((cell) => ({ ...cell, x: box.x + box.width - (cell.x - box.x) - cell.width })) : ordered;
|
|
6685
|
+
};
|
|
6686
|
+
const chunk = (from, to) => numbering !== void 0 ? sliceNumberedItems(values, numbering, from, to) : values.slice(from, to);
|
|
6687
|
+
const sourcePaths = (index) => {
|
|
6688
|
+
const source = values[index], object2 = source !== null && typeof source === "object" && !Array.isArray(source);
|
|
6689
|
+
return { textPath: `${node.path}.${index}${object2 ? ".text" : ""}`, descriptionPath: `${node.path}.${index}.description` };
|
|
6690
|
+
};
|
|
6691
|
+
const renumber = (fit, from) => ({ ...fit, listEntries: fit.listEntries.map((entry) => ({ ...entry, index: entry.index + from, ...sourcePaths(entry.index + from) })) });
|
|
6692
|
+
const split = (count2, size2, minimum) => {
|
|
6693
|
+
const boxes = columnBoxes(count2);
|
|
6694
|
+
const whole = fitList(values, { ...boxes[0], height: 1e6 }, start, start, listOptions);
|
|
6695
|
+
const first = whole.listEntries[0].textBox.y;
|
|
6696
|
+
const heights = whole.listEntries.map((entry, index) => (whole.listEntries[index + 1]?.textBox.y ?? first + whole.height) - entry.textBox.y);
|
|
6697
|
+
const breaks = [0, ...listColumnBreaks(heights, whole.listEntries.map((entry) => entry.level), count2), values.length];
|
|
6698
|
+
return boxes.slice(0, breaks.length - 1).map((cell, index) => ({ box: cell, start: breaks[index], end: breaks[index + 1], text: renumber(fitList(chunk(breaks[index], breaks[index + 1]), cell, size2, minimum, listOptions), breaks[index]) }));
|
|
6699
|
+
};
|
|
6700
|
+
const quarter = width / 4;
|
|
6701
|
+
const counts = typeof mode === "number" ? [mode] : [2, 3].filter((count2) => (box.width - columnGap(count2) * (count2 - 1)) / count2 >= quarter);
|
|
6702
|
+
if (mode === "auto") {
|
|
6703
|
+
if (!fitList(values, box, start, start, listOptions).overflow) return void 0;
|
|
6704
|
+
for (const count2 of counts) {
|
|
6705
|
+
const columns2 = split(count2, start, start);
|
|
6706
|
+
if (columns2.every((column) => !column.text.overflow)) return columns2;
|
|
6707
|
+
}
|
|
6708
|
+
}
|
|
6709
|
+
const count = counts.at(-1);
|
|
6710
|
+
if (count === void 0) return void 0;
|
|
6711
|
+
const shrunk = split(count, start, floor);
|
|
6712
|
+
const size = Math.min(...shrunk.map((column) => column.text.fontSize));
|
|
6713
|
+
return shrunk.map((column) => ({ ...column, text: renumber(fitList(chunk(column.start, column.end), column.box, size, size, listOptions), column.start) }));
|
|
6714
|
+
};
|
|
6715
|
+
const LONG_LINES = 6, LONG_CODE_LINES = 12, startSize = 25 * scale;
|
|
6716
|
+
const estimatedLines = (value, cellWidth, size) => flatten(value).split("\n").reduce((sum, paragraph) => sum + Math.max(1, wrapText(paragraph, Math.max(1, cellWidth), size).length), 0);
|
|
6717
|
+
const isLong = (node, cellWidth) => {
|
|
6718
|
+
if (node.children) return node.children.some((child) => isLong(child, cellWidth));
|
|
6719
|
+
if (node.field === "text") return estimatedLines(node.value, cellWidth, startSize) > LONG_LINES;
|
|
6720
|
+
if (node.field === "items" || node.field === "bullets") {
|
|
6721
|
+
const listSize = contentNominalSize(node.field) * scale;
|
|
6722
|
+
let lines = 0;
|
|
6723
|
+
for (const entry of Array.isArray(node.value) ? node.value : []) {
|
|
6724
|
+
const object2 = entry !== null && typeof entry === "object" && !Array.isArray(entry) ? entry : void 0;
|
|
6725
|
+
const indent = listSize * 1.1 * (1 + (typeof object2?.level === "number" ? object2.level : 0));
|
|
6726
|
+
lines += estimatedLines(object2 ? object2.text : entry, cellWidth - indent, listSize);
|
|
6727
|
+
if (object2?.description !== void 0) lines += estimatedLines(object2.description, cellWidth - indent, listSize * 0.82);
|
|
6728
|
+
}
|
|
6729
|
+
return lines > LONG_LINES;
|
|
6730
|
+
}
|
|
6731
|
+
if (node.field === "quote") return estimatedLines(typeof node.value === "string" ? node.value : record8(node.value).text, cellWidth, startSize) > LONG_LINES;
|
|
6732
|
+
if (node.field === "table") {
|
|
6733
|
+
const value = record8(node.value);
|
|
6734
|
+
return (Array.isArray(value.rows) ? value.rows.length + (Array.isArray(value.columns) ? 1 : 0) : 0) > LONG_LINES;
|
|
6735
|
+
}
|
|
6736
|
+
if (node.field === "code") return String(typeof node.value === "string" ? node.value : record8(node.value).source ?? "").split("\n").length > LONG_CODE_LINES;
|
|
6737
|
+
return false;
|
|
6738
|
+
};
|
|
6739
|
+
const naturalHeight = (node, cellWidth, cards, metricReferenceHeight, naturalSettings = composition) => {
|
|
6740
|
+
const pad = cards ? 2 * Math.min(12 * scale, cellWidth / 4) : 0, inner = Math.max(scale, cellWidth - pad);
|
|
6741
|
+
if (node.children) return node.children.reduce((sum, child) => sum + naturalHeight(child, cellWidth, false), 0) + gap * Math.max(0, node.children.length - 1) + pad;
|
|
6742
|
+
let content;
|
|
6743
|
+
if (node.field === "text" || node.field === "items" || node.field === "bullets") {
|
|
6744
|
+
const size = contentNominalSize(node.field) * scale;
|
|
6745
|
+
const fit = fitContent(node.field, node.value, contentText(node.field, node.value) ?? "", { x: 0, y: 0, width: inner, height: 1e6 }, size, size, node.path, node.payload.numbering);
|
|
6746
|
+
content = "height" in fit && typeof fit.height === "number" ? fit.height : fit.lines.length * fit.lineHeight;
|
|
6747
|
+
} else if (node.field === "quote") content = measureQuote(node, { x: 0, y: 0, width: inner, height: 1e6 }, naturalSettings).bounds.height + 18;
|
|
6748
|
+
else if (node.field === "code") content = String(typeof node.value === "string" ? node.value : record8(node.value).source ?? "").split("\n").length * 18 * 1.4 * scale + 24 * scale;
|
|
6749
|
+
else if (node.field === "metric") content = measureMetric(node, { x: 0, y: 0, width: inner, height: metricReferenceHeight === void 0 ? 1e6 : Math.max(scale, metricReferenceHeight - pad) }, naturalSettings).bounds.height;
|
|
6750
|
+
else if (node.field === "timeline") content = 170 * scale;
|
|
6751
|
+
else if (node.field === "table") {
|
|
6752
|
+
const value = record8(node.value);
|
|
6753
|
+
content = ((Array.isArray(value.rows) ? value.rows.length : 4) + 1) * 36 * scale;
|
|
6754
|
+
} else content = inner / 1.6;
|
|
6755
|
+
return content + (node.caption !== void 0 ? 32 * scale : 0) + pad;
|
|
6756
|
+
};
|
|
6757
|
+
const templateRegions = [], headingAreas = [];
|
|
6758
|
+
const requestedTemplateGap = gap;
|
|
6759
|
+
const composeTemplate = () => {
|
|
6760
|
+
const plan2 = template, frame = contentBox;
|
|
6761
|
+
const binding = bindRegions(slide, layout, { slideIndex: options.slideIndex ?? 0 });
|
|
6762
|
+
for (const entry of binding.diagnostics) diagnostics.push({ code: entry.code, path: entry.path, message: entry.message, ...entry.region !== void 0 ? { region: entry.region } : {} });
|
|
6763
|
+
const unitOf = (bound) => {
|
|
6764
|
+
const host = bound.block !== void 0 ? record8(slide.blocks[bound.block]) : { ...Object.fromEntries((bound.fields ?? []).map((field) => [field, slide[field]])), ...Object.fromEntries(["type", "caption", "numbering"].filter((key) => slide[key] !== void 0).map((key) => [key, slide[key]])) };
|
|
6765
|
+
const parts = collect(host, bound.block !== void 0 ? `${path}.blocks.${bound.block}` : path);
|
|
6766
|
+
return parts.length === 1 ? parts[0] : { field: "blocks", type: "group", value: parts.map((part) => part.payload), path: bound.path, payload: {}, children: parts, composition: { mode: "column" }, synthetic: true };
|
|
6767
|
+
};
|
|
6768
|
+
const contents = new Map(binding.regions.map((entry) => [entry.name, [...entry.blocks, ...entry.overflow].map(unitOf)]));
|
|
6769
|
+
const BELOW = "(below)";
|
|
6770
|
+
const belowUnits = binding.below.map(unitOf);
|
|
6771
|
+
const belowRegion = { name: BELOW, accepts: [], role: "supporting", flow: "auto", max: belowUnits.length, bleed: false, listColumns: 1, anchor: "top", empty: "collapse" };
|
|
6772
|
+
const unitsOf = (name) => name === BELOW ? belowUnits : contents.get(name) ?? [];
|
|
6773
|
+
const shown = (field) => !!slide[field] && !(Array.isArray(slide[field]) && !annotationText(slide[field]));
|
|
6774
|
+
const titleFields = ["tag", "title", ...plan2.subtitle ? [] : ["subtitle"]].filter(shown);
|
|
6775
|
+
const subtitleFields = plan2.subtitle && shown("subtitle") ? ["subtitle"] : [];
|
|
6776
|
+
const columnCount = plan2.columns.length;
|
|
6777
|
+
const cells = plan2.grid.map((row) => [...row]);
|
|
6778
|
+
const rowSizes = [...plan2.rows];
|
|
6779
|
+
const implicitTitle = !plan2.title && titleFields.length > 0;
|
|
6780
|
+
if (implicitTitle) {
|
|
6781
|
+
cells.unshift(Array.from({ length: columnCount }, () => "title"));
|
|
6782
|
+
rowSizes.unshift("auto");
|
|
6783
|
+
}
|
|
6784
|
+
if (belowUnits.length) {
|
|
6785
|
+
cells.push(Array.from({ length: columnCount }, () => BELOW));
|
|
6786
|
+
rowSizes.push("auto");
|
|
6787
|
+
}
|
|
6788
|
+
const gap2 = Math.max(0, Math.min(requestedTemplateGap, frame.width / (columnCount * 2), frame.height / (rowSizes.length * 2)));
|
|
6789
|
+
const regionOf = new Map(plan2.regions.map((region) => [region.name, region]));
|
|
6790
|
+
const empty2 = /* @__PURE__ */ new Set();
|
|
6791
|
+
for (const region of plan2.regions) if (!unitsOf(region.name).length && region.empty !== "keep") empty2.add(region.name);
|
|
6792
|
+
if (plan2.title && !titleFields.length) empty2.add("title");
|
|
6793
|
+
if (plan2.subtitle && !subtitleFields.length) empty2.add("subtitle");
|
|
6794
|
+
const collapsed = collapseAreas(cells, empty2, (name) => name === "title" || name === "subtitle", (name) => name !== BELOW);
|
|
6795
|
+
const rects = areaRects(collapsed.grid), ownRects = areaRects(cells);
|
|
6796
|
+
const widths = columnWidths(plan2.columns, frame.width, gap2);
|
|
6797
|
+
const columnX = [];
|
|
6798
|
+
widths.reduce((x, size) => {
|
|
6799
|
+
columnX.push(x);
|
|
6800
|
+
return x + size + gap2;
|
|
6801
|
+
}, 0);
|
|
6802
|
+
const spanWidth = (rect) => widths.slice(rect.column, rect.column + rect.columnSpan).reduce((a, b) => a + b, 0) + gap2 * (rect.columnSpan - 1);
|
|
6803
|
+
const headingItemsAt = (fields2, x, y2, areaWidth) => {
|
|
6804
|
+
const list = [];
|
|
6805
|
+
let top = y2;
|
|
6806
|
+
for (const field of fields2) {
|
|
6807
|
+
const requested = (field === "title" ? 54 : field === "tag" ? 16 : 25) * scale;
|
|
6808
|
+
const maxHeight = Math.max(height * (field === "title" ? 0.26 : field === "subtitle" ? 0.12 : 0.045), minSize * 1.22 + 2 * rasterPadding);
|
|
6809
|
+
const box = { x, y: top, width: areaWidth, height: maxHeight };
|
|
6810
|
+
const text2 = fitPlacedText(field, slide[field], annotationText(slide[field]), box, requested, minSize, `${path}.${field}`);
|
|
6811
|
+
box.height = Math.min(maxHeight, Math.max("richLines" in text2 ? text2.height : text2.lines.length * text2.lineHeight, text2.placement?.height ?? 0));
|
|
6812
|
+
list.push({ path: `${path}.${field}`, field, type: "text", value: slide[field], payload: { text: slide[field] }, box, text: text2, textStyle: styleFor(field, `${path}.${field}`), composition, alignment: alignmentFor(field) });
|
|
6813
|
+
top += box.height + gap2 * 0.5;
|
|
6814
|
+
}
|
|
6815
|
+
return list;
|
|
6816
|
+
};
|
|
6817
|
+
const groupHeight = (list) => list.length ? list.at(-1).box.y + list.at(-1).box.height - list[0].box.y : 0;
|
|
6818
|
+
const arrangementOf = (region, units, cell) => {
|
|
6819
|
+
if (direction !== void 0 && region.flow !== "none") return direction === "horizontal" ? "row" : "column";
|
|
6820
|
+
const flow = region.flow === "none" && units.length > 1 ? "auto" : region.flow;
|
|
6821
|
+
if (flow === "none" || flow === "column") return "column";
|
|
6822
|
+
if (flow === "grid") return "grid";
|
|
6823
|
+
const shape = gridFlowShape(units.length, cell.width >= cell.height);
|
|
6824
|
+
const cards = hasCards && !region.bleed;
|
|
6825
|
+
const cellWidth = (cell.width - gap2 * (shape.columns - 1)) / shape.columns - (cards ? 2 * Math.min(12 * scale, cell.width / 4) : 0);
|
|
6826
|
+
return units.some((unit) => isLong(unit, cellWidth)) ? "column" : "grid";
|
|
6827
|
+
};
|
|
6828
|
+
const regionNeed = (name, areaWidth) => {
|
|
6829
|
+
const units = unitsOf(name), region = name === BELOW ? belowRegion : regionOf.get(name);
|
|
6830
|
+
if (!units.length) return region.empty === "keep" ? 2 * startSize * 1.22 + (hasCards && !region.bleed ? 2 * Math.min(12 * scale, areaWidth / 4) : 0) : 0;
|
|
6831
|
+
const shape = flowShape(arrangementOf(region, units, { width: areaWidth, height: areaWidth / 4 }), units.length, true);
|
|
6832
|
+
const cellWidth = (areaWidth - gap2 * (shape.columns - 1)) / shape.columns, cards = hasCards && !region.bleed;
|
|
6833
|
+
let total = 0, index = 0;
|
|
6834
|
+
for (const count of shape.perRow) {
|
|
6835
|
+
let row = 0;
|
|
6836
|
+
for (let k = 0; k < count; k++) row = Math.max(row, naturalHeight(units[index++], cellWidth, cards));
|
|
6837
|
+
total += row;
|
|
6838
|
+
}
|
|
6839
|
+
return total + gap2 * Math.max(0, shape.rows - 1);
|
|
6840
|
+
};
|
|
6841
|
+
const areaNeed = (name, rect) => name === "title" ? groupHeight(headingItemsAt(titleFields, 0, 0, spanWidth(rect))) : name === "subtitle" ? groupHeight(headingItemsAt(subtitleFields, 0, 0, spanWidth(rect))) : regionNeed(name, spanWidth(rect));
|
|
6842
|
+
const demands = rowSizes.map((size, row) => {
|
|
6843
|
+
let need = 0, heading = false, below = false;
|
|
6844
|
+
for (const [name, rect] of rects) {
|
|
6845
|
+
if (size === "auto" ? rect.row !== row || rect.rowSpan !== 1 : row < rect.row || row >= rect.row + rect.rowSpan) continue;
|
|
6846
|
+
if (size !== "auto" && rect.rowSpan > 1 && rowSizes.slice(rect.row, rect.row + rect.rowSpan).some((entry) => entry === "auto")) continue;
|
|
6847
|
+
const value = areaNeed(name, rect) / rect.rowSpan;
|
|
6848
|
+
if (value > need) {
|
|
6849
|
+
need = value;
|
|
6850
|
+
heading = name === "title" || name === "subtitle";
|
|
6851
|
+
below = name === BELOW;
|
|
5959
6852
|
}
|
|
5960
|
-
const textValue = contentText(node.field, node.value);
|
|
5961
|
-
const quoteLayout = node.field === "quote" ? measureQuote(node, box, settings) : void 0;
|
|
5962
|
-
const codeLayout = node.field === "code" ? measureCode(node, box, settings) : void 0;
|
|
5963
|
-
const metricLayout = node.field === "metric" ? measureMetric(node, box, settings) : void 0;
|
|
5964
|
-
const timelineLayout = node.field === "timeline" ? measureTimeline(node, box, settings) : void 0;
|
|
5965
|
-
const internal = quoteLayout ?? codeLayout ?? metricLayout ?? timelineLayout, body = internal?.parts.find((part) => part.role === "body" || part.role === "value");
|
|
5966
|
-
const text2 = internal ? body?.fit : textValue !== void 0 ? fitContent(node.field, node.value, textValue, box, 25 * scale, snapFontSizeUp((settings.minFontSize ?? 16) * scale), node.path, node.payload.numbering) : void 0;
|
|
5967
|
-
const image = node.field === "image" ? composeImage(node.host ?? {}, node.hostPath ?? node.path, box, box, imageContext()) : void 0;
|
|
5968
|
-
items.push({
|
|
5969
|
-
path: node.path,
|
|
5970
|
-
field: node.field,
|
|
5971
|
-
type: node.type,
|
|
5972
|
-
value: node.value,
|
|
5973
|
-
payload: node.payload,
|
|
5974
|
-
box: internal ? acceptedBox(box) : box,
|
|
5975
|
-
...image ? { image } : {},
|
|
5976
|
-
...frameBox ? { frameBox } : {},
|
|
5977
|
-
text: text2,
|
|
5978
|
-
textStyle: body?.style ?? styleFor(node.field, node.path),
|
|
5979
|
-
composition: settings,
|
|
5980
|
-
alignment: alignmentFor(node.field),
|
|
5981
|
-
...quoteLayout ? { quoteLayout } : {},
|
|
5982
|
-
...codeLayout ? { codeLayout } : {},
|
|
5983
|
-
...metricLayout ? { metricLayout } : {},
|
|
5984
|
-
...timelineLayout ? { timelineLayout } : {},
|
|
5985
|
-
...bulletImage && node.payload.numbering === void 0 && (node.field === "items" || node.field === "bullets") ? { bulletImage } : {},
|
|
5986
|
-
...caption ? { caption } : {}
|
|
5987
|
-
});
|
|
5988
|
-
if (box.width < 100 * scale || box.height < 60 * scale) diagnostics.push({ code: "small-cell", path: node.path, message: "Content cell is too small for comfortable reading; use fewer blocks or a different composition." });
|
|
5989
6853
|
}
|
|
6854
|
+
return { size, need, kind: heading ? "heading" : below ? "below" : "body" };
|
|
5990
6855
|
});
|
|
6856
|
+
const heights = allocateRows(demands, frame.height, gap2);
|
|
6857
|
+
const rowY = [];
|
|
6858
|
+
heights.reduce((y2, size, row) => {
|
|
6859
|
+
rowY.push(size > 0 || !heights.slice(0, row).some((above) => above > 0) ? y2 : y2 - gap2);
|
|
6860
|
+
return size > 0 ? y2 + size + gap2 : y2;
|
|
6861
|
+
}, 0);
|
|
6862
|
+
const logical = (rect) => {
|
|
6863
|
+
const last = rect.row + rect.rowSpan - 1, y2 = frame.y + rowY[rect.row];
|
|
6864
|
+
return { x: frame.x + columnX[rect.column], y: y2, width: spanWidth(rect), height: Math.max(0, frame.y + rowY[last] + heights[last] - y2) };
|
|
6865
|
+
};
|
|
6866
|
+
const flip = hints.mirror === true !== rtl;
|
|
6867
|
+
const physical = (cell) => flip ? { ...cell, x: frame.x + frame.width - (cell.x - frame.x) - cell.width } : cell;
|
|
6868
|
+
const bleed = (cell) => {
|
|
6869
|
+
const near = (a, b) => Math.abs(a - b) < 0.01;
|
|
6870
|
+
const left = near(cell.x, frame.x) ? area.left : cell.x, top = near(cell.y, frame.y) ? area.top : cell.y;
|
|
6871
|
+
const right = near(cell.x + cell.width, frame.x + frame.width) ? area.right : cell.x + cell.width;
|
|
6872
|
+
const bottom = near(cell.y + cell.height, frame.y + frame.height) ? area.bottom : cell.y + cell.height;
|
|
6873
|
+
return { x: left, y: top, width: right - left, height: bottom - top };
|
|
6874
|
+
};
|
|
6875
|
+
const placeHeadings = (name, fields2) => {
|
|
6876
|
+
const rect = rects.get(name), original = ownRects.get(name);
|
|
6877
|
+
if (!rect) {
|
|
6878
|
+
if (original) headingAreas.push({ name, box: roundBox(physical(logical(original))), collapsed: true });
|
|
6879
|
+
return;
|
|
6880
|
+
}
|
|
6881
|
+
const cell = physical(logical(rect));
|
|
6882
|
+
const list = headingItemsAt(fields2, cell.x, cell.y, cell.width);
|
|
6883
|
+
const centred = !rowSizes.slice(rect.row, rect.row + rect.rowSpan).every((size) => size === "auto");
|
|
6884
|
+
const shift = centred ? Math.max(0, (cell.height - groupHeight(list)) / 2) : 0;
|
|
6885
|
+
for (const item of list) {
|
|
6886
|
+
if (shift) {
|
|
6887
|
+
item.box.y += shift;
|
|
6888
|
+
if (item.text) item.text = translateTextFit(item.text, shift);
|
|
6889
|
+
}
|
|
6890
|
+
if (furniture && item.box.y + item.box.height > bodyBottom + 0.01) diagnostics.push({ code: "text-overflow", path: item.path, message: "Repeated furniture leaves too little room for this heading. Change the header/footer or slide design." });
|
|
6891
|
+
items.push(item);
|
|
6892
|
+
}
|
|
6893
|
+
let parts;
|
|
6894
|
+
const upper = list.filter((item) => item.field !== "subtitle"), lower = list.find((item) => item.field === "subtitle");
|
|
6895
|
+
if (name === "title" && !plan2.subtitle && list.length) {
|
|
6896
|
+
const bottom = cell.y + cell.height, last = upper.at(-1);
|
|
6897
|
+
const split = Math.min(bottom, lower ? lower.box.y : last.box.y + last.box.height + gap2 * 0.5);
|
|
6898
|
+
const titleBottom = Math.max(cell.y, last ? last.box.y + last.box.height : split - gap2 * 0.5);
|
|
6899
|
+
parts = { title: roundBox({ x: cell.x, y: cell.y, width: cell.width, height: titleBottom - cell.y }), subtitle: roundBox({ x: cell.x, y: split, width: cell.width, height: Math.max(0, bottom - split) }) };
|
|
6900
|
+
}
|
|
6901
|
+
headingAreas.push({ name, box: roundBox(cell), ...name === "title" && implicitTitle ? { implicit: true } : {}, ...parts ? { parts } : {} });
|
|
6902
|
+
};
|
|
6903
|
+
placeHeadings("title", titleFields);
|
|
6904
|
+
if (plan2.subtitle) placeHeadings("subtitle", subtitleFields);
|
|
6905
|
+
const slideComposition = record8(slide.composition);
|
|
6906
|
+
const overridden = ["mode", "columns", "weights"].some((key) => slideComposition[key] !== void 0) ? plan2.regions.find((region) => region.role === "primary" && region.flow !== "none")?.name : void 0;
|
|
6907
|
+
const settings = { ...composition };
|
|
6908
|
+
const placeRegion = (region, units, area2) => {
|
|
6909
|
+
regionTag = region.name === BELOW ? void 0 : region.name;
|
|
6910
|
+
const cell = { ...area2, width: Math.max(scale, area2.width), height: Math.max(scale, area2.height) };
|
|
6911
|
+
templateCell = true;
|
|
6912
|
+
try {
|
|
6913
|
+
const cards = hasCards && !region.bleed;
|
|
6914
|
+
if (region.name === overridden) {
|
|
6915
|
+
arrange(units, cell, { ...settings, mode: slideComposition.mode ?? "auto" }, 0, gap2, path, true);
|
|
6916
|
+
return "composition";
|
|
6917
|
+
}
|
|
6918
|
+
const arrangement = arrangementOf(region, units, cell);
|
|
6919
|
+
let boxes = flowCells(flowShape(arrangement, units.length, cell.width >= cell.height), cell, gap2).cells;
|
|
6920
|
+
const referenceHeights = boxes.map((box) => box.height);
|
|
6921
|
+
if (arrangement === "column" && region.anchor !== "top" && units.every((unit) => !unit.children && (unit.field === "text" || unit.field === "items" || unit.field === "bullets" || !unit.caption && (unit.field === "quote" || unit.field === "metric")))) {
|
|
6922
|
+
const naturals = units.map((unit, index) => naturalHeight(unit, cell.width, cards, referenceHeights[index], settings) + 2 * rasterPadding + scale);
|
|
6923
|
+
const used = naturals.reduce((a, b) => a + b, 0) + gap2 * (units.length - 1);
|
|
6924
|
+
if (used < cell.height) {
|
|
6925
|
+
let y2 = cell.y + (region.anchor === "middle" ? (cell.height - used) / 2 : cell.height - used);
|
|
6926
|
+
boxes = naturals.map((size) => {
|
|
6927
|
+
const next = { x: cell.x, y: y2, width: cell.width, height: size };
|
|
6928
|
+
y2 += size + gap2;
|
|
6929
|
+
return next;
|
|
6930
|
+
});
|
|
6931
|
+
}
|
|
6932
|
+
}
|
|
6933
|
+
if ((arrangement === "grid" || arrangement === "row") && region.anchor !== "top") {
|
|
6934
|
+
const naturals = boxes.map((box, index) => {
|
|
6935
|
+
const unit = units[index];
|
|
6936
|
+
return unit.children || unit.caption || !["text", "items", "bullets", "quote", "metric"].includes(unit.field) ? void 0 : naturalHeight(unit, box.width, cards, referenceHeights[index], settings) + 2 * rasterPadding + scale;
|
|
6937
|
+
});
|
|
6938
|
+
boxes = boxes.map((box, index) => {
|
|
6939
|
+
const height2 = naturals[index];
|
|
6940
|
+
if (height2 === void 0 || height2 >= box.height) return box;
|
|
6941
|
+
const rowHeight = Math.max(...boxes.flatMap((peer, peerIndex) => peer.y === box.y && naturals[peerIndex] !== void 0 ? [naturals[peerIndex]] : []));
|
|
6942
|
+
const spare = Math.max(0, box.height - rowHeight);
|
|
6943
|
+
return { ...box, y: box.y + (region.anchor === "middle" ? spare / 2 : spare), height: height2 };
|
|
6944
|
+
});
|
|
6945
|
+
}
|
|
6946
|
+
if (rtl) boxes = boxes.map((box) => ({ ...box, x: cell.x + cell.width - (box.x - cell.x) - box.width }));
|
|
6947
|
+
units.forEach((unit, index) => {
|
|
6948
|
+
placeNode(unit, boxes[index], settings, cards, region.listColumns, region.anchor === "top" ? void 0 : referenceHeights[index]);
|
|
6949
|
+
});
|
|
6950
|
+
return arrangement;
|
|
6951
|
+
} finally {
|
|
6952
|
+
regionTag = void 0;
|
|
6953
|
+
templateCell = false;
|
|
6954
|
+
}
|
|
6955
|
+
};
|
|
6956
|
+
for (const region of plan2.regions) {
|
|
6957
|
+
const units = unitsOf(region.name), bound = binding.regions.find((entry) => entry.name === region.name);
|
|
6958
|
+
const rect = rects.get(region.name);
|
|
6959
|
+
let cell = physical(logical(rect ?? ownRects.get(region.name)));
|
|
6960
|
+
const areaBox = region.bleed && rect ? roundBox(cell) : void 0;
|
|
6961
|
+
if (region.bleed && rect) cell = bleed(cell);
|
|
6962
|
+
const arrangement = units.length && rect ? placeRegion(region, units, cell) : void 0;
|
|
6963
|
+
templateRegions.push({
|
|
6964
|
+
name: region.name,
|
|
6965
|
+
box: roundBox(cell),
|
|
6966
|
+
accepts: [...region.accepts],
|
|
6967
|
+
role: region.role,
|
|
6968
|
+
flow: region.flow,
|
|
6969
|
+
max: region.max,
|
|
6970
|
+
anchor: region.anchor,
|
|
6971
|
+
...arrangement ? { arrangement } : {},
|
|
6972
|
+
content: bound.blocks.map((block) => block.path),
|
|
6973
|
+
...bound.overflow.length ? { overflow: bound.overflow.map((block) => block.path) } : {},
|
|
6974
|
+
...collapsed.joined.has(region.name) ? { collapsed: true } : {},
|
|
6975
|
+
...region.bleed ? { bleed: true } : {},
|
|
6976
|
+
...areaBox ? { areaBox } : {}
|
|
6977
|
+
});
|
|
6978
|
+
}
|
|
6979
|
+
if (belowUnits.length) placeRegion(belowRegion, belowUnits, physical(logical(rects.get(BELOW))));
|
|
5991
6980
|
};
|
|
5992
|
-
const
|
|
5993
|
-
const placedSlots = new Set(placed.flatMap((entry) => imagePlaceholders[entry.slot] ? [imagePlaceholders[entry.slot].placeholder] : []));
|
|
5994
|
-
if (placedSlots.size) {
|
|
5995
|
-
for (let index = placeholders.length - 1; index >= 0; index--) if (placedSlots.has(placeholders[index])) placeholders.splice(index, 1);
|
|
5996
|
-
}
|
|
5997
|
-
const ownMode = record6(slide.composition).mode;
|
|
6981
|
+
const ownMode = record8(slide.composition).mode;
|
|
5998
6982
|
const direction = hints.contentDirection;
|
|
5999
6983
|
const directionMode = direction === "vertical" ? "column" : direction === "horizontal" ? "row" : "auto";
|
|
6000
6984
|
const chartHint = hints.chartPrimary;
|
|
6001
6985
|
const chartSide = chartHint === "left" || chartHint === "right" || chartHint === "top" || chartHint === "bottom" ? chartHint : void 0;
|
|
6002
6986
|
const chartIndex = pending.findIndex((node) => !node.children && node.field === "chart");
|
|
6003
|
-
const chartPrimary = chartSide !== void 0 && !ownMode && !regions.length && chartIndex >= 0 && pending.some((node) => node.children || node.field !== "chart") ? chartSide : void 0;
|
|
6004
|
-
const
|
|
6005
|
-
const
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
const templated = !sugar && !regions.length && recordSlots.some((slot) => slot.children) && pending.every((node) => !node.children);
|
|
6009
|
-
const fillSlots = (entries, queue, cursor, recordSlot) => {
|
|
6010
|
-
const nodes = [];
|
|
6011
|
-
for (const entry of entries) {
|
|
6012
|
-
if (cursor.next >= queue.length) break;
|
|
6013
|
-
if (!entry.children) {
|
|
6014
|
-
nodes.push({ ...queue[cursor.next++], ...recordSlot ? { slot: entry } : {} });
|
|
6015
|
-
continue;
|
|
6016
|
-
}
|
|
6017
|
-
const own2 = record6(entry.placeholder.composition);
|
|
6018
|
-
assertComposition(own2);
|
|
6019
|
-
const children = fillSlots(entry.children, queue, cursor, recordSlot);
|
|
6020
|
-
nodes.push({
|
|
6021
|
-
field: "blocks",
|
|
6022
|
-
type: "group",
|
|
6023
|
-
value: children.map((child) => child.payload),
|
|
6024
|
-
path,
|
|
6025
|
-
payload: {},
|
|
6026
|
-
children,
|
|
6027
|
-
composition: own2,
|
|
6028
|
-
synthetic: true,
|
|
6029
|
-
reserved: own2.mode ? 0 : entry.children.length,
|
|
6030
|
-
...recordSlot ? { slot: entry, slots: entry.children } : {}
|
|
6031
|
-
});
|
|
6032
|
-
}
|
|
6033
|
-
return nodes;
|
|
6034
|
-
};
|
|
6035
|
-
if (sugar) {
|
|
6987
|
+
const chartPrimary = chartSide !== void 0 && !useTemplate && !ownMode && !regions.length && chartIndex >= 0 && pending.some((node) => node.children || node.field !== "chart") ? chartSide : void 0;
|
|
6988
|
+
const firstChart = chartPrimary === "left" || chartPrimary === "top";
|
|
6989
|
+
const rootSettings = chartPrimary ? { ...composition, mode: chartPrimary === "left" || chartPrimary === "right" ? "row" : "column", weights: firstChart ? [3, 2] : [2, 3], columns: void 0 } : { ...composition, mode: composition.mode ?? directionMode };
|
|
6990
|
+
if (useTemplate) composeTemplate();
|
|
6991
|
+
else if (chartPrimary) {
|
|
6036
6992
|
const primary = pending[chartIndex], rest = pending.filter((_, index) => index !== chartIndex);
|
|
6037
|
-
const
|
|
6038
|
-
arrange(
|
|
6039
|
-
} else
|
|
6040
|
-
const cursor = { next: 0 };
|
|
6041
|
-
const nodes = fillSlots(recordSlots, pending, cursor, true);
|
|
6042
|
-
arrange([...nodes, ...pending.slice(cursor.next)], contentBox, rootSettings, composition.mode ? 0 : placeholders.length, void 0, path, true, recordSlots);
|
|
6043
|
-
const order = /* @__PURE__ */ new Map();
|
|
6044
|
-
const number = (entries) => entries.forEach((entry) => {
|
|
6045
|
-
order.set(entry.path, order.size);
|
|
6046
|
-
if (entry.children) number(entry.children);
|
|
6047
|
-
});
|
|
6048
|
-
number(recordSlots);
|
|
6049
|
-
slots.sort((a, b) => order.get(a.path) - order.get(b.path));
|
|
6050
|
-
} else arrange(pending, contentBox, rootSettings, composition.mode ? 0 : placeholders.length);
|
|
6993
|
+
const support = { field: "blocks", type: "group", value: rest.map((node) => node.payload), path, payload: {}, children: rest, composition: {}, synthetic: true };
|
|
6994
|
+
arrange(firstChart ? [primary, support] : [support, primary], contentBox, rootSettings, 0);
|
|
6995
|
+
} else arrange(pending, contentBox, rootSettings, 0);
|
|
6051
6996
|
if (listBullet?.value === "image" && !bulletImage && items.some((item) => (item.field === "items" || item.field === "bullets") && item.payload.numbering === void 0)) {
|
|
6052
6997
|
diagnostics.push({ code: "unresolved-content", path: listBullet.path, message: "Picture bullets (listBullet: image) need an organization logo (the primary organization, or the one design.logo names); the marker glyph is drawn instead." });
|
|
6053
6998
|
}
|
|
@@ -6087,8 +7032,7 @@ function composeSlide(input, options = {}) {
|
|
|
6087
7032
|
} : void 0;
|
|
6088
7033
|
if (failures.length) throw new OPFCompositionError(failures, explanation);
|
|
6089
7034
|
diagnostics.push(...imageDiagnostics, ...numberingDiagnostics);
|
|
6090
|
-
|
|
6091
|
-
return { width, height, contentBox, items, groups, flows, ...slots.length ? { slots } : {}, diagnostics, composition, design: hints, ...furniture ? { furniture } : {}, ...backgroundImage ? { backgroundImage } : {}, ...logo ? { logo } : {}, ...rtl ? { direction: "rtl" } : {}, ...footnotes ? { footnotes } : {}, ...explanation ? { explanation } : {} };
|
|
7035
|
+
return { width, height, contentBox, items, groups, flows, ...useTemplate ? { regions: templateRegions, headingAreas } : {}, diagnostics, composition, design: hints, ...furniture ? { furniture } : {}, ...backgroundImage ? { backgroundImage } : {}, ...logo ? { logo } : {}, ...rtl ? { direction: "rtl" } : {}, ...footnotes ? { footnotes } : {}, ...explanation ? { explanation } : {} };
|
|
6092
7036
|
}
|
|
6093
7037
|
function resolveCanvasDimensions(input) {
|
|
6094
7038
|
const presets = {
|
|
@@ -6103,7 +7047,7 @@ function resolveCanvasDimensions(input) {
|
|
|
6103
7047
|
letter: [11, 8.5],
|
|
6104
7048
|
a4: [11.69, 8.27]
|
|
6105
7049
|
};
|
|
6106
|
-
const value =
|
|
7050
|
+
const value = record8(input);
|
|
6107
7051
|
const preset = presets[typeof input === "string" ? input : value.preset] ?? presets.widescreen;
|
|
6108
7052
|
const width = (value.widthInches ?? preset[0]) * 96;
|
|
6109
7053
|
const height = (value.heightInches ?? preset[1]) * 96;
|
|
@@ -6111,4 +7055,4 @@ function resolveCanvasDimensions(input) {
|
|
|
6111
7055
|
return { width, height };
|
|
6112
7056
|
}
|
|
6113
7057
|
|
|
6114
|
-
export { CAPTIONABLE_FIELDS, CAPTION_FONT_RATIO, CAPTION_MAX_RATIO, CHART_HIGHLIGHT_MUTED_MIN_CONTRAST, CHART_HIGHLIGHT_MUTED_MIX, CHART_SERIES_MIN_DIFFERENCE, CHART_SERIES_MIN_LIGHTNESS_STEP, CHART_TYPES, CITATION_MARKER_RAISE, CITATION_MARKER_SCALE, CODE_HIGHLIGHT_LANGUAGES, CODE_HIGHLIGHT_MAX_LENGTH, CODE_PANEL_BACKGROUND, CODE_PANEL_FOREGROUND, CODE_SYNTAX_MIN_CONTRAST, DARK_BACKGROUND_LUMINANCE, DEFAULT_CHART_LABEL_SEPARATOR, DEFAULT_FURNITURE_DATE_FORMAT, DEFAULT_VARIABLE_DATE_FORMAT, DESIGN_HINT_KEYS, ENGINE_DEFAULT_CHART_TYPES, ENGINE_DEFAULT_COLOR_SCHEME, ENGINE_DEFAULT_FONT_SCHEME, ENGINE_DEFAULT_THEME, FONT_SIZE_GRID_PER_PX, FOOTNOTE_MAX_RATIO, FURNITURE_GAP, FURNITURE_IMAGE_SHARE, LANGUAGES, LAYOUT_BODY_KINDS, LOGO_SHAPES, MAX_COMPOSITION_DEPTH, MAX_NUMBERING_LEVELS, MAX_NUMBERING_VALUE,
|
|
7058
|
+
export { AUTO_LAYOUT, CAPTIONABLE_FIELDS, CAPTION_FONT_RATIO, CAPTION_MAX_RATIO, CATALOG_GROUP_PATTERN, CATALOG_REFERENCE_PATTERN, CHART_HIGHLIGHT_MUTED_MIN_CONTRAST, CHART_HIGHLIGHT_MUTED_MIX, CHART_SERIES_MIN_DIFFERENCE, CHART_SERIES_MIN_LIGHTNESS_STEP, CHART_TYPES, CITATION_MARKER_RAISE, CITATION_MARKER_SCALE, CODE_HIGHLIGHT_LANGUAGES, CODE_HIGHLIGHT_MAX_LENGTH, CODE_PANEL_BACKGROUND, CODE_PANEL_FOREGROUND, CODE_SYNTAX_MIN_CONTRAST, DARK_BACKGROUND_LUMINANCE, DEFAULT_CHART_LABEL_SEPARATOR, DEFAULT_FURNITURE_DATE_FORMAT, DEFAULT_VARIABLE_DATE_FORMAT, DESIGN_HINT_KEYS, ENGINE_DEFAULT_CHART_TYPES, ENGINE_DEFAULT_COLOR_SCHEME, ENGINE_DEFAULT_FONT_SCHEME, ENGINE_DEFAULT_THEME, FONT_SIZE_GRID_PER_PX, FOOTNOTE_MAX_RATIO, FURNITURE_GAP, FURNITURE_IMAGE_SHARE, HEADING_AREAS, LANGUAGES, LAYOUT_BODY_KINDS, LOGO_SHAPES, MAX_COMPOSITION_DEPTH, MAX_NUMBERING_LEVELS, MAX_NUMBERING_VALUE, MAX_REGION_BLOCKS, MAX_ROMAN_VALUE, MAX_TEMPLATE_TRACKS, METRIC_TREND_MIN_CONTRAST, METRIC_TREND_SHAPES, NUMBERING_STYLES, NUMBERING_SUFFIXES, OPFCatalogsOptionError, OPFCompositionError, OPFLayoutTemplateError, OPFUnresolvedReferenceError, OPFVariableError, PATTERN_PRESETS, PATTERN_PRESET_ALIASES, PATTERN_TILE_SIZE, PICTURE_BULLET_SCALE, PROMOTED_REGION_KEY, REGION_ANCHORS, REGION_FLOWS, REGION_KINDS, REGION_ROLES, RESERVED_REGION_NAMES, SLIDE_SCOPED_BUILTINS, SOCIAL_PLATFORMS, SURFACE_ALT_MIN_CONTRAST, SURFACE_ALT_MIX, THEME_DESIGN_KEYS, TIMELINE_OUTLINE_MIN_CONTRAST, TIMELINE_STATUSES, TIMELINE_TEXT_MIN_CONTRAST, VARIABLE_KINDS, allocateRows, annotationText, bindRegions, blockKind, captionSettings, catalogGroupDeclared, catalogGroupSource, catalogKinds, catalogRecords, catalogReferenceSites, chartColorForFill, chartHighlightColors, chartHighlightMarks, chartLabelText, chartNumber, chartNumberFixesByCell, chartOptionSupport, chartOptionTarget, chartPaletteForFill, checkCatalogsOption, citationMarkerText, codeHighlightBands, codeHighlightColors, codeHighlightLines, codeHighlightSlice, codeLineNumbers, codeLineRuns, codeSyntaxPalette, codeSyntaxPaletteForScheme, coerceVariableValue, collectCitations, colorContrast, composeLayoutAreas, composeSlide, datasetDiagnostics, defaultSlideBackground, dottedPath, embeddedCopy, fitImage, fitList, fitRichText, fitText, formatChartLabelNumber, formatChartLabelPercent, formatDataNumber, formatFurnitureDate, formatListNumber, formatVariableNumber, fromExcelNumberFormat, gridFlowShape, hasContentVariables, imageBackground, imageShape, inlineChartData, inlineDatasets, inlineTableData, instantiateForValidation, intrinsicImageAspect, intrinsicImageSize, isDarkColor, isDatasetRef, isLayoutTemplate, isRecord, isTemplate, isXYChartType, layoutCaption, layoutCode, layoutContent, layoutFootnotes, layoutFurniture, layoutMetric, layoutQuote, layoutRegion, layoutStructure, layoutTable, layoutTemplate, layoutTemplateIssues, layoutTimeline, layoutWatermark, listBuiltinVariables, listColumnBreaks, listNumbers, listVariables, measureText, measureTextOutline, metricTrendColor, metricTrendMark, metricTrendPoints, normalizeHexColor, normalizeLanguageFamily, numberFormatError, numberingAtLevel, numberingFindings, numberingStyleDraws, paragraphDirection, paragraphDirectionAt, parseReference, pathFor, patternBitmap, patternRuns, physicalAlignment, placeTextLines, placedImageBlocks, pointerPath, promotedRegionKeys, provenanceOf, readingRows, recordReferenceSites, referencesSlide, regionAccepts, regionRoleRank, registeredCatalog, resolveCanvasDimensions, resolveChartData, resolveChartOptions, resolveCodeLanguage, resolveColorRef, resolveColorRoles, resolveDesignHints, resolveDesignRecords, resolveFontFamilies, resolveFontScheme, resolveLogo, resolveNumbering, resolvePatternPreset, resolveReference, resolveScriptFonts, resolveSlideDirection, resolveSlideVariables, resolveSocialProfile, resolveTableData, resolveTextStyle, resolveVariables, rootNodes, scriptFontRole, sliceNumberedItems, slideCitations, slideTokenSpans, snapFontSizeDown, snapFontSizeUp, suggestChartNumberFix, surfaceAltColor, tableCellDisplayValue, tableGrid, tableRowBoundaries, textColorForFill, textWidthMeasurer, timelineMarkerShapes, timelineTextColor, toExcelNumberFormat, tokenizeCode, unresolvedReference, unusedDatasets, usesSlideBuiltin, variableDeclarations, visitContentPayloads, visualReadingOrder, walkCitationRuns, wrapText };
|