@formfeed/devkit 0.3.12 → 0.3.14

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/index.cjs CHANGED
@@ -31,6 +31,7 @@ __export(index_exports, {
31
31
  defaultProjectConfig: () => defaultProjectConfig,
32
32
  defaultTypesFile: () => defaultTypesFile,
33
33
  diagnose: () => diagnose,
34
+ diagnoseAccessibility: () => diagnoseAccessibility,
34
35
  diagnoseEinvoice: () => diagnoseEinvoice,
35
36
  findProject: () => findProject,
36
37
  generateTypes: () => generateTypes,
@@ -809,7 +810,8 @@ function previewDocument(tpl, rendered, mode, pagedScriptUrl) {
809
810
  settings: rendered.settings,
810
811
  kind
811
812
  };
812
- return mode === "paged" && kind === "pdf" ? (0, import_engine4.pagedDocument)(draft, { pagedScriptUrl }) : (0, import_engine4.flowDocument)(draft);
813
+ const audit = kind === "pdf" && (0, import_engine4.resolveUa)(rendered.settings.pdf?.ua) !== null;
814
+ return mode === "paged" && kind === "pdf" ? (0, import_engine4.pagedDocument)(draft, { pagedScriptUrl, audit }) : (0, import_engine4.flowDocument)(draft, { audit });
813
815
  }
814
816
 
815
817
  // packages/devkit/src/lib/einvoice.ts
@@ -905,6 +907,62 @@ function localEinvoiceXml(tpl, data, override) {
905
907
  return { xml: result.xml, invoice: result.invoice, options };
906
908
  }
907
909
 
910
+ // packages/devkit/src/lib/accessibility.ts
911
+ var import_engine6 = require("@formfeed/engine");
912
+ var nowhere3 = { start: { line: 1, column: 1 }, end: { line: 1, column: 1 } };
913
+ var about = (severity, code, message) => ({
914
+ file: "settings.json",
915
+ diagnostics: [{ severity, code, message, range: nowhere3 }]
916
+ });
917
+ function diagnoseAccessibility(tpl) {
918
+ const declared = tpl.settings.pdf?.ua;
919
+ if (declared !== void 0 && !(0, import_engine6.isUaSetting)(declared))
920
+ return [
921
+ about(
922
+ "error",
923
+ "accessibility-setting",
924
+ 'pdf.ua is true, false or { "check": "strict" | "report" }'
925
+ )
926
+ ];
927
+ const ua = (0, import_engine6.resolveUa)(declared);
928
+ if (!ua) return [];
929
+ if (tpl.meta.kind === "image")
930
+ return [
931
+ about(
932
+ "warning",
933
+ "accessibility-image",
934
+ "settings.json declares pdf.ua, which an image template never produces: PDF/UA is a format of PDF"
935
+ )
936
+ ];
937
+ if ((0, import_engine6.isOfficeKind)(tpl.meta.kind))
938
+ return [about("error", "accessibility-office", import_engine6.UA_REFUSALS.office)];
939
+ const out = [];
940
+ const body = [];
941
+ for (const found of (0, import_engine6.staticAuditDiagnostics)(
942
+ {
943
+ engine: tpl.meta.engine,
944
+ html: tpl.html,
945
+ head: tpl.head,
946
+ title: tpl.settings.pdf?.metadata?.title
947
+ },
948
+ ua
949
+ )) {
950
+ if (!found.location) {
951
+ out.push(about(found.severity, found.code, found.message));
952
+ continue;
953
+ }
954
+ body.push({
955
+ severity: found.severity,
956
+ code: found.code,
957
+ message: found.message,
958
+ range: { start: found.location, end: found.location }
959
+ });
960
+ }
961
+ if (body.length)
962
+ out.push({ file: templateFileName(tpl.meta.kind), diagnostics: body });
963
+ return out;
964
+ }
965
+
908
966
  // packages/devkit/src/lib/files.ts
909
967
  var import_node_crypto2 = require("node:crypto");
910
968
  var import_node_fs5 = require("node:fs");
@@ -1043,7 +1101,7 @@ function isRecord(value) {
1043
1101
  }
1044
1102
 
1045
1103
  // packages/devkit/src/lib/types/index.ts
1046
- var import_engine6 = require("@formfeed/engine");
1104
+ var import_engine7 = require("@formfeed/engine");
1047
1105
 
1048
1106
  // packages/devkit/src/lib/types/model.ts
1049
1107
  var isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
@@ -1531,7 +1589,7 @@ function localTypeSource(tpl) {
1531
1589
  const sets = Object.values(tpl.dataSets);
1532
1590
  return {
1533
1591
  slug: tpl.slug,
1534
- schema: (0, import_engine6.inferSchemaFromDataSets)(sets.length ? sets : [{}]),
1592
+ schema: (0, import_engine7.inferSchemaFromDataSets)(sets.length ? sets : [{}]),
1535
1593
  origin: "inferred"
1536
1594
  };
1537
1595
  }
@@ -1548,6 +1606,7 @@ function localTypeSource(tpl) {
1548
1606
  defaultProjectConfig,
1549
1607
  defaultTypesFile,
1550
1608
  diagnose,
1609
+ diagnoseAccessibility,
1551
1610
  diagnoseEinvoice,
1552
1611
  findProject,
1553
1612
  generateTypes,
package/index.js CHANGED
@@ -543,7 +543,8 @@ import {
543
543
  pagedDocument,
544
544
  parseDesign,
545
545
  renderOffice,
546
- renderVersion
546
+ renderVersion,
547
+ resolveUa
547
548
  } from "@formfeed/engine";
548
549
  function diagnose(tpl, sampleData) {
549
550
  if (tpl.file) return diagnoseOffice(tpl, tpl.file.bytes, sampleData);
@@ -757,7 +758,8 @@ function previewDocument(tpl, rendered, mode, pagedScriptUrl) {
757
758
  settings: rendered.settings,
758
759
  kind
759
760
  };
760
- return mode === "paged" && kind === "pdf" ? pagedDocument(draft, { pagedScriptUrl }) : flowDocument(draft);
761
+ const audit = kind === "pdf" && resolveUa(rendered.settings.pdf?.ua) !== null;
762
+ return mode === "paged" && kind === "pdf" ? pagedDocument(draft, { pagedScriptUrl, audit }) : flowDocument(draft, { audit });
761
763
  }
762
764
 
763
765
  // packages/devkit/src/lib/einvoice.ts
@@ -859,6 +861,68 @@ function localEinvoiceXml(tpl, data, override) {
859
861
  return { xml: result.xml, invoice: result.invoice, options };
860
862
  }
861
863
 
864
+ // packages/devkit/src/lib/accessibility.ts
865
+ import {
866
+ UA_REFUSALS,
867
+ isOfficeKind as isOfficeKind3,
868
+ isUaSetting,
869
+ resolveUa as resolveUa2,
870
+ staticAuditDiagnostics
871
+ } from "@formfeed/engine";
872
+ var nowhere3 = { start: { line: 1, column: 1 }, end: { line: 1, column: 1 } };
873
+ var about = (severity, code, message) => ({
874
+ file: "settings.json",
875
+ diagnostics: [{ severity, code, message, range: nowhere3 }]
876
+ });
877
+ function diagnoseAccessibility(tpl) {
878
+ const declared = tpl.settings.pdf?.ua;
879
+ if (declared !== void 0 && !isUaSetting(declared))
880
+ return [
881
+ about(
882
+ "error",
883
+ "accessibility-setting",
884
+ 'pdf.ua is true, false or { "check": "strict" | "report" }'
885
+ )
886
+ ];
887
+ const ua = resolveUa2(declared);
888
+ if (!ua) return [];
889
+ if (tpl.meta.kind === "image")
890
+ return [
891
+ about(
892
+ "warning",
893
+ "accessibility-image",
894
+ "settings.json declares pdf.ua, which an image template never produces: PDF/UA is a format of PDF"
895
+ )
896
+ ];
897
+ if (isOfficeKind3(tpl.meta.kind))
898
+ return [about("error", "accessibility-office", UA_REFUSALS.office)];
899
+ const out = [];
900
+ const body = [];
901
+ for (const found of staticAuditDiagnostics(
902
+ {
903
+ engine: tpl.meta.engine,
904
+ html: tpl.html,
905
+ head: tpl.head,
906
+ title: tpl.settings.pdf?.metadata?.title
907
+ },
908
+ ua
909
+ )) {
910
+ if (!found.location) {
911
+ out.push(about(found.severity, found.code, found.message));
912
+ continue;
913
+ }
914
+ body.push({
915
+ severity: found.severity,
916
+ code: found.code,
917
+ message: found.message,
918
+ range: { start: found.location, end: found.location }
919
+ });
920
+ }
921
+ if (body.length)
922
+ out.push({ file: templateFileName(tpl.meta.kind), diagnostics: body });
923
+ return out;
924
+ }
925
+
862
926
  // packages/devkit/src/lib/files.ts
863
927
  import { createHash as createHash2 } from "node:crypto";
864
928
  import { existsSync as existsSync5, mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync5, statSync as statSync2, writeFileSync as writeFileSync4 } from "node:fs";
@@ -1501,6 +1565,7 @@ export {
1501
1565
  defaultProjectConfig,
1502
1566
  defaultTypesFile,
1503
1567
  diagnose,
1568
+ diagnoseAccessibility,
1504
1569
  diagnoseEinvoice,
1505
1570
  findProject,
1506
1571
  generateTypes,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@formfeed/devkit",
3
- "version": "0.3.12",
3
+ "version": "0.3.14",
4
4
  "description": "Formfeed template folders, project config and local rendering, shared by the CLI and @formfeed/testing.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -30,8 +30,8 @@
30
30
  ],
31
31
  "sideEffects": false,
32
32
  "dependencies": {
33
- "@formfeed/engine": "0.3.12",
34
- "@formfeed/sdk": "0.3.12"
33
+ "@formfeed/engine": "0.3.14",
34
+ "@formfeed/sdk": "0.3.14"
35
35
  },
36
36
  "keywords": [
37
37
  "formfeed",
package/types/index.d.cts CHANGED
@@ -10,6 +10,8 @@ export { diagnose, htmlSnapshot, officeSnapshot, prettyXml, previewDocument, ren
10
10
  export type { LocalDiagnostic, OfficeLocalOptions } from './lib/local-render.cjs';
11
11
  export { declaredEinvoice, diagnoseEinvoice, localEinvoiceXml, } from './lib/einvoice.cjs';
12
12
  export type { DataSetDiagnostics } from './lib/einvoice.cjs';
13
+ export { diagnoseAccessibility } from './lib/accessibility.cjs';
14
+ export type { FileDiagnostics } from './lib/accessibility.cjs';
13
15
  export { contentTypeFor, listLocalFiles, localFilePath, sha256File, writeLocalFile, } from './lib/files.cjs';
14
16
  export type { LocalFile, LocalFileListing } from './lib/files.cjs';
15
17
  export type { LocalRenderOptions } from './lib/local-render.cjs';
package/types/index.d.ts CHANGED
@@ -10,6 +10,8 @@ export { diagnose, htmlSnapshot, officeSnapshot, prettyXml, previewDocument, ren
10
10
  export type { LocalDiagnostic, OfficeLocalOptions } from './lib/local-render.js';
11
11
  export { declaredEinvoice, diagnoseEinvoice, localEinvoiceXml, } from './lib/einvoice.js';
12
12
  export type { DataSetDiagnostics } from './lib/einvoice.js';
13
+ export { diagnoseAccessibility } from './lib/accessibility.js';
14
+ export type { FileDiagnostics } from './lib/accessibility.js';
13
15
  export { contentTypeFor, listLocalFiles, localFilePath, sha256File, writeLocalFile, } from './lib/files.js';
14
16
  export type { LocalFile, LocalFileListing } from './lib/files.js';
15
17
  export type { LocalRenderOptions } from './lib/local-render.js';
@@ -0,0 +1,21 @@
1
+ import type { LocalDiagnostic } from './local-render.cjs';
2
+ import { type LocalTemplate } from './project.cjs';
3
+ /**
4
+ * `pdf.ua` of a template folder (plan 21 §6): what can be said about a template that declares
5
+ * PDF/UA-1 without rendering it. `formfeed validate` and the MCP server's validation report it. It
6
+ * is the static half of the template check: a document without a title, an image written without
7
+ * `alt`, and a declaration the API will refuse. What depends on the data (heading levels, table
8
+ * rows, a chart's name) is found in the rendered page, by the editor's preview and by the render.
9
+ */
10
+ /** The findings of one file of a template folder. */
11
+ export interface FileDiagnostics {
12
+ /** Relative to the template folder: `template.html`, `settings.json`. */
13
+ file: string;
14
+ diagnostics: LocalDiagnostic[];
15
+ }
16
+ /**
17
+ * Empty for a template that does not declare `pdf.ua`. A fault the validator fails the file for is
18
+ * an error where the template is strict, since every render of it then fails, and a warning where
19
+ * it only reports; what a reader stumbles over without a rule failing is a warning either way.
20
+ */
21
+ export declare function diagnoseAccessibility(tpl: LocalTemplate): FileDiagnostics[];
@@ -0,0 +1,21 @@
1
+ import type { LocalDiagnostic } from './local-render.js';
2
+ import { type LocalTemplate } from './project.js';
3
+ /**
4
+ * `pdf.ua` of a template folder (plan 21 §6): what can be said about a template that declares
5
+ * PDF/UA-1 without rendering it. `formfeed validate` and the MCP server's validation report it. It
6
+ * is the static half of the template check: a document without a title, an image written without
7
+ * `alt`, and a declaration the API will refuse. What depends on the data (heading levels, table
8
+ * rows, a chart's name) is found in the rendered page, by the editor's preview and by the render.
9
+ */
10
+ /** The findings of one file of a template folder. */
11
+ export interface FileDiagnostics {
12
+ /** Relative to the template folder: `template.html`, `settings.json`. */
13
+ file: string;
14
+ diagnostics: LocalDiagnostic[];
15
+ }
16
+ /**
17
+ * Empty for a template that does not declare `pdf.ua`. A fault the validator fails the file for is
18
+ * an error where the template is strict, since every render of it then fails, and a warning where
19
+ * it only reports; what a reader stumbles over without a rule failing is a warning either way.
20
+ */
21
+ export declare function diagnoseAccessibility(tpl: LocalTemplate): FileDiagnostics[];