@json-to-office/core-pptx 6.6.0 → 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 +234 -44
- 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/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
|
@@ -5972,6 +5972,37 @@ function horizontalAlign(props, ctx) {
|
|
|
5972
5972
|
const styled = typeof props.style === "string" ? ctx.styles[props.style]?.align : void 0;
|
|
5973
5973
|
return styled && HORIZONTAL_ALIGNMENTS.has(styled) ? styled : "left";
|
|
5974
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
|
+
}
|
|
5975
6006
|
function bulletItems(props) {
|
|
5976
6007
|
const runs = Array.isArray(props.runs) ? props.runs : void 0;
|
|
5977
6008
|
const whole = props.bullet !== void 0 && props.bullet !== false;
|
|
@@ -6130,7 +6161,7 @@ function isOpaqueComponent(componentName, props) {
|
|
|
6130
6161
|
const type = typeof props.type === "string" ? props.type : "rect";
|
|
6131
6162
|
return RECTANGULAR_SHAPES.has(type) && isOpaqueFill(props.fill);
|
|
6132
6163
|
}
|
|
6133
|
-
function collectSlideNodes(component, path4, text, surfaces, boxes, contentNodes, counter) {
|
|
6164
|
+
function collectSlideNodes(component, path4, text, richText, surfaces, boxes, contentNodes, counter) {
|
|
6134
6165
|
const rec = asRecord(component);
|
|
6135
6166
|
if (!rec || rec.enabled === false) return;
|
|
6136
6167
|
const props = asRecord(rec.props) ?? {};
|
|
@@ -6146,6 +6177,13 @@ function collectSlideNodes(component, path4, text, surfaces, boxes, contentNodes
|
|
|
6146
6177
|
text.push({ props, path: path4, text: content, order });
|
|
6147
6178
|
}
|
|
6148
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
|
+
}
|
|
6149
6187
|
const componentName = typeof rec.name === "string" ? rec.name : "";
|
|
6150
6188
|
if (componentName === "chart" || componentName === "highcharts" || componentName === "table") {
|
|
6151
6189
|
contentNodes.push({ props, path: path4, componentName });
|
|
@@ -6165,6 +6203,7 @@ function collectSlideNodes(component, path4, text, surfaces, boxes, contentNodes
|
|
|
6165
6203
|
child,
|
|
6166
6204
|
`${path4}/children/${index}`,
|
|
6167
6205
|
text,
|
|
6206
|
+
richText,
|
|
6168
6207
|
surfaces,
|
|
6169
6208
|
boxes,
|
|
6170
6209
|
contentNodes,
|
|
@@ -6335,8 +6374,9 @@ function authoredPropsAtPointer(root, pointer) {
|
|
|
6335
6374
|
}
|
|
6336
6375
|
return asRecord(asRecord(node)?.props);
|
|
6337
6376
|
}
|
|
6338
|
-
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) {
|
|
6339
6378
|
const nodes = [];
|
|
6379
|
+
const richNodes = [];
|
|
6340
6380
|
const surfaces = [];
|
|
6341
6381
|
const boxes = [];
|
|
6342
6382
|
const contentNodes = [];
|
|
@@ -6346,6 +6386,7 @@ function addSlideFacts(roots, slidePath, renderedIndex, grid, slideWidthIn, slid
|
|
|
6346
6386
|
root.component,
|
|
6347
6387
|
root.path,
|
|
6348
6388
|
nodes,
|
|
6389
|
+
richNodes,
|
|
6349
6390
|
surfaces,
|
|
6350
6391
|
boxes,
|
|
6351
6392
|
contentNodes,
|
|
@@ -6359,13 +6400,18 @@ function addSlideFacts(roots, slidePath, renderedIndex, grid, slideWidthIn, slid
|
|
|
6359
6400
|
if (fact) addFact(fact);
|
|
6360
6401
|
}
|
|
6361
6402
|
boxes.forEach((node, boxIndex) => {
|
|
6362
|
-
const box =
|
|
6403
|
+
const box = imageBox(
|
|
6404
|
+
node,
|
|
6405
|
+
resolveBox(node.props, grid, slideWidthIn, slideHeightIn),
|
|
6406
|
+
statedPropsAt
|
|
6407
|
+
);
|
|
6363
6408
|
if (!isCompleteBox(box)) return;
|
|
6364
6409
|
addFact({
|
|
6365
6410
|
id: `pptx:box:${renderedIndex}:${boxIndex}:${node.path}`,
|
|
6366
6411
|
kind: "pptx/box",
|
|
6367
6412
|
path: node.path,
|
|
6368
6413
|
slidePath,
|
|
6414
|
+
nodePath: node.path,
|
|
6369
6415
|
componentName: node.componentName,
|
|
6370
6416
|
order: node.order,
|
|
6371
6417
|
opaque: node.opaque,
|
|
@@ -6382,7 +6428,7 @@ function addSlideFacts(roots, slidePath, renderedIndex, grid, slideWidthIn, slid
|
|
|
6382
6428
|
let bodyWords = 0;
|
|
6383
6429
|
nodes.forEach((node, nodeIndex) => {
|
|
6384
6430
|
const typography = resolveTypography(node.props, ctx);
|
|
6385
|
-
if (
|
|
6431
|
+
if (!NOT_BODY_STYLES.has(typography.styleName ?? "")) {
|
|
6386
6432
|
bodyWords += node.text.split(/\s+/).filter(Boolean).length;
|
|
6387
6433
|
}
|
|
6388
6434
|
if (analyzedTextPaths.has(node.path)) return;
|
|
@@ -6481,6 +6527,8 @@ function addSlideFacts(roots, slidePath, renderedIndex, grid, slideWidthIn, slid
|
|
|
6481
6527
|
kind: "pptx/text",
|
|
6482
6528
|
path: node.path,
|
|
6483
6529
|
slidePath,
|
|
6530
|
+
...page === void 0 ? { slideHidden: true } : { page },
|
|
6531
|
+
nodePath: node.path,
|
|
6484
6532
|
text: node.text,
|
|
6485
6533
|
fontSizePt: typography.fontSize,
|
|
6486
6534
|
lineSpacingPt: typography.lineSpacing,
|
|
@@ -6495,7 +6543,10 @@ function addSlideFacts(roots, slidePath, renderedIndex, grid, slideWidthIn, slid
|
|
|
6495
6543
|
align: horizontalAlign(node.props, ctx),
|
|
6496
6544
|
rotationDeg: asNumber(node.props.rotate) ?? 0,
|
|
6497
6545
|
bold: typography.bold,
|
|
6498
|
-
|
|
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 && {
|
|
6499
6550
|
sizePath: `${node.path}/props/fontSize`
|
|
6500
6551
|
},
|
|
6501
6552
|
generated: authoredPath(node.path) !== node.path,
|
|
@@ -6504,6 +6555,46 @@ function addSlideFacts(roots, slidePath, renderedIndex, grid, slideWidthIn, slid
|
|
|
6504
6555
|
...!backgroundUnknown && backgroundHexes.length > 0 && { backgroundHexes }
|
|
6505
6556
|
});
|
|
6506
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
|
+
});
|
|
6507
6598
|
const CHROME_STYLES = /* @__PURE__ */ new Set(["footer", "tracker", "source", "caption"]);
|
|
6508
6599
|
const carriesContent = (box) => box.componentName !== "shape" || typeof box.props.text === "string" && box.props.text.trim() !== "";
|
|
6509
6600
|
addFact({
|
|
@@ -6526,10 +6617,15 @@ function addSlideFacts(roots, slidePath, renderedIndex, grid, slideWidthIn, slid
|
|
|
6526
6617
|
const stretched = authored.w !== void 0 && authored.h !== void 0 && !["contain", "cover"].includes(
|
|
6527
6618
|
String(asRecord(authored.sizing)?.type ?? "")
|
|
6528
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);
|
|
6529
6623
|
addFact({
|
|
6530
6624
|
id: `pptx:image:${renderedIndex}:${box.path}`,
|
|
6531
6625
|
kind: "pptx/image",
|
|
6532
6626
|
path: box.path,
|
|
6627
|
+
slidePath,
|
|
6628
|
+
bleed,
|
|
6533
6629
|
...typeof alt === "string" && alt.trim() !== "" && { alt },
|
|
6534
6630
|
...stretched && isCompleteBox(resolved) && resolved.heightPt > 0 && {
|
|
6535
6631
|
drawnRatio: resolved.widthPt / resolved.heightPt
|
|
@@ -6538,11 +6634,11 @@ function addSlideFacts(roots, slidePath, renderedIndex, grid, slideWidthIn, slid
|
|
|
6538
6634
|
});
|
|
6539
6635
|
}
|
|
6540
6636
|
const bullets = bulletItems(box.props);
|
|
6541
|
-
if (bullets.length >
|
|
6637
|
+
if (bullets.length > 0)
|
|
6542
6638
|
addFact({
|
|
6543
6639
|
id: `pptx:bullets:${renderedIndex}:${box.path}`,
|
|
6544
6640
|
kind: "pptx/bullets",
|
|
6545
|
-
path: box.path,
|
|
6641
|
+
path: slotOrNode(box.path, authoredPath),
|
|
6546
6642
|
slidePath,
|
|
6547
6643
|
items: bullets.length,
|
|
6548
6644
|
longestWords: Math.max(
|
|
@@ -6701,10 +6797,13 @@ function preparePptxQualityDocument(document, options = {}) {
|
|
|
6701
6797
|
(value) => `#${resolveColor(value, processed.theme)}`
|
|
6702
6798
|
) ?? SERIES_COLOR_TOKENS.filter((token) => paletteHexes[token] !== void 0);
|
|
6703
6799
|
const authoredPropsAt = (pointer) => authoredPropsAtPointer(document, authoredPath(pointer));
|
|
6800
|
+
const statedPropsAt = (pointer) => authoredPropsAtPointer(expanded.document, pointer);
|
|
6801
|
+
let exportedPages = 0;
|
|
6704
6802
|
processed.slides.forEach((slide, renderedIndex) => {
|
|
6705
6803
|
const authoredIndex = slideIndexes[renderedIndex];
|
|
6706
6804
|
if (authoredIndex === void 0) return;
|
|
6707
6805
|
const slidePath = `/children/${authoredIndex}`;
|
|
6806
|
+
const page = slide.hidden === true ? void 0 : exportedPages++;
|
|
6708
6807
|
const roots = slide.components.map(
|
|
6709
6808
|
(component, index) => ({
|
|
6710
6809
|
component,
|
|
@@ -6715,6 +6814,7 @@ function preparePptxQualityDocument(document, options = {}) {
|
|
|
6715
6814
|
roots,
|
|
6716
6815
|
slidePath,
|
|
6717
6816
|
renderedIndex,
|
|
6817
|
+
page,
|
|
6718
6818
|
processed.grid,
|
|
6719
6819
|
processed.slideWidth,
|
|
6720
6820
|
processed.slideHeight,
|
|
@@ -6732,6 +6832,7 @@ function preparePptxQualityDocument(document, options = {}) {
|
|
|
6732
6832
|
analyzedContentPaths,
|
|
6733
6833
|
paletteTokens,
|
|
6734
6834
|
authoredPropsAt,
|
|
6835
|
+
statedPropsAt,
|
|
6735
6836
|
authoredPath,
|
|
6736
6837
|
addFact
|
|
6737
6838
|
);
|
|
@@ -6745,7 +6846,7 @@ function preparePptxQualityDocument(document, options = {}) {
|
|
|
6745
6846
|
}
|
|
6746
6847
|
const slotTextNodes = textNodesBySlot(processed, slideIndexes, sourceMap);
|
|
6747
6848
|
for (const role of blockSlotRoles(context.document, expanded.blocks)) {
|
|
6748
|
-
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);
|
|
6749
6850
|
const bound = slotTextNodes.get(role.path);
|
|
6750
6851
|
let measured;
|
|
6751
6852
|
if (bound && typeof bound.props.text === "string") {
|
|
@@ -6779,6 +6880,7 @@ function preparePptxQualityDocument(document, options = {}) {
|
|
|
6779
6880
|
slot: role.slot,
|
|
6780
6881
|
role: role.role,
|
|
6781
6882
|
present,
|
|
6883
|
+
...bound && { nodePath: bound.path },
|
|
6782
6884
|
...typeof role.value === "string" && { text: role.value },
|
|
6783
6885
|
...measured
|
|
6784
6886
|
});
|
|
@@ -6812,7 +6914,7 @@ function textNodesBySlot(processed, slideIndexes, sourceMap) {
|
|
|
6812
6914
|
if (component.name === "text") {
|
|
6813
6915
|
const origin = toAuthoredPointer(sourceMap, `${path4}/props/text`);
|
|
6814
6916
|
if (origin !== `${path4}/props/text` && !found.has(origin))
|
|
6815
|
-
found.set(origin, { props: asRecord(component.props) ?? {} });
|
|
6917
|
+
found.set(origin, { props: asRecord(component.props) ?? {}, path: path4 });
|
|
6816
6918
|
}
|
|
6817
6919
|
(component.children ?? []).forEach(
|
|
6818
6920
|
(child, index) => visit(child, `${path4}/children/${index}`)
|
|
@@ -8225,7 +8327,8 @@ var pptxOffCanvasRule = {
|
|
|
8225
8327
|
code: QUALITY_CODES.OFF_CANVAS,
|
|
8226
8328
|
category: "integrity",
|
|
8227
8329
|
defaultSeverity: "warning",
|
|
8228
|
-
|
|
8330
|
+
// The box is measured; the ink inside it is the width model's estimate.
|
|
8331
|
+
defaultCertainty: "estimated",
|
|
8229
8332
|
formats: ["pptx"],
|
|
8230
8333
|
defaultParameters: {
|
|
8231
8334
|
tolerancePt: DEFAULT_OFF_CANVAS_TOLERANCE_PT,
|
|
@@ -8331,7 +8434,12 @@ var pptxRequiredChromeRule = {
|
|
|
8331
8434
|
relatedPaths: [fact.invocation],
|
|
8332
8435
|
message: `${fact.block} states no ${fact.role} in its "${fact.slot}" slot; the ${profile?.id ?? "selected"} profile expects one on every ${fact.block}.`,
|
|
8333
8436
|
suggestion: `Fill the "${fact.slot}" slot. The theme already styles it.`,
|
|
8334
|
-
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
|
+
}
|
|
8335
8443
|
}));
|
|
8336
8444
|
}
|
|
8337
8445
|
};
|
|
@@ -8369,19 +8477,43 @@ var PPTX_TYPE_VOCABULARY = {
|
|
|
8369
8477
|
subject: "deck",
|
|
8370
8478
|
keepTo: "Keep to the theme styles \u2014 title, heading, body, label, statistic \u2014 and drop the ad-hoc sizes."
|
|
8371
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
|
+
};
|
|
8372
8484
|
function pptxThemeFact(facts) {
|
|
8373
8485
|
return facts.find(
|
|
8374
8486
|
(fact) => fact.kind === "pptx/theme"
|
|
8375
8487
|
);
|
|
8376
8488
|
}
|
|
8377
8489
|
function paintedSizes(facts) {
|
|
8378
|
-
|
|
8379
|
-
|
|
8380
|
-
|
|
8381
|
-
|
|
8382
|
-
|
|
8383
|
-
|
|
8384
|
-
|
|
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;
|
|
8385
8517
|
}
|
|
8386
8518
|
var pptxTypeScaleRule = {
|
|
8387
8519
|
id: "pptx/type-scale",
|
|
@@ -8407,21 +8539,52 @@ var pptxTypeScaleRule = {
|
|
|
8407
8539
|
};
|
|
8408
8540
|
var pptxSizeCountRule = {
|
|
8409
8541
|
id: "pptx/size-count",
|
|
8410
|
-
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.",
|
|
8411
8543
|
code: QUALITY_CODES.TYPE_SIZE_COUNT,
|
|
8412
8544
|
category: "consistency",
|
|
8413
8545
|
defaultSeverity: "warning",
|
|
8414
8546
|
defaultCertainty: "deterministic",
|
|
8415
8547
|
formats: ["pptx"],
|
|
8416
8548
|
defaultEnabled: false,
|
|
8417
|
-
defaultParameters: { maximumSizes: 8 },
|
|
8418
|
-
evaluate: ({ facts, configuration, profile }) =>
|
|
8419
|
-
paintedSizes(facts)
|
|
8420
|
-
|
|
8421
|
-
|
|
8422
|
-
|
|
8423
|
-
|
|
8424
|
-
|
|
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
|
+
}
|
|
8425
8588
|
};
|
|
8426
8589
|
var pptxRoleDriftRule = {
|
|
8427
8590
|
id: "pptx/role-drift",
|
|
@@ -8626,20 +8789,16 @@ var pptxSafeAreaRule = {
|
|
|
8626
8789
|
);
|
|
8627
8790
|
const safe = canvas?.safeAreaPt;
|
|
8628
8791
|
if (canvas === void 0 || safe === void 0 || safe <= 0) return [];
|
|
8629
|
-
const
|
|
8792
|
+
const chromeNodes = new Set(
|
|
8630
8793
|
facts.filter(
|
|
8631
|
-
(fact) => fact.kind === "pptx/chrome-slot" && (fact.role === "tracker" || fact.role === "footer")
|
|
8632
|
-
).
|
|
8633
|
-
);
|
|
8634
|
-
const chromeStyles = /* @__PURE__ */ new Set(["footer", "tracker"]);
|
|
8635
|
-
const styledChrome = new Set(
|
|
8636
|
-
textFacts(facts).filter(
|
|
8637
|
-
(fact) => fact.styleName !== void 0 && chromeStyles.has(fact.styleName)
|
|
8638
|
-
).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] : [])
|
|
8639
8796
|
);
|
|
8640
|
-
|
|
8641
|
-
|
|
8642
|
-
|
|
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) => {
|
|
8643
8802
|
const right = fact.xPt + fact.widthPt;
|
|
8644
8803
|
const bottom = fact.yPt + fact.heightPt;
|
|
8645
8804
|
const spansWidth = fact.xPt <= tolerance && right >= canvas.widthPt - tolerance;
|
|
@@ -8688,8 +8847,8 @@ var pptxSlideTitleRule = {
|
|
|
8688
8847
|
evaluate: ({ facts, configuration }) => {
|
|
8689
8848
|
const styles = stringListParameter(configuration.parameters, "titleStyles");
|
|
8690
8849
|
const titledSlides = /* @__PURE__ */ new Set();
|
|
8691
|
-
for (const fact of
|
|
8692
|
-
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))
|
|
8693
8852
|
titledSlides.add(fact.slidePath);
|
|
8694
8853
|
for (const fact of facts)
|
|
8695
8854
|
if (fact.kind === "pptx/chrome-slot" && fact.role === "actionTitle" && fact.present)
|
|
@@ -8710,6 +8869,28 @@ var pptxSlideTitleRule = {
|
|
|
8710
8869
|
}));
|
|
8711
8870
|
}
|
|
8712
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
|
+
};
|
|
8713
8894
|
var pptxImageAspectRule = {
|
|
8714
8895
|
id: "pptx/image-aspect",
|
|
8715
8896
|
description: "An image drawn at an aspect the asset does not have, where the asset can be read from the document.",
|
|
@@ -8766,6 +8947,7 @@ var PPTX_QUALITY_RULES = {
|
|
|
8766
8947
|
pptxBulletRule,
|
|
8767
8948
|
pptxSafeAreaRule,
|
|
8768
8949
|
pptxSlideTitleRule,
|
|
8950
|
+
pptxFigureLabelRule,
|
|
8769
8951
|
pptxImageAspectRule
|
|
8770
8952
|
]
|
|
8771
8953
|
};
|
|
@@ -8791,7 +8973,7 @@ var PPTX_QUALITY_PROFILES = {
|
|
|
8791
8973
|
"consulting-deck": {
|
|
8792
8974
|
id: "consulting-deck",
|
|
8793
8975
|
formats: ["pptx"],
|
|
8794
|
-
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.",
|
|
8795
8977
|
rules: {
|
|
8796
8978
|
"pptx/required-chrome": {
|
|
8797
8979
|
parameters: { required: ["takeaway", "source"] }
|
|
@@ -8799,7 +8981,14 @@ var PPTX_QUALITY_PROFILES = {
|
|
|
8799
8981
|
"pptx/action-title": { parameters: { maxLines: 2 } },
|
|
8800
8982
|
"pptx/slide-density": { parameters: { maximumBodyWords: 90 } },
|
|
8801
8983
|
"pptx/type-scale": { enabled: true },
|
|
8802
|
-
|
|
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
|
+
},
|
|
8803
8992
|
"pptx/role-drift": { enabled: true },
|
|
8804
8993
|
"pptx/title-drift": {
|
|
8805
8994
|
enabled: true,
|
|
@@ -8809,7 +8998,8 @@ var PPTX_QUALITY_PROFILES = {
|
|
|
8809
8998
|
parameters: { maximumBullets: 5, maximumWordsPerBullet: 12 }
|
|
8810
8999
|
},
|
|
8811
9000
|
"pptx/safe-area": { enabled: true },
|
|
8812
|
-
"pptx/slide-title": { enabled: true }
|
|
9001
|
+
"pptx/slide-title": { enabled: true },
|
|
9002
|
+
"pptx/figure-label": { enabled: true }
|
|
8813
9003
|
}
|
|
8814
9004
|
}
|
|
8815
9005
|
};
|