@openpresentation/opf 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -2
- package/dist/{catalog-refs-_anZs-Qz.d.ts → catalog-refs-C4K4y-vh.d.ts} +1 -1
- package/dist/{catalog-schemas-BZCjgAxu.d.ts → catalog-schemas-g7RFQBdc.d.ts} +1 -1
- package/dist/catalog.d.ts +2 -2
- package/dist/catalog.js +3 -23712
- package/dist/{chart-data-BnNqgnC-.d.ts → chart-data-DTxdRRT1.d.ts} +1 -1
- package/dist/{chunk-FQSIIADJ.js → chunk-BIC3SWPK.js} +4 -4
- package/dist/{chunk-5PDN7BN6.js → chunk-CW7GEAV3.js} +151 -49
- package/dist/{chunk-NAWQR7MN.js → chunk-ESRYBYLY.js} +1 -1
- package/dist/chunk-IPW5BS3X.js +973 -0
- package/dist/{chunk-5UEUAW57.js → chunk-IS5H5JKH.js} +1 -1
- package/dist/{chunk-UM24JFUE.js → chunk-M4UR3NPN.js} +2 -2
- package/dist/{chunk-KINQFU6X.js → chunk-N4EVOFEA.js} +19 -12
- package/dist/{chunk-PX5AWL7Y.js → chunk-NLNYNBTS.js} +79 -10
- package/dist/{chunk-SMLMI6IZ.js → chunk-O263APNI.js} +1 -1
- package/dist/{chunk-BSYQDWT4.js → chunk-O2CX5NEH.js} +26 -14
- package/dist/{chunk-3XDRQYWZ.js → chunk-O3CVNJTL.js} +1 -1
- package/dist/{chunk-5TO6I3GB.js → chunk-PPROJP2E.js} +1 -1
- package/dist/{chunk-WEDGVC5W.js → chunk-RA64UQKI.js} +18 -42
- package/dist/{chunk-K4DQQIT4.js → chunk-TCD2FB2K.js} +5 -5
- package/dist/chunk-WCG3THTD.js +23712 -0
- package/dist/chunk-WWYWFVOI.js +793 -0
- package/dist/{chunk-6OR326EA.js → chunk-YT7FMQER.js} +1 -1
- package/dist/{composition-D4ADF5c-.d.ts → composition-BbZ_9C-c.d.ts} +152 -132
- package/dist/composition.d.ts +3 -3
- package/dist/composition.js +1 -1
- package/dist/conversion-SBpTOwdg.d.ts +444 -0
- package/dist/convert.d.ts +4 -4
- package/dist/convert.js +7 -7
- package/dist/data.d.ts +2 -2
- package/dist/data.js +2 -2
- package/dist/deck-report-Bx3naFlF.d.ts +40 -0
- package/dist/deck.d.ts +23 -53
- package/dist/deck.js +10 -10
- package/dist/diff.d.ts +1 -1
- package/dist/diff.js +5 -5
- package/dist/docs.js +29 -23
- package/dist/examples.d.ts +1 -1
- package/dist/examples.js +237 -237
- package/dist/{finding-CT_f_vbD.d.ts → finding-CDQ_wH8j.d.ts} +1 -1
- package/dist/format.js +2 -2
- package/dist/index.d.ts +42 -12
- package/dist/index.js +15 -807
- package/dist/markdown.d.ts +6 -6
- package/dist/markdown.js +7 -7
- package/dist/node-engine.d.ts +94 -0
- package/dist/node-engine.js +21 -0
- package/dist/node.d.ts +60 -0
- package/dist/node.js +54 -0
- package/dist/{pagination-DzZPFheM.d.ts → pagination-BhX4M48Y.d.ts} +21 -7
- package/dist/pagination.d.ts +4 -4
- package/dist/pagination.js +4 -4
- package/dist/patch.d.ts +1 -1
- package/dist/patch.js +4 -4
- package/dist/{presentation-COrFuj2g.d.ts → presentation-fb8CZmRq.d.ts} +12 -75
- package/dist/repo-readme.js +1 -1
- package/dist/schemas.js +1 -1
- package/dist/spec/catalogs/manifest.json +1 -1
- package/dist/spec/schemas/opf.schema.json +16 -37
- package/dist/types.d.ts +3 -3
- package/dist/{validation-types-HxIgJfKx.d.ts → validation-types-iZbXfES6.d.ts} +19 -8
- package/dist/validator.d.ts +8 -8
- package/dist/validator.js +3 -3
- package/dist/yaml.d.ts +6 -6
- package/dist/yaml.js +7 -7
- package/package.json +34 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { jsonEqual, formatPointer } from './chunk-
|
|
2
|
-
import { annotationText } from './chunk-
|
|
1
|
+
import { jsonEqual, formatPointer } from './chunk-O3CVNJTL.js';
|
|
2
|
+
import { annotationText } from './chunk-CW7GEAV3.js';
|
|
3
3
|
|
|
4
4
|
// src/diff-match.ts
|
|
5
5
|
var DEFAULT_MATCH_THRESHOLD = 0.5;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { fromMarkdown, toMarkdown } from './chunk-
|
|
2
|
-
import { fromYaml, toYaml } from './chunk-
|
|
3
|
-
import { NOT_CHECKED } from './chunk-
|
|
4
|
-
import { parseSource, validate } from './chunk-
|
|
1
|
+
import { fromMarkdown, toMarkdown } from './chunk-BIC3SWPK.js';
|
|
2
|
+
import { fromYaml, toYaml } from './chunk-TCD2FB2K.js';
|
|
3
|
+
import { NOT_CHECKED } from './chunk-IS5H5JKH.js';
|
|
4
|
+
import { parseSource, validate, OPFValidationError } from './chunk-NLNYNBTS.js';
|
|
5
5
|
import { checkCatalogsOption } from './chunk-SPFV27O5.js';
|
|
6
6
|
|
|
7
|
-
// src/deck.ts
|
|
7
|
+
// src/deck-report.ts
|
|
8
8
|
var DECK_FORMATS = ["json", "yaml", "markdown"];
|
|
9
9
|
function deckFormatOf(filename) {
|
|
10
10
|
if (filename === void 0) return "json";
|
|
@@ -17,10 +17,10 @@ function resolveFormat(caller, options) {
|
|
|
17
17
|
if (!DECK_FORMATS.includes(options.format)) throw new TypeError(`${caller}: unknown format ${JSON.stringify(options.format)}. Formats: ${DECK_FORMATS.join(", ")}.`);
|
|
18
18
|
return options.format;
|
|
19
19
|
}
|
|
20
|
-
function
|
|
21
|
-
if (typeof text !== "string") throw new TypeError(
|
|
22
|
-
checkCatalogsOption(options.catalogs,
|
|
23
|
-
const format = resolveFormat(
|
|
20
|
+
function readDeckReport(text, options = {}, caller = "parse") {
|
|
21
|
+
if (typeof text !== "string") throw new TypeError(`${caller} expects a string.`);
|
|
22
|
+
checkCatalogsOption(options.catalogs, caller);
|
|
23
|
+
const format = resolveFormat(caller, options);
|
|
24
24
|
const { catalogs } = options;
|
|
25
25
|
const check = options.validate ?? true;
|
|
26
26
|
const validateOptions = typeof check === "object" ? { ...catalogs && check.catalogs === void 0 ? { catalogs } : {}, ...check } : { only: ["format", "references"], ...catalogs ? { catalogs } : {} };
|
|
@@ -40,12 +40,19 @@ function report(findings) {
|
|
|
40
40
|
for (const found of findings) counts[found.severity]++;
|
|
41
41
|
return { valid: counts.error === 0, schemaValid: null, findings, counts, checks: NOT_CHECKED };
|
|
42
42
|
}
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
|
|
44
|
+
// src/deck.ts
|
|
45
|
+
function parse(text, options = {}) {
|
|
46
|
+
const { presentation, format: _format, ...result } = readDeckReport(text, { ...options, validate: true }, "parse");
|
|
47
|
+
if (!result.valid) throw new OPFValidationError(result);
|
|
48
|
+
return presentation;
|
|
49
|
+
}
|
|
50
|
+
function stringify(presentation, options = {}) {
|
|
51
|
+
const format = resolveFormat("stringify", options);
|
|
45
52
|
if (format === "yaml") return toYaml(presentation, { schemaComment: options.schemaComment === true }).yaml;
|
|
46
53
|
if (format === "markdown") return toMarkdown(presentation).markdown;
|
|
47
54
|
return `${JSON.stringify(presentation, null, 2)}
|
|
48
55
|
`;
|
|
49
56
|
}
|
|
50
57
|
|
|
51
|
-
export { DECK_FORMATS, deckFormatOf,
|
|
58
|
+
export { DECK_FORMATS, deckFormatOf, parse, readDeckReport, stringify };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { promotedRegionKeys, VARIABLE_KINDS, resolveChartData, chartPaletteForFill, imageBackground, tableGrid, timelineTextColor, visitContentPayloads, readingRows, visualReadingOrder, intrinsicImageSize, textWidthMeasurer, normalizeHexColor, resolveColorRef, resolveDesignRecords,
|
|
1
|
+
import { promotedRegionKeys, VARIABLE_KINDS, resolveChartData, chartPaletteForFill, imageBackground, tableGrid, timelineTextColor, visitContentPayloads, readingRows, visualReadingOrder, intrinsicImageSize, textWidthMeasurer, normalizeHexColor, resolveColorRef, resolveDesignRecords, resolveFontFamilies, resolveColorRoles, resolveCanvasDimensions, resolveSlideVariables, defaultSlideBackground, isRecord, hasContentVariables, isTemplate, instantiateForValidation, resolveScriptFonts, unusedDatasets, MAX_COMPOSITION_DEPTH, datasetDiagnostics, pathFor, collectCitations, numberingFindings, walkCitationRuns, resolveTableData, resolveChartOptions, chartOptionTarget, codeHighlightLines, chartNumberFixesByCell, MAX_PLACEHOLDER_GROUP_DEPTH, OPFCompositionError, composeSlide } from './chunk-CW7GEAV3.js';
|
|
2
2
|
import { catalogSchemaNames } from './chunk-TRDXRRQK.js';
|
|
3
3
|
import { resolveReference, checkCatalogsOption, provenanceOf, unresolvedReference, OPFUnresolvedReferenceError, catalogReferenceSites, parseReference, catalogGroupDeclared, pointerPath, catalogRecords, catalogKinds, catalogGroupSource, registeredCatalog } from './chunk-SPFV27O5.js';
|
|
4
|
-
import { schemaEntries, schemas } from './chunk-
|
|
4
|
+
import { schemaEntries, schemas } from './chunk-RA64UQKI.js';
|
|
5
5
|
import Ajv2020 from 'ajv/dist/2020.js';
|
|
6
6
|
import addFormats from 'ajv-formats';
|
|
7
7
|
import { parseTree, printParseErrorCode, getNodePath } from 'jsonc-parser';
|
|
@@ -2421,7 +2421,7 @@ var formatRules = [
|
|
|
2421
2421
|
rule("chart-mapping-unknown-column", "format", "error", "A chart mapping names a column the data does not have.", "The series cannot be built from a column that is not there.", { standard: SCHEMA }),
|
|
2422
2422
|
rule("number-format-invalid", "format", "error", "A number format cannot be read.", "A format code that no engine can parse is drawn as the plain number or fails to export.", { standard: "Excel number format codes, as far as OPF supports them" }),
|
|
2423
2423
|
rule("variable-invalid-value", "format", "error", "A variable value does not match its declared type.", "A number variable given text, or a date given a non-date, cannot be filled into the deck.", { standard: SCHEMA }),
|
|
2424
|
-
rule("variable-unknown-builtin", "format", "error", "A token names a built-in variable that does not exist.", "The `deck.`, `speaker.` and `
|
|
2424
|
+
rule("variable-unknown-builtin", "format", "error", "A token names a built-in variable that does not exist.", "The `deck.`, `speaker.`, `organization.` and `slide.` names (and `speakers`) are reserved for built-in variables; a name under them that is not a built-in can never be filled, so the token would show literally. The slide-scoped `slide.number`, `slide.section` and `deck.slideCount` are inline tokens only, so `var:slide.*` and `var:deck.slideCount` are reported too.", { standard: SCHEMA }),
|
|
2425
2425
|
rule("chart-highlight-unknown-name", "format", "error", "A chart highlight names a series or category the chart does not have.", "`chart.highlight` emphasises marks by name; a name that matches no series or category in the chart data highlights nothing, so the chart is not drawn as authored.", { standard: SCHEMA }),
|
|
2426
2426
|
rule("variable-format", "format", "error", "A variable cannot be formatted.", "A number or date format that does not apply to the value leaves the token unreadable.", { standard: SCHEMA }),
|
|
2427
2427
|
rule(
|
|
@@ -2505,7 +2505,7 @@ var dataRules = [
|
|
|
2505
2505
|
rule("chart-highlight-adapted", "content", "warning", "A chart highlight is adapted by the chart type.", "A highlight the chart type cannot show as authored (a category highlight on a chart without categories, for example) is adapted by every engine, so the emphasis is not exactly what was written.", { standard: SCHEMA }),
|
|
2506
2506
|
rule("code-highlight-out-of-range", "content", "warning", "A code highlight marks a line the code does not have.", "Marked lines count from 1 by line break in code.source; an entry past the last line marks nothing.", { standard: SCHEMA }),
|
|
2507
2507
|
rule("code-highlight-range-reversed", "content", "warning", "A code highlight range ends before it starts.", "A range written end before start marks nothing; write the smaller line number first.", { standard: SCHEMA }),
|
|
2508
|
-
rule("variable-builtin-missing", "content", "warning", "A built-in variable has no value in this document.", "A `{{deck.*}}`, `{{speaker.*}}` or `{{organization.*}}` token whose field the document does not set resolves to nothing, so the text shows a gap.", { standard: SCHEMA }),
|
|
2508
|
+
rule("variable-builtin-missing", "content", "warning", "A built-in variable has no value in this document.", "A `{{deck.*}}`, `{{speaker.*}}` or `{{organization.*}}` token whose field the document does not set resolves to nothing, so the text shows a gap. `{{slide.section}}` is checked per slide: a slide without a `section` that uses it, in its own text or in the header or footer it inherits, is reported at that slide.", { standard: SCHEMA }),
|
|
2509
2509
|
rule("duration-outside-narrative", "content", "warning", "The target duration is outside the range the narrative suits.", "A narrative records the talk lengths it suits. A deck whose duration is outside that range probably needs a different narrative or a different length; nothing is drawn or exported differently.", { standard: SCHEMA }),
|
|
2510
2510
|
rule("narrative-duration-range", "content", "warning", "An inline narrative duration range has min greater than max.", "A range with its bounds swapped matches no duration, so the duration check cannot help.", { standard: "spec/schemas/narrative.schema.json" })
|
|
2511
2511
|
];
|
|
@@ -3245,6 +3245,67 @@ function parseSource(source) {
|
|
|
3245
3245
|
};
|
|
3246
3246
|
}
|
|
3247
3247
|
|
|
3248
|
+
// src/script-measurement.ts
|
|
3249
|
+
function scriptProfile(presentation, slideIndex, options, language) {
|
|
3250
|
+
let resolved;
|
|
3251
|
+
try {
|
|
3252
|
+
resolved = resolveScriptFonts(presentation, { slideIndex, ...options.catalogs !== void 0 ? { catalogs: options.catalogs } : {}, ...language === void 0 ? {} : { language } });
|
|
3253
|
+
} catch {
|
|
3254
|
+
resolved = void 0;
|
|
3255
|
+
}
|
|
3256
|
+
const slots = (role) => {
|
|
3257
|
+
const latin = options.fontFamilies[role];
|
|
3258
|
+
const slot = (key) => !resolved || resolved.sources[key] === "latin" || resolved.sources[key] === "schemeFamily" ? latin : resolved[role][key] ?? latin;
|
|
3259
|
+
return { latin, eastAsian: slot("eastAsian"), complexScript: slot("complexScript") };
|
|
3260
|
+
};
|
|
3261
|
+
return {
|
|
3262
|
+
heading: slots("heading"),
|
|
3263
|
+
body: slots("body"),
|
|
3264
|
+
...resolved?.supplement ? { supplement: resolved.supplement } : {},
|
|
3265
|
+
script: resolved?.script ?? "Zzzz",
|
|
3266
|
+
...resolved ? { scriptRole: resolved.scriptRole, bcp47: resolved.bcp47, lang: resolved.lang, languageSource: resolved.languageSource, direction: resolved.direction } : {},
|
|
3267
|
+
rtl: resolved?.rtl === true,
|
|
3268
|
+
serif: options.serif
|
|
3269
|
+
};
|
|
3270
|
+
}
|
|
3271
|
+
function slideScriptMeasurement(presentation, slideIndex, measurement, options) {
|
|
3272
|
+
const forScripts = measurement.forScripts;
|
|
3273
|
+
if (typeof forScripts !== "function") return measurement;
|
|
3274
|
+
const deckProfile = scriptProfile(presentation, slideIndex, options);
|
|
3275
|
+
const deck = forScripts.call(measurement, deckProfile);
|
|
3276
|
+
const languages = /* @__PURE__ */ new Map();
|
|
3277
|
+
const forLanguage = (lang) => {
|
|
3278
|
+
if (typeof lang !== "string" || !lang) return void 0;
|
|
3279
|
+
if (!languages.has(lang)) {
|
|
3280
|
+
let own2;
|
|
3281
|
+
try {
|
|
3282
|
+
const profile = scriptProfile(presentation, slideIndex, options, lang);
|
|
3283
|
+
own2 = profile.languageSource === "option" && profile.bcp47?.toLowerCase() !== deckProfile.bcp47?.toLowerCase() ? forScripts.call(measurement, profile) : void 0;
|
|
3284
|
+
} catch {
|
|
3285
|
+
own2 = void 0;
|
|
3286
|
+
}
|
|
3287
|
+
languages.set(lang, own2);
|
|
3288
|
+
}
|
|
3289
|
+
return languages.get(lang);
|
|
3290
|
+
};
|
|
3291
|
+
const pick = (style) => forLanguage(style?.lang) ?? deck;
|
|
3292
|
+
const scripted = { ...deck, measure: (text, size, style) => pick(style).measure(text, size, style) };
|
|
3293
|
+
if (typeof deck.resolveStyle === "function") scripted.resolveStyle = (style) => deck.resolveStyle.call(deck, style);
|
|
3294
|
+
if (typeof deck.outlineBounds === "function")
|
|
3295
|
+
scripted.outlineBounds = (text, size, style) => {
|
|
3296
|
+
const own2 = pick(style);
|
|
3297
|
+
return typeof own2.outlineBounds === "function" ? own2.outlineBounds(text, size, style) : deck.outlineBounds.call(deck, text, size, style);
|
|
3298
|
+
};
|
|
3299
|
+
return scripted;
|
|
3300
|
+
}
|
|
3301
|
+
function resolveSlideScriptMeasurement(presentation, slideIndex, measurement, options = {}) {
|
|
3302
|
+
if (typeof measurement.forScripts !== "function") return measurement;
|
|
3303
|
+
const { fontScheme } = resolveDesignRecords(presentation, slideIndex, options.catalogs !== void 0 ? { catalogs: options.catalogs } : {});
|
|
3304
|
+
const resolved = resolveFontFamilies(fontScheme);
|
|
3305
|
+
const fontFamilies = { heading: options.fontFamilies?.heading ?? resolved.heading, body: options.fontFamilies?.body ?? resolved.body };
|
|
3306
|
+
return slideScriptMeasurement(presentation, slideIndex, measurement, { ...options.catalogs !== void 0 ? { catalogs: options.catalogs } : {}, fontFamilies, serif: fontScheme.type === "serif" });
|
|
3307
|
+
}
|
|
3308
|
+
|
|
3248
3309
|
// src/slide-context.ts
|
|
3249
3310
|
var rec2 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
3250
3311
|
function resolveSlideContext(presentation, index, options = {}) {
|
|
@@ -3280,7 +3341,8 @@ function resolveSlideContext(presentation, index, options = {}) {
|
|
|
3280
3341
|
...options.fonts?.textMeasurement ? { textMeasurement: options.fonts.textMeasurement } : {},
|
|
3281
3342
|
...options.date !== void 0 ? { date: options.date } : {}
|
|
3282
3343
|
};
|
|
3283
|
-
|
|
3344
|
+
const resolvedSlide = resolveSlideVariables(slide, { slideNumber: composeOptions.slideNumber, slideCount: composeOptions.slideCount });
|
|
3345
|
+
return { slide: resolvedSlide, options: composeOptions, diagnostics, resolved: { theme, colorScheme, fontScheme, fontSchemePath: records.fontSchemePath, ...layout ? { layout } : {}, provenance: { ...layoutProvenance ? { layout: layoutProvenance } : {}, ...records.provenance } } };
|
|
3284
3346
|
}
|
|
3285
3347
|
|
|
3286
3348
|
// src/rule-slides.ts
|
|
@@ -3316,10 +3378,17 @@ function buildSlides(document, options) {
|
|
|
3316
3378
|
const slides = Array.isArray(document.slides) ? document.slides : [];
|
|
3317
3379
|
return slides.map((slide, index) => {
|
|
3318
3380
|
const path = pointer2("slides", index);
|
|
3319
|
-
const
|
|
3381
|
+
const baseContext = lazy(() => resolveSlideContext(document, index, { catalogs: options.catalogs, date: "2000-01-01" }));
|
|
3382
|
+
const measurement = lazy(() => {
|
|
3383
|
+
const host = measurementFor(options, index);
|
|
3384
|
+
if (!host) return void 0;
|
|
3385
|
+
const { resolved: resolved2 } = baseContext();
|
|
3386
|
+
return slideScriptMeasurement(document, index, host, { catalogs: options.catalogs, fontFamilies: resolveFontFamilies(resolved2.fontScheme), serif: resolved2.fontScheme.type === "serif" });
|
|
3387
|
+
});
|
|
3320
3388
|
const resolved = lazy(() => {
|
|
3321
3389
|
const textMeasurement = measurement();
|
|
3322
|
-
|
|
3390
|
+
const slideContext = baseContext();
|
|
3391
|
+
return textMeasurement ? { ...slideContext, options: { ...slideContext.options, textMeasurement } } : slideContext;
|
|
3323
3392
|
});
|
|
3324
3393
|
const design = lazy(() => resolveDesign(document, index, resolved()));
|
|
3325
3394
|
const layout = lazy(() => resolved().options.layout);
|
|
@@ -3327,14 +3396,14 @@ function buildSlides(document, options) {
|
|
|
3327
3396
|
const result = { layoutDiagnostics: [] };
|
|
3328
3397
|
const compose = (input, withLayout) => composeSlide(input, { ...resolved().options, layout: withLayout });
|
|
3329
3398
|
try {
|
|
3330
|
-
result.composition = compose(slide, layout());
|
|
3399
|
+
result.composition = compose(resolved().slide, layout());
|
|
3331
3400
|
result.layoutDiagnostics.push(...result.composition.diagnostics.map((diagnostic) => ({ diagnostic, strict: false })));
|
|
3332
3401
|
} catch (error) {
|
|
3333
3402
|
if (error instanceof OPFCompositionError) {
|
|
3334
3403
|
result.layoutDiagnostics.push(...error.diagnostics.map((diagnostic) => ({ diagnostic, strict: true })));
|
|
3335
3404
|
try {
|
|
3336
3405
|
const relaxedLayout = layout();
|
|
3337
|
-
result.composition = compose(relax(slide), relaxedLayout ? relax(relaxedLayout) : void 0);
|
|
3406
|
+
result.composition = compose(relax(resolved().slide), relaxedLayout ? relax(relaxedLayout) : void 0);
|
|
3338
3407
|
} catch (second) {
|
|
3339
3408
|
result.layoutError = second instanceof Error ? second.message : String(second);
|
|
3340
3409
|
}
|
|
@@ -3640,4 +3709,4 @@ function assertValidCatalogRecord(kind, value) {
|
|
|
3640
3709
|
if (!report2.valid) throw new OPFValidationError(report2);
|
|
3641
3710
|
}
|
|
3642
3711
|
|
|
3643
|
-
export { DEFAULT_CHART_PALETTE, DEFAULT_VALIDATION_THRESHOLDS, OPFValidationError, assertValid, assertValidCatalogRecord, findValidationRule, parseSource, resolveSlideContext, validate, validateCatalogRecord, validationCategories, validationRules };
|
|
3712
|
+
export { DEFAULT_CHART_PALETTE, DEFAULT_VALIDATION_THRESHOLDS, OPFValidationError, assertValid, assertValidCatalogRecord, findValidationRule, parseSource, resolveSlideContext, resolveSlideScriptMeasurement, validate, validateCatalogRecord, validationCategories, validationRules };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { assertValid, resolveSlideContext } from './chunk-
|
|
2
|
-
import { composeSlide, codeHighlightSlice, tableRowBoundaries, visitContentPayloads, sliceNumberedItems } from './chunk-
|
|
1
|
+
import { assertValid, resolveSlideScriptMeasurement, resolveSlideContext } from './chunk-NLNYNBTS.js';
|
|
2
|
+
import { resolveSlideVariables, usesSlideBuiltin, composeSlide, codeHighlightSlice, tableRowBoundaries, visitContentPayloads, slideTokenSpans, sliceNumberedItems } from './chunk-CW7GEAV3.js';
|
|
3
3
|
import { checkCatalogsOption } from './chunk-SPFV27O5.js';
|
|
4
4
|
|
|
5
5
|
// src/pagination.ts
|
|
@@ -39,6 +39,10 @@ var deckContext = (presentation) => {
|
|
|
39
39
|
const deck = isRecord(presentation) ? presentation : {};
|
|
40
40
|
return { ...Array.isArray(deck.references) ? { references: deck.references } : {}, ...isRecord(deck.datasets) ? { datasets: deck.datasets } : {} };
|
|
41
41
|
};
|
|
42
|
+
function keepTokensWhole(boundaries, text) {
|
|
43
|
+
const spans = slideTokenSpans(text);
|
|
44
|
+
return spans.length ? boundaries.filter((boundary) => !spans.some(([start, end]) => boundary > start && boundary < end)) : boundaries;
|
|
45
|
+
}
|
|
42
46
|
function leafFor(path, field, value) {
|
|
43
47
|
const leaf = { path, field, value };
|
|
44
48
|
let text;
|
|
@@ -62,7 +66,7 @@ function leafFor(path, field, value) {
|
|
|
62
66
|
}
|
|
63
67
|
if (text !== void 0) {
|
|
64
68
|
leaf.unit = "utf16";
|
|
65
|
-
leaf.boundaries = [0, ...Array.from(graphemes.segment(text), (segment) => segment.index + segment.segment.length)];
|
|
69
|
+
leaf.boundaries = keepTokensWhole([0, ...Array.from(graphemes.segment(text), (segment) => segment.index + segment.segment.length)], text);
|
|
66
70
|
} else if (field === "items" || field === "bullets") {
|
|
67
71
|
leaf.unit = "items";
|
|
68
72
|
leaf.boundaries = Array.from({ length: value.length + 1 }, (_, i) => i);
|
|
@@ -103,8 +107,9 @@ function paginateSlide(input, options = {}) {
|
|
|
103
107
|
};
|
|
104
108
|
source = withReadability(source);
|
|
105
109
|
let evaluations = 0;
|
|
106
|
-
const { fonts, minFontSize: _minFontSize, maxSlides: _maxSlides, reservedIds: _reservedIds, ...engineOptions } = options;
|
|
107
|
-
const
|
|
110
|
+
const { fonts, catalogs, minFontSize: _minFontSize, maxSlides: _maxSlides, reservedIds: _reservedIds, ...engineOptions } = options;
|
|
111
|
+
const textMeasurement = fonts?.textMeasurement && options.presentation !== void 0 ? resolveSlideScriptMeasurement(options.presentation, sourceIndex, fonts.textMeasurement, { ...catalogs !== void 0 ? { catalogs } : {}, ...options.fontFamilies ? { fontFamilies: options.fontFamilies } : {} }) : fonts?.textMeasurement;
|
|
112
|
+
const composeOptions = { ...engineOptions, ...textMeasurement ? { textMeasurement } : {} };
|
|
108
113
|
const readableLayout = (layout) => {
|
|
109
114
|
if (!isRecord(layout) || !Array.isArray(layout.placeholders) || !layout.placeholders.some((entry) => isRecord(entry) && entry.type === "group")) return layout;
|
|
110
115
|
const visit = (entries) => entries.map((entry) => {
|
|
@@ -115,9 +120,12 @@ function paginateSlide(input, options = {}) {
|
|
|
115
120
|
return { ...layout, placeholders: visit(layout.placeholders) };
|
|
116
121
|
};
|
|
117
122
|
if (options.layout !== void 0) composeOptions.layout = readableLayout(options.layout);
|
|
123
|
+
const presentationSlides = options.presentation?.slides;
|
|
124
|
+
const slideCount = options.slideCount ?? (Array.isArray(presentationSlides) && presentationSlides.length ? presentationSlides.length : void 0);
|
|
118
125
|
const geometry = (slide, pageIndex = 0) => {
|
|
119
126
|
if (++evaluations > 2e4) throw new OPFPaginationError("Pagination exceeded its layout evaluation limit. Split the input into smaller sections.");
|
|
120
|
-
|
|
127
|
+
const slideNumber = (options.slideNumber ?? sourceIndex + 1) + pageIndex;
|
|
128
|
+
return composeSlide(resolveSlideVariables(withReadability(slide, true), { slideNumber, ...slideCount !== void 0 ? { slideCount } : {} }), { ...composeOptions, slideNumber });
|
|
121
129
|
};
|
|
122
130
|
const initial = geometry(source);
|
|
123
131
|
const fit = (diagnostics) => diagnostics.filter((issue) => issue.code === "text-overflow" || issue.code === "small-cell" || !!initial.furniture?.diagnostics.includes(issue));
|
|
@@ -133,7 +141,14 @@ function paginateSlide(input, options = {}) {
|
|
|
133
141
|
if (!fit(initial.diagnostics).length) return { slides: [source], pages: [{ slideIndex: sourceIndex, mappings: initial.items.map((item) => ({ sourcePath: item.path, outputPath: item.path })), ...initial.furniture ? { repeatedMappings: repeatedMappings(0) } : {} }] };
|
|
134
142
|
const headerIssues = initial.diagnostics.filter((issue) => headingFields.has(issue.path.slice(sourceBase.length + 1)) || initial.furniture?.diagnostics.includes(issue));
|
|
135
143
|
if (headerIssues.length) throw new OPFPaginationError("Repeated headings or header/footer content cannot fit or resolve. Change the repeated content or slide design before pagination.", headerIssues);
|
|
136
|
-
const
|
|
144
|
+
const tokens = resolveSlideVariables(source, { slideNumber: 1, slideCount: 1 }) !== source;
|
|
145
|
+
const sourceValue = (path, fallback) => {
|
|
146
|
+
if (!tokens || !path.startsWith(`${sourceBase}.`)) return fallback;
|
|
147
|
+
let node = source;
|
|
148
|
+
for (const key of path.slice(sourceBase.length + 1).split(".")) node = isRecord(node) || Array.isArray(node) ? node[key] : void 0;
|
|
149
|
+
return node === void 0 ? fallback : node;
|
|
150
|
+
};
|
|
151
|
+
const leaves = initial.items.filter((item) => !headingFields.has(item.field)).map((item) => leafFor(item.path, item.field, sourceValue(item.path, item.value)));
|
|
137
152
|
const leafPaths = new Set(leaves.map((leaf) => leaf.path));
|
|
138
153
|
const slides = [], pages = [];
|
|
139
154
|
let selected = /* @__PURE__ */ new Map();
|
|
@@ -256,10 +271,6 @@ function paginateSlide(input, options = {}) {
|
|
|
256
271
|
if (!slides.length) throw new OPFPaginationError("No body content can be paginated.", initial.diagnostics);
|
|
257
272
|
return { slides, pages };
|
|
258
273
|
}
|
|
259
|
-
var usesSlideTotal = (presentation) => [presentation, ...presentation.slides].some((owner) => ["header", "footer"].some((kind) => ["left", "center", "right"].some((zone) => {
|
|
260
|
-
const content = owner?.design?.[kind]?.[zone];
|
|
261
|
-
return content?.slideNumber === true && typeof content.slideNumberFormat === "string" && content.slideNumberFormat.includes("{total}");
|
|
262
|
-
})));
|
|
263
274
|
function paginate(input, options = {}) {
|
|
264
275
|
checkCatalogsOption(options.catalogs, "paginate");
|
|
265
276
|
assertValid(input, { only: ["format"] });
|
|
@@ -280,7 +291,7 @@ function paginate(input, options = {}) {
|
|
|
280
291
|
}
|
|
281
292
|
}
|
|
282
293
|
if (output2.length >= maxSlides) throw new OPFPaginationError(`Pagination needs more than ${maxSlides} slides. No partial result was returned.`);
|
|
283
|
-
const result2 = paginateSlide(slide, { ...context.options, textRasterPadding: options.textRasterPadding, fonts: options.fonts, presentation, slideIndex: index, slideNumber: output2.length + 1, slideCount: slideCount2, date: options.date, maxSlides: maxSlides - output2.length, minFontSize: options.minFontSize, reservedIds });
|
|
294
|
+
const result2 = paginateSlide(slide, { ...context.options, textRasterPadding: options.textRasterPadding, fonts: options.fonts, ...options.catalogs ? { catalogs: options.catalogs } : {}, presentation, slideIndex: index, slideNumber: output2.length + 1, slideCount: slideCount2, date: options.date, maxSlides: maxSlides - output2.length, minFontSize: options.minFontSize, reservedIds });
|
|
284
295
|
const outputStart = output2.length;
|
|
285
296
|
result2.pages.forEach((page, pageIndex) => {
|
|
286
297
|
const remap = (mapping) => ({ ...mapping, outputPath: mapping.outputPath.replace(/^slides\.\d+/, `slides.${outputStart + pageIndex}`) });
|
|
@@ -291,9 +302,10 @@ function paginate(input, options = {}) {
|
|
|
291
302
|
});
|
|
292
303
|
return { output: output2, pages: pages2 };
|
|
293
304
|
};
|
|
305
|
+
const usesSlideCount = usesSlideBuiltin(presentation, "deck.slideCount");
|
|
294
306
|
let slideCount = presentation.slides.length, result = run(slideCount);
|
|
295
|
-
for (let attempt = 0;
|
|
296
|
-
if (attempt >= 3) throw new OPFPaginationError("
|
|
307
|
+
for (let attempt = 0; usesSlideCount && result.output.length !== slideCount; attempt++) {
|
|
308
|
+
if (attempt >= 3) throw new OPFPaginationError("The slide count did not converge. Change the text around {{deck.slideCount}} or split the input.");
|
|
297
309
|
slideCount = result.output.length;
|
|
298
310
|
result = run(slideCount);
|
|
299
311
|
}
|
|
@@ -52,7 +52,7 @@ var presentation = {
|
|
|
52
52
|
"minItems": 1
|
|
53
53
|
}
|
|
54
54
|
],
|
|
55
|
-
"description": "Organization associated with the presentation, usually the presenting company. Array form supports hosts, partners, clients, and sponsors. The primary organization (Organization.role 'primary', else the first item) supplies the default deck logo, the '
|
|
55
|
+
"description": "Organization associated with the presentation, usually the presenting company. Array form supports hosts, partners, clients, and sponsors. The primary organization (Organization.role 'primary', else the first item) supplies the default deck logo, the 'socials' header/footer field and the 'organization.<field>' built-in variables; the others are available by id as 'organization.<id>.<field>' and are not drawn automatically."
|
|
56
56
|
},
|
|
57
57
|
"speaker": {
|
|
58
58
|
"oneOf": [
|
|
@@ -67,7 +67,7 @@ var presentation = {
|
|
|
67
67
|
"minItems": 1
|
|
68
68
|
}
|
|
69
69
|
],
|
|
70
|
-
"description": "Person presenting the deck. Array form supports panels and multi-speaker decks. The first speaker is the primary speaker: the built-in variables 'speaker.<field>'
|
|
70
|
+
"description": "Person presenting the deck. Array form supports panels and multi-speaker decks. The first speaker is the primary speaker: the built-in variables 'speaker.<field>' read it, 'speakers' lists every name, and 'speaker.<id>.<field>' addresses one by id. A speaker is drawn nowhere else."
|
|
71
71
|
},
|
|
72
72
|
"author": {
|
|
73
73
|
"oneOf": [
|
|
@@ -775,7 +775,7 @@ var presentation = {
|
|
|
775
775
|
},
|
|
776
776
|
"Organization": {
|
|
777
777
|
"type": "object",
|
|
778
|
-
"description": "An organization associated with the presentation, typically the presenting company, but also hosts, partners, clients, or sponsors. The primary organization (role 'primary', else the first one) supplies the default deck logo (unless design.logo overrides it)
|
|
778
|
+
"description": "An organization associated with the presentation, typically the presenting company, but also hosts, partners, clients, or sponsors. The primary organization (role 'primary', else the first one) supplies the default deck logo (unless design.logo overrides it) and the 'socials' header/footer field (its socials). Every field is also a built-in variable ('{{organization.name}}', 'var:organization.logo', 'organization.<id>.<field>'). Nothing else about an organization is drawn automatically. See docs/templates-and-variables.md.",
|
|
779
779
|
"required": [
|
|
780
780
|
"id",
|
|
781
781
|
"name"
|
|
@@ -793,7 +793,7 @@ var presentation = {
|
|
|
793
793
|
},
|
|
794
794
|
"name": {
|
|
795
795
|
"type": "string",
|
|
796
|
-
"description": "Display name.
|
|
796
|
+
"description": "Display name. The built-in variable 'organization.name' (primary organization) or 'organization.<id>.name' carries it into any string, such as a header or footer text of '{{organization.name}}'.",
|
|
797
797
|
"examples": [
|
|
798
798
|
"Acme Corp",
|
|
799
799
|
"DevConf 2026",
|
|
@@ -863,7 +863,7 @@ var presentation = {
|
|
|
863
863
|
"sponsor",
|
|
864
864
|
"host"
|
|
865
865
|
],
|
|
866
|
-
"description": "Role of the organization relative to the presentation. Only 'primary' has behavior: it selects the primary organization (deck logo,
|
|
866
|
+
"description": "Role of the organization relative to the presentation. Only 'primary' has behavior: it selects the primary organization (deck logo, the 'socials' header/footer field, and the 'organization.<field>' built-ins). When no organization has role 'primary', the first one is primary. 'partner', 'client', 'sponsor' and 'host' are descriptive labels that change nothing."
|
|
867
867
|
},
|
|
868
868
|
"socials": {
|
|
869
869
|
"$ref": "#/$defs/Socials",
|
|
@@ -873,7 +873,7 @@ var presentation = {
|
|
|
873
873
|
},
|
|
874
874
|
"Speaker": {
|
|
875
875
|
"type": "object",
|
|
876
|
-
"description": "A person presenting the deck. A speaker is drawn only through built-in variables ('{{speaker.name}}' inside any string, 'var:speaker.photo' as a whole image field)
|
|
876
|
+
"description": "A person presenting the deck. A speaker is drawn only through built-in variables ('{{speaker.name}}' inside any string, a header or footer text included, and 'var:speaker.photo' as a whole image field). No layout, cover or bio slide places a speaker on its own. See docs/templates-and-variables.md.",
|
|
877
877
|
"required": [
|
|
878
878
|
"id",
|
|
879
879
|
"name"
|
|
@@ -891,7 +891,7 @@ var presentation = {
|
|
|
891
891
|
},
|
|
892
892
|
"name": {
|
|
893
893
|
"type": "string",
|
|
894
|
-
"description": "Display name. Built-in variable 'speaker.name' (first speaker) or 'speaker.<id>.name';
|
|
894
|
+
"description": "Display name. Built-in variable 'speaker.name' (first speaker) or 'speaker.<id>.name'; every name is listed by 'speakers'.",
|
|
895
895
|
"examples": [
|
|
896
896
|
"Alice Chen",
|
|
897
897
|
"Bob Lee",
|
|
@@ -900,7 +900,7 @@ var presentation = {
|
|
|
900
900
|
},
|
|
901
901
|
"title": {
|
|
902
902
|
"type": "string",
|
|
903
|
-
"description": "Role or title. Built-in variable 'speaker.title'
|
|
903
|
+
"description": "Role or title. Built-in variable 'speaker.title' (or 'speaker.<id>.title'), for example in a footer text of '{{speaker.name}}, {{speaker.title}}'.",
|
|
904
904
|
"examples": [
|
|
905
905
|
"VP of Engineering",
|
|
906
906
|
"Founder & CEO",
|
|
@@ -1144,7 +1144,7 @@ var presentation = {
|
|
|
1144
1144
|
false,
|
|
1145
1145
|
{
|
|
1146
1146
|
"left": {
|
|
1147
|
-
"
|
|
1147
|
+
"text": "{{slide.section}}"
|
|
1148
1148
|
},
|
|
1149
1149
|
"right": {
|
|
1150
1150
|
"image": "asset:acme-logo"
|
|
@@ -1173,7 +1173,7 @@ var presentation = {
|
|
|
1173
1173
|
"text": "Confidential"
|
|
1174
1174
|
},
|
|
1175
1175
|
"right": {
|
|
1176
|
-
"
|
|
1176
|
+
"text": "{{slide.number}}"
|
|
1177
1177
|
}
|
|
1178
1178
|
}
|
|
1179
1179
|
]
|
|
@@ -1666,7 +1666,7 @@ var presentation = {
|
|
|
1666
1666
|
"additionalProperties": {
|
|
1667
1667
|
"$ref": "#/$defs/Variable"
|
|
1668
1668
|
},
|
|
1669
|
-
"description": "Named variables, keyed by stable kebab-case id. A variable is a typed, named value the deck declares once and uses in many places: a color ('var:<id>' in color fields, the original use), or content that fills a template (text, number, date, image, url, list). Content is referenced inline as '{{<id>}}' inside any string, or whole as 'var:<id>' in a field of the matching type; '\\{{' writes a literal '{{'. A hex string is shorthand for a color variable. A variable with no 'value' is unfilled: expected in a template (root 'template': true), an error in a normal deck. Engines resolve variables with resolveVariables() before composing, rendering or exporting, so a template plus its values previews and exports exactly like the equivalent hand-written deck. Read-only built-in variables come from the deck's own metadata and use dotted names that a user id can never take: 'deck.name', 'deck.description', 'deck.author', 'speaker.name|title|email|phone|bio|photo' (first speaker), 'speakers' (every speaker's name, a list), 'organization.name|legalName|tagline|domain|email|phone|logo' (primary organization), and 'speaker.<id>.<field>' / 'organization.<id>.<field>' by id. They are written the same two ways ('{{speaker.name}}', 'var:speaker.photo'), are never declared, and an unknown built-in path is a validation error; a known one with no source value resolves to nothing with a warning. The id 'speakers' is reserved. See docs/templates-and-variables.md.",
|
|
1669
|
+
"description": "Named variables, keyed by stable kebab-case id. A variable is a typed, named value the deck declares once and uses in many places: a color ('var:<id>' in color fields, the original use), or content that fills a template (text, number, date, image, url, list). Content is referenced inline as '{{<id>}}' inside any string, or whole as 'var:<id>' in a field of the matching type; '\\{{' writes a literal '{{'. A hex string is shorthand for a color variable. A variable with no 'value' is unfilled: expected in a template (root 'template': true), an error in a normal deck. Engines resolve variables with resolveVariables() before composing, rendering or exporting, so a template plus its values previews and exports exactly like the equivalent hand-written deck. Read-only built-in variables come from the deck's own metadata and use dotted names that a user id can never take: 'deck.name', 'deck.description', 'deck.author', 'speaker.name|title|email|phone|bio|photo' (first speaker), 'speakers' (every speaker's name, a list), 'organization.name|legalName|tagline|domain|email|phone|logo' (primary organization), and 'speaker.<id>.<field>' / 'organization.<id>.<field>' by id. They are written the same two ways ('{{speaker.name}}', 'var:speaker.photo'), are never declared, and an unknown built-in path is a validation error; a known one with no source value resolves to nothing with a warning. The id 'speakers' is reserved. Three built-ins are slide-scoped and written only as inline tokens: '{{slide.number}}' (the displayed slide number after pagination), '{{slide.section}}' (the slide's section) and '{{deck.slideCount}}' (the number of slides after pagination). resolveVariables() leaves them as written; they resolve per slide as it is composed (resolveSlideVariables(), and header/footer text in layoutFurniture()), so every 'slide.' name is reserved and 'var:slide.*' or 'var:deck.slideCount' is a validation error. See docs/templates-and-variables.md.",
|
|
1670
1670
|
"examples": [
|
|
1671
1671
|
{
|
|
1672
1672
|
"risk": "#B42318",
|
|
@@ -2625,7 +2625,8 @@ var presentation = {
|
|
|
2625
2625
|
},
|
|
2626
2626
|
"HeaderFooterItem": {
|
|
2627
2627
|
"type": "object",
|
|
2628
|
-
"description": "One header/footer zone. Every configured field renders; fields in one zone stack top to bottom in the order logo, image, text,
|
|
2628
|
+
"description": "One header/footer zone. Every configured field renders; fields in one zone stack top to bottom in the order logo, image, text, socials, date. Generated values such as the slide number, the slide count, the section, the organization or the speaker are variables inside text ('{{slide.number}} / {{deck.slideCount}}', '{{organization.name}}'), so one text writes several values in the author's order; a line break is '\\n'. Put a date and a slide number in different zones to keep each on the zone's single line. See docs/templates-and-variables.md.",
|
|
2629
|
+
"additionalProperties": false,
|
|
2629
2630
|
"properties": {
|
|
2630
2631
|
"logo": {
|
|
2631
2632
|
"type": "boolean",
|
|
@@ -2633,10 +2634,12 @@ var presentation = {
|
|
|
2633
2634
|
},
|
|
2634
2635
|
"text": {
|
|
2635
2636
|
"type": "string",
|
|
2636
|
-
"description": "
|
|
2637
|
+
"description": "Text rendered in this zone. Variables resolve inside it like any string: deck-wide ones ('{{organization.name}}', '{{speaker.name}}, {{speaker.title}}', '{{customer}}') before composition, and the slide-scoped built-ins '{{slide.number}}', '{{slide.section}}' and '{{deck.slideCount}}' for each slide as it is laid out. Each '{{slide.number}}' is a live slide-number field: PPTX export writes it as a native field when its value fits within one accepted text line, and as static text with a diagnostic otherwise. '{{deck.slideCount}}' is fixed text, because PowerPoint has no slide-count field. Write '\\{{' for literal braces.",
|
|
2637
2638
|
"examples": [
|
|
2638
2639
|
"Confidential",
|
|
2639
|
-
"Q4 Business Review"
|
|
2640
|
+
"Q4 Business Review",
|
|
2641
|
+
"{{slide.number}} / {{deck.slideCount}}",
|
|
2642
|
+
"{{organization.name}}\n{{slide.section}}"
|
|
2640
2643
|
]
|
|
2641
2644
|
},
|
|
2642
2645
|
"image": {
|
|
@@ -2647,21 +2650,6 @@ var presentation = {
|
|
|
2647
2650
|
"./assets/footer-badge.svg"
|
|
2648
2651
|
]
|
|
2649
2652
|
},
|
|
2650
|
-
"slideNumber": {
|
|
2651
|
-
"type": "boolean",
|
|
2652
|
-
"description": "Whether to render the current slide number in this zone. PPTX export writes a native slide-number field when its value fits within one accepted text line; a value split across lines exports as static text with a diagnostic."
|
|
2653
|
-
},
|
|
2654
|
-
"slideNumberFormat": {
|
|
2655
|
-
"type": "string",
|
|
2656
|
-
"pattern": "[{]current[}]",
|
|
2657
|
-
"description": 'Template for the slide number when slideNumber is true. {current} is the displayed slide number (a native PPTX field when its value fits within one accepted text line); {total} is the number of slides in the rendered or exported deck, written as fixed text because PowerPoint has no slide-count field. Other characters are literal. Defaults to "{current}".',
|
|
2658
|
-
"examples": [
|
|
2659
|
-
"{current}",
|
|
2660
|
-
"{current} / {total}",
|
|
2661
|
-
"A-{current}",
|
|
2662
|
-
"Page {current} of {total}"
|
|
2663
|
-
]
|
|
2664
|
-
},
|
|
2665
2653
|
"date": {
|
|
2666
2654
|
"oneOf": [
|
|
2667
2655
|
{
|
|
@@ -2689,18 +2677,6 @@ var presentation = {
|
|
|
2689
2677
|
"MMMM d, yyyy"
|
|
2690
2678
|
]
|
|
2691
2679
|
},
|
|
2692
|
-
"organization": {
|
|
2693
|
-
"type": "boolean",
|
|
2694
|
-
"description": "Whether to render the primary organization's name from organization (role 'primary', else the first organization)."
|
|
2695
|
-
},
|
|
2696
|
-
"speaker": {
|
|
2697
|
-
"type": "boolean",
|
|
2698
|
-
"description": "Whether to render the primary (first) speaker's name and title from speaker, joined as 'Ada Lovelace, CTO' (just the name when the speaker has no title). It is generated text: without a named speaker the engine reports unresolved-content at this field. PPTX export writes it as static text and import restores the flag from the file's furniture provenance."
|
|
2699
|
-
},
|
|
2700
|
-
"section": {
|
|
2701
|
-
"type": "boolean",
|
|
2702
|
-
"description": "Whether to render the current slide section label."
|
|
2703
|
-
},
|
|
2704
2680
|
"socials": {
|
|
2705
2681
|
"type": "boolean",
|
|
2706
2682
|
"description": "Whether to render the primary organization's social profiles from organization.socials, one line per platform in key order. A handle is formatted through the platform's socialPlatforms record (companyUrlPattern, else profileUrlPattern, else baseUrl, with handlePrefix stripped) and shown as that profile URL without its 'https://' scheme; a value that is already a URL is shown without an 'https://' scheme; an unknown platform key shows the raw value. Exporters link each line to its full URL when one exists. Speaker socials are not rendered by this field."
|
|
@@ -3100,7 +3076,7 @@ var presentation = {
|
|
|
3100
3076
|
},
|
|
3101
3077
|
"section": {
|
|
3102
3078
|
"type": "string",
|
|
3103
|
-
"description": "PowerPoint-style slide section label. Consecutive slides with the same value belong to the same section in presenter view, outlines, and PowerPoint section-aware exports.",
|
|
3079
|
+
"description": "PowerPoint-style slide section label. Consecutive slides with the same value belong to the same section in presenter view, outlines, and PowerPoint section-aware exports. Also the slide-scoped built-in variable '{{slide.section}}', for example in a header text.",
|
|
3104
3080
|
"examples": [
|
|
3105
3081
|
"Intro",
|
|
3106
3082
|
"Problem",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { NOT_CHECKED, Ctx } from './chunk-
|
|
2
|
-
import { sortPresentationKeys } from './chunk-
|
|
3
|
-
import { same } from './chunk-
|
|
4
|
-
import { validate } from './chunk-
|
|
1
|
+
import { NOT_CHECKED, Ctx } from './chunk-IS5H5JKH.js';
|
|
2
|
+
import { sortPresentationKeys } from './chunk-YT7FMQER.js';
|
|
3
|
+
import { same } from './chunk-PPROJP2E.js';
|
|
4
|
+
import { validate } from './chunk-NLNYNBTS.js';
|
|
5
5
|
import { checkCatalogsOption } from './chunk-SPFV27O5.js';
|
|
6
|
-
import { presentation } from './chunk-
|
|
6
|
+
import { presentation } from './chunk-RA64UQKI.js';
|
|
7
7
|
import { Parser, parseDocument, isMap, Document, visit, isScalar, isAlias, isSeq } from 'yaml';
|
|
8
8
|
|
|
9
9
|
var MAX_ALIAS_COUNT = 100;
|