@openpresentation/opf 0.15.1 → 0.16.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 +4 -0
- package/dist/{catalog-refs-BSfGELpt.d.ts → catalog-refs-_anZs-Qz.d.ts} +1 -1
- package/dist/{catalog-schemas-CinPh5WA.d.ts → catalog-schemas-BZCjgAxu.d.ts} +1 -1
- package/dist/catalog.d.ts +2 -2
- package/dist/catalog.js +609 -121
- package/dist/{chunk-5FTUIDUH.js → chunk-3XDRQYWZ.js} +1 -1
- package/dist/{chunk-O744SXXA.js → chunk-5PDN7BN6.js} +202 -95
- package/dist/{chunk-VGAOJEY7.js → chunk-5TO6I3GB.js} +1 -1
- package/dist/{chunk-3RKB4RDJ.js → chunk-5UEUAW57.js} +4 -2
- package/dist/{chunk-ZPU46TFA.js → chunk-6OR326EA.js} +1 -1
- package/dist/{chunk-UBFJ2QHH.js → chunk-BSYQDWT4.js} +12 -2
- package/dist/{chunk-3JG4YXWF.js → chunk-FQSIIADJ.js} +12 -5
- package/dist/chunk-K4DQQIT4.js +319 -0
- package/dist/chunk-KINQFU6X.js +51 -0
- package/dist/{chunk-374R35TJ.js → chunk-NAWQR7MN.js} +1 -1
- package/dist/{chunk-QDI75P2M.js → chunk-PX5AWL7Y.js} +141 -13
- package/dist/{chunk-U4J75TRG.js → chunk-SMLMI6IZ.js} +5 -2
- package/dist/{chunk-TWQJLI6E.js → chunk-UM24JFUE.js} +2 -2
- package/dist/{chunk-2CJPC4HI.js → chunk-WEDGVC5W.js} +185 -11
- package/dist/{composition-D2tghM82.d.ts → composition-D4ADF5c-.d.ts} +88 -9
- package/dist/composition.d.ts +2 -2
- package/dist/composition.js +1 -1
- package/dist/convert.d.ts +3 -3
- package/dist/convert.js +7 -7
- package/dist/data.d.ts +27 -10
- package/dist/data.js +2 -2
- package/dist/deck.d.ts +77 -0
- package/dist/deck.js +12 -0
- package/dist/diff.js +5 -5
- package/dist/docs.js +24 -24
- package/dist/examples.d.ts +1 -1
- package/dist/examples.js +2992 -748
- package/dist/format.js +2 -2
- package/dist/index.d.ts +9 -8
- package/dist/index.js +15 -13
- package/dist/markdown.d.ts +6 -7
- package/dist/markdown.js +7 -7
- package/dist/{pagination-wedbe7eq.d.ts → pagination-DzZPFheM.d.ts} +2 -2
- package/dist/pagination.d.ts +3 -3
- package/dist/pagination.js +4 -4
- package/dist/patch.js +4 -4
- package/dist/{presentation-CDKQVkyI.d.ts → presentation-COrFuj2g.d.ts} +16 -8
- package/dist/repo-readme.js +1 -1
- package/dist/schemas.d.ts +14 -0
- package/dist/schemas.js +1 -1
- package/dist/spec/catalogs/layouts/business-model-canvas.json +66 -1
- package/dist/spec/catalogs/layouts/capability-map.json +53 -3
- package/dist/spec/catalogs/layouts/chart-2x.json +32 -8
- package/dist/spec/catalogs/layouts/chart-3x-bottom-vertical-title-left.json +16 -10
- package/dist/spec/catalogs/layouts/chart-3x-left-title-center.json +16 -10
- package/dist/spec/catalogs/layouts/chart-3x-left.json +16 -10
- package/dist/spec/catalogs/layouts/chart-3x-right-title-center.json +16 -10
- package/dist/spec/catalogs/layouts/chart-3x-right.json +16 -10
- package/dist/spec/catalogs/layouts/chart-3x-top-vertical-title-left.json +16 -10
- package/dist/spec/catalogs/layouts/chart-3x.json +48 -12
- package/dist/spec/catalogs/layouts/dashboard.json +37 -5
- package/dist/spec/catalogs/layouts/image-2x.json +32 -8
- package/dist/spec/catalogs/layouts/image-3x.json +48 -12
- package/dist/spec/catalogs/layouts/index.json +1 -1
- package/dist/spec/catalogs/layouts/kpi-scorecard.json +48 -3
- package/dist/spec/catalogs/layouts/logic-tree.json +69 -0
- package/dist/spec/catalogs/layouts/market-size.json +26 -2
- package/dist/spec/catalogs/layouts/org-chart.json +53 -6
- package/dist/spec/catalogs/manifest.json +3 -3
- package/dist/spec/schemas/layout.schema.json +172 -5
- package/dist/spec/schemas/opf.schema.json +11 -6
- package/dist/types.d.ts +9 -31
- package/dist/{validation-types-BOcY9GTs.d.ts → validation-types-HxIgJfKx.d.ts} +2 -2
- package/dist/validator.d.ts +6 -6
- package/dist/validator.js +3 -3
- package/dist/yaml.d.ts +4 -4
- package/dist/yaml.js +8 -321
- package/package.json +5 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { promotedRegionKeys, VARIABLE_KINDS, resolveChartData, chartPaletteForFill, imageBackground, tableGrid, timelineTextColor, visitContentPayloads, readingRows, visualReadingOrder, intrinsicImageSize, textWidthMeasurer, normalizeHexColor, resolveColorRef, resolveDesignRecords, resolveColorRoles, resolveFontFamilies, resolveCanvasDimensions, defaultSlideBackground, isRecord, hasContentVariables, isTemplate, instantiateForValidation, unusedDatasets, MAX_COMPOSITION_DEPTH, datasetDiagnostics, pathFor, collectCitations, numberingFindings, walkCitationRuns, resolveTableData, resolveChartOptions, chartOptionTarget, codeHighlightLines, chartNumberFixesByCell, OPFCompositionError, composeSlide, resolveScriptFonts } from './chunk-
|
|
1
|
+
import { promotedRegionKeys, VARIABLE_KINDS, resolveChartData, chartPaletteForFill, imageBackground, tableGrid, timelineTextColor, visitContentPayloads, readingRows, visualReadingOrder, intrinsicImageSize, textWidthMeasurer, normalizeHexColor, resolveColorRef, resolveDesignRecords, resolveColorRoles, resolveFontFamilies, resolveCanvasDimensions, defaultSlideBackground, isRecord, hasContentVariables, isTemplate, instantiateForValidation, unusedDatasets, MAX_COMPOSITION_DEPTH, datasetDiagnostics, pathFor, collectCitations, numberingFindings, walkCitationRuns, resolveTableData, resolveChartOptions, chartOptionTarget, codeHighlightLines, chartNumberFixesByCell, MAX_PLACEHOLDER_GROUP_DEPTH, OPFCompositionError, composeSlide, resolveScriptFonts } from './chunk-5PDN7BN6.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-WEDGVC5W.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';
|
|
@@ -864,6 +864,33 @@ function dataUnionErrors(errors, value) {
|
|
|
864
864
|
return { ...error, message: field === "fields" ? "'fields' applies only to a dataset-backed table; add 'dataset' or remove 'fields'" : datasetTableMessage(field) };
|
|
865
865
|
});
|
|
866
866
|
}
|
|
867
|
+
var placeholderHeadings = /* @__PURE__ */ new Set(["title", "subtitle", "tag"]);
|
|
868
|
+
function placeholderGroupIssues(value) {
|
|
869
|
+
const issues = [];
|
|
870
|
+
if (!isRecord(value) || !Array.isArray(value.placeholders)) return issues;
|
|
871
|
+
const walk = (entries, path, depth) => entries.forEach((entry, index) => {
|
|
872
|
+
if (!isRecord(entry)) return;
|
|
873
|
+
const at2 = `${path}/${index}`;
|
|
874
|
+
if (entry.type === "group") {
|
|
875
|
+
if (depth >= MAX_PLACEHOLDER_GROUP_DEPTH) issues.push(semanticIssue(at2, `placeholder groups nest at most ${MAX_PLACEHOLDER_GROUP_DEPTH} levels inside a layout record; this group would be level ${depth + 1}`, { code: "layout-placeholder-group", depth: depth + 1, maxDepth: MAX_PLACEHOLDER_GROUP_DEPTH }));
|
|
876
|
+
else if (Array.isArray(entry.placeholders)) walk(entry.placeholders, `${at2}/placeholders`, depth + 1);
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
if (depth === 0) return;
|
|
880
|
+
if (typeof entry.type === "string" && placeholderHeadings.has(entry.type)) issues.push(semanticIssue(`${at2}/type`, `a placeholder group holds body regions only; a '${entry.type}' placeholder belongs at the record's top level`, { code: "layout-placeholder-group" }));
|
|
881
|
+
if (hasOwn(entry, "placement")) issues.push(semanticIssue(`${at2}/placement`, "placement is only valid on a top-level image placeholder; a region inside a placeholder group cannot bleed to a slide edge", { code: "image-placement-invalid" }));
|
|
882
|
+
});
|
|
883
|
+
walk(value.placeholders, "/placeholders", 0);
|
|
884
|
+
return issues;
|
|
885
|
+
}
|
|
886
|
+
function withPlaceholderGroupIssues(errors, value) {
|
|
887
|
+
const issues = placeholderGroupIssues(value);
|
|
888
|
+
const entries = issues.map((issue2) => issue2.path.replace(/\/(type|placement)$/, ""));
|
|
889
|
+
const covered = (error) => entries.some((entry) => error.path === entry || error.path.startsWith(`${entry}/`));
|
|
890
|
+
const kept = errors.filter((error) => !covered(error));
|
|
891
|
+
const reported = [...kept.filter((error) => error.keyword !== "if"), ...issues].map((error) => error.path);
|
|
892
|
+
return [...kept.filter((error) => error.keyword !== "if" || !reported.some((path) => path === error.path || path.startsWith(`${error.path}/`))), ...issues];
|
|
893
|
+
}
|
|
867
894
|
function validateAgainstSchema(value, schemaOrKind = "presentation", options = {}) {
|
|
868
895
|
const resolved = resolveValidator(schemaOrKind);
|
|
869
896
|
if (resolved.schemaName === "presentation") {
|
|
@@ -895,7 +922,8 @@ function validateAgainstSchema(value, schemaOrKind = "presentation", options = {
|
|
|
895
922
|
}
|
|
896
923
|
const valid = resolved.validate(subject) === true;
|
|
897
924
|
const ajvErrors = valid ? [] : typedVariableErrors(resolved.validate.errors ?? [], subject);
|
|
898
|
-
const
|
|
925
|
+
const mapped = (resolved.schemaName === "presentation" ? dataUnionErrors(ajvErrors, subject) : ajvErrors).map(toIssue);
|
|
926
|
+
const errors = resolved.schemaName === "layout" ? withPlaceholderGroupIssues(mapped, subject) : mapped;
|
|
899
927
|
const warnings = [];
|
|
900
928
|
if (resolved.schemaName === "presentation") {
|
|
901
929
|
errors.push(...presentationSemanticIssues(subject));
|
|
@@ -1918,7 +1946,7 @@ var languageRule = rule(
|
|
|
1918
1946
|
"info",
|
|
1919
1947
|
"The presentation does not declare its language.",
|
|
1920
1948
|
"Screen readers and text-to-speech choose pronunciation and hyphenation from the declared language; spell checkers and translation tools use it too.",
|
|
1921
|
-
{ standard: "WCAG 2.2 SC 3.1.1 Language of Page, level A", approximations: "Only the presentation-level `language` is checked, not the language of individual runs (
|
|
1949
|
+
{ standard: "WCAG 2.2 SC 3.1.1 Language of Page, level A", approximations: "Only the presentation-level `language` is checked, not the language of individual runs (`TextRun.lang`; opf/language-tag checks how those tags are written)." }
|
|
1922
1950
|
);
|
|
1923
1951
|
var languageRules = [
|
|
1924
1952
|
{
|
|
@@ -1944,6 +1972,105 @@ var accessibilityRules = [
|
|
|
1944
1972
|
...languageRules
|
|
1945
1973
|
];
|
|
1946
1974
|
|
|
1975
|
+
// src/language-tag.ts
|
|
1976
|
+
var REGION_ALIASES = { UK: "GB" };
|
|
1977
|
+
var privateRegion = /^(?:AA|Q[M-Z]|X[A-Z]|ZZ)$/;
|
|
1978
|
+
var regionNames;
|
|
1979
|
+
var assignedRegion = (region) => {
|
|
1980
|
+
if (privateRegion.test(region)) return true;
|
|
1981
|
+
regionNames ??= new Intl.DisplayNames(["en"], { type: "region", fallback: "code" });
|
|
1982
|
+
try {
|
|
1983
|
+
return regionNames.of(region) !== region;
|
|
1984
|
+
} catch {
|
|
1985
|
+
return false;
|
|
1986
|
+
}
|
|
1987
|
+
};
|
|
1988
|
+
var canonical = (tag) => {
|
|
1989
|
+
try {
|
|
1990
|
+
return Intl.getCanonicalLocales(tag)[0];
|
|
1991
|
+
} catch {
|
|
1992
|
+
return void 0;
|
|
1993
|
+
}
|
|
1994
|
+
};
|
|
1995
|
+
function regionSubtag(tag) {
|
|
1996
|
+
const subtags = tag.split("-");
|
|
1997
|
+
for (let index = 1; index < subtags.length; index++) {
|
|
1998
|
+
const subtag = subtags[index];
|
|
1999
|
+
if (/^(?:[a-z]{2}|\d{3})$/i.test(subtag)) return { region: subtag.toUpperCase(), index };
|
|
2000
|
+
if (!/^[a-z]{3,4}$/i.test(subtag)) return void 0;
|
|
2001
|
+
}
|
|
2002
|
+
return void 0;
|
|
2003
|
+
}
|
|
2004
|
+
function languageTagProblem(tag) {
|
|
2005
|
+
if (/^[ix]-/i.test(tag)) return void 0;
|
|
2006
|
+
const parsed = canonical(tag);
|
|
2007
|
+
if (parsed === void 0) return { message: `'${tag}' is not a well-formed BCP 47 language tag (subtags are letters and digits joined by hyphens, such as 'en-US' or 'zh-Hans').`, caseOnly: false };
|
|
2008
|
+
const found = regionSubtag(tag);
|
|
2009
|
+
if (found) {
|
|
2010
|
+
const alias = REGION_ALIASES[found.region];
|
|
2011
|
+
if (alias || !assignedRegion(found.region)) {
|
|
2012
|
+
const subtags = tag.split("-");
|
|
2013
|
+
subtags[found.index] = alias ?? found.region;
|
|
2014
|
+
const suggestion = alias ? canonical(subtags.join("-")) : void 0;
|
|
2015
|
+
return {
|
|
2016
|
+
message: `'${tag}' names the region '${found.region}', which is not an assigned region${suggestion ? `; '${suggestion}' is the tag for ${new Intl.DisplayNames(["en"], { type: "region" }).of(alias)}` : ""}.`,
|
|
2017
|
+
...suggestion ? { suggestion } : {},
|
|
2018
|
+
caseOnly: false
|
|
2019
|
+
};
|
|
2020
|
+
}
|
|
2021
|
+
}
|
|
2022
|
+
if (parsed === tag) return void 0;
|
|
2023
|
+
if (parsed.toLowerCase() === tag.toLowerCase())
|
|
2024
|
+
return { message: `'${tag}' is not in canonical case; the canonical form is '${parsed}' (language lower case, script title case, region upper case).`, suggestion: parsed, caseOnly: true };
|
|
2025
|
+
const replacement = found && regionSubtag(parsed)?.region;
|
|
2026
|
+
if (found && replacement && replacement !== found.region) {
|
|
2027
|
+
const subtags = tag.split("-");
|
|
2028
|
+
subtags[found.index] = replacement;
|
|
2029
|
+
return { message: `'${tag}' names the region '${found.region}', which is deprecated; use '${replacement}'.`, suggestion: subtags.join("-"), caseOnly: false };
|
|
2030
|
+
}
|
|
2031
|
+
return void 0;
|
|
2032
|
+
}
|
|
2033
|
+
|
|
2034
|
+
// src/rules-language.ts
|
|
2035
|
+
var languageTagRule = rule(
|
|
2036
|
+
"language-tag",
|
|
2037
|
+
"content",
|
|
2038
|
+
"warning",
|
|
2039
|
+
"A language tag is malformed, uses an unassigned region or is not in canonical case.",
|
|
2040
|
+
"Engines read the deck language and each run's `lang` as BCP 47 tags to choose script fonts, text direction, proofing language and the PowerPoint `lang` attribute. A tag such as `en-a`, or a region that does not exist (`en-UK`; the United Kingdom is `GB`), is guessed at or dropped, and a wrong-case tag (`EN-us`) is not what a locale lookup expects.",
|
|
2041
|
+
{
|
|
2042
|
+
standard: "BCP 47 (RFC 5646, section 2.1) and the platform locale data (Intl.getCanonicalLocales, Intl.DisplayNames)",
|
|
2043
|
+
approximations: "Checks the root `language` (a tag string, or the `bcp47` of an inline Language object) and `lang` on the TextRun objects of titles, subtitles, tags, text, lists, tables, quotes, metrics and timelines. A region is assigned when the runtime's CLDR data names it (ISO 3166-1 codes and UN M.49 areas such as 419); private-use regions (`AA`, `QM`-`QZ`, `XA`-`XZ`) and `ZZ` are accepted, as are private-use (`x-...`) tags. Only the spelling of a tag is checked, not whether the language subtag is assigned or whether the language suits the text. The schema rejects tags with characters other than letters, digits and hyphens (`en_US` is a schema error, with no suggestion), and `en-UK` as the deck language is already an error of the schema rule, so those are not reported twice."
|
|
2044
|
+
}
|
|
2045
|
+
);
|
|
2046
|
+
var report = (context, tag, path, slide) => {
|
|
2047
|
+
if (typeof tag !== "string") return;
|
|
2048
|
+
const problem = languageTagProblem(tag);
|
|
2049
|
+
if (!problem) return;
|
|
2050
|
+
context.report(languageTagRule, {
|
|
2051
|
+
path,
|
|
2052
|
+
slide,
|
|
2053
|
+
message: problem.message,
|
|
2054
|
+
help: problem.suggestion ? `Write '${problem.suggestion}'.` : 'Write a well-formed BCP 47 tag with an assigned region, such as "en-US", "pt-BR" or "es-419".',
|
|
2055
|
+
...problem.suggestion ? { fixes: [{ id: "use-canonical-tag", title: `Use '${problem.suggestion}'`, kind: "patch", safe: problem.caseOnly, patch: [{ op: "replace", path, value: problem.suggestion }] }] } : {}
|
|
2056
|
+
});
|
|
2057
|
+
};
|
|
2058
|
+
var isEnUk = (tag) => typeof tag === "string" && tag.toLowerCase() === "en-uk";
|
|
2059
|
+
var languageTagRules = [
|
|
2060
|
+
{
|
|
2061
|
+
info: languageTagRule,
|
|
2062
|
+
run(context) {
|
|
2063
|
+
const language = context.document.language;
|
|
2064
|
+
if (typeof language === "string") {
|
|
2065
|
+
if (!isEnUk(language)) report(context, language, "/language");
|
|
2066
|
+
} else if (language !== void 0 && !isEnUk(rec(language).bcp47)) report(context, rec(language).bcp47, "/language/bcp47");
|
|
2067
|
+
for (const slide of context.slides)
|
|
2068
|
+
for (const tv of slide.texts)
|
|
2069
|
+
if (typeof tv.value !== "string") for (const run of runsOf(tv)) report(context, run.style.lang, `${run.path}/lang`, slide);
|
|
2070
|
+
}
|
|
2071
|
+
}
|
|
2072
|
+
];
|
|
2073
|
+
|
|
1947
2074
|
// src/rules-layout-content.ts
|
|
1948
2075
|
var PX_TO_PT2 = 0.75;
|
|
1949
2076
|
var round2 = (value, places = 1) => Math.round(value * 10 ** places) / 10 ** places;
|
|
@@ -2287,6 +2414,7 @@ var formatRules = [
|
|
|
2287
2414
|
rule("caption-unsupported-payload", "format", "error", "A caption is on a payload that cannot carry one.", "A caption belongs to exactly one image, chart, table or video; a group, text or code block has no place to draw it.", { standard: SCHEMA }),
|
|
2288
2415
|
rule("image-option-unsupported-payload", "format", "error", "An image option is on a payload that is not an image.", "`fit`, `focus`, the image treatments (`shape`, `cornerRadius`, `border`, `opacity`, `recolor`, `overlay`, `aspectRatio`) and `placement` describe how a picture is drawn; a group, text or chart block has no picture for them to apply to.", { standard: SCHEMA }),
|
|
2289
2416
|
rule("image-placement-invalid", "format", "error", "An image placement cannot be honoured.", "A placed image bleeds to a slide edge and the rest of the slide composes beside it. Only a top-level block (slides.N.blocks.I) can do that, and a slide edge holds one placed image; a block in a group or a promoted region, or a second block on the same edge, has nowhere to go.", { standard: SCHEMA }),
|
|
2417
|
+
rule("layout-placeholder-group", "format", "error", "A layout record's placeholder group breaks a nesting rule.", "A placeholder group arranges body regions inside one cell of its layout record. Groups nest at most three levels inside a record, and a group holds body regions and groups only: the headings (title, subtitle, tag) stay at the record's top level, where the engine places them. Composition cannot use a record that breaks either rule.", { standard: SCHEMA }),
|
|
2290
2418
|
rule("dataset-unknown", "format", "error", "A chart or table names a dataset that does not exist.", "The data cannot be drawn without the dataset it refers to.", { standard: SCHEMA }),
|
|
2291
2419
|
rule("dataset-field-unknown", "format", "error", "A table asks a dataset for a column it does not have.", "The column cannot be shown when the dataset has no column of that name.", { standard: SCHEMA }),
|
|
2292
2420
|
rule("data-column-duplicate", "format", "error", "A dataset or table has two columns with the same name.", "Series, mappings and fields address columns by name, so a repeated name makes them ambiguous.", { standard: SCHEMA }),
|
|
@@ -2381,7 +2509,7 @@ var dataRules = [
|
|
|
2381
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 }),
|
|
2382
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" })
|
|
2383
2511
|
];
|
|
2384
|
-
var implementations = [...accessibilityRules, ...layoutContentRules];
|
|
2512
|
+
var implementations = [...accessibilityRules, ...layoutContentRules, ...languageTagRules];
|
|
2385
2513
|
var ruleImplementations = implementations;
|
|
2386
2514
|
var infos = [
|
|
2387
2515
|
...formatRules,
|
|
@@ -3248,12 +3376,12 @@ var OPFValidationError = class extends Error {
|
|
|
3248
3376
|
report;
|
|
3249
3377
|
/** The error-severity findings of the report. */
|
|
3250
3378
|
findings;
|
|
3251
|
-
constructor(
|
|
3252
|
-
const errors =
|
|
3379
|
+
constructor(report2) {
|
|
3380
|
+
const errors = report2.findings.filter((entry) => entry.severity === "error");
|
|
3253
3381
|
const first = errors[0];
|
|
3254
3382
|
super(first ? `OPF validation failed at ${first.path || "/"}: ${first.message}` : "OPF validation failed");
|
|
3255
3383
|
this.name = "OPFValidationError";
|
|
3256
|
-
this.report =
|
|
3384
|
+
this.report = report2;
|
|
3257
3385
|
this.findings = errors;
|
|
3258
3386
|
}
|
|
3259
3387
|
};
|
|
@@ -3486,8 +3614,8 @@ function validate(input, options = {}) {
|
|
|
3486
3614
|
}
|
|
3487
3615
|
function assertValid(value, options = {}) {
|
|
3488
3616
|
if (typeof value === "string") throw new TypeError("assertValid takes a parsed presentation. Use validate(text) for JSON text.");
|
|
3489
|
-
const
|
|
3490
|
-
if (!
|
|
3617
|
+
const report2 = validate(value, options);
|
|
3618
|
+
if (!report2.valid) throw new OPFValidationError(report2);
|
|
3491
3619
|
}
|
|
3492
3620
|
function validateCatalogRecord(kind, value) {
|
|
3493
3621
|
const kinds = Object.keys(catalogSchemaNames);
|
|
@@ -3508,8 +3636,8 @@ function validateCatalogRecord(kind, value) {
|
|
|
3508
3636
|
return { valid: tally.error === 0, schemaValid: engine.valid, findings, counts: tally, checks };
|
|
3509
3637
|
}
|
|
3510
3638
|
function assertValidCatalogRecord(kind, value) {
|
|
3511
|
-
const
|
|
3512
|
-
if (!
|
|
3639
|
+
const report2 = validateCatalogRecord(kind, value);
|
|
3640
|
+
if (!report2.valid) throw new OPFValidationError(report2);
|
|
3513
3641
|
}
|
|
3514
3642
|
|
|
3515
|
-
export { DEFAULT_CHART_PALETTE, DEFAULT_VALIDATION_THRESHOLDS, OPFValidationError, assertValid, assertValidCatalogRecord, findValidationRule, resolveSlideContext, validate, validateCatalogRecord, validationCategories, validationRules };
|
|
3643
|
+
export { DEFAULT_CHART_PALETTE, DEFAULT_VALIDATION_THRESHOLDS, OPFValidationError, assertValid, assertValidCatalogRecord, findValidationRule, parseSource, resolveSlideContext, validate, validateCatalogRecord, validationCategories, validationRules };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { chartNumber } from './chunk-
|
|
1
|
+
import { chartNumber } from './chunk-5PDN7BN6.js';
|
|
2
2
|
|
|
3
3
|
// src/data.ts
|
|
4
4
|
var OPFDataImportError = class extends Error {
|
|
@@ -138,7 +138,10 @@ function importData(input, options) {
|
|
|
138
138
|
if (circular && numeric < 0) fail(`Row ${i + 1}: pie and donut values cannot be negative.`);
|
|
139
139
|
return numeric;
|
|
140
140
|
}));
|
|
141
|
-
return { chart: { type: options.chartType ?? "column", data: {
|
|
141
|
+
return { chart: { type: options.chartType ?? "column", data: {
|
|
142
|
+
columns: names,
|
|
143
|
+
rows
|
|
144
|
+
} } };
|
|
142
145
|
}
|
|
143
146
|
|
|
144
147
|
export { OPFDataImportError, importData, parseTabularData };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { jsonEqual, formatPointer } from './chunk-
|
|
2
|
-
import { annotationText } from './chunk-
|
|
1
|
+
import { jsonEqual, formatPointer } from './chunk-3XDRQYWZ.js';
|
|
2
|
+
import { annotationText } from './chunk-5PDN7BN6.js';
|
|
3
3
|
|
|
4
4
|
// src/diff-match.ts
|
|
5
5
|
var DEFAULT_MATCH_THRESHOLD = 0.5;
|
|
@@ -1217,7 +1217,7 @@ var presentation = {
|
|
|
1217
1217
|
"left",
|
|
1218
1218
|
"right"
|
|
1219
1219
|
],
|
|
1220
|
-
"description": "Where the primary chart sits relative to supporting content. Effective value: slide design, then deck design, then the layout record's design.chartPrimary. When the slide has no promoted regions and no composition.mode of its own, and its root nodes mix at least one chart with other content, the first chart becomes a primary track and the other nodes form one synthetic sub-grid: 'left'/'right' is a two-track row and 'top'/'bottom' a two-track column, weighted 3:2 in favor of the chart; explicit root columns and weights are ignored while it applies. 'none' (the default) keeps the ordinary automatic grid with equal weight."
|
|
1220
|
+
"description": "Where the primary chart sits relative to supporting content. Effective value: slide design, then deck design, then the layout record's design.chartPrimary. When the slide has no promoted regions and no composition.mode of its own, and its root nodes mix at least one chart with other content, the first chart becomes a primary track and the other nodes form one synthetic sub-grid: 'left'/'right' is a two-track row and 'top'/'bottom' a two-track column, weighted 3:2 in favor of the chart; explicit root columns and weights are ignored while it applies. 'none' (the default) keeps the ordinary automatic grid with equal weight. It is shorthand for a placeholder group (layout.schema.json PlaceholderGroup): the slide composes exactly as on a layout record whose root composition is that weighted row or column and whose placeholders are the chart and one automatic group of the other content, and while it applies it replaces the layout record's own placeholder groups as well."
|
|
1221
1221
|
},
|
|
1222
1222
|
"imageFit": {
|
|
1223
1223
|
"type": "string",
|
|
@@ -2846,14 +2846,14 @@ var presentation = {
|
|
|
2846
2846
|
"items": {
|
|
2847
2847
|
"$ref": "#/$defs/ListItem"
|
|
2848
2848
|
},
|
|
2849
|
-
"description": "Full-slide
|
|
2849
|
+
"description": "Full-slide structured list payload. Presence of this field infers type 'list'. Entries are strings, TextRun[] or objects with `text`, optional `description` (supporting detail under the entry), `level` and `start`. Use `items` when entries share a shape (features, steps, options, risks) or any entry needs a `description`; use `bullets` for plain talking points. Both draw the same marker, nesting and numbering; they differ in the inferred kind and in `description`, which only `items` accepts. At slide root, multiple content payload kinds with no explicit type, blocks, or regions are accepted as shorthand for layout-agnostic blocks, so `items` next to `text` or `bullets` composes as separate blocks side by side."
|
|
2850
2850
|
},
|
|
2851
2851
|
"bullets": {
|
|
2852
2852
|
"type": "array",
|
|
2853
2853
|
"items": {
|
|
2854
2854
|
"$ref": "#/$defs/BulletItem"
|
|
2855
2855
|
},
|
|
2856
|
-
"description": "Full-slide
|
|
2856
|
+
"description": "Full-slide prose bullet payload: short talking points, each standing alone. Presence of this field infers type 'text', so it may sit beside `text` in one payload. Entries are strings, TextRun[] or objects with `text`, `level` and `start`; there is no `description` (use `items` for entries with supporting detail)."
|
|
2857
2857
|
},
|
|
2858
2858
|
"numbering": {
|
|
2859
2859
|
"$ref": "#/$defs/NumberingSpec",
|
|
@@ -3187,7 +3187,7 @@ var presentation = {
|
|
|
3187
3187
|
"items": {
|
|
3188
3188
|
"$ref": "#/$defs/ListItem"
|
|
3189
3189
|
},
|
|
3190
|
-
"description": "
|
|
3190
|
+
"description": "Structured list payload (type 'list'). Each item is either a plain string, a TextRun[] rich text sequence, or a ListItem object with optional `description`. List nesting uses item.level rather than nested content payloads. Use `items` when entries share a shape or any entry needs a `description`; use `bullets` for plain talking points. Both draw the same marker, nesting and numbering. A block or region holds `items` or `bullets`, never both, and `items` cannot sit beside `text`.",
|
|
3191
3191
|
"examples": [
|
|
3192
3192
|
[
|
|
3193
3193
|
"Sub-second agent latency",
|
|
@@ -3210,7 +3210,7 @@ var presentation = {
|
|
|
3210
3210
|
"items": {
|
|
3211
3211
|
"$ref": "#/$defs/BulletItem"
|
|
3212
3212
|
},
|
|
3213
|
-
"description": "
|
|
3213
|
+
"description": "Prose bullet payload: short talking points, each standing alone. Presence of this field infers type 'text', so it may sit beside `text` in one payload. Entries have no `description`; use `items` for entries with supporting detail.",
|
|
3214
3214
|
"examples": [
|
|
3215
3215
|
[
|
|
3216
3216
|
"Sub-second agent latency",
|
|
@@ -4822,6 +4822,13 @@ var presentation = {
|
|
|
4822
4822
|
"fields": {
|
|
4823
4823
|
"$ref": "#/$defs/DatasetFields",
|
|
4824
4824
|
"description": "Dataset tables only: the dataset columns to show, by name and in order. Absent shows every column. An unknown name is a 'dataset-field-unknown' error."
|
|
4825
|
+
},
|
|
4826
|
+
"alt": {
|
|
4827
|
+
"type": "string",
|
|
4828
|
+
"description": "Text alternative for the table: what it shows (the point and the key numbers), not 'a table'. The preview exposes it as the table's accessible name (role group with aria-label; the cells stay readable) and the PowerPoint export writes it as the table frame's alternative text (descr); import reads it back. An empty string hides a purely decorative table, with the same meaning as an empty Asset alt. The alt is a summary read before the cells, which stay readable, so it is most useful for a large or dense table; validate does not require one and does not report a missing one.",
|
|
4829
|
+
"examples": [
|
|
4830
|
+
"North America grew 46% to $18.1M in Q4, ahead of EMEA at 40%."
|
|
4831
|
+
]
|
|
4825
4832
|
}
|
|
4826
4833
|
}
|
|
4827
4834
|
},
|
|
@@ -5708,7 +5715,7 @@ var presentation = {
|
|
|
5708
5715
|
"Composition": {
|
|
5709
5716
|
"type": "object",
|
|
5710
5717
|
"additionalProperties": false,
|
|
5711
|
-
"description": "Portable dynamic composition. Slide fields override the resolved layout. Nested groups arrange their children independently, inheriting only minFontSize and overflow. Explicit promoted regions retain their positions.",
|
|
5718
|
+
"description": "Portable dynamic composition. Slide fields override the resolved layout. Nested groups (content groups here, placeholder groups in a layout record) arrange their children independently, inheriting only minFontSize and overflow. Explicit promoted regions retain their positions.",
|
|
5712
5719
|
"properties": {
|
|
5713
5720
|
"mode": {
|
|
5714
5721
|
"type": "string",
|
|
@@ -6453,9 +6460,9 @@ var layout = {
|
|
|
6453
6460
|
"placeholders": {
|
|
6454
6461
|
"type": "array",
|
|
6455
6462
|
"items": {
|
|
6456
|
-
"$ref": "#/$defs/
|
|
6463
|
+
"$ref": "#/$defs/PlaceholderEntry"
|
|
6457
6464
|
},
|
|
6458
|
-
"description":
|
|
6465
|
+
"description": `Ordered regions the layout exposes. This is the single source of truth for what the layout holds: the content kind, the number of body regions and whether it has a title, subtitle or tag are derived from it (layoutContent in @openpresentation/opf, which counts the leaves of placeholder groups), never stored separately. The engine fills 'title', 'subtitle' and 'tag' placeholders from Slide.title, Slide.subtitle and Slide.tag. The other placeholders are content-kind regions that composition uses to size the body and that pickers use to match layouts. An entry may instead be a placeholder group ({ "type": "group", "composition", "placeholders" }) that arranges its own regions inside one cell of this record's composition, so a record can say 'two stacked panels beside a chart' once; groups nest at most three levels. Slide content stays flat: its body payloads fill the leaf regions in reading order (depth first, in array order). Slide content itself lives either in root payload fields, blocks or promoted region keys on Slide. Chrome (slide number, footer, date) is not included here; it is owned by Design.header / Design.footer.`
|
|
6459
6466
|
},
|
|
6460
6467
|
"tags": {
|
|
6461
6468
|
"type": "array",
|
|
@@ -6513,6 +6520,173 @@ var layout = {
|
|
|
6513
6520
|
}
|
|
6514
6521
|
},
|
|
6515
6522
|
"$defs": {
|
|
6523
|
+
"PlaceholderEntry": {
|
|
6524
|
+
"description": "One entry of a layout's placeholders: a region (Placeholder) or, when its type is 'group', a placeholder group (PlaceholderGroup).",
|
|
6525
|
+
"if": {
|
|
6526
|
+
"type": "object",
|
|
6527
|
+
"required": [
|
|
6528
|
+
"type"
|
|
6529
|
+
],
|
|
6530
|
+
"properties": {
|
|
6531
|
+
"type": {
|
|
6532
|
+
"const": "group"
|
|
6533
|
+
}
|
|
6534
|
+
}
|
|
6535
|
+
},
|
|
6536
|
+
"then": {
|
|
6537
|
+
"$ref": "#/$defs/PlaceholderGroup"
|
|
6538
|
+
},
|
|
6539
|
+
"else": {
|
|
6540
|
+
"$ref": "#/$defs/Placeholder"
|
|
6541
|
+
}
|
|
6542
|
+
},
|
|
6543
|
+
"PlaceholderGroup": {
|
|
6544
|
+
"type": "object",
|
|
6545
|
+
"additionalProperties": false,
|
|
6546
|
+
"required": [
|
|
6547
|
+
"type",
|
|
6548
|
+
"placeholders"
|
|
6549
|
+
],
|
|
6550
|
+
"description": "A placeholder group: regions arranged by their own composition inside one cell of the record's composition, the way a content group (a block with blocks) arranges its children. Slide content fills the group's leaf regions in reading order, as part of one flat sequence for the whole record. A group holds body regions and groups only (no title, subtitle or tag, and no placement), and groups nest at most three levels inside a record: this is the first. Groups draw nothing of their own and have no slide path; design.chartPrimary is shorthand for a record whose root holds the chart and one group of the other content.",
|
|
6551
|
+
"properties": {
|
|
6552
|
+
"type": {
|
|
6553
|
+
"const": "group",
|
|
6554
|
+
"description": "Marks the entry as a placeholder group."
|
|
6555
|
+
},
|
|
6556
|
+
"composition": {
|
|
6557
|
+
"$ref": "#/$defs/Composition",
|
|
6558
|
+
"description": "How the group arranges its regions, with the semantics of a content group's composition: only minFontSize and overflow inherit from the enclosing composition; padding defaults to 0 and gap is a fraction of the group's short edge. Omitted, the group arranges its regions automatically."
|
|
6559
|
+
},
|
|
6560
|
+
"placeholders": {
|
|
6561
|
+
"type": "array",
|
|
6562
|
+
"minItems": 1,
|
|
6563
|
+
"items": {
|
|
6564
|
+
"$ref": "#/$defs/PlaceholderGroupEntry2"
|
|
6565
|
+
},
|
|
6566
|
+
"description": "The group's regions and nested groups, in reading order."
|
|
6567
|
+
}
|
|
6568
|
+
}
|
|
6569
|
+
},
|
|
6570
|
+
"PlaceholderGroupEntry2": {
|
|
6571
|
+
"description": "An entry of a first-level group: a region (GroupedPlaceholder) or a second-level group (PlaceholderGroup2).",
|
|
6572
|
+
"if": {
|
|
6573
|
+
"type": "object",
|
|
6574
|
+
"required": [
|
|
6575
|
+
"type"
|
|
6576
|
+
],
|
|
6577
|
+
"properties": {
|
|
6578
|
+
"type": {
|
|
6579
|
+
"const": "group"
|
|
6580
|
+
}
|
|
6581
|
+
}
|
|
6582
|
+
},
|
|
6583
|
+
"then": {
|
|
6584
|
+
"$ref": "#/$defs/PlaceholderGroup2"
|
|
6585
|
+
},
|
|
6586
|
+
"else": {
|
|
6587
|
+
"$ref": "#/$defs/GroupedPlaceholder"
|
|
6588
|
+
}
|
|
6589
|
+
},
|
|
6590
|
+
"PlaceholderGroup2": {
|
|
6591
|
+
"type": "object",
|
|
6592
|
+
"additionalProperties": false,
|
|
6593
|
+
"required": [
|
|
6594
|
+
"type",
|
|
6595
|
+
"placeholders"
|
|
6596
|
+
],
|
|
6597
|
+
"description": "A placeholder group nested in another (the second level). Same fields as PlaceholderGroup.",
|
|
6598
|
+
"properties": {
|
|
6599
|
+
"type": {
|
|
6600
|
+
"const": "group",
|
|
6601
|
+
"description": "Marks the entry as a placeholder group."
|
|
6602
|
+
},
|
|
6603
|
+
"composition": {
|
|
6604
|
+
"$ref": "#/$defs/Composition",
|
|
6605
|
+
"description": "How the group arranges its regions; see PlaceholderGroup.composition."
|
|
6606
|
+
},
|
|
6607
|
+
"placeholders": {
|
|
6608
|
+
"type": "array",
|
|
6609
|
+
"minItems": 1,
|
|
6610
|
+
"items": {
|
|
6611
|
+
"$ref": "#/$defs/PlaceholderGroupEntry3"
|
|
6612
|
+
},
|
|
6613
|
+
"description": "The group's regions and nested groups, in reading order."
|
|
6614
|
+
}
|
|
6615
|
+
}
|
|
6616
|
+
},
|
|
6617
|
+
"PlaceholderGroupEntry3": {
|
|
6618
|
+
"description": "An entry of a second-level group: a region (GroupedPlaceholder) or a third-level group (PlaceholderGroup3).",
|
|
6619
|
+
"if": {
|
|
6620
|
+
"type": "object",
|
|
6621
|
+
"required": [
|
|
6622
|
+
"type"
|
|
6623
|
+
],
|
|
6624
|
+
"properties": {
|
|
6625
|
+
"type": {
|
|
6626
|
+
"const": "group"
|
|
6627
|
+
}
|
|
6628
|
+
}
|
|
6629
|
+
},
|
|
6630
|
+
"then": {
|
|
6631
|
+
"$ref": "#/$defs/PlaceholderGroup3"
|
|
6632
|
+
},
|
|
6633
|
+
"else": {
|
|
6634
|
+
"$ref": "#/$defs/GroupedPlaceholder"
|
|
6635
|
+
}
|
|
6636
|
+
},
|
|
6637
|
+
"PlaceholderGroup3": {
|
|
6638
|
+
"type": "object",
|
|
6639
|
+
"additionalProperties": false,
|
|
6640
|
+
"required": [
|
|
6641
|
+
"type",
|
|
6642
|
+
"placeholders"
|
|
6643
|
+
],
|
|
6644
|
+
"description": "The innermost placeholder group (the third level): it holds regions only, never another group.",
|
|
6645
|
+
"properties": {
|
|
6646
|
+
"type": {
|
|
6647
|
+
"const": "group",
|
|
6648
|
+
"description": "Marks the entry as a placeholder group."
|
|
6649
|
+
},
|
|
6650
|
+
"composition": {
|
|
6651
|
+
"$ref": "#/$defs/Composition",
|
|
6652
|
+
"description": "How the group arranges its regions; see PlaceholderGroup.composition."
|
|
6653
|
+
},
|
|
6654
|
+
"placeholders": {
|
|
6655
|
+
"type": "array",
|
|
6656
|
+
"minItems": 1,
|
|
6657
|
+
"items": {
|
|
6658
|
+
"$ref": "#/$defs/GroupedPlaceholder"
|
|
6659
|
+
},
|
|
6660
|
+
"description": "The group's regions, in reading order."
|
|
6661
|
+
}
|
|
6662
|
+
}
|
|
6663
|
+
},
|
|
6664
|
+
"GroupedPlaceholder": {
|
|
6665
|
+
"type": "object",
|
|
6666
|
+
"additionalProperties": false,
|
|
6667
|
+
"required": [
|
|
6668
|
+
"type"
|
|
6669
|
+
],
|
|
6670
|
+
"description": "A region inside a placeholder group: a body content kind only. Headings ('title', 'subtitle', 'tag') stay at the record's top level, and only a top-level image placeholder may carry a placement.",
|
|
6671
|
+
"properties": {
|
|
6672
|
+
"type": {
|
|
6673
|
+
"type": "string",
|
|
6674
|
+
"enum": [
|
|
6675
|
+
"text",
|
|
6676
|
+
"list",
|
|
6677
|
+
"image",
|
|
6678
|
+
"video",
|
|
6679
|
+
"chart",
|
|
6680
|
+
"table",
|
|
6681
|
+
"code",
|
|
6682
|
+
"metric",
|
|
6683
|
+
"quote",
|
|
6684
|
+
"timeline"
|
|
6685
|
+
],
|
|
6686
|
+
"description": "The content kind of the region, from the one OPF content-kind vocabulary (see Placeholder.type)."
|
|
6687
|
+
}
|
|
6688
|
+
}
|
|
6689
|
+
},
|
|
6516
6690
|
"Placeholder": {
|
|
6517
6691
|
"type": "object",
|
|
6518
6692
|
"required": [
|
|
@@ -6553,7 +6727,7 @@ var layout = {
|
|
|
6553
6727
|
},
|
|
6554
6728
|
"placement": {
|
|
6555
6729
|
"$ref": "#/$defs/ImagePlacement",
|
|
6556
|
-
"description": "Image placeholders only. Bleeds the slide's image for this region to one slide edge, as an image block's placement does: the n-th image placeholder places the slide's n-th top-level image (Slide.image or an image block in blocks) unless that block sets its own placement. The headings and the other content compose in the rest of the slide."
|
|
6730
|
+
"description": "Image placeholders only. Bleeds the slide's image for this region to one slide edge, as an image block's placement does: the n-th image placeholder (counting the image regions of placeholder groups too, in reading order) places the slide's n-th top-level image (Slide.image or an image block in blocks) unless that block sets its own placement. Only a top-level image placeholder may carry a placement; a region inside a placeholder group cannot bleed to a slide edge. The headings and the other content compose in the rest of the slide."
|
|
6557
6731
|
}
|
|
6558
6732
|
}
|
|
6559
6733
|
},
|
|
@@ -6631,7 +6805,7 @@ var layout = {
|
|
|
6631
6805
|
"left",
|
|
6632
6806
|
"right"
|
|
6633
6807
|
],
|
|
6634
|
-
"description": "Where the primary chart sits relative to the other body content. Composition applies it below the slide's and the deck's design.chartPrimary, with the semantics described there."
|
|
6808
|
+
"description": "Where the primary chart sits relative to the other body content. Composition applies it below the slide's and the deck's design.chartPrimary, with the semantics described there. It is shorthand for a placeholder group: a record can state the same structure explicitly as a root row or column of the chart and one PlaceholderGroup of the other regions, weighted 3:2."
|
|
6635
6809
|
},
|
|
6636
6810
|
"imageFit": {
|
|
6637
6811
|
"type": "string",
|
|
@@ -6655,7 +6829,7 @@ var layout = {
|
|
|
6655
6829
|
"Composition": {
|
|
6656
6830
|
"type": "object",
|
|
6657
6831
|
"additionalProperties": false,
|
|
6658
|
-
"description": "Portable dynamic composition. Slide fields override the resolved layout. Nested groups arrange their children independently, inheriting only minFontSize and overflow. Explicit promoted regions retain their positions.",
|
|
6832
|
+
"description": "Portable dynamic composition. Slide fields override the resolved layout. Nested groups (placeholder groups here, content groups in a slide) arrange their children independently, inheriting only minFontSize and overflow. Explicit promoted regions retain their positions.",
|
|
6659
6833
|
"properties": {
|
|
6660
6834
|
"mode": {
|
|
6661
6835
|
"type": "string",
|