@formfeed/devkit 0.3.11 → 0.3.13

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
@@ -26,10 +26,13 @@ __export(index_exports, {
26
26
  collectPartials: () => collectPartials,
27
27
  contentHash: () => contentHash,
28
28
  contentTypeFor: () => contentTypeFor,
29
+ declaredEinvoice: () => declaredEinvoice,
29
30
  defaultData: () => defaultData,
30
31
  defaultProjectConfig: () => defaultProjectConfig,
31
32
  defaultTypesFile: () => defaultTypesFile,
32
33
  diagnose: () => diagnose,
34
+ diagnoseAccessibility: () => diagnoseAccessibility,
35
+ diagnoseEinvoice: () => diagnoseEinvoice,
33
36
  findProject: () => findProject,
34
37
  generateTypes: () => generateTypes,
35
38
  htmlSnapshot: () => htmlSnapshot,
@@ -37,6 +40,7 @@ __export(index_exports, {
37
40
  listLocalFiles: () => listLocalFiles,
38
41
  listTemplateSlugs: () => listTemplateSlugs,
39
42
  loadProject: () => loadProject,
43
+ localEinvoiceXml: () => localEinvoiceXml,
40
44
  localFilePath: () => localFilePath,
41
45
  localTypeSource: () => localTypeSource,
42
46
  officeSnapshot: () => officeSnapshot,
@@ -806,13 +810,163 @@ function previewDocument(tpl, rendered, mode, pagedScriptUrl) {
806
810
  settings: rendered.settings,
807
811
  kind
808
812
  };
809
- 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 });
810
815
  }
811
816
 
812
- // packages/devkit/src/lib/files.ts
813
- var import_node_crypto2 = require("node:crypto");
817
+ // packages/devkit/src/lib/einvoice.ts
814
818
  var import_node_fs4 = require("node:fs");
815
819
  var import_node_path4 = require("node:path");
820
+ var import_engine5 = require("@formfeed/engine");
821
+ function declaredEinvoice(tpl, override) {
822
+ const resolved = (0, import_engine5.resolveEinvoiceOptions)(tpl.settings.einvoice, override);
823
+ if (!resolved.ok)
824
+ throw new DevkitError(
825
+ `${tpl.slug}: e-invoice ${resolved.field} "${resolved.value}": ${resolved.reason}`,
826
+ "validation"
827
+ );
828
+ return resolved.options;
829
+ }
830
+ var nowhere2 = { start: { line: 1, column: 1 }, end: { line: 1, column: 1 } };
831
+ function diagnoseEinvoice(tpl) {
832
+ let options;
833
+ try {
834
+ options = declaredEinvoice(tpl);
835
+ } catch (e) {
836
+ return [
837
+ {
838
+ dataSet: "",
839
+ file: "settings.json",
840
+ diagnostics: [
841
+ {
842
+ severity: "error",
843
+ code: "einvoice-profile",
844
+ message: e instanceof Error ? e.message : String(e),
845
+ range: nowhere2
846
+ }
847
+ ]
848
+ }
849
+ ];
850
+ }
851
+ if (!options) return [];
852
+ if (tpl.meta.kind === "image")
853
+ return [
854
+ {
855
+ dataSet: "",
856
+ file: "settings.json",
857
+ diagnostics: [
858
+ {
859
+ severity: "warning",
860
+ code: "einvoice-image",
861
+ message: "settings.json declares an e-invoice, which an image template never produces: an e-invoice is a PDF",
862
+ range: nowhere2
863
+ }
864
+ ]
865
+ }
866
+ ];
867
+ const out = [];
868
+ for (const [name, data] of Object.entries(tpl.dataSets)) {
869
+ const result = (0, import_engine5.einvoiceXml)(data, options);
870
+ if (result.ok) continue;
871
+ const file = `data/${name}.json`;
872
+ const path = (0, import_node_path4.join)(tpl.dir, "data", `${name}.json`);
873
+ const text2 = (0, import_node_fs4.existsSync)(path) ? (0, import_node_fs4.readFileSync)(path, "utf8") : null;
874
+ out.push({
875
+ dataSet: name,
876
+ file,
877
+ diagnostics: result.problems.map((problem) => {
878
+ const at = text2 ? (0, import_engine5.locateJsonPath)(text2, [
879
+ import_engine5.INVOICE_DATA_KEY,
880
+ ...(0, import_engine5.invoicePathSegments)(problem.path)
881
+ ]) : null;
882
+ const start = at ? { line: at.line, column: at.column } : nowhere2.start;
883
+ return {
884
+ severity: "error",
885
+ code: `einvoice-${problem.code.replace(/_/g, "-")}`,
886
+ message: problem.message,
887
+ range: { start, end: start }
888
+ };
889
+ })
890
+ });
891
+ }
892
+ return out;
893
+ }
894
+ function localEinvoiceXml(tpl, data, override) {
895
+ const options = declaredEinvoice(tpl, override ?? {});
896
+ if (!options)
897
+ throw new DevkitError(`${tpl.slug} declares no e-invoice`, "validation");
898
+ const result = (0, import_engine5.einvoiceXml)(data, options);
899
+ if (!result.ok)
900
+ throw new DevkitError(
901
+ [
902
+ `${tpl.slug}: the _invoice block does not make an e-invoice`,
903
+ ...result.problems.map((problem) => ` ${problem.message}`)
904
+ ].join("\n"),
905
+ "validation"
906
+ );
907
+ return { xml: result.xml, invoice: result.invoice, options };
908
+ }
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
+
966
+ // packages/devkit/src/lib/files.ts
967
+ var import_node_crypto2 = require("node:crypto");
968
+ var import_node_fs5 = require("node:fs");
969
+ var import_node_path5 = require("node:path");
816
970
 
817
971
  // packages/api-types/src/lib/assets.ts
818
972
  var SEGMENT = "[A-Za-z0-9][A-Za-z0-9._-]*";
@@ -844,25 +998,25 @@ function sha256File(bytes) {
844
998
  }
845
999
  function listLocalFiles(project) {
846
1000
  const listing = { files: [], skipped: [] };
847
- if (!(0, import_node_fs4.existsSync)(project.filesDir)) return listing;
1001
+ if (!(0, import_node_fs5.existsSync)(project.filesDir)) return listing;
848
1002
  const walk2 = (dir) => {
849
- for (const entry of (0, import_node_fs4.readdirSync)(dir, { withFileTypes: true })) {
1003
+ for (const entry of (0, import_node_fs5.readdirSync)(dir, { withFileTypes: true })) {
850
1004
  if (entry.name.startsWith(".")) continue;
851
- const path = (0, import_node_path4.join)(dir, entry.name);
1005
+ const path = (0, import_node_path5.join)(dir, entry.name);
852
1006
  if (entry.isDirectory()) {
853
1007
  walk2(path);
854
1008
  continue;
855
1009
  }
856
1010
  if (!entry.isFile()) continue;
857
- const name = (0, import_node_path4.relative)(project.filesDir, path).split(import_node_path4.sep).join("/");
858
- const size = (0, import_node_fs4.statSync)(path).size;
1011
+ const name = (0, import_node_path5.relative)(project.filesDir, path).split(import_node_path5.sep).join("/");
1012
+ const size = (0, import_node_fs5.statSync)(path).size;
859
1013
  const contentType = contentTypeFor(name);
860
1014
  const reason = !isAssetName(name) ? "the name has characters a library name cannot have (letters, digits, dot, dash, underscore)" : !contentType ? "not an image or a PDF" : size === 0 ? "empty" : size > ASSET_MAX_BYTES ? `larger than ${ASSET_MAX_BYTES / 1024 / 1024} MB` : null;
861
1015
  if (reason) {
862
1016
  listing.skipped.push({ path, reason });
863
1017
  continue;
864
1018
  }
865
- const bytes = (0, import_node_fs4.readFileSync)(path);
1019
+ const bytes = (0, import_node_fs5.readFileSync)(path);
866
1020
  listing.files.push({ name, path, bytes: size, sha256: sha256File(bytes), contentType });
867
1021
  }
868
1022
  };
@@ -872,14 +1026,14 @@ function listLocalFiles(project) {
872
1026
  }
873
1027
  function localFilePath(project, name) {
874
1028
  if (!isAssetName(name)) throw new DevkitError(`"${name}" is not a library file name`);
875
- const path = (0, import_node_path4.resolve)(project.filesDir, ...name.split("/"));
876
- if (!path.startsWith((0, import_node_path4.resolve)(project.filesDir) + import_node_path4.sep)) throw new DevkitError(`"${name}" is not inside the files folder`);
1029
+ const path = (0, import_node_path5.resolve)(project.filesDir, ...name.split("/"));
1030
+ if (!path.startsWith((0, import_node_path5.resolve)(project.filesDir) + import_node_path5.sep)) throw new DevkitError(`"${name}" is not inside the files folder`);
877
1031
  return path;
878
1032
  }
879
1033
  function writeLocalFile(project, name, bytes) {
880
1034
  const path = localFilePath(project, name);
881
- (0, import_node_fs4.mkdirSync)((0, import_node_path4.dirname)(path), { recursive: true });
882
- (0, import_node_fs4.writeFileSync)(path, bytes);
1035
+ (0, import_node_fs5.mkdirSync)((0, import_node_path5.dirname)(path), { recursive: true });
1036
+ (0, import_node_fs5.writeFileSync)(path, bytes);
883
1037
  return path;
884
1038
  }
885
1039
 
@@ -947,7 +1101,7 @@ function isRecord(value) {
947
1101
  }
948
1102
 
949
1103
  // packages/devkit/src/lib/types/index.ts
950
- var import_engine5 = require("@formfeed/engine");
1104
+ var import_engine7 = require("@formfeed/engine");
951
1105
 
952
1106
  // packages/devkit/src/lib/types/model.ts
953
1107
  var isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
@@ -1435,7 +1589,7 @@ function localTypeSource(tpl) {
1435
1589
  const sets = Object.values(tpl.dataSets);
1436
1590
  return {
1437
1591
  slug: tpl.slug,
1438
- schema: (0, import_engine5.inferSchemaFromDataSets)(sets.length ? sets : [{}]),
1592
+ schema: (0, import_engine7.inferSchemaFromDataSets)(sets.length ? sets : [{}]),
1439
1593
  origin: "inferred"
1440
1594
  };
1441
1595
  }
@@ -1447,10 +1601,13 @@ function localTypeSource(tpl) {
1447
1601
  collectPartials,
1448
1602
  contentHash,
1449
1603
  contentTypeFor,
1604
+ declaredEinvoice,
1450
1605
  defaultData,
1451
1606
  defaultProjectConfig,
1452
1607
  defaultTypesFile,
1453
1608
  diagnose,
1609
+ diagnoseAccessibility,
1610
+ diagnoseEinvoice,
1454
1611
  findProject,
1455
1612
  generateTypes,
1456
1613
  htmlSnapshot,
@@ -1458,6 +1615,7 @@ function localTypeSource(tpl) {
1458
1615
  listLocalFiles,
1459
1616
  listTemplateSlugs,
1460
1617
  loadProject,
1618
+ localEinvoiceXml,
1461
1619
  localFilePath,
1462
1620
  localTypeSource,
1463
1621
  officeSnapshot,
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,13 +758,175 @@ 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 });
763
+ }
764
+
765
+ // packages/devkit/src/lib/einvoice.ts
766
+ import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
767
+ import { join as join4 } from "node:path";
768
+ import {
769
+ INVOICE_DATA_KEY,
770
+ einvoiceXml,
771
+ invoicePathSegments,
772
+ locateJsonPath,
773
+ resolveEinvoiceOptions
774
+ } from "@formfeed/engine";
775
+ function declaredEinvoice(tpl, override) {
776
+ const resolved = resolveEinvoiceOptions(tpl.settings.einvoice, override);
777
+ if (!resolved.ok)
778
+ throw new DevkitError(
779
+ `${tpl.slug}: e-invoice ${resolved.field} "${resolved.value}": ${resolved.reason}`,
780
+ "validation"
781
+ );
782
+ return resolved.options;
783
+ }
784
+ var nowhere2 = { start: { line: 1, column: 1 }, end: { line: 1, column: 1 } };
785
+ function diagnoseEinvoice(tpl) {
786
+ let options;
787
+ try {
788
+ options = declaredEinvoice(tpl);
789
+ } catch (e) {
790
+ return [
791
+ {
792
+ dataSet: "",
793
+ file: "settings.json",
794
+ diagnostics: [
795
+ {
796
+ severity: "error",
797
+ code: "einvoice-profile",
798
+ message: e instanceof Error ? e.message : String(e),
799
+ range: nowhere2
800
+ }
801
+ ]
802
+ }
803
+ ];
804
+ }
805
+ if (!options) return [];
806
+ if (tpl.meta.kind === "image")
807
+ return [
808
+ {
809
+ dataSet: "",
810
+ file: "settings.json",
811
+ diagnostics: [
812
+ {
813
+ severity: "warning",
814
+ code: "einvoice-image",
815
+ message: "settings.json declares an e-invoice, which an image template never produces: an e-invoice is a PDF",
816
+ range: nowhere2
817
+ }
818
+ ]
819
+ }
820
+ ];
821
+ const out = [];
822
+ for (const [name, data] of Object.entries(tpl.dataSets)) {
823
+ const result = einvoiceXml(data, options);
824
+ if (result.ok) continue;
825
+ const file = `data/${name}.json`;
826
+ const path = join4(tpl.dir, "data", `${name}.json`);
827
+ const text2 = existsSync4(path) ? readFileSync4(path, "utf8") : null;
828
+ out.push({
829
+ dataSet: name,
830
+ file,
831
+ diagnostics: result.problems.map((problem) => {
832
+ const at = text2 ? locateJsonPath(text2, [
833
+ INVOICE_DATA_KEY,
834
+ ...invoicePathSegments(problem.path)
835
+ ]) : null;
836
+ const start = at ? { line: at.line, column: at.column } : nowhere2.start;
837
+ return {
838
+ severity: "error",
839
+ code: `einvoice-${problem.code.replace(/_/g, "-")}`,
840
+ message: problem.message,
841
+ range: { start, end: start }
842
+ };
843
+ })
844
+ });
845
+ }
846
+ return out;
847
+ }
848
+ function localEinvoiceXml(tpl, data, override) {
849
+ const options = declaredEinvoice(tpl, override ?? {});
850
+ if (!options)
851
+ throw new DevkitError(`${tpl.slug} declares no e-invoice`, "validation");
852
+ const result = einvoiceXml(data, options);
853
+ if (!result.ok)
854
+ throw new DevkitError(
855
+ [
856
+ `${tpl.slug}: the _invoice block does not make an e-invoice`,
857
+ ...result.problems.map((problem) => ` ${problem.message}`)
858
+ ].join("\n"),
859
+ "validation"
860
+ );
861
+ return { xml: result.xml, invoice: result.invoice, options };
862
+ }
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;
761
924
  }
762
925
 
763
926
  // packages/devkit/src/lib/files.ts
764
927
  import { createHash as createHash2 } from "node:crypto";
765
- import { existsSync as existsSync4, mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync4, statSync as statSync2, writeFileSync as writeFileSync4 } from "node:fs";
766
- import { dirname as dirname3, join as join4, relative as relative2, resolve as resolve2, sep as sep2 } from "node:path";
928
+ import { existsSync as existsSync5, mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync5, statSync as statSync2, writeFileSync as writeFileSync4 } from "node:fs";
929
+ import { dirname as dirname3, join as join5, relative as relative2, resolve as resolve2, sep as sep2 } from "node:path";
767
930
 
768
931
  // packages/api-types/src/lib/assets.ts
769
932
  var SEGMENT = "[A-Za-z0-9][A-Za-z0-9._-]*";
@@ -795,11 +958,11 @@ function sha256File(bytes) {
795
958
  }
796
959
  function listLocalFiles(project) {
797
960
  const listing = { files: [], skipped: [] };
798
- if (!existsSync4(project.filesDir)) return listing;
961
+ if (!existsSync5(project.filesDir)) return listing;
799
962
  const walk2 = (dir) => {
800
963
  for (const entry of readdirSync2(dir, { withFileTypes: true })) {
801
964
  if (entry.name.startsWith(".")) continue;
802
- const path = join4(dir, entry.name);
965
+ const path = join5(dir, entry.name);
803
966
  if (entry.isDirectory()) {
804
967
  walk2(path);
805
968
  continue;
@@ -813,7 +976,7 @@ function listLocalFiles(project) {
813
976
  listing.skipped.push({ path, reason });
814
977
  continue;
815
978
  }
816
- const bytes = readFileSync4(path);
979
+ const bytes = readFileSync5(path);
817
980
  listing.files.push({ name, path, bytes: size, sha256: sha256File(bytes), contentType });
818
981
  }
819
982
  };
@@ -1397,10 +1560,13 @@ export {
1397
1560
  collectPartials,
1398
1561
  contentHash,
1399
1562
  contentTypeFor,
1563
+ declaredEinvoice,
1400
1564
  defaultData,
1401
1565
  defaultProjectConfig,
1402
1566
  defaultTypesFile,
1403
1567
  diagnose,
1568
+ diagnoseAccessibility,
1569
+ diagnoseEinvoice,
1404
1570
  findProject,
1405
1571
  generateTypes,
1406
1572
  htmlSnapshot,
@@ -1408,6 +1574,7 @@ export {
1408
1574
  listLocalFiles,
1409
1575
  listTemplateSlugs,
1410
1576
  loadProject,
1577
+ localEinvoiceXml,
1411
1578
  localFilePath,
1412
1579
  localTypeSource,
1413
1580
  officeSnapshot,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@formfeed/devkit",
3
- "version": "0.3.11",
3
+ "version": "0.3.13",
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.11",
34
- "@formfeed/sdk": "0.3.11"
33
+ "@formfeed/engine": "0.3.13",
34
+ "@formfeed/sdk": "0.3.13"
35
35
  },
36
36
  "keywords": [
37
37
  "formfeed",
package/types/index.d.cts CHANGED
@@ -1,16 +1,20 @@
1
1
  export { DevkitError } from './lib/errors.cjs';
2
- export { defaultProjectConfig, findProject, isIgnored, loadProject, projectAround, writeProjectConfig } from './lib/project-config.cjs';
2
+ export { defaultProjectConfig, findProject, isIgnored, loadProject, projectAround, writeProjectConfig, } from './lib/project-config.cjs';
3
3
  export type { Project, ProjectConfig } from './lib/project-config.cjs';
4
4
  export { contentHash, defaultData, listTemplateSlugs, officeVersionPayload, partialContentHash, partialResolver, readState, readTemplate, recordSharedPartial, recordSync, sharedPartialNames, sharedPartialPath, templateDir, templateFileName, titleFromSlug, versionPayload, writePartials, writeState, writeTemplate, } from './lib/project.cjs';
5
- export type { LocalOfficeFile, LocalTemplate, ProjectState, SharedPartialState, TemplateMeta, TemplateState } from './lib/project.cjs';
5
+ export type { LocalOfficeFile, LocalTemplate, ProjectState, SharedPartialState, TemplateMeta, TemplateState, } from './lib/project.cjs';
6
6
  export { brandFromJson, brandPath, readBrand, writeBrand } from './lib/brand.cjs';
7
7
  export { collectPartials } from './lib/partials.cjs';
8
8
  export type { CollectedPartials } from './lib/partials.cjs';
9
- export { diagnose, htmlSnapshot, officeSnapshot, prettyXml, previewDocument, renderContext, renderLocal, renderOfficeLocal, renderedSettings } from './lib/local-render.cjs';
9
+ export { diagnose, htmlSnapshot, officeSnapshot, prettyXml, previewDocument, renderContext, renderLocal, renderOfficeLocal, renderedSettings, } from './lib/local-render.cjs';
10
10
  export type { LocalDiagnostic, OfficeLocalOptions } from './lib/local-render.cjs';
11
- export { contentTypeFor, listLocalFiles, localFilePath, sha256File, writeLocalFile } from './lib/files.cjs';
11
+ export { declaredEinvoice, diagnoseEinvoice, localEinvoiceXml, } from './lib/einvoice.cjs';
12
+ export type { DataSetDiagnostics } from './lib/einvoice.cjs';
13
+ export { diagnoseAccessibility } from './lib/accessibility.cjs';
14
+ export type { FileDiagnostics } from './lib/accessibility.cjs';
15
+ export { contentTypeFor, listLocalFiles, localFilePath, sha256File, writeLocalFile, } from './lib/files.cjs';
12
16
  export type { LocalFile, LocalFileListing } from './lib/files.cjs';
13
17
  export type { LocalRenderOptions } from './lib/local-render.cjs';
14
18
  export { parseRedactPath, redactData, redactString } from './lib/redact.cjs';
15
19
  export { defaultTypesFile, generateTypes, localTypeSource } from './lib/types/index.cjs';
16
- export type { SchemaOrigin, TypeScriptOptions, TypeSource, TypesLanguage } from './lib/types/index.cjs';
20
+ export type { SchemaOrigin, TypeScriptOptions, TypeSource, TypesLanguage, } from './lib/types/index.cjs';
package/types/index.d.ts CHANGED
@@ -1,16 +1,20 @@
1
1
  export { DevkitError } from './lib/errors.js';
2
- export { defaultProjectConfig, findProject, isIgnored, loadProject, projectAround, writeProjectConfig } from './lib/project-config.js';
2
+ export { defaultProjectConfig, findProject, isIgnored, loadProject, projectAround, writeProjectConfig, } from './lib/project-config.js';
3
3
  export type { Project, ProjectConfig } from './lib/project-config.js';
4
4
  export { contentHash, defaultData, listTemplateSlugs, officeVersionPayload, partialContentHash, partialResolver, readState, readTemplate, recordSharedPartial, recordSync, sharedPartialNames, sharedPartialPath, templateDir, templateFileName, titleFromSlug, versionPayload, writePartials, writeState, writeTemplate, } from './lib/project.js';
5
- export type { LocalOfficeFile, LocalTemplate, ProjectState, SharedPartialState, TemplateMeta, TemplateState } from './lib/project.js';
5
+ export type { LocalOfficeFile, LocalTemplate, ProjectState, SharedPartialState, TemplateMeta, TemplateState, } from './lib/project.js';
6
6
  export { brandFromJson, brandPath, readBrand, writeBrand } from './lib/brand.js';
7
7
  export { collectPartials } from './lib/partials.js';
8
8
  export type { CollectedPartials } from './lib/partials.js';
9
- export { diagnose, htmlSnapshot, officeSnapshot, prettyXml, previewDocument, renderContext, renderLocal, renderOfficeLocal, renderedSettings } from './lib/local-render.js';
9
+ export { diagnose, htmlSnapshot, officeSnapshot, prettyXml, previewDocument, renderContext, renderLocal, renderOfficeLocal, renderedSettings, } from './lib/local-render.js';
10
10
  export type { LocalDiagnostic, OfficeLocalOptions } from './lib/local-render.js';
11
- export { contentTypeFor, listLocalFiles, localFilePath, sha256File, writeLocalFile } from './lib/files.js';
11
+ export { declaredEinvoice, diagnoseEinvoice, localEinvoiceXml, } from './lib/einvoice.js';
12
+ export type { DataSetDiagnostics } from './lib/einvoice.js';
13
+ export { diagnoseAccessibility } from './lib/accessibility.js';
14
+ export type { FileDiagnostics } from './lib/accessibility.js';
15
+ export { contentTypeFor, listLocalFiles, localFilePath, sha256File, writeLocalFile, } from './lib/files.js';
12
16
  export type { LocalFile, LocalFileListing } from './lib/files.js';
13
17
  export type { LocalRenderOptions } from './lib/local-render.js';
14
18
  export { parseRedactPath, redactData, redactString } from './lib/redact.js';
15
19
  export { defaultTypesFile, generateTypes, localTypeSource } from './lib/types/index.js';
16
- export type { SchemaOrigin, TypeScriptOptions, TypeSource, TypesLanguage } from './lib/types/index.js';
20
+ export type { SchemaOrigin, TypeScriptOptions, TypeSource, TypesLanguage, } from './lib/types/index.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[];
@@ -0,0 +1,37 @@
1
+ import { type EinvoiceOptions, type EinvoiceOptionsInput, type Invoice } from '@formfeed/engine';
2
+ import type { LocalDiagnostic } from './local-render.cjs';
3
+ import type { LocalTemplate } from './project.cjs';
4
+ /**
5
+ * The e-invoice of a template folder (spec 17): what `settings.json` declares, the check of every
6
+ * data set against it, and the XML itself. All of it runs offline, with the code the API runs, so
7
+ * what `formfeed validate` accepts the API accepts too.
8
+ */
9
+ /**
10
+ * The e-invoice a template declares in `settings.json`, with every default filled in; `null` when
11
+ * it declares none. `override` is merged over it like a request's `post.einvoice`; `{}` asks for an
12
+ * e-invoice with the defaults from a template that declares nothing.
13
+ */
14
+ export declare function declaredEinvoice(tpl: LocalTemplate, override?: EinvoiceOptionsInput | false): EinvoiceOptions | null;
15
+ /** The findings of one data set, with the file they are in. */
16
+ export interface DataSetDiagnostics {
17
+ dataSet: string;
18
+ /** Relative to the template folder: `data/default.json`. */
19
+ file: string;
20
+ diagnostics: LocalDiagnostic[];
21
+ }
22
+ /**
23
+ * Every data set of an invoice template against the `_invoice` schema and the rules of EN 16931
24
+ * (spec 17 §8). Each is an error: a render with that data fails with `einvoice_data_invalid`, and a
25
+ * template that declares an e-invoice renders nothing else. Empty for a template that declares
26
+ * none; one warning for an image template, where the declaration has no effect.
27
+ */
28
+ export declare function diagnoseEinvoice(tpl: LocalTemplate): DataSetDiagnostics[];
29
+ /**
30
+ * The XML of one data set, as a render of the template would embed it. Throws a validation error
31
+ * that lists what is wrong with the block when it does not pass.
32
+ */
33
+ export declare function localEinvoiceXml(tpl: LocalTemplate, data: unknown, override?: EinvoiceOptionsInput): {
34
+ xml: string;
35
+ invoice: Invoice;
36
+ options: EinvoiceOptions;
37
+ };
@@ -0,0 +1,37 @@
1
+ import { type EinvoiceOptions, type EinvoiceOptionsInput, type Invoice } from '@formfeed/engine';
2
+ import type { LocalDiagnostic } from './local-render.js';
3
+ import type { LocalTemplate } from './project.js';
4
+ /**
5
+ * The e-invoice of a template folder (spec 17): what `settings.json` declares, the check of every
6
+ * data set against it, and the XML itself. All of it runs offline, with the code the API runs, so
7
+ * what `formfeed validate` accepts the API accepts too.
8
+ */
9
+ /**
10
+ * The e-invoice a template declares in `settings.json`, with every default filled in; `null` when
11
+ * it declares none. `override` is merged over it like a request's `post.einvoice`; `{}` asks for an
12
+ * e-invoice with the defaults from a template that declares nothing.
13
+ */
14
+ export declare function declaredEinvoice(tpl: LocalTemplate, override?: EinvoiceOptionsInput | false): EinvoiceOptions | null;
15
+ /** The findings of one data set, with the file they are in. */
16
+ export interface DataSetDiagnostics {
17
+ dataSet: string;
18
+ /** Relative to the template folder: `data/default.json`. */
19
+ file: string;
20
+ diagnostics: LocalDiagnostic[];
21
+ }
22
+ /**
23
+ * Every data set of an invoice template against the `_invoice` schema and the rules of EN 16931
24
+ * (spec 17 §8). Each is an error: a render with that data fails with `einvoice_data_invalid`, and a
25
+ * template that declares an e-invoice renders nothing else. Empty for a template that declares
26
+ * none; one warning for an image template, where the declaration has no effect.
27
+ */
28
+ export declare function diagnoseEinvoice(tpl: LocalTemplate): DataSetDiagnostics[];
29
+ /**
30
+ * The XML of one data set, as a render of the template would embed it. Throws a validation error
31
+ * that lists what is wrong with the block when it does not pass.
32
+ */
33
+ export declare function localEinvoiceXml(tpl: LocalTemplate, data: unknown, override?: EinvoiceOptionsInput): {
34
+ xml: string;
35
+ invoice: Invoice;
36
+ options: EinvoiceOptions;
37
+ };