@json-to-office/core-pptx 6.4.1 → 6.8.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/dist/core/finalizePackage.d.ts +1 -0
- package/dist/core/finalizePackage.d.ts.map +1 -1
- package/dist/core/generateFromIr.d.ts +1 -0
- package/dist/core/generateFromIr.d.ts.map +1 -1
- package/dist/core/generationOptions.d.ts +1 -0
- package/dist/core/generationOptions.d.ts.map +1 -1
- package/dist/core/generator.d.ts +1 -0
- package/dist/core/generator.d.ts.map +1 -1
- package/dist/index.js +254 -67
- package/dist/index.js.map +1 -1
- package/dist/plugin/types.d.ts +1 -0
- package/dist/plugin/types.d.ts.map +1 -1
- package/dist/quality/facts.d.ts +43 -1
- package/dist/quality/facts.d.ts.map +1 -1
- package/dist/quality/rules.d.ts +24 -9
- package/dist/quality/rules.d.ts.map +1 -1
- package/dist/renderers/office-open/index.d.ts.map +1 -1
- package/dist/renderers/pptxgenjs/packaging.d.ts +1 -0
- package/dist/renderers/pptxgenjs/packaging.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -6
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* package is still read once and written once.
|
|
13
13
|
*/
|
|
14
14
|
/// <reference types="node" />
|
|
15
|
+
/// <reference types="node" />
|
|
15
16
|
import JSZip from 'jszip';
|
|
16
17
|
/** Stable default shared by package entries and OOXML core metadata. */
|
|
17
18
|
export declare const DEFAULT_GENERATED_AT = "2000-01-01T00:00:00.000Z";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"finalizePackage.d.ts","sourceRoot":"","sources":["../../src/core/finalizePackage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG
|
|
1
|
+
{"version":3,"file":"finalizePackage.d.ts","sourceRoot":"","sources":["../../src/core/finalizePackage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;;;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,wEAAwE;AACxE,eAAO,MAAM,oBAAoB,6BAA6B,CAAC;AAE/D,8DAA8D;AAC9D,MAAM,WAAW,4BAA4B;IAC3C,+DAA+D;IAC/D,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,0DAA0D;IAC1D,WAAW,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;CAC7B;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAEhE;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAE9D;AAED,wBAAgB,kBAAkB,CAAC,KAAK,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAY9D;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,KAAK,EACV,WAAW,EAAE,IAAI,GAChB,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,uDAAuD;AACvD,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,IAAI,GAAG,MAAM,CAAA;CAAO,GAC5C,OAAO,CAAC,MAAM,CAAC,CAIjB"}
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* this function refuses rather than shipping a deck with content missing.
|
|
14
14
|
*/
|
|
15
15
|
/// <reference types="node" />
|
|
16
|
+
/// <reference types="node" />
|
|
16
17
|
import { compilePresentation } from '../ir/compiler';
|
|
17
18
|
import type { PptxIR } from '../ir/types';
|
|
18
19
|
import type { PipelineWarning, PresentationComponentDefinition, ProcessedPresentation } from '../types';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateFromIr.d.ts","sourceRoot":"","sources":["../../src/core/generateFromIr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG
|
|
1
|
+
{"version":3,"file":"generateFromIr.d.ts","sourceRoot":"","sources":["../../src/core/generateFromIr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;;;AAKH,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,KAAK,EACV,eAAe,EACf,+BAA+B,EAC/B,qBAAqB,EACtB,MAAM,UAAU,CAAC;AAIlB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,qBAAqB,CAAC;AAK7B,uEAAuE;AACvE,MAAM,MAAM,mBAAmB,GAAG,iBAAiB,CAAC;AAEpD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;IACjD,SAAgB,IAAI,0BAA0B;IAC9C,SAAgB,UAAU,EAAE,aAAa,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;gBAE9D,UAAU,EAAE,aAAa,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAYtE;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,GAAG,+BAA+B,EACpD,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC;IACT,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,QAAQ,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,UAAU,CAAC,CAAC;IAC7D,WAAW,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,aAAa,CAAC,CAAC;CACpE,CAAC,CAsCD;AAED,0EAA0E;AAC1E,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,GAAG,+BAA+B,EACpD,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,kBAAkB,CAAC,CAkD7B;AAED;;;;;;;;;GASG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,qBAAqB,EAChC,QAAQ,EAAE,eAAe,EAAE,EAC3B,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,MAAM,CAAC,CAkCjB;AAED,0DAA0D;AAC1D,MAAM,MAAM,eAAe,GAAG,IAAI,CAChC,iBAAiB,EACjB,UAAU,GAAG,UAAU,GAAG,eAAe,GAAG,aAAa,CAC1D,GAAG;IACF,6EAA6E;IAC7E,UAAU,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;CAC3C,CAAC;AAEF,0EAA0E;AAC1E,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,qBAAqB,GAClC,OAAO,CAiBT"}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* importing the module that now delegates to it.
|
|
6
6
|
*/
|
|
7
7
|
/// <reference types="node" />
|
|
8
|
+
/// <reference types="node" />
|
|
8
9
|
import type { ServicesConfig, FontRuntimeOpts } from '@json-to-office/shared';
|
|
9
10
|
import { type ValidationError } from '@json-to-office/shared-pptx';
|
|
10
11
|
import type { PipelineWarning, PptxThemeConfig, PresentationComponentDefinition } from '../types';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generationOptions.d.ts","sourceRoot":"","sources":["../../src/core/generationOptions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG
|
|
1
|
+
{"version":3,"file":"generationOptions.d.ts","sourceRoot":"","sources":["../../src/core/generationOptions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,+BAA+B,EAChC,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAC;AACtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAE1E,MAAM,WAAW,2BAA2B;IAC1C,+EAA+E;IAC/E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,4EAA4E;IAC5E,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,iBAAkB,SAAQ,4BAA4B;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC/C;;;;OAIG;IACH,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,UAAU,CAAC,EAAE,2BAA2B,CAAC;IACzC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,kFAAkF;IAClF,QAAQ,CAAC,EAAE,gBAAgB,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAC;IAC/D;;;;OAIG;IACH,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7C;;;;OAIG;IACH,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAC;CAC9B;AAED,gDAAgD;AAChD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAED,6EAA6E;AAC7E,qBAAa,2BAA4B,SAAQ,KAAK;IACpD,SAAgB,MAAM,EAAE,eAAe,EAAE,CAAC;gBAE9B,MAAM,EAAE,eAAe,EAAE;CAStC;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,GAAG,OAAO,EACvB,UAAU,CAAC,EAAE,2BAA2B,GACvC,IAAI,CAEN;AAED,4EAA4E;AAC5E,wBAAgB,oCAAoC,CAClD,KAAK,EAAE,MAAM,GAAG,OAAO,EACvB,UAAU,CAAC,EAAE,2BAA2B,GACvC,IAAI,CAEN;AA2BD;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAYhE;AAED,0DAA0D;AAC1D,wBAAgB,iCAAiC,CAC/C,UAAU,EAAE,OAAO,GAClB,UAAU,IAAI,+BAA+B,CAI/C"}
|
package/dist/core/generator.d.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* produced — see `src/__tests__/corpus-goldens.test.ts`.
|
|
8
8
|
*/
|
|
9
9
|
/// <reference types="node" />
|
|
10
|
+
/// <reference types="node" />
|
|
10
11
|
import type { PipelineWarning, PresentationComponentDefinition } from '../types';
|
|
11
12
|
export { PresentationValidationError, assertNoContentConflicts, assertValidPresentation, isPresentationComponentDefinition, } from './generationOptions';
|
|
12
13
|
export type { GenerationOptions, GenerationResult, GenerationValidationOptions, } from './generationOptions';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/core/generator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/core/generator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;;;AAGH,OAAO,KAAK,EACV,eAAe,EACf,+BAA+B,EAChC,MAAM,UAAU,CAAC;AAGlB,OAAO,EACL,2BAA2B,EAC3B,wBAAwB,EACxB,uBAAuB,EACvB,iCAAiC,GAClC,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,iBAAiB,EACjB,gBAAgB,EAChB,2BAA2B,GAC5B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,iCAAiC,EACjC,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACtB,MAAM,qBAAqB,CAAC;AAE7B;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,UAAU,EAAE,MAAM,GAAG,+BAA+B,EACpD,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED;;GAEG;AACH,wBAAsB,0BAA0B,CAC9C,UAAU,EAAE,MAAM,GAAG,+BAA+B,EACpD,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,gBAAgB,CAAC,CAG3B;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,GAAG,+BAA+B,EACpD,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAGf;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAIf;AAED,YAAY,EAAE,eAAe,EAAE,CAAC;AAEhC;;;;GAIG;AACH,eAAO,MAAM,qBAAqB;;;;;;CAMjC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1895,6 +1895,7 @@ __export(office_open_exports, {
|
|
|
1895
1895
|
createOfficeOpenPptxRenderer: () => createOfficeOpenPptxRenderer
|
|
1896
1896
|
});
|
|
1897
1897
|
import { readFile } from "fs/promises";
|
|
1898
|
+
import { assetUnreadableError } from "@json-to-office/shared/rendering";
|
|
1898
1899
|
async function createOfficeOpenPptxRenderer() {
|
|
1899
1900
|
const backend = await import(
|
|
1900
1901
|
/* @vite-ignore */
|
|
@@ -1993,32 +1994,28 @@ function colorSchemeOptions(palette) {
|
|
|
1993
1994
|
}
|
|
1994
1995
|
async function loadResourceBytes(resources) {
|
|
1995
1996
|
const entries = await Promise.all(
|
|
1996
|
-
resources.map(
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
return [resource.id, resource.origin.bytes];
|
|
2000
|
-
case "file":
|
|
2001
|
-
return [
|
|
2002
|
-
resource.id,
|
|
2003
|
-
new Uint8Array(await readFile(resource.origin.path))
|
|
2004
|
-
];
|
|
2005
|
-
case "remote": {
|
|
2006
|
-
const response = await fetch(resource.origin.url);
|
|
2007
|
-
if (!response.ok) {
|
|
2008
|
-
throw new Error(
|
|
2009
|
-
`failed to fetch image ${resource.origin.url}: ${response.status} ${response.statusText}`
|
|
2010
|
-
);
|
|
2011
|
-
}
|
|
2012
|
-
return [
|
|
2013
|
-
resource.id,
|
|
2014
|
-
new Uint8Array(await response.arrayBuffer())
|
|
2015
|
-
];
|
|
2016
|
-
}
|
|
2017
|
-
}
|
|
2018
|
-
})
|
|
1997
|
+
resources.map(
|
|
1998
|
+
async (resource) => [resource.id, await resourceBytes(resource.origin)]
|
|
1999
|
+
)
|
|
2019
2000
|
);
|
|
2020
2001
|
return new Map(entries);
|
|
2021
2002
|
}
|
|
2003
|
+
async function resourceBytes(origin) {
|
|
2004
|
+
if (origin.kind === "inline") return origin.bytes;
|
|
2005
|
+
const location = origin.kind === "file" ? origin.path : origin.url;
|
|
2006
|
+
try {
|
|
2007
|
+
if (origin.kind === "file") {
|
|
2008
|
+
return new Uint8Array(await readFile(origin.path));
|
|
2009
|
+
}
|
|
2010
|
+
const response = await fetch(origin.url);
|
|
2011
|
+
if (!response.ok) {
|
|
2012
|
+
throw new Error(`HTTP ${response.status} ${response.statusText}`);
|
|
2013
|
+
}
|
|
2014
|
+
return new Uint8Array(await response.arrayBuffer());
|
|
2015
|
+
} catch (error) {
|
|
2016
|
+
throw assetUnreadableError(location, error);
|
|
2017
|
+
}
|
|
2018
|
+
}
|
|
2022
2019
|
var OFFICE_OPEN_PPTX_RENDERER_ID, OFFICE_OPEN_PPTX, OFFICE_OPEN_CAPABILITIES, SCHEME_SLOTS;
|
|
2023
2020
|
var init_office_open = __esm({
|
|
2024
2021
|
"src/renderers/office-open/index.ts"() {
|
|
@@ -5975,6 +5972,37 @@ function horizontalAlign(props, ctx) {
|
|
|
5975
5972
|
const styled = typeof props.style === "string" ? ctx.styles[props.style]?.align : void 0;
|
|
5976
5973
|
return styled && HORIZONTAL_ALIGNMENTS.has(styled) ? styled : "left";
|
|
5977
5974
|
}
|
|
5975
|
+
var BLEED_TOLERANCE_PT = 2;
|
|
5976
|
+
var NOT_BODY_STYLES = /* @__PURE__ */ new Set([
|
|
5977
|
+
"title",
|
|
5978
|
+
"subtitle",
|
|
5979
|
+
"display",
|
|
5980
|
+
"tracker",
|
|
5981
|
+
"footer",
|
|
5982
|
+
"source"
|
|
5983
|
+
]);
|
|
5984
|
+
function imageBox(node, box, statedPropsAt) {
|
|
5985
|
+
if (node.componentName !== "image" || !isCompleteBox(box)) return box;
|
|
5986
|
+
const ratio = readablePptxRatio(node.props);
|
|
5987
|
+
if (ratio === void 0 || ratio <= 0) return box;
|
|
5988
|
+
const authored = statedPropsAt(node.path) ?? node.props;
|
|
5989
|
+
const statesWidth = authored.w !== void 0;
|
|
5990
|
+
const statesHeight = authored.h !== void 0;
|
|
5991
|
+
if (statesWidth && !statesHeight)
|
|
5992
|
+
return { ...box, heightPt: box.widthPt / ratio };
|
|
5993
|
+
if (statesHeight && !statesWidth)
|
|
5994
|
+
return { ...box, widthPt: box.heightPt * ratio };
|
|
5995
|
+
return box;
|
|
5996
|
+
}
|
|
5997
|
+
function slotOrNode(nodePath, authoredPath) {
|
|
5998
|
+
for (const prop of ["text", "runs"]) {
|
|
5999
|
+
const compiled = `${nodePath}/props/${prop}`;
|
|
6000
|
+
const authored = authoredPath(compiled);
|
|
6001
|
+
if (authored !== compiled && authored.includes("/props/slots/"))
|
|
6002
|
+
return authored;
|
|
6003
|
+
}
|
|
6004
|
+
return nodePath;
|
|
6005
|
+
}
|
|
5978
6006
|
function bulletItems(props) {
|
|
5979
6007
|
const runs = Array.isArray(props.runs) ? props.runs : void 0;
|
|
5980
6008
|
const whole = props.bullet !== void 0 && props.bullet !== false;
|
|
@@ -6133,7 +6161,7 @@ function isOpaqueComponent(componentName, props) {
|
|
|
6133
6161
|
const type = typeof props.type === "string" ? props.type : "rect";
|
|
6134
6162
|
return RECTANGULAR_SHAPES.has(type) && isOpaqueFill(props.fill);
|
|
6135
6163
|
}
|
|
6136
|
-
function collectSlideNodes(component, path4, text, surfaces, boxes, contentNodes, counter) {
|
|
6164
|
+
function collectSlideNodes(component, path4, text, richText, surfaces, boxes, contentNodes, counter) {
|
|
6137
6165
|
const rec = asRecord(component);
|
|
6138
6166
|
if (!rec || rec.enabled === false) return;
|
|
6139
6167
|
const props = asRecord(rec.props) ?? {};
|
|
@@ -6149,6 +6177,13 @@ function collectSlideNodes(component, path4, text, surfaces, boxes, contentNodes
|
|
|
6149
6177
|
text.push({ props, path: path4, text: content, order });
|
|
6150
6178
|
}
|
|
6151
6179
|
}
|
|
6180
|
+
if (Array.isArray(props.runs) && (rec.name === "text" || rec.name === "shape")) {
|
|
6181
|
+
const joined = props.runs.map(asRecord).map(
|
|
6182
|
+
(run) => run && typeof run.text === "string" ? `${run.text}${run.breakLine === true ? "\n" : ""}` : ""
|
|
6183
|
+
).join("");
|
|
6184
|
+
if (joined.trim() !== "")
|
|
6185
|
+
richText.push({ props, path: path4, text: joined, order });
|
|
6186
|
+
}
|
|
6152
6187
|
const componentName = typeof rec.name === "string" ? rec.name : "";
|
|
6153
6188
|
if (componentName === "chart" || componentName === "highcharts" || componentName === "table") {
|
|
6154
6189
|
contentNodes.push({ props, path: path4, componentName });
|
|
@@ -6168,6 +6203,7 @@ function collectSlideNodes(component, path4, text, surfaces, boxes, contentNodes
|
|
|
6168
6203
|
child,
|
|
6169
6204
|
`${path4}/children/${index}`,
|
|
6170
6205
|
text,
|
|
6206
|
+
richText,
|
|
6171
6207
|
surfaces,
|
|
6172
6208
|
boxes,
|
|
6173
6209
|
contentNodes,
|
|
@@ -6338,8 +6374,9 @@ function authoredPropsAtPointer(root, pointer) {
|
|
|
6338
6374
|
}
|
|
6339
6375
|
return asRecord(asRecord(node)?.props);
|
|
6340
6376
|
}
|
|
6341
|
-
function addSlideFacts(roots, slidePath, renderedIndex, grid, slideWidthIn, slideHeightIn, ctx, theme, slideBackground, analyzedTextPaths, analyzedContentPaths, paletteTokens, authoredPropsAt, authoredPath, addFact) {
|
|
6377
|
+
function addSlideFacts(roots, slidePath, renderedIndex, page, grid, slideWidthIn, slideHeightIn, ctx, theme, slideBackground, analyzedTextPaths, analyzedContentPaths, paletteTokens, authoredPropsAt, statedPropsAt, authoredPath, addFact) {
|
|
6342
6378
|
const nodes = [];
|
|
6379
|
+
const richNodes = [];
|
|
6343
6380
|
const surfaces = [];
|
|
6344
6381
|
const boxes = [];
|
|
6345
6382
|
const contentNodes = [];
|
|
@@ -6349,6 +6386,7 @@ function addSlideFacts(roots, slidePath, renderedIndex, grid, slideWidthIn, slid
|
|
|
6349
6386
|
root.component,
|
|
6350
6387
|
root.path,
|
|
6351
6388
|
nodes,
|
|
6389
|
+
richNodes,
|
|
6352
6390
|
surfaces,
|
|
6353
6391
|
boxes,
|
|
6354
6392
|
contentNodes,
|
|
@@ -6362,13 +6400,18 @@ function addSlideFacts(roots, slidePath, renderedIndex, grid, slideWidthIn, slid
|
|
|
6362
6400
|
if (fact) addFact(fact);
|
|
6363
6401
|
}
|
|
6364
6402
|
boxes.forEach((node, boxIndex) => {
|
|
6365
|
-
const box =
|
|
6403
|
+
const box = imageBox(
|
|
6404
|
+
node,
|
|
6405
|
+
resolveBox(node.props, grid, slideWidthIn, slideHeightIn),
|
|
6406
|
+
statedPropsAt
|
|
6407
|
+
);
|
|
6366
6408
|
if (!isCompleteBox(box)) return;
|
|
6367
6409
|
addFact({
|
|
6368
6410
|
id: `pptx:box:${renderedIndex}:${boxIndex}:${node.path}`,
|
|
6369
6411
|
kind: "pptx/box",
|
|
6370
6412
|
path: node.path,
|
|
6371
6413
|
slidePath,
|
|
6414
|
+
nodePath: node.path,
|
|
6372
6415
|
componentName: node.componentName,
|
|
6373
6416
|
order: node.order,
|
|
6374
6417
|
opaque: node.opaque,
|
|
@@ -6385,7 +6428,7 @@ function addSlideFacts(roots, slidePath, renderedIndex, grid, slideWidthIn, slid
|
|
|
6385
6428
|
let bodyWords = 0;
|
|
6386
6429
|
nodes.forEach((node, nodeIndex) => {
|
|
6387
6430
|
const typography = resolveTypography(node.props, ctx);
|
|
6388
|
-
if (
|
|
6431
|
+
if (!NOT_BODY_STYLES.has(typography.styleName ?? "")) {
|
|
6389
6432
|
bodyWords += node.text.split(/\s+/).filter(Boolean).length;
|
|
6390
6433
|
}
|
|
6391
6434
|
if (analyzedTextPaths.has(node.path)) return;
|
|
@@ -6484,6 +6527,8 @@ function addSlideFacts(roots, slidePath, renderedIndex, grid, slideWidthIn, slid
|
|
|
6484
6527
|
kind: "pptx/text",
|
|
6485
6528
|
path: node.path,
|
|
6486
6529
|
slidePath,
|
|
6530
|
+
...page === void 0 ? { slideHidden: true } : { page },
|
|
6531
|
+
nodePath: node.path,
|
|
6487
6532
|
text: node.text,
|
|
6488
6533
|
fontSizePt: typography.fontSize,
|
|
6489
6534
|
lineSpacingPt: typography.lineSpacing,
|
|
@@ -6498,7 +6543,10 @@ function addSlideFacts(roots, slidePath, renderedIndex, grid, slideWidthIn, slid
|
|
|
6498
6543
|
align: horizontalAlign(node.props, ctx),
|
|
6499
6544
|
rotationDeg: asNumber(node.props.rotate) ?? 0,
|
|
6500
6545
|
bold: typography.bold,
|
|
6501
|
-
|
|
6546
|
+
// Only a size the author wrote has a pointer: component defaults and
|
|
6547
|
+
// the fit pass also write `fontSize` into the processed props, onto a
|
|
6548
|
+
// member the document does not have.
|
|
6549
|
+
...asNumber(node.props.fontSize) !== void 0 && asNumber(authoredPropsAt(node.path)?.fontSize) !== void 0 && {
|
|
6502
6550
|
sizePath: `${node.path}/props/fontSize`
|
|
6503
6551
|
},
|
|
6504
6552
|
generated: authoredPath(node.path) !== node.path,
|
|
@@ -6507,6 +6555,46 @@ function addSlideFacts(roots, slidePath, renderedIndex, grid, slideWidthIn, slid
|
|
|
6507
6555
|
...!backgroundUnknown && backgroundHexes.length > 0 && { backgroundHexes }
|
|
6508
6556
|
});
|
|
6509
6557
|
});
|
|
6558
|
+
richNodes.forEach((node, nodeIndex) => {
|
|
6559
|
+
if (analyzedTextPaths.has(node.path)) return;
|
|
6560
|
+
analyzedTextPaths.add(node.path);
|
|
6561
|
+
const typography = resolveTypography(node.props, ctx);
|
|
6562
|
+
const box = resolveBox(node.props, grid, slideWidthIn, slideHeightIn);
|
|
6563
|
+
const runs = node.props.runs.map(asRecord);
|
|
6564
|
+
addFact({
|
|
6565
|
+
id: `pptx:rich-text:${renderedIndex}:${nodeIndex}:${node.path}`,
|
|
6566
|
+
kind: "pptx/rich-text",
|
|
6567
|
+
path: node.path,
|
|
6568
|
+
slidePath,
|
|
6569
|
+
...page === void 0 ? { slideHidden: true } : { page },
|
|
6570
|
+
nodePath: node.path,
|
|
6571
|
+
text: node.text,
|
|
6572
|
+
...typography.styleName && { styleName: typography.styleName },
|
|
6573
|
+
runSizes: runs.flatMap((run, index) => {
|
|
6574
|
+
if (!run || typeof run.text !== "string" || run.text.trim() === "")
|
|
6575
|
+
return [];
|
|
6576
|
+
const own = asNumber(run.fontSize);
|
|
6577
|
+
return [
|
|
6578
|
+
{
|
|
6579
|
+
fontSizePt: own ?? typography.fontSize,
|
|
6580
|
+
...own !== void 0 && {
|
|
6581
|
+
sizePath: `${node.path}/props/runs/${index}/fontSize`
|
|
6582
|
+
}
|
|
6583
|
+
}
|
|
6584
|
+
];
|
|
6585
|
+
}),
|
|
6586
|
+
generated: authoredPath(node.path) !== node.path,
|
|
6587
|
+
...box.xPt !== void 0 && { boxXPt: box.xPt },
|
|
6588
|
+
...box.yPt !== void 0 && { boxYPt: box.yPt },
|
|
6589
|
+
...box.widthPt !== void 0 && box.widthPt > 0 && {
|
|
6590
|
+
boxWidthPt: box.widthPt
|
|
6591
|
+
},
|
|
6592
|
+
...box.heightPt !== void 0 && box.heightPt > 0 && {
|
|
6593
|
+
boxHeightPt: box.heightPt
|
|
6594
|
+
},
|
|
6595
|
+
rotationDeg: asNumber(node.props.rotate) ?? 0
|
|
6596
|
+
});
|
|
6597
|
+
});
|
|
6510
6598
|
const CHROME_STYLES = /* @__PURE__ */ new Set(["footer", "tracker", "source", "caption"]);
|
|
6511
6599
|
const carriesContent = (box) => box.componentName !== "shape" || typeof box.props.text === "string" && box.props.text.trim() !== "";
|
|
6512
6600
|
addFact({
|
|
@@ -6529,10 +6617,15 @@ function addSlideFacts(roots, slidePath, renderedIndex, grid, slideWidthIn, slid
|
|
|
6529
6617
|
const stretched = authored.w !== void 0 && authored.h !== void 0 && !["contain", "cover"].includes(
|
|
6530
6618
|
String(asRecord(authored.sizing)?.type ?? "")
|
|
6531
6619
|
);
|
|
6620
|
+
const widthPt = slideWidthIn * 72;
|
|
6621
|
+
const heightPt = slideHeightIn * 72;
|
|
6622
|
+
const bleed = isCompleteBox(resolved) && (resolved.xPt <= BLEED_TOLERANCE_PT && resolved.xPt + resolved.widthPt >= widthPt - BLEED_TOLERANCE_PT || resolved.yPt <= BLEED_TOLERANCE_PT && resolved.yPt + resolved.heightPt >= heightPt - BLEED_TOLERANCE_PT);
|
|
6532
6623
|
addFact({
|
|
6533
6624
|
id: `pptx:image:${renderedIndex}:${box.path}`,
|
|
6534
6625
|
kind: "pptx/image",
|
|
6535
6626
|
path: box.path,
|
|
6627
|
+
slidePath,
|
|
6628
|
+
bleed,
|
|
6536
6629
|
...typeof alt === "string" && alt.trim() !== "" && { alt },
|
|
6537
6630
|
...stretched && isCompleteBox(resolved) && resolved.heightPt > 0 && {
|
|
6538
6631
|
drawnRatio: resolved.widthPt / resolved.heightPt
|
|
@@ -6541,11 +6634,11 @@ function addSlideFacts(roots, slidePath, renderedIndex, grid, slideWidthIn, slid
|
|
|
6541
6634
|
});
|
|
6542
6635
|
}
|
|
6543
6636
|
const bullets = bulletItems(box.props);
|
|
6544
|
-
if (bullets.length >
|
|
6637
|
+
if (bullets.length > 0)
|
|
6545
6638
|
addFact({
|
|
6546
6639
|
id: `pptx:bullets:${renderedIndex}:${box.path}`,
|
|
6547
6640
|
kind: "pptx/bullets",
|
|
6548
|
-
path: box.path,
|
|
6641
|
+
path: slotOrNode(box.path, authoredPath),
|
|
6549
6642
|
slidePath,
|
|
6550
6643
|
items: bullets.length,
|
|
6551
6644
|
longestWords: Math.max(
|
|
@@ -6704,10 +6797,13 @@ function preparePptxQualityDocument(document, options = {}) {
|
|
|
6704
6797
|
(value) => `#${resolveColor(value, processed.theme)}`
|
|
6705
6798
|
) ?? SERIES_COLOR_TOKENS.filter((token) => paletteHexes[token] !== void 0);
|
|
6706
6799
|
const authoredPropsAt = (pointer) => authoredPropsAtPointer(document, authoredPath(pointer));
|
|
6800
|
+
const statedPropsAt = (pointer) => authoredPropsAtPointer(expanded.document, pointer);
|
|
6801
|
+
let exportedPages = 0;
|
|
6707
6802
|
processed.slides.forEach((slide, renderedIndex) => {
|
|
6708
6803
|
const authoredIndex = slideIndexes[renderedIndex];
|
|
6709
6804
|
if (authoredIndex === void 0) return;
|
|
6710
6805
|
const slidePath = `/children/${authoredIndex}`;
|
|
6806
|
+
const page = slide.hidden === true ? void 0 : exportedPages++;
|
|
6711
6807
|
const roots = slide.components.map(
|
|
6712
6808
|
(component, index) => ({
|
|
6713
6809
|
component,
|
|
@@ -6718,6 +6814,7 @@ function preparePptxQualityDocument(document, options = {}) {
|
|
|
6718
6814
|
roots,
|
|
6719
6815
|
slidePath,
|
|
6720
6816
|
renderedIndex,
|
|
6817
|
+
page,
|
|
6721
6818
|
processed.grid,
|
|
6722
6819
|
processed.slideWidth,
|
|
6723
6820
|
processed.slideHeight,
|
|
@@ -6735,6 +6832,7 @@ function preparePptxQualityDocument(document, options = {}) {
|
|
|
6735
6832
|
analyzedContentPaths,
|
|
6736
6833
|
paletteTokens,
|
|
6737
6834
|
authoredPropsAt,
|
|
6835
|
+
statedPropsAt,
|
|
6738
6836
|
authoredPath,
|
|
6739
6837
|
addFact
|
|
6740
6838
|
);
|
|
@@ -6748,7 +6846,7 @@ function preparePptxQualityDocument(document, options = {}) {
|
|
|
6748
6846
|
}
|
|
6749
6847
|
const slotTextNodes = textNodesBySlot(processed, slideIndexes, sourceMap);
|
|
6750
6848
|
for (const role of blockSlotRoles(context.document, expanded.blocks)) {
|
|
6751
|
-
const present = role.value !== void 0 && role.value !== null && role.value !== ""
|
|
6849
|
+
const present = role.value !== void 0 && role.value !== null && role.value !== false && (typeof role.value !== "string" || role.value.trim() !== "") && (!Array.isArray(role.value) || role.value.length > 0);
|
|
6752
6850
|
const bound = slotTextNodes.get(role.path);
|
|
6753
6851
|
let measured;
|
|
6754
6852
|
if (bound && typeof bound.props.text === "string") {
|
|
@@ -6782,6 +6880,7 @@ function preparePptxQualityDocument(document, options = {}) {
|
|
|
6782
6880
|
slot: role.slot,
|
|
6783
6881
|
role: role.role,
|
|
6784
6882
|
present,
|
|
6883
|
+
...bound && { nodePath: bound.path },
|
|
6785
6884
|
...typeof role.value === "string" && { text: role.value },
|
|
6786
6885
|
...measured
|
|
6787
6886
|
});
|
|
@@ -6815,7 +6914,7 @@ function textNodesBySlot(processed, slideIndexes, sourceMap) {
|
|
|
6815
6914
|
if (component.name === "text") {
|
|
6816
6915
|
const origin = toAuthoredPointer(sourceMap, `${path4}/props/text`);
|
|
6817
6916
|
if (origin !== `${path4}/props/text` && !found.has(origin))
|
|
6818
|
-
found.set(origin, { props: asRecord(component.props) ?? {} });
|
|
6917
|
+
found.set(origin, { props: asRecord(component.props) ?? {}, path: path4 });
|
|
6819
6918
|
}
|
|
6820
6919
|
(component.children ?? []).forEach(
|
|
6821
6920
|
(child, index) => visit(child, `${path4}/children/${index}`)
|
|
@@ -8228,7 +8327,8 @@ var pptxOffCanvasRule = {
|
|
|
8228
8327
|
code: QUALITY_CODES.OFF_CANVAS,
|
|
8229
8328
|
category: "integrity",
|
|
8230
8329
|
defaultSeverity: "warning",
|
|
8231
|
-
|
|
8330
|
+
// The box is measured; the ink inside it is the width model's estimate.
|
|
8331
|
+
defaultCertainty: "estimated",
|
|
8232
8332
|
formats: ["pptx"],
|
|
8233
8333
|
defaultParameters: {
|
|
8234
8334
|
tolerancePt: DEFAULT_OFF_CANVAS_TOLERANCE_PT,
|
|
@@ -8334,7 +8434,12 @@ var pptxRequiredChromeRule = {
|
|
|
8334
8434
|
relatedPaths: [fact.invocation],
|
|
8335
8435
|
message: `${fact.block} states no ${fact.role} in its "${fact.slot}" slot; the ${profile?.id ?? "selected"} profile expects one on every ${fact.block}.`,
|
|
8336
8436
|
suggestion: `Fill the "${fact.slot}" slot. The theme already styles it.`,
|
|
8337
|
-
context: { block: fact.block, slot: fact.slot, role: fact.role }
|
|
8437
|
+
context: { block: fact.block, slot: fact.slot, role: fact.role },
|
|
8438
|
+
evidence: {
|
|
8439
|
+
actual: "empty",
|
|
8440
|
+
expected: fact.role,
|
|
8441
|
+
values: { source: "profile", required }
|
|
8442
|
+
}
|
|
8338
8443
|
}));
|
|
8339
8444
|
}
|
|
8340
8445
|
};
|
|
@@ -8372,19 +8477,43 @@ var PPTX_TYPE_VOCABULARY = {
|
|
|
8372
8477
|
subject: "deck",
|
|
8373
8478
|
keepTo: "Keep to the theme styles \u2014 title, heading, body, label, statistic \u2014 and drop the ad-hoc sizes."
|
|
8374
8479
|
};
|
|
8480
|
+
var PPTX_SLIDE_TYPE_VOCABULARY = {
|
|
8481
|
+
subject: "slide",
|
|
8482
|
+
keepTo: "Give the slide fewer levels: let the title, the body and one supporting size carry it, in the theme styles."
|
|
8483
|
+
};
|
|
8375
8484
|
function pptxThemeFact(facts) {
|
|
8376
8485
|
return facts.find(
|
|
8377
8486
|
(fact) => fact.kind === "pptx/theme"
|
|
8378
8487
|
);
|
|
8379
8488
|
}
|
|
8380
8489
|
function paintedSizes(facts) {
|
|
8381
|
-
|
|
8382
|
-
|
|
8383
|
-
|
|
8384
|
-
|
|
8385
|
-
|
|
8386
|
-
|
|
8387
|
-
|
|
8490
|
+
const sizes = [];
|
|
8491
|
+
for (const fact of textFacts(facts)) {
|
|
8492
|
+
if (fact.slideHidden) continue;
|
|
8493
|
+
sizes.push({
|
|
8494
|
+
path: fact.path,
|
|
8495
|
+
slidePath: fact.slidePath,
|
|
8496
|
+
...fact.styleName !== void 0 && { role: fact.styleName },
|
|
8497
|
+
fontSizePt: fact.fontSizePt,
|
|
8498
|
+
...fact.sizePath !== void 0 && { sizePath: fact.sizePath },
|
|
8499
|
+
generated: fact.generated
|
|
8500
|
+
});
|
|
8501
|
+
}
|
|
8502
|
+
for (const fact of facts) {
|
|
8503
|
+
if (fact.kind !== "pptx/rich-text") continue;
|
|
8504
|
+
const rich = fact;
|
|
8505
|
+
if (rich.slideHidden) continue;
|
|
8506
|
+
for (const run of rich.runSizes)
|
|
8507
|
+
sizes.push({
|
|
8508
|
+
path: rich.path,
|
|
8509
|
+
slidePath: rich.slidePath,
|
|
8510
|
+
...rich.styleName !== void 0 && { role: rich.styleName },
|
|
8511
|
+
fontSizePt: run.fontSizePt,
|
|
8512
|
+
...run.sizePath !== void 0 && { sizePath: run.sizePath },
|
|
8513
|
+
generated: rich.generated
|
|
8514
|
+
});
|
|
8515
|
+
}
|
|
8516
|
+
return sizes;
|
|
8388
8517
|
}
|
|
8389
8518
|
var pptxTypeScaleRule = {
|
|
8390
8519
|
id: "pptx/type-scale",
|
|
@@ -8410,21 +8539,52 @@ var pptxTypeScaleRule = {
|
|
|
8410
8539
|
};
|
|
8411
8540
|
var pptxSizeCountRule = {
|
|
8412
8541
|
id: "pptx/size-count",
|
|
8413
|
-
description: "More distinct text sizes than maximumSizes allows, blocks included. Off until a profile or policy enables it.",
|
|
8542
|
+
description: "More distinct text sizes than maximumSizes allows across the deck, or than maximumSizesPerSlide allows on one slide (0: no per-slide ceiling), blocks and runs included. Off until a profile or policy enables it.",
|
|
8414
8543
|
code: QUALITY_CODES.TYPE_SIZE_COUNT,
|
|
8415
8544
|
category: "consistency",
|
|
8416
8545
|
defaultSeverity: "warning",
|
|
8417
8546
|
defaultCertainty: "deterministic",
|
|
8418
8547
|
formats: ["pptx"],
|
|
8419
8548
|
defaultEnabled: false,
|
|
8420
|
-
defaultParameters: { maximumSizes: 8 },
|
|
8421
|
-
evaluate: ({ facts, configuration, profile }) =>
|
|
8422
|
-
paintedSizes(facts)
|
|
8423
|
-
|
|
8424
|
-
|
|
8425
|
-
|
|
8426
|
-
|
|
8427
|
-
|
|
8549
|
+
defaultParameters: { maximumSizes: 8, maximumSizesPerSlide: 0 },
|
|
8550
|
+
evaluate: ({ facts, configuration, profile }) => {
|
|
8551
|
+
const sizes = paintedSizes(facts);
|
|
8552
|
+
const findings = sizeCountFinding(
|
|
8553
|
+
sizes,
|
|
8554
|
+
numberParameter(configuration.parameters, "maximumSizes", 8),
|
|
8555
|
+
pptxThemeFact(facts)?.path ?? "/props",
|
|
8556
|
+
profile?.id,
|
|
8557
|
+
PPTX_TYPE_VOCABULARY
|
|
8558
|
+
).map((finding) => ({
|
|
8559
|
+
...finding,
|
|
8560
|
+
context: { ...finding.context, scope: "deck" }
|
|
8561
|
+
}));
|
|
8562
|
+
const perSlide = numberParameter(
|
|
8563
|
+
configuration.parameters,
|
|
8564
|
+
"maximumSizesPerSlide",
|
|
8565
|
+
0
|
|
8566
|
+
);
|
|
8567
|
+
if (perSlide <= 0) return findings;
|
|
8568
|
+
const bySlide = /* @__PURE__ */ new Map();
|
|
8569
|
+
for (const size of sizes)
|
|
8570
|
+
bySlide.set(size.slidePath, [
|
|
8571
|
+
...bySlide.get(size.slidePath) ?? [],
|
|
8572
|
+
size
|
|
8573
|
+
]);
|
|
8574
|
+
for (const [slidePath, onSlide] of bySlide)
|
|
8575
|
+
for (const finding of sizeCountFinding(
|
|
8576
|
+
onSlide,
|
|
8577
|
+
perSlide,
|
|
8578
|
+
slidePath,
|
|
8579
|
+
profile?.id,
|
|
8580
|
+
PPTX_SLIDE_TYPE_VOCABULARY
|
|
8581
|
+
))
|
|
8582
|
+
findings.push({
|
|
8583
|
+
...finding,
|
|
8584
|
+
context: { ...finding.context, scope: "slide" }
|
|
8585
|
+
});
|
|
8586
|
+
return findings;
|
|
8587
|
+
}
|
|
8428
8588
|
};
|
|
8429
8589
|
var pptxRoleDriftRule = {
|
|
8430
8590
|
id: "pptx/role-drift",
|
|
@@ -8629,20 +8789,16 @@ var pptxSafeAreaRule = {
|
|
|
8629
8789
|
);
|
|
8630
8790
|
const safe = canvas?.safeAreaPt;
|
|
8631
8791
|
if (canvas === void 0 || safe === void 0 || safe <= 0) return [];
|
|
8632
|
-
const
|
|
8792
|
+
const chromeNodes = new Set(
|
|
8633
8793
|
facts.filter(
|
|
8634
|
-
(fact) => fact.kind === "pptx/chrome-slot" && (fact.role === "tracker" || fact.role === "footer")
|
|
8635
|
-
).
|
|
8636
|
-
);
|
|
8637
|
-
const chromeStyles = /* @__PURE__ */ new Set(["footer", "tracker"]);
|
|
8638
|
-
const styledChrome = new Set(
|
|
8639
|
-
textFacts(facts).filter(
|
|
8640
|
-
(fact) => fact.styleName !== void 0 && chromeStyles.has(fact.styleName)
|
|
8641
|
-
).map((fact) => fact.path)
|
|
8794
|
+
(fact) => fact.kind === "pptx/chrome-slot" && (fact.role === "tracker" || fact.role === "footer" || fact.role === "source")
|
|
8795
|
+
).flatMap((fact) => fact.nodePath ? [fact.nodePath] : [])
|
|
8642
8796
|
);
|
|
8643
|
-
|
|
8644
|
-
|
|
8645
|
-
|
|
8797
|
+
const chromeStyles = /* @__PURE__ */ new Set(["footer", "tracker", "source"]);
|
|
8798
|
+
for (const fact of facts)
|
|
8799
|
+
if ((fact.kind === "pptx/text" || fact.kind === "pptx/rich-text") && fact.styleName !== void 0 && chromeStyles.has(fact.styleName))
|
|
8800
|
+
chromeNodes.add(fact.nodePath);
|
|
8801
|
+
return facts.filter((fact) => fact.kind === "pptx/box").filter((fact) => !chromeNodes.has(fact.nodePath)).flatMap((fact) => {
|
|
8646
8802
|
const right = fact.xPt + fact.widthPt;
|
|
8647
8803
|
const bottom = fact.yPt + fact.heightPt;
|
|
8648
8804
|
const spansWidth = fact.xPt <= tolerance && right >= canvas.widthPt - tolerance;
|
|
@@ -8691,8 +8847,8 @@ var pptxSlideTitleRule = {
|
|
|
8691
8847
|
evaluate: ({ facts, configuration }) => {
|
|
8692
8848
|
const styles = stringListParameter(configuration.parameters, "titleStyles");
|
|
8693
8849
|
const titledSlides = /* @__PURE__ */ new Set();
|
|
8694
|
-
for (const fact of
|
|
8695
|
-
if (fact.styleName !== void 0 && styles.includes(fact.styleName))
|
|
8850
|
+
for (const fact of facts)
|
|
8851
|
+
if ((fact.kind === "pptx/text" || fact.kind === "pptx/rich-text") && fact.styleName !== void 0 && styles.includes(fact.styleName))
|
|
8696
8852
|
titledSlides.add(fact.slidePath);
|
|
8697
8853
|
for (const fact of facts)
|
|
8698
8854
|
if (fact.kind === "pptx/chrome-slot" && fact.role === "actionTitle" && fact.present)
|
|
@@ -8713,6 +8869,28 @@ var pptxSlideTitleRule = {
|
|
|
8713
8869
|
}));
|
|
8714
8870
|
}
|
|
8715
8871
|
};
|
|
8872
|
+
var pptxFigureLabelRule = {
|
|
8873
|
+
id: "pptx/figure-label",
|
|
8874
|
+
description: "An image with no alt text, a background that bleeds off the slide aside. Off until a profile or policy enables it.",
|
|
8875
|
+
code: QUALITY_CODES.FIGURE_UNLABELLED,
|
|
8876
|
+
category: "accessibility",
|
|
8877
|
+
defaultSeverity: "warning",
|
|
8878
|
+
defaultCertainty: "deterministic",
|
|
8879
|
+
formats: ["pptx"],
|
|
8880
|
+
defaultEnabled: false,
|
|
8881
|
+
evaluate: ({ facts }) => {
|
|
8882
|
+
const unlabelled = /* @__PURE__ */ new Map();
|
|
8883
|
+
for (const fact of facts)
|
|
8884
|
+
if (fact.kind === "pptx/image" && fact.alt === void 0 && !fact.bleed)
|
|
8885
|
+
unlabelled.set(fact.path, fact);
|
|
8886
|
+
return [...unlabelled.values()].map((fact) => ({
|
|
8887
|
+
path: fact.path,
|
|
8888
|
+
message: "This image carries no alt text, so nothing in the deck says what it shows to a reader who cannot see it.",
|
|
8889
|
+
suggestion: "Write `alt` on the image: what it shows, in a sentence. A decorative background can bleed off the slide instead.",
|
|
8890
|
+
context: { slidePath: fact.slidePath }
|
|
8891
|
+
}));
|
|
8892
|
+
}
|
|
8893
|
+
};
|
|
8716
8894
|
var pptxImageAspectRule = {
|
|
8717
8895
|
id: "pptx/image-aspect",
|
|
8718
8896
|
description: "An image drawn at an aspect the asset does not have, where the asset can be read from the document.",
|
|
@@ -8769,6 +8947,7 @@ var PPTX_QUALITY_RULES = {
|
|
|
8769
8947
|
pptxBulletRule,
|
|
8770
8948
|
pptxSafeAreaRule,
|
|
8771
8949
|
pptxSlideTitleRule,
|
|
8950
|
+
pptxFigureLabelRule,
|
|
8772
8951
|
pptxImageAspectRule
|
|
8773
8952
|
]
|
|
8774
8953
|
};
|
|
@@ -8794,7 +8973,7 @@ var PPTX_QUALITY_PROFILES = {
|
|
|
8794
8973
|
"consulting-deck": {
|
|
8795
8974
|
id: "consulting-deck",
|
|
8796
8975
|
formats: ["pptx"],
|
|
8797
|
-
description: "Consulting readout: every content slide leads with a two-line action title, every chart carries a takeaway and a source, content stays inside the theme\u2019s safe area,
|
|
8976
|
+
description: "Consulting readout: every content slide leads with a two-line action title, every chart carries a takeaway and a source, content stays inside the theme\u2019s safe area, a box holds at most five bullets of at most twelve words, every figure carries alt text, every size is on the theme scale with at most nine in the deck and six on a slide, and titles of one kind hold one line.",
|
|
8798
8977
|
rules: {
|
|
8799
8978
|
"pptx/required-chrome": {
|
|
8800
8979
|
parameters: { required: ["takeaway", "source"] }
|
|
@@ -8802,7 +8981,14 @@ var PPTX_QUALITY_PROFILES = {
|
|
|
8802
8981
|
"pptx/action-title": { parameters: { maxLines: 2 } },
|
|
8803
8982
|
"pptx/slide-density": { parameters: { maximumBodyWords: 90 } },
|
|
8804
8983
|
"pptx/type-scale": { enabled: true },
|
|
8805
|
-
|
|
8984
|
+
// Measured 2026-09-15, runs included: the house deck paints nine sizes
|
|
8985
|
+
// (9, 10, 12, 14, 16, 18, 28, 32, 40) and six on its busiest slide, and
|
|
8986
|
+
// so did every one of the 22 verification decks built from its blocks.
|
|
8987
|
+
// A size past these is one no house block paints.
|
|
8988
|
+
"pptx/size-count": {
|
|
8989
|
+
enabled: true,
|
|
8990
|
+
parameters: { maximumSizes: 9, maximumSizesPerSlide: 6 }
|
|
8991
|
+
},
|
|
8806
8992
|
"pptx/role-drift": { enabled: true },
|
|
8807
8993
|
"pptx/title-drift": {
|
|
8808
8994
|
enabled: true,
|
|
@@ -8812,7 +8998,8 @@ var PPTX_QUALITY_PROFILES = {
|
|
|
8812
8998
|
parameters: { maximumBullets: 5, maximumWordsPerBullet: 12 }
|
|
8813
8999
|
},
|
|
8814
9000
|
"pptx/safe-area": { enabled: true },
|
|
8815
|
-
"pptx/slide-title": { enabled: true }
|
|
9001
|
+
"pptx/slide-title": { enabled: true },
|
|
9002
|
+
"pptx/figure-label": { enabled: true }
|
|
8816
9003
|
}
|
|
8817
9004
|
}
|
|
8818
9005
|
};
|