@heroiclands/package-build 8.1.0 → 10.0.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.
Files changed (122) hide show
  1. package/CHANGELOG.md +748 -0
  2. package/CONTENT.md +273 -13
  3. package/bin/content-build.mjs +479 -123
  4. package/bin/package-build.mjs +27 -69
  5. package/bin/report.mjs +1 -2
  6. package/bundle.mjs +2 -10
  7. package/config.mjs +31 -106
  8. package/container.mjs +13 -57
  9. package/content-config.mjs +300 -188
  10. package/coverage.mjs +14 -55
  11. package/deploy.mjs +4 -13
  12. package/docs/content-format.md +1418 -0
  13. package/e2e.mjs +16 -55
  14. package/engine/address-charset.mjs +62 -0
  15. package/engine/address-diff.mjs +1 -4
  16. package/engine/alias-index.mjs +153 -0
  17. package/engine/base-compiler.mjs +203 -31
  18. package/engine/code-fences.mjs +4 -13
  19. package/engine/compendiums.mjs +13 -37
  20. package/engine/content-address.mjs +6 -10
  21. package/engine/content-format-check.mjs +570 -0
  22. package/engine/content-format.mjs +253 -0
  23. package/engine/content-links.mjs +144 -99
  24. package/engine/content-lint.mjs +12 -16
  25. package/engine/content-slug.mjs +2 -6
  26. package/engine/content-tables.mjs +26 -79
  27. package/engine/diagnostics.mjs +37 -15
  28. package/engine/document-subtypes.mjs +440 -0
  29. package/engine/field-reference.mjs +6 -20
  30. package/engine/field-spec.mjs +49 -45
  31. package/engine/foreign-catalog.mjs +7 -22
  32. package/engine/foreign-manifests.mjs +1 -4
  33. package/engine/frontmatter-lint.mjs +347 -43
  34. package/engine/frontmatter.mjs +3 -8
  35. package/engine/generate.mjs +36 -20
  36. package/engine/helpers.mjs +54 -81
  37. package/engine/homepage.mjs +4 -15
  38. package/engine/ids.mjs +21 -12
  39. package/engine/index.mjs +15 -0
  40. package/engine/item-registry.mjs +72 -9
  41. package/engine/journals.mjs +4 -14
  42. package/engine/kb-manifest.mjs +41 -24
  43. package/engine/macros.mjs +2 -10
  44. package/engine/manifest-emit.mjs +6 -17
  45. package/engine/map-notes.mjs +53 -87
  46. package/engine/note-claims.mjs +383 -0
  47. package/engine/note-package.mjs +1 -4
  48. package/engine/note-vocabulary.mjs +678 -0
  49. package/engine/pack-config.mjs +56 -60
  50. package/engine/pack-router.mjs +18 -8
  51. package/engine/prose-config.mjs +20 -4
  52. package/engine/prose-lint.mjs +61 -17
  53. package/engine/region-events.mjs +1 -3
  54. package/engine/retired-fields.mjs +117 -3
  55. package/engine/scene-levels.mjs +8 -22
  56. package/engine/scenes.mjs +31 -47
  57. package/engine/schema-check.mjs +348 -7
  58. package/engine/schema-extract.mjs +11 -39
  59. package/engine/site-build.mjs +13 -38
  60. package/engine/site-index.mjs +40 -35
  61. package/engine/system-block.mjs +513 -0
  62. package/engine/web-wikilinks.mjs +115 -92
  63. package/engine/wikilink-syntax.mjs +30 -0
  64. package/engine/wikilinks.mjs +147 -183
  65. package/index.mjs +1 -5
  66. package/lang.mjs +1 -3
  67. package/manifest.mjs +10 -37
  68. package/markdownlint-config.mjs +1 -5
  69. package/package.json +6 -2
  70. package/sohl/actors.mjs +251 -68
  71. package/sohl/being-info.mjs +3 -6
  72. package/sohl/document-subtypes.mjs +82 -0
  73. package/sohl/index.mjs +4 -6
  74. package/sohl/item-builders.mjs +1 -3
  75. package/sohl/item-fields.mjs +16 -34
  76. package/sohl/items.mjs +111 -17
  77. package/sohl/kb-passes.mjs +29 -39
  78. package/sohl/note-schemas.mjs +11 -7
  79. package/sohl/skill-base.mjs +7 -23
  80. package/stage.mjs +3 -13
  81. package/templates.mjs +4 -15
  82. package/types/bundle.d.mts +1 -1
  83. package/types/container.d.mts +2 -2
  84. package/types/content-config.d.mts +48 -4
  85. package/types/coverage.d.mts +1 -1
  86. package/types/e2e.d.mts +4 -4
  87. package/types/engine/address-charset.d.mts +45 -0
  88. package/types/engine/alias-index.d.mts +122 -0
  89. package/types/engine/base-compiler.d.mts +132 -4
  90. package/types/engine/content-address.d.mts +2 -2
  91. package/types/engine/content-format-check.d.mts +163 -0
  92. package/types/engine/content-format.d.mts +101 -0
  93. package/types/engine/content-links.d.mts +16 -1
  94. package/types/engine/content-lint.d.mts +6 -0
  95. package/types/engine/diagnostics.d.mts +29 -0
  96. package/types/engine/document-subtypes.d.mts +233 -0
  97. package/types/engine/field-spec.d.mts +76 -23
  98. package/types/engine/frontmatter-lint.d.mts +47 -2
  99. package/types/engine/generate.d.mts +15 -2
  100. package/types/engine/helpers.d.mts +22 -14
  101. package/types/engine/ids.d.mts +10 -0
  102. package/types/engine/index.d.mts +5 -0
  103. package/types/engine/item-registry.d.mts +21 -2
  104. package/types/engine/kb-manifest.d.mts +35 -8
  105. package/types/engine/map-notes.d.mts +21 -11
  106. package/types/engine/note-claims.d.mts +113 -0
  107. package/types/engine/note-vocabulary.d.mts +251 -0
  108. package/types/engine/pack-config.d.mts +4 -3
  109. package/types/engine/pack-router.d.mts +4 -4
  110. package/types/engine/prose-lint.d.mts +6 -2
  111. package/types/engine/retired-fields.d.mts +73 -2
  112. package/types/engine/schema-check.d.mts +182 -0
  113. package/types/engine/schema-extract.d.mts +1 -1
  114. package/types/engine/site-index.d.mts +1 -1
  115. package/types/engine/system-block.d.mts +281 -0
  116. package/types/engine/web-wikilinks.d.mts +23 -12
  117. package/types/engine/wikilink-syntax.d.mts +29 -0
  118. package/types/manifest.d.mts +1 -1
  119. package/types/sohl/actors.d.mts +62 -6
  120. package/types/sohl/document-subtypes.d.mts +14 -0
  121. package/types/sohl/index.d.mts +1 -0
  122. package/types/sohl/items.d.mts +21 -0
package/coverage.mjs CHANGED
@@ -230,12 +230,7 @@ function shapeOf(literal) {
230
230
  export function collectScriptReferences(source, { file, roots }) {
231
231
  const { whole, scan } = patternsFor(roots);
232
232
  const result = emptySet();
233
- const sourceFile = ts.createSourceFile(
234
- file,
235
- source,
236
- ts.ScriptTarget.Latest,
237
- true,
238
- );
233
+ const sourceFile = ts.createSourceFile(file, source, ts.ScriptTarget.Latest, true);
239
234
 
240
235
  // `parseDiagnostics` is TypeScript's own and not part of its published
241
236
  // surface, hence the guard. A file that does not parse contributes no
@@ -278,11 +273,7 @@ export function collectScriptReferences(source, { file, roots }) {
278
273
  * @returns {boolean} Whether its `.text` is the whole literal.
279
274
  */
280
275
  const isPlainString = (node) =>
281
- Boolean(
282
- node &&
283
- (ts.isStringLiteral(node) ||
284
- ts.isNoSubstitutionTemplateLiteral(node)),
285
- );
276
+ Boolean(node && (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)));
286
277
 
287
278
  /**
288
279
  * Read the concrete keys out of one literal chunk of a template.
@@ -316,11 +307,7 @@ export function collectScriptReferences(source, { file, roots }) {
316
307
  const prefixLiterals = new Set();
317
308
 
318
309
  const visit = (node) => {
319
- if (
320
- ts.isStringLiteral(node) &&
321
- whole.test(node.text) &&
322
- !prefixLiterals.has(node)
323
- ) {
310
+ if (ts.isStringLiteral(node) && whole.test(node.text) && !prefixLiterals.has(node)) {
324
311
  addKey(node.text, node.getStart());
325
312
  }
326
313
 
@@ -328,20 +315,12 @@ export function collectScriptReferences(source, { file, roots }) {
328
315
  // not string-literal nodes — inline markup in a helper puts them inside
329
316
  // the literal's text — so they would otherwise be invisible.
330
317
  if (ts.isNoSubstitutionTemplateLiteral(node)) {
331
- addChunkKeys(
332
- node.text,
333
- { openStart: false, openEnd: false },
334
- node.getStart(),
335
- );
318
+ addChunkKeys(node.text, { openStart: false, openEnd: false }, node.getStart());
336
319
  }
337
320
 
338
321
  if (ts.isTemplateExpression(node)) {
339
322
  const spans = node.templateSpans;
340
- addChunkKeys(
341
- node.head.text,
342
- { openStart: false, openEnd: true },
343
- node.getStart(),
344
- );
323
+ addChunkKeys(node.head.text, { openStart: false, openEnd: true }, node.getStart());
345
324
  spans.forEach((span, index) => {
346
325
  addChunkKeys(
347
326
  span.literal.text,
@@ -366,8 +345,7 @@ export function collectScriptReferences(source, { file, roots }) {
366
345
  // it, so those leaves are never named in any source file.
367
346
  if (
368
347
  (ts.isPropertyDeclaration(node) || ts.isPropertyAssignment(node)) &&
369
- node.name?.getText(sourceFile).replace(/["']/g, "") ===
370
- "LOCALIZATION_PREFIXES" &&
348
+ node.name?.getText(sourceFile).replace(/["']/g, "") === "LOCALIZATION_PREFIXES" &&
371
349
  node.initializer &&
372
350
  ts.isArrayLiteralExpression(node.initializer)
373
351
  ) {
@@ -423,10 +401,7 @@ export function collectTemplateReferences(source, { file, roots }) {
423
401
 
424
402
  // A substitution written directly against the token completes its last
425
403
  // segment, so the namespace is one segment shorter than the token.
426
- const namespace =
427
- rest.startsWith("${") ?
428
- token.replace(/\.[A-Za-z0-9_]*$/, "")
429
- : token;
404
+ const namespace = rest.startsWith("${") ? token.replace(/\.[A-Za-z0-9_]*$/, "") : token;
430
405
  result.namespaces.push(namespace);
431
406
 
432
407
  // Recover the whole literal so its shape, not merely its head, decides
@@ -436,9 +411,7 @@ export function collectTemplateReferences(source, { file, roots }) {
436
411
  const quote = source[index - 1];
437
412
  if (quote === "'" || quote === '"' || quote === "`") {
438
413
  const end = source.indexOf(quote, index);
439
- const pattern = shapeOf(
440
- source.slice(index, end === -1 ? undefined : end),
441
- );
414
+ const pattern = shapeOf(source.slice(index, end === -1 ? undefined : end));
442
415
  if (pattern) result.patterns.push(pattern);
443
416
  }
444
417
  }
@@ -478,9 +451,7 @@ export function mergeReferences(sets) {
478
451
  * @returns {RegExp} The matcher.
479
452
  */
480
453
  function matcherFor(pattern) {
481
- return new RegExp(
482
- `^${pattern.split("*").map(escapeRegExp).join("[^.]+")}$`,
483
- );
454
+ return new RegExp(`^${pattern.split("*").map(escapeRegExp).join("[^.]+")}$`);
484
455
  }
485
456
 
486
457
  /**
@@ -502,13 +473,7 @@ function matcherFor(pattern) {
502
473
  * questions: one says the package is broken, the other that it carries
503
474
  * something nobody could see a use for.
504
475
  */
505
- export function analyzeCoverage({
506
- langSource,
507
- langFile,
508
- references,
509
- retained = [],
510
- roots,
511
- }) {
476
+ export function analyzeCoverage({ langSource, langFile, references, retained = [], roots }) {
512
477
  let declared;
513
478
  try {
514
479
  declared = JSON.parse(langSource);
@@ -578,17 +543,14 @@ export function analyzeCoverage({
578
543
  });
579
544
  }
580
545
 
581
- const referenced = new Set(
582
- (references.keys ?? []).map((reference) => reference.key),
583
- );
546
+ const referenced = new Set((references.keys ?? []).map((reference) => reference.key));
584
547
  const shapes = (references.patterns ?? []).map(matcherFor);
585
548
  // Foundry localizes a DataModel's field labels and hints off the declared
586
549
  // prefix, so no source names them one by one.
587
550
  const fieldShapes = [...namespaces].map(
588
551
  (namespace) =>
589
552
  new RegExp(
590
- `^${escapeRegExp(namespace)}\\.FIELDS\\.` +
591
- `[A-Za-z0-9_.]+\\.(?:label|hint)$`,
553
+ `^${escapeRegExp(namespace)}\\.FIELDS\\.` + `[A-Za-z0-9_.]+\\.(?:label|hint)$`,
592
554
  ),
593
555
  );
594
556
 
@@ -596,13 +558,10 @@ export function analyzeCoverage({
596
558
  referenced.has(key) ||
597
559
  shapes.some((shape) => shape.test(key)) ||
598
560
  fieldShapes.some((shape) => shape.test(key));
599
- const isRetained = (key) =>
600
- retained.some((prefix) => key === prefix || key.startsWith(prefix));
561
+ const isRetained = (key) => retained.some((prefix) => key === prefix || key.startsWith(prefix));
601
562
 
602
563
  const unreferenced = declaredKeys
603
- .filter((key) =>
604
- known.some((root) => key === root || key.startsWith(`${root}.`)),
605
- )
564
+ .filter((key) => known.some((root) => key === root || key.startsWith(`${root}.`)))
606
565
  .filter((key) => !isReferenced(key) && !isRetained(key))
607
566
  .map((key) => ({
608
567
  file: langFile,
package/deploy.mjs CHANGED
@@ -146,9 +146,7 @@ export function resolveAgent(env, stageUpper, prefix = "SOHL") {
146
146
  env[`FOUNDRYVTT_${stageUpper}_AGENT`] ||
147
147
  env[`${prefix}_SFTP_AGENT`] ||
148
148
  env.SSH_AUTH_SOCK ||
149
- (process.platform === "win32" ?
150
- "\\\\.\\pipe\\openssh-ssh-agent"
151
- : undefined)
149
+ (process.platform === "win32" ? "\\\\.\\pipe\\openssh-ssh-agent" : undefined)
152
150
  );
153
151
  }
154
152
 
@@ -171,13 +169,8 @@ export async function buildConnection(
171
169
  remote,
172
170
  { env = process.env, prefix = "SOHL" } = {},
173
171
  ) {
174
- const port = Number(
175
- env[`FOUNDRYVTT_${stageUpper}_PORT`] ??
176
- env[`${prefix}_SFTP_PORT`] ??
177
- 22,
178
- );
179
- const username =
180
- remote.username || env[`FOUNDRYVTT_${stageUpper}_USER`] || env.USER;
172
+ const port = Number(env[`FOUNDRYVTT_${stageUpper}_PORT`] ?? env[`${prefix}_SFTP_PORT`] ?? 22);
173
+ const username = remote.username || env[`FOUNDRYVTT_${stageUpper}_USER`] || env.USER;
181
174
 
182
175
  const conn = { host: remote.host, port, username };
183
176
 
@@ -318,9 +311,7 @@ export async function deployStage({
318
311
  env,
319
312
  prefix,
320
313
  });
321
- log(
322
- `Deploying ${source} → ${conn.username}@${conn.host}:${remoteDir} (sftp)`,
323
- );
314
+ log(`Deploying ${source} → ${conn.username}@${conn.host}:${remoteDir} (sftp)`);
324
315
  await deployRemote(conn, source, remoteDir, {
325
316
  onUpload: (f) => log(` ${f}`),
326
317
  });