@patterkit/compiler 0.9.0 → 0.11.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.cjs CHANGED
@@ -555,6 +555,7 @@ function extensionPass(input) {
555
555
  }
556
556
  }
557
557
  const bundle = {};
558
+ const chosen = new Map(takenList.map((t) => [t.id, t.settings]));
558
559
  for (const [id, manifest] of [...sound.entries()].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)) {
559
560
  const fields = {};
560
561
  for (const kind of Object.keys(manifest.targets.patter ?? {}).sort()) {
@@ -562,7 +563,13 @@ function extensionPass(input) {
562
563
  if (target !== void 0) fields[kind] = (0, import_extensions.compiledTarget)(target);
563
564
  }
564
565
  const projectEntry = projectValues.get(id);
565
- bundle[id] = { version: manifest.version, fields, ...projectEntry !== void 0 ? { project: projectEntry } : {} };
566
+ const settings = (manifest.settings ?? []).length > 0 ? sortRecord((0, import_extensions.settingValues)(manifest, chosen.get(id))) : void 0;
567
+ bundle[id] = {
568
+ version: manifest.version,
569
+ fields,
570
+ ...projectEntry !== void 0 ? { project: projectEntry } : {},
571
+ ...settings !== void 0 ? { settings } : {}
572
+ };
566
573
  }
567
574
  const sortedNodes = new Map([...values.entries()].map(([id, v]) => [id, sortRecord(v)]));
568
575
  return { issues, compiled: { bundle, nodes: sortedNodes } };
@@ -592,10 +599,11 @@ function claimIssues(input, nodes, claims) {
592
599
  });
593
600
  continue;
594
601
  }
602
+ const effective = (0, import_extensions.effectiveClaim)(claim.claim, decl);
595
603
  for (const [id, node] of nodes) {
596
604
  if (node.kind !== claim.kind || node.gameData === void 0 || !own(node.gameData, claim.field)) continue;
597
605
  const file = (node.scene !== void 0 ? input.sceneFiles?.[node.scene] : void 0) ?? projectPath;
598
- for (const p of (0, import_extensions.valueProblems)(claim.claim, node.gameData[claim.field])) {
606
+ for (const p of (0, import_extensions.valueProblems)(effective, node.gameData[claim.field])) {
599
607
  issues.push({
600
608
  severity: p.severity,
601
609
  file,
@@ -610,11 +618,21 @@ function claimIssues(input, nodes, claims) {
610
618
  }
611
619
 
612
620
  // src/export.ts
613
- function compileBeat(beat, ctx) {
621
+ function compileBeat(beat, ctx, asAction = false) {
614
622
  const values = ctx.extensions.get(beat.id);
615
- if (values === void 0 && !Object.prototype.hasOwnProperty.call(beat, "extensions")) return beat;
616
- const { extensions: _source, ...rest } = beat;
617
- return values !== void 0 ? { ...rest, extensions: values } : rest;
623
+ const action = asAction && beat.kind === "text";
624
+ const has = (k) => Object.prototype.hasOwnProperty.call(beat, k);
625
+ if (values === void 0 && !action && !has("extensions") && !has("action")) return beat;
626
+ const { extensions: _source, action: _action, ...rest } = beat;
627
+ return { ...rest, ...values !== void 0 ? { extensions: values } : {}, ...action ? { action: true } : {} };
628
+ }
629
+ function collectActionIds(scene, out) {
630
+ for (const block of scene.blocks) {
631
+ (0, import_model3.walkNodes)(block.children, (node) => {
632
+ if (node.type !== "snippet") return;
633
+ for (const beat of node.beats ?? []) if (beat.kind === "text" && beat.action) out.push(beat.id);
634
+ });
635
+ }
618
636
  }
619
637
  function compileEffect(e, foreign) {
620
638
  return { kind: "set", target: e.target, value: compileExpression(e.value, foreign) };
@@ -648,7 +666,7 @@ function compileNode(node, ctx) {
648
666
  id: node.id,
649
667
  type: "snippet",
650
668
  condition: node.condition !== void 0 ? compileExpression(node.condition, foreign) : void 0,
651
- beats: node.beats && node.beats.map((b) => compileBeat(b, ctx)),
669
+ beats: node.beats && node.beats.map((b) => compileBeat(b, ctx, ctx.action)),
652
670
  onEnter: node.onEnter?.map((e) => compileEffect(e, foreign)),
653
671
  onExit: node.onExit?.map((e) => compileEffect(e, foreign)),
654
672
  padAfterDefault: node.padAfterDefault,
@@ -734,7 +752,12 @@ function exportBundle(input) {
734
752
  const extensionSection = compiledExt !== void 0 && Object.keys(compiledExt.bundle).length > 0 ? compiledExt.bundle : void 0;
735
753
  const ctx = { foreign: compileScopes, extensions: compiledExt?.nodes ?? /* @__PURE__ */ new Map() };
736
754
  const scenesOut = {};
737
- for (const scene of scenes) scenesOut[scene.id] = compileScene(scene, ctx);
755
+ const actionIds = [];
756
+ for (const scene of scenes) {
757
+ const action = (0, import_model3.textIsAction)(project, scene);
758
+ scenesOut[scene.id] = compileScene(scene, action ? { ...ctx, action } : ctx);
759
+ if (action) collectActionIds(scenesOut[scene.id], actionIds);
760
+ }
738
761
  const externalScopes = externalScopesIn(scenesOut, /* @__PURE__ */ new Set([...import_dialect3.EXTERNAL_SCOPES, ...gameExternal.map((s) => s.token)]));
739
762
  const qualifiers = (0, import_model3.usedQualifiers)(project, scenes).map((q) => ({ gameId: q.gameId, name: q.name }));
740
763
  const usedPairs = new Set((0, import_model3.usedSpeakerPairs)(scenes).map((p) => `${p.character}\0${p.qualifier}`));
@@ -750,6 +773,17 @@ function exportBundle(input) {
750
773
  table[key] = text;
751
774
  }
752
775
  }
776
+ if (actionIds.length > 0) {
777
+ const source = {};
778
+ for (const loc of locales) if (loc.locale === project.locales.default) Object.assign(source, loc.strings);
779
+ for (const [locale, table] of Object.entries(strings)) {
780
+ if (locale === project.locales.default) continue;
781
+ for (const id of actionIds) {
782
+ if (id in source) table[id] = source[id];
783
+ else delete table[id];
784
+ }
785
+ }
786
+ }
753
787
  return {
754
788
  schema: "patter/bundle@0",
755
789
  content: {
@@ -809,7 +843,8 @@ function exportBundle(input) {
809
843
  Object.entries(project.gameDataFields).map(([kind, fields]) => [kind, resolved(fields)])
810
844
  ),
811
845
  // The extensions the project takes: each one's version, its compiled declarations by node kind (every
812
- // default resolved, editor-only fields and the editor's words left out) and the project node's values.
846
+ // default resolved, editor-only fields and the editor's words left out), the project node's values, and
847
+ // its settings, each the project's value or else the default.
813
848
  ...extensionSection !== void 0 ? { extensions: extensionSection } : {},
814
849
  // Closed-caption delimiters ride along only when the project pins a non-default pair (#214); the
815
850
  // runtime falls back to `[` / `]` when absent, so default projects keep their exact prior bundle.
package/dist/index.js CHANGED
@@ -315,7 +315,7 @@ import { hostScopesToSpec as hostScopesToSpec4, EXTERNAL_SCOPES as EXTERNAL_SCOP
315
315
  import { defaultFor } from "@wildwinter/scoperegistry";
316
316
  import { canonicalStringify, hash32 } from "@patterkit/core";
317
317
  import { hostScopesToSpec as hostScopesToSpec3, withEngineScopes as withEngineScopes2, EXTERNAL_SCOPES } from "@patterkit/dialect";
318
- import { usedQualifiers, usedSpeakerPairs, DEFAULT_SPEAKER_PATTERN } from "@patterkit/model";
318
+ import { textIsAction, usedQualifiers, usedSpeakerPairs, walkNodes as walkNodes2, DEFAULT_SPEAKER_PATTERN } from "@patterkit/model";
319
319
 
320
320
  // src/extensions.ts
321
321
  import { EXTENSIONS_DIR, MANIFEST_EXTENSION, PROJECT_LOCALE_SCENE } from "@patterkit/model";
@@ -324,10 +324,12 @@ import {
324
324
  claimClashes,
325
325
  compileEntry,
326
326
  compiledTarget,
327
+ effectiveClaim,
327
328
  entryProblems,
328
329
  manifestProblems,
329
330
  orphanedEntries,
330
331
  resolvedClaims,
332
+ settingValues,
331
333
  targetOf,
332
334
  valueProblems
333
335
  } from "@wildwinter/toolkit/extensions";
@@ -530,6 +532,7 @@ function extensionPass(input) {
530
532
  }
531
533
  }
532
534
  const bundle = {};
535
+ const chosen = new Map(takenList.map((t) => [t.id, t.settings]));
533
536
  for (const [id, manifest] of [...sound.entries()].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)) {
534
537
  const fields = {};
535
538
  for (const kind of Object.keys(manifest.targets.patter ?? {}).sort()) {
@@ -537,7 +540,13 @@ function extensionPass(input) {
537
540
  if (target !== void 0) fields[kind] = compiledTarget(target);
538
541
  }
539
542
  const projectEntry = projectValues.get(id);
540
- bundle[id] = { version: manifest.version, fields, ...projectEntry !== void 0 ? { project: projectEntry } : {} };
543
+ const settings = (manifest.settings ?? []).length > 0 ? sortRecord(settingValues(manifest, chosen.get(id))) : void 0;
544
+ bundle[id] = {
545
+ version: manifest.version,
546
+ fields,
547
+ ...projectEntry !== void 0 ? { project: projectEntry } : {},
548
+ ...settings !== void 0 ? { settings } : {}
549
+ };
541
550
  }
542
551
  const sortedNodes = new Map([...values.entries()].map(([id, v]) => [id, sortRecord(v)]));
543
552
  return { issues, compiled: { bundle, nodes: sortedNodes } };
@@ -567,10 +576,11 @@ function claimIssues(input, nodes, claims) {
567
576
  });
568
577
  continue;
569
578
  }
579
+ const effective = effectiveClaim(claim.claim, decl);
570
580
  for (const [id, node] of nodes) {
571
581
  if (node.kind !== claim.kind || node.gameData === void 0 || !own(node.gameData, claim.field)) continue;
572
582
  const file = (node.scene !== void 0 ? input.sceneFiles?.[node.scene] : void 0) ?? projectPath;
573
- for (const p of valueProblems(claim.claim, node.gameData[claim.field])) {
583
+ for (const p of valueProblems(effective, node.gameData[claim.field])) {
574
584
  issues.push({
575
585
  severity: p.severity,
576
586
  file,
@@ -585,11 +595,21 @@ function claimIssues(input, nodes, claims) {
585
595
  }
586
596
 
587
597
  // src/export.ts
588
- function compileBeat(beat, ctx) {
598
+ function compileBeat(beat, ctx, asAction = false) {
589
599
  const values = ctx.extensions.get(beat.id);
590
- if (values === void 0 && !Object.prototype.hasOwnProperty.call(beat, "extensions")) return beat;
591
- const { extensions: _source, ...rest } = beat;
592
- return values !== void 0 ? { ...rest, extensions: values } : rest;
600
+ const action = asAction && beat.kind === "text";
601
+ const has = (k) => Object.prototype.hasOwnProperty.call(beat, k);
602
+ if (values === void 0 && !action && !has("extensions") && !has("action")) return beat;
603
+ const { extensions: _source, action: _action, ...rest } = beat;
604
+ return { ...rest, ...values !== void 0 ? { extensions: values } : {}, ...action ? { action: true } : {} };
605
+ }
606
+ function collectActionIds(scene, out) {
607
+ for (const block of scene.blocks) {
608
+ walkNodes2(block.children, (node) => {
609
+ if (node.type !== "snippet") return;
610
+ for (const beat of node.beats ?? []) if (beat.kind === "text" && beat.action) out.push(beat.id);
611
+ });
612
+ }
593
613
  }
594
614
  function compileEffect(e, foreign) {
595
615
  return { kind: "set", target: e.target, value: compileExpression(e.value, foreign) };
@@ -623,7 +643,7 @@ function compileNode(node, ctx) {
623
643
  id: node.id,
624
644
  type: "snippet",
625
645
  condition: node.condition !== void 0 ? compileExpression(node.condition, foreign) : void 0,
626
- beats: node.beats && node.beats.map((b) => compileBeat(b, ctx)),
646
+ beats: node.beats && node.beats.map((b) => compileBeat(b, ctx, ctx.action)),
627
647
  onEnter: node.onEnter?.map((e) => compileEffect(e, foreign)),
628
648
  onExit: node.onExit?.map((e) => compileEffect(e, foreign)),
629
649
  padAfterDefault: node.padAfterDefault,
@@ -709,7 +729,12 @@ function exportBundle(input) {
709
729
  const extensionSection = compiledExt !== void 0 && Object.keys(compiledExt.bundle).length > 0 ? compiledExt.bundle : void 0;
710
730
  const ctx = { foreign: compileScopes, extensions: compiledExt?.nodes ?? /* @__PURE__ */ new Map() };
711
731
  const scenesOut = {};
712
- for (const scene of scenes) scenesOut[scene.id] = compileScene(scene, ctx);
732
+ const actionIds = [];
733
+ for (const scene of scenes) {
734
+ const action = textIsAction(project, scene);
735
+ scenesOut[scene.id] = compileScene(scene, action ? { ...ctx, action } : ctx);
736
+ if (action) collectActionIds(scenesOut[scene.id], actionIds);
737
+ }
713
738
  const externalScopes = externalScopesIn(scenesOut, /* @__PURE__ */ new Set([...EXTERNAL_SCOPES, ...gameExternal.map((s) => s.token)]));
714
739
  const qualifiers = usedQualifiers(project, scenes).map((q) => ({ gameId: q.gameId, name: q.name }));
715
740
  const usedPairs = new Set(usedSpeakerPairs(scenes).map((p) => `${p.character}\0${p.qualifier}`));
@@ -725,6 +750,17 @@ function exportBundle(input) {
725
750
  table[key] = text;
726
751
  }
727
752
  }
753
+ if (actionIds.length > 0) {
754
+ const source = {};
755
+ for (const loc of locales) if (loc.locale === project.locales.default) Object.assign(source, loc.strings);
756
+ for (const [locale, table] of Object.entries(strings)) {
757
+ if (locale === project.locales.default) continue;
758
+ for (const id of actionIds) {
759
+ if (id in source) table[id] = source[id];
760
+ else delete table[id];
761
+ }
762
+ }
763
+ }
728
764
  return {
729
765
  schema: "patter/bundle@0",
730
766
  content: {
@@ -784,7 +820,8 @@ function exportBundle(input) {
784
820
  Object.entries(project.gameDataFields).map(([kind, fields]) => [kind, resolved(fields)])
785
821
  ),
786
822
  // The extensions the project takes: each one's version, its compiled declarations by node kind (every
787
- // default resolved, editor-only fields and the editor's words left out) and the project node's values.
823
+ // default resolved, editor-only fields and the editor's words left out), the project node's values, and
824
+ // its settings, each the project's value or else the default.
788
825
  ...extensionSection !== void 0 ? { extensions: extensionSection } : {},
789
826
  // Closed-caption delimiters ride along only when the project pins a non-default pair (#214); the
790
827
  // runtime falls back to `[` / `]` when absent, so default projects keep their exact prior bundle.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patterkit/compiler",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "description": "Patter compiler: compile condition/effect expressions, validate them, and export source to the runtime bundle.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -34,11 +34,11 @@
34
34
  "build": "tsup src/index.ts --format esm,cjs --dts --clean"
35
35
  },
36
36
  "dependencies": {
37
- "@patterkit/model": "0.16.0",
38
- "@patterkit/core": "0.9.0",
39
- "@patterkit/dialect": "0.2.13",
37
+ "@patterkit/model": "0.18.0",
38
+ "@patterkit/core": "0.9.2",
39
+ "@patterkit/dialect": "0.2.15",
40
40
  "@wildwinter/expr": "^0.6.0",
41
- "@wildwinter/toolkit": "^0.2.0"
41
+ "@wildwinter/toolkit": "^0.2.1"
42
42
  },
43
43
  "peerDependencies": {
44
44
  "@wildwinter/scoperegistry": ">=0.9.0 <1.0.0"