@json-to-office/shared 1.6.0 → 2.5.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/index.js CHANGED
@@ -2,9 +2,11 @@ import {
2
2
  FONT_URL_ALLOWLIST,
3
3
  detectFontFormat,
4
4
  isAllowedFontUrl,
5
+ readFontFamilyNames,
6
+ readNameRecords,
5
7
  rewriteFontFamilyName,
6
8
  standardSubfamilyNames
7
- } from "./chunk-MCUIFSUN.js";
9
+ } from "./chunk-OM2IOZMT.js";
8
10
  import {
9
11
  ComponentValidationError,
10
12
  DuplicateComponentError,
@@ -58,13 +60,33 @@ import {
58
60
  unionBranches
59
61
  } from "./chunk-6TNT7DGC.js";
60
62
  import {
63
+ CANVASES,
64
+ ChromeSchema,
65
+ DesignSpacingSchema,
66
+ DesignSystemProperties,
67
+ DesignSystemSchema,
61
68
  FontFamilyNameSchema,
62
69
  FontRegistryEntrySchema,
63
70
  FontRegistrySchema,
64
71
  FontSourceSchema,
72
+ MotifSchema,
73
+ PaletteSchema,
74
+ ROLE_SCALE_STEPS,
65
75
  SAFE_FONTS,
66
- isSafeFont
67
- } from "./chunk-6KUQYVPT.js";
76
+ TYPE_ROLES,
77
+ TextCaseSchema,
78
+ TypeRoleNameSchema,
79
+ TypeRoleSchema,
80
+ TypeRolesSchema,
81
+ TypographySchema,
82
+ capsFormatting,
83
+ designCanvas,
84
+ designColors,
85
+ isSafeFont,
86
+ resolveDesignColor,
87
+ resolveTypeRoles,
88
+ validateDesignColors
89
+ } from "./chunk-4MJFAJFW.js";
68
90
  import {
69
91
  compareSemver,
70
92
  isValidSemver,
@@ -570,36 +592,6 @@ function readUsWeightClass(ttf) {
570
592
  if (os2.off + 6 > ttf.length) return null;
571
593
  return ttf.readUInt16BE(os2.off + 4);
572
594
  }
573
- function readNames(ttf, wanted) {
574
- const nt = readTable(ttf, "name");
575
- if (!nt) return [];
576
- const tableOff = nt.off;
577
- if (tableOff + 6 > ttf.length) return [];
578
- const count = ttf.readUInt16BE(tableOff + 2);
579
- const storageRel = ttf.readUInt16BE(tableOff + 4);
580
- const storage = tableOff + storageRel;
581
- const out = [];
582
- for (let j = 0; j < count; j++) {
583
- const r = tableOff + 6 + j * 12;
584
- if (r + 12 > ttf.length) break;
585
- const platformID = ttf.readUInt16BE(r);
586
- const nameID = ttf.readUInt16BE(r + 6);
587
- if (!wanted.has(nameID)) continue;
588
- const length = ttf.readUInt16BE(r + 8);
589
- const offset = ttf.readUInt16BE(r + 10);
590
- const raw = ttf.slice(storage + offset, storage + offset + length);
591
- let value;
592
- if (platformID === 1) {
593
- value = raw.toString("ascii");
594
- } else {
595
- const swapped = Buffer.from(raw);
596
- if (swapped.length % 2 === 0) swapped.swap16();
597
- value = swapped.toString("utf16le");
598
- }
599
- out.push({ platformID, nameID, value });
600
- }
601
- return out;
602
- }
603
595
  function validateFontMetadata(ttf, weight, italic, familyLabel) {
604
596
  const diags = [];
605
597
  const usWeight = readUsWeightClass(ttf);
@@ -609,11 +601,20 @@ function validateFontMetadata(ttf, weight, italic, familyLabel) {
609
601
  message: `Font "${familyLabel}" weight ${weight}: OS/2.usWeightClass reports ${usWeight}. Likely a defective redistribution \u2014 consider adding an upstream override.`
610
602
  });
611
603
  }
604
+ const declaredFamilies = readFontFamilyNames(ttf);
605
+ if (declaredFamilies.length > 0 && !declaredFamilies.includes(familyLabel.trim())) {
606
+ diags.push({
607
+ code: "FAMILY_MISMATCH",
608
+ message: `Font "${familyLabel}" weight ${weight}${italic ? " italic" : ""}: name table declares ${declaredFamilies.map((f) => `"${f}"`).join(
609
+ " / "
610
+ )}, not "${familyLabel}". Referencing runs will not resolve this face.`
611
+ });
612
+ }
612
613
  const std = standardSubfamilyNames(weight, italic);
613
614
  if (!std) return diags;
614
615
  const expected17 = std.typographic;
615
616
  const expected2 = std.legacy;
616
- const names = readNames(ttf, /* @__PURE__ */ new Set([2, 17]));
617
+ const names = readNameRecords(ttf, /* @__PURE__ */ new Set([2, 17]));
617
618
  for (const n of names) {
618
619
  if (n.nameID === 17 && n.value !== expected17) {
619
620
  diags.push({
@@ -631,6 +632,75 @@ function validateFontMetadata(ttf, weight, italic, familyLabel) {
631
632
  return diags;
632
633
  }
633
634
 
635
+ // src/fonts/sources/ttf-structure.ts
636
+ var SFNT_VERSIONS = /* @__PURE__ */ new Set([
637
+ 65536,
638
+ // TrueType outlines
639
+ 1330926671,
640
+ // 'OTTO' — CFF outlines
641
+ 1953658213,
642
+ // 'true'
643
+ 1954115633
644
+ // 'typ1'
645
+ ]);
646
+ var HEADER_SIZE2 = 12;
647
+ var TABLE_RECORD_SIZE2 = 16;
648
+ function validateFontStructure(ttf, weight, italic, familyLabel) {
649
+ const face = `Font "${familyLabel}" weight ${weight}${italic ? " italic" : ""}`;
650
+ const unreadable = (reason) => ({
651
+ code: "FONT_UNREADABLE",
652
+ message: `${face}: ${reason} The face will not resolve; text referencing it renders in a fallback.`
653
+ });
654
+ if (ttf.length < HEADER_SIZE2) {
655
+ return unreadable(
656
+ `${ttf.length} bytes is shorter than an sfnt header \u2014 the download is truncated or empty.`
657
+ );
658
+ }
659
+ const version = ttf.readUInt32BE(0);
660
+ if (!SFNT_VERSIONS.has(version)) {
661
+ return unreadable(
662
+ `sfnt version 0x${version.toString(16).padStart(8, "0")} is neither TrueType nor OpenType.`
663
+ );
664
+ }
665
+ const numTables = ttf.readUInt16BE(4);
666
+ if (numTables === 0) return unreadable("its table directory is empty.");
667
+ const directoryEnd = HEADER_SIZE2 + numTables * TABLE_RECORD_SIZE2;
668
+ if (directoryEnd > ttf.length) {
669
+ return unreadable(
670
+ `its directory claims ${numTables} tables (${directoryEnd} bytes) but the file is ${ttf.length} bytes \u2014 truncated.`
671
+ );
672
+ }
673
+ const tags = /* @__PURE__ */ new Set();
674
+ for (let i = 0; i < numTables; i += 1) {
675
+ const ro = HEADER_SIZE2 + i * TABLE_RECORD_SIZE2;
676
+ const tag = ttf.toString("ascii", ro, ro + 4);
677
+ const offset = ttf.readUInt32BE(ro + 8);
678
+ const length = ttf.readUInt32BE(ro + 12);
679
+ if (offset + length > ttf.length) {
680
+ return unreadable(
681
+ `its "${tag}" table runs to byte ${offset + length} but the file is ${ttf.length} bytes \u2014 truncated.`
682
+ );
683
+ }
684
+ tags.add(tag);
685
+ }
686
+ for (const required of ["name", "head"]) {
687
+ if (!tags.has(required)) {
688
+ return unreadable(`it has no "${required}" table.`);
689
+ }
690
+ }
691
+ const hasTrueTypeOutlines = tags.has("glyf") && tags.has("loca");
692
+ const hasCffOutlines = tags.has("CFF ") || tags.has("CFF2");
693
+ if (!hasTrueTypeOutlines && !hasCffOutlines) {
694
+ return unreadable(
695
+ 'it carries no glyph outlines (neither "glyf" + "loca" nor "CFF ").'
696
+ );
697
+ }
698
+ if (readNameRecords(ttf).length === 0) {
699
+ return unreadable('its "name" table carries no readable records.');
700
+ }
701
+ return null;
702
+ }
703
+
634
704
  // src/fonts/cache/memory-cache.ts
635
705
  var FontMemoryCache = class {
636
706
  store = /* @__PURE__ */ new Map();
@@ -665,6 +735,19 @@ var FontMemoryCache = class {
665
735
  };
666
736
 
667
737
  // src/fonts/registry.ts
738
+ function stampResolvedFamily(source, family) {
739
+ if (source.format !== "ttf" && source.format !== "otf") return source;
740
+ const declared = readFontFamilyNames(source.data);
741
+ if (declared.length === 0 || declared.includes(family)) return source;
742
+ const subfamily = standardSubfamilyNames(
743
+ source.weight,
744
+ source.italic
745
+ )?.legacy;
746
+ return {
747
+ ...source,
748
+ data: rewriteFontFamilyName(source.data, family, subfamily)
749
+ };
750
+ }
668
751
  var FontRegistry = class {
669
752
  index;
670
753
  cache;
@@ -721,8 +804,21 @@ var FontRegistry = class {
721
804
  for (const source of entry.sources) {
722
805
  try {
723
806
  const materialized = await this.materializeSource(source, warnings);
724
- for (const s of materialized) {
725
- if (s.format === "ttf" || s.format === "otf") {
807
+ for (const raw of materialized) {
808
+ const sfnt = raw.format === "ttf" || raw.format === "otf";
809
+ const broken = sfnt ? validateFontStructure(
810
+ raw.data,
811
+ raw.weight,
812
+ raw.italic,
813
+ entry.family
814
+ ) : null;
815
+ if (broken) {
816
+ warnings.push(`[${broken.code}] ${broken.message}`);
817
+ sources.push(raw);
818
+ continue;
819
+ }
820
+ const s = stampResolvedFamily(raw, entry.family);
821
+ if (sfnt) {
726
822
  for (const d of validateFontMetadata(
727
823
  s.data,
728
824
  s.weight,
@@ -1300,10 +1396,15 @@ function mergeWithDefaults(userConfig, themeDefaults) {
1300
1396
  return deepMerge(themeDefaults, userConfig);
1301
1397
  }
1302
1398
  export {
1399
+ CANVASES,
1400
+ ChromeSchema,
1303
1401
  ComponentValidationError,
1304
1402
  DEFAULT_CHART_THEME_COLORS,
1305
1403
  DEFAULT_ERROR_CONFIG,
1306
1404
  DEFAULT_VISUAL_DPI,
1405
+ DesignSpacingSchema,
1406
+ DesignSystemProperties,
1407
+ DesignSystemSchema,
1307
1408
  DuplicateComponentError,
1308
1409
  ERROR_EMOJIS,
1309
1410
  FONT_URL_ALLOWLIST,
@@ -1318,10 +1419,19 @@ export {
1318
1419
  MAX_RASTERIZE_FONT_BYTES,
1319
1420
  MAX_VISUAL_DPI,
1320
1421
  MIN_VISUAL_DPI,
1422
+ MotifSchema,
1321
1423
  POPULAR_GOOGLE_FONTS,
1424
+ PaletteSchema,
1322
1425
  RENDERER_DEPENDENCY_MISSING,
1426
+ ROLE_SCALE_STEPS,
1323
1427
  RendererRegistry,
1324
1428
  SAFE_FONTS,
1429
+ TYPE_ROLES,
1430
+ TextCaseSchema,
1431
+ TypeRoleNameSchema,
1432
+ TypeRoleSchema,
1433
+ TypeRolesSchema,
1434
+ TypographySchema,
1325
1435
  UPSTREAM_OVERRIDES,
1326
1436
  UnknownPreservedComponentError,
1327
1437
  UnsupportedRendererFeatureError,
@@ -1332,6 +1442,7 @@ export {
1332
1442
  assertRendererSupports,
1333
1443
  buildDefaultSubstitutionMap,
1334
1444
  calculatePosition,
1445
+ capsFormatting,
1335
1446
  clampVisualDpi,
1336
1447
  clearComponentNamesCache,
1337
1448
  collectFontNamesFromDocx,
@@ -1345,6 +1456,8 @@ export {
1345
1456
  createJsonParseError,
1346
1457
  createVersion,
1347
1458
  defaultSubstituteFor,
1459
+ designCanvas,
1460
+ designColors,
1348
1461
  detectFontFormat,
1349
1462
  diagnoseUnsupportedFeatures,
1350
1463
  documentFontRegistry,
@@ -1375,6 +1488,8 @@ export {
1375
1488
  rendererError,
1376
1489
  rendererWarning,
1377
1490
  resolveComponentVersion,
1491
+ resolveDesignColor,
1492
+ resolveTypeRoles,
1378
1493
  restructureNameDiscriminatedUnions,
1379
1494
  rewriteFontFamilyName,
1380
1495
  synthesizeFamilyName,
@@ -1383,6 +1498,7 @@ export {
1383
1498
  transformValueErrors,
1384
1499
  unionBranches,
1385
1500
  validateCustomComponentProps,
1501
+ validateDesignColors,
1386
1502
  validateFontReferences
1387
1503
  };
1388
1504
  //# sourceMappingURL=index.js.map