@cratis/scene.engine 4.1.1 → 4.2.1

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 (116) hide show
  1. package/dist/cjs/index.js +4 -0
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/cjs/resolveStrings.js +72 -0
  4. package/dist/cjs/resolveStrings.js.map +1 -0
  5. package/dist/esm/index.d.ts +1 -0
  6. package/dist/esm/index.d.ts.map +1 -1
  7. package/dist/esm/index.js +1 -0
  8. package/dist/esm/index.js.map +1 -1
  9. package/dist/esm/resolveStrings.d.ts +6 -0
  10. package/dist/esm/resolveStrings.d.ts.map +1 -0
  11. package/dist/esm/resolveStrings.js +68 -0
  12. package/dist/esm/resolveStrings.js.map +1 -0
  13. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  14. package/index.ts +1 -0
  15. package/package.json +5 -4
  16. package/resolveStrings.ts +84 -0
  17. package/dist/esm/for_aggregateContributions/when_aggregating_by_contribution_point.d.ts +0 -2
  18. package/dist/esm/for_aggregateContributions/when_aggregating_by_contribution_point.d.ts.map +0 -1
  19. package/dist/esm/for_aggregateContributions/when_aggregating_by_contribution_point.js +0 -23
  20. package/dist/esm/for_aggregateContributions/when_aggregating_by_contribution_point.js.map +0 -1
  21. package/dist/esm/for_buildStarterProfile/when_checking_against_the_shared_fixture_corpus.d.ts +0 -2
  22. package/dist/esm/for_buildStarterProfile/when_checking_against_the_shared_fixture_corpus.d.ts.map +0 -1
  23. package/dist/esm/for_buildStarterProfile/when_checking_against_the_shared_fixture_corpus.js +0 -16
  24. package/dist/esm/for_buildStarterProfile/when_checking_against_the_shared_fixture_corpus.js.map +0 -1
  25. package/dist/esm/for_computeSizeClass/when_computing_the_size_class.d.ts +0 -2
  26. package/dist/esm/for_computeSizeClass/when_computing_the_size_class.d.ts.map +0 -1
  27. package/dist/esm/for_computeSizeClass/when_computing_the_size_class.js +0 -17
  28. package/dist/esm/for_computeSizeClass/when_computing_the_size_class.js.map +0 -1
  29. package/dist/esm/for_evaluateFlowArrangement/when_evaluating_against_the_shared_fixture_corpus.d.ts +0 -2
  30. package/dist/esm/for_evaluateFlowArrangement/when_evaluating_against_the_shared_fixture_corpus.d.ts.map +0 -1
  31. package/dist/esm/for_evaluateFlowArrangement/when_evaluating_against_the_shared_fixture_corpus.js +0 -43
  32. package/dist/esm/for_evaluateFlowArrangement/when_evaluating_against_the_shared_fixture_corpus.js.map +0 -1
  33. package/dist/esm/for_evaluateFreeformArrangement/when_evaluating_against_the_shared_fixture_corpus.d.ts +0 -2
  34. package/dist/esm/for_evaluateFreeformArrangement/when_evaluating_against_the_shared_fixture_corpus.d.ts.map +0 -1
  35. package/dist/esm/for_evaluateFreeformArrangement/when_evaluating_against_the_shared_fixture_corpus.js +0 -46
  36. package/dist/esm/for_evaluateFreeformArrangement/when_evaluating_against_the_shared_fixture_corpus.js.map +0 -1
  37. package/dist/esm/for_evaluateFreeformSlotArrangement/when_evaluating_against_the_shared_fixture_corpus.d.ts +0 -2
  38. package/dist/esm/for_evaluateFreeformSlotArrangement/when_evaluating_against_the_shared_fixture_corpus.d.ts.map +0 -1
  39. package/dist/esm/for_evaluateFreeformSlotArrangement/when_evaluating_against_the_shared_fixture_corpus.js +0 -25
  40. package/dist/esm/for_evaluateFreeformSlotArrangement/when_evaluating_against_the_shared_fixture_corpus.js.map +0 -1
  41. package/dist/esm/for_incompatibleStarterThemes/when_checking_against_the_shared_fixture_corpus.d.ts +0 -2
  42. package/dist/esm/for_incompatibleStarterThemes/when_checking_against_the_shared_fixture_corpus.d.ts.map +0 -1
  43. package/dist/esm/for_incompatibleStarterThemes/when_checking_against_the_shared_fixture_corpus.js +0 -17
  44. package/dist/esm/for_incompatibleStarterThemes/when_checking_against_the_shared_fixture_corpus.js.map +0 -1
  45. package/dist/esm/for_packageCatalog/when_querying_against_the_shared_fixture_corpus.d.ts +0 -2
  46. package/dist/esm/for_packageCatalog/when_querying_against_the_shared_fixture_corpus.d.ts.map +0 -1
  47. package/dist/esm/for_packageCatalog/when_querying_against_the_shared_fixture_corpus.js +0 -22
  48. package/dist/esm/for_packageCatalog/when_querying_against_the_shared_fixture_corpus.js.map +0 -1
  49. package/dist/esm/for_packageDependencies/fixtures.d.ts +0 -38
  50. package/dist/esm/for_packageDependencies/fixtures.d.ts.map +0 -1
  51. package/dist/esm/for_packageDependencies/fixtures.js +0 -5
  52. package/dist/esm/for_packageDependencies/fixtures.js.map +0 -1
  53. package/dist/esm/for_packageDependencies/when_resolving_against_the_shared_fixture_corpus.d.ts +0 -2
  54. package/dist/esm/for_packageDependencies/when_resolving_against_the_shared_fixture_corpus.d.ts.map +0 -1
  55. package/dist/esm/for_packageDependencies/when_resolving_against_the_shared_fixture_corpus.js +0 -29
  56. package/dist/esm/for_packageDependencies/when_resolving_against_the_shared_fixture_corpus.js.map +0 -1
  57. package/dist/esm/for_packageVersionRange/when_checking_against_the_shared_fixture_corpus.d.ts +0 -2
  58. package/dist/esm/for_packageVersionRange/when_checking_against_the_shared_fixture_corpus.d.ts.map +0 -1
  59. package/dist/esm/for_packageVersionRange/when_checking_against_the_shared_fixture_corpus.js +0 -10
  60. package/dist/esm/for_packageVersionRange/when_checking_against_the_shared_fixture_corpus.js.map +0 -1
  61. package/dist/esm/for_panelKind/when_telling_the_panels_apart.d.ts +0 -2
  62. package/dist/esm/for_panelKind/when_telling_the_panels_apart.d.ts.map +0 -1
  63. package/dist/esm/for_panelKind/when_telling_the_panels_apart.js +0 -38
  64. package/dist/esm/for_panelKind/when_telling_the_panels_apart.js.map +0 -1
  65. package/dist/esm/for_renderElement/when_rendering_a_mixed_tree.d.ts +0 -2
  66. package/dist/esm/for_renderElement/when_rendering_a_mixed_tree.d.ts.map +0 -1
  67. package/dist/esm/for_renderElement/when_rendering_a_mixed_tree.js +0 -46
  68. package/dist/esm/for_renderElement/when_rendering_a_mixed_tree.js.map +0 -1
  69. package/dist/esm/for_resolveBehaviors/when_resolving_additive_attachments.d.ts +0 -2
  70. package/dist/esm/for_resolveBehaviors/when_resolving_additive_attachments.d.ts.map +0 -1
  71. package/dist/esm/for_resolveBehaviors/when_resolving_additive_attachments.js +0 -68
  72. package/dist/esm/for_resolveBehaviors/when_resolving_additive_attachments.js.map +0 -1
  73. package/dist/esm/for_resolveComponentName/when_resolving_against_the_shared_fixture_corpus.d.ts +0 -2
  74. package/dist/esm/for_resolveComponentName/when_resolving_against_the_shared_fixture_corpus.d.ts.map +0 -1
  75. package/dist/esm/for_resolveComponentName/when_resolving_against_the_shared_fixture_corpus.js +0 -20
  76. package/dist/esm/for_resolveComponentName/when_resolving_against_the_shared_fixture_corpus.js.map +0 -1
  77. package/dist/esm/for_resolveScreenTemplates/when_resolving_against_the_shared_fixture_corpus.d.ts +0 -2
  78. package/dist/esm/for_resolveScreenTemplates/when_resolving_against_the_shared_fixture_corpus.d.ts.map +0 -1
  79. package/dist/esm/for_resolveScreenTemplates/when_resolving_against_the_shared_fixture_corpus.js +0 -30
  80. package/dist/esm/for_resolveScreenTemplates/when_resolving_against_the_shared_fixture_corpus.js.map +0 -1
  81. package/dist/esm/for_runActions/given/a_recording_dispatcher.d.ts +0 -21
  82. package/dist/esm/for_runActions/given/a_recording_dispatcher.d.ts.map +0 -1
  83. package/dist/esm/for_runActions/given/a_recording_dispatcher.js +0 -45
  84. package/dist/esm/for_runActions/given/a_recording_dispatcher.js.map +0 -1
  85. package/dist/esm/for_runActions/when_running_a_sequence_of_actions.d.ts +0 -2
  86. package/dist/esm/for_runActions/when_running_a_sequence_of_actions.d.ts.map +0 -1
  87. package/dist/esm/for_runActions/when_running_a_sequence_of_actions.js +0 -126
  88. package/dist/esm/for_runActions/when_running_a_sequence_of_actions.js.map +0 -1
  89. package/dist/esm/for_runActions/when_running_against_the_shared_fixture_corpus.d.ts +0 -2
  90. package/dist/esm/for_runActions/when_running_against_the_shared_fixture_corpus.d.ts.map +0 -1
  91. package/dist/esm/for_runActions/when_running_against_the_shared_fixture_corpus.js +0 -61
  92. package/dist/esm/for_runActions/when_running_against_the_shared_fixture_corpus.js.map +0 -1
  93. package/dist/esm/for_themeCompatibility/when_checking_against_the_shared_fixture_corpus.d.ts +0 -2
  94. package/dist/esm/for_themeCompatibility/when_checking_against_the_shared_fixture_corpus.d.ts.map +0 -1
  95. package/dist/esm/for_themeCompatibility/when_checking_against_the_shared_fixture_corpus.js +0 -18
  96. package/dist/esm/for_themeCompatibility/when_checking_against_the_shared_fixture_corpus.js.map +0 -1
  97. package/for_aggregateContributions/when_aggregating_by_contribution_point.ts +0 -31
  98. package/for_buildStarterProfile/when_checking_against_the_shared_fixture_corpus.ts +0 -32
  99. package/for_computeSizeClass/when_computing_the_size_class.ts +0 -23
  100. package/for_evaluateFlowArrangement/when_evaluating_against_the_shared_fixture_corpus.ts +0 -67
  101. package/for_evaluateFreeformArrangement/when_evaluating_against_the_shared_fixture_corpus.ts +0 -68
  102. package/for_evaluateFreeformSlotArrangement/when_evaluating_against_the_shared_fixture_corpus.ts +0 -47
  103. package/for_incompatibleStarterThemes/when_checking_against_the_shared_fixture_corpus.ts +0 -34
  104. package/for_packageCatalog/when_querying_against_the_shared_fixture_corpus.ts +0 -26
  105. package/for_packageDependencies/fixtures.ts +0 -44
  106. package/for_packageDependencies/when_resolving_against_the_shared_fixture_corpus.ts +0 -39
  107. package/for_packageVersionRange/when_checking_against_the_shared_fixture_corpus.ts +0 -13
  108. package/for_panelKind/when_telling_the_panels_apart.ts +0 -47
  109. package/for_renderElement/when_rendering_a_mixed_tree.ts +0 -58
  110. package/for_resolveBehaviors/when_resolving_additive_attachments.ts +0 -100
  111. package/for_resolveComponentName/when_resolving_against_the_shared_fixture_corpus.ts +0 -36
  112. package/for_resolveScreenTemplates/when_resolving_against_the_shared_fixture_corpus.ts +0 -49
  113. package/for_runActions/given/a_recording_dispatcher.ts +0 -72
  114. package/for_runActions/when_running_a_sequence_of_actions.ts +0 -226
  115. package/for_runActions/when_running_against_the_shared_fixture_corpus.ts +0 -124
  116. package/for_themeCompatibility/when_checking_against_the_shared_fixture_corpus.ts +0 -37
package/dist/cjs/index.js CHANGED
@@ -20,6 +20,7 @@ var buildStarterProfile = require('./buildStarterProfile.js');
20
20
  var incompatibleStarterThemes = require('./incompatibleStarterThemes.js');
21
21
  var runActions = require('./runActions.js');
22
22
  var resolveBehaviors = require('./resolveBehaviors.js');
23
+ var resolveStrings = require('./resolveStrings.js');
23
24
 
24
25
 
25
26
 
@@ -71,4 +72,7 @@ exports.resolveApplicationTriggerBehaviors = resolveBehaviors.resolveApplication
71
72
  exports.resolveBehaviors = resolveBehaviors.resolveBehaviors;
72
73
  exports.resolveEventBehaviors = resolveBehaviors.resolveEventBehaviors;
73
74
  exports.resolveIntervalBehaviors = resolveBehaviors.resolveIntervalBehaviors;
75
+ exports.isStringsReference = resolveStrings.isStringsReference;
76
+ exports.resolveStringsInElement = resolveStrings.resolveStringsInElement;
77
+ exports.resolveStringsValue = resolveStrings.resolveStringsValue;
74
78
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,72 @@
1
+ 'use strict';
2
+
3
+ var elementKind = require('./elementKind.js');
4
+
5
+ // Copyright (c) Cratis. All rights reserved.
6
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
7
+ const referencePrefix = '$strings.';
8
+ /**
9
+ * Whether a property value is a `$strings.<key>` reference rather than a literal value.
10
+ *
11
+ * A document prints `$strings.<key>` unquoted - see Screenplay's internationalization documentation - so
12
+ * the reference survives into a compiled element's properties as this exact string shape, indistinguishable
13
+ * from any other string property until something resolves it.
14
+ */ function isStringsReference(value) {
15
+ return typeof value === 'string' && value.startsWith(referencePrefix);
16
+ }
17
+ /**
18
+ * Resolves a single property value against a locale's dictionary.
19
+ *
20
+ * A value that is not a `$strings.` reference passes through unchanged - resolving is a no-op on anything
21
+ * else a screen might put in the same property. A reference whose key is missing from the dictionary is
22
+ * left as the literal `$strings.<key>` text rather than blanked out - the same failure mode the frontend
23
+ * already had before resolution existed, and one an author notices immediately rather than a silently
24
+ * empty label.
25
+ */ function resolveStringsValue(value, dictionary) {
26
+ if (!isStringsReference(value)) {
27
+ return value;
28
+ }
29
+ const key = value.slice(referencePrefix.length);
30
+ return Object.hasOwn(dictionary, key) ? dictionary[key] : value;
31
+ }
32
+ /**
33
+ * Resolves every `$strings.` reference in an element tree's `properties` against a locale's dictionary,
34
+ * returning a new tree - the input is never mutated, so a caller holding the original (a cached scene,
35
+ * a Studio design-time fixture) keeps seeing the unresolved symbolic form.
36
+ *
37
+ * Walks every shape an element tree actually nests content in: an `ExternalComponent`'s named `slots`, a
38
+ * `ContentControl`'s single `content`, an `ItemsControl`'s `itemTemplate`, and a `Panel`'s `children`. This
39
+ * is the same set {@link isExternalComponent}/{@link isContentControl}/{@link isItemsControl}/{@link isPanel}
40
+ * already distinguish elsewhere in this package, so a new element kind that starts nesting content a new
41
+ * way needs a matching type guard there before it can be walked here too.
42
+ */ function resolveStringsInElement(element, dictionary) {
43
+ const properties = Object.fromEntries(Object.entries(element.properties ?? {}).map(([key, value])=>[
44
+ key,
45
+ resolveStringsValue(value, dictionary)
46
+ ]));
47
+ const resolved = {
48
+ ...element,
49
+ properties
50
+ };
51
+ if (elementKind.isExternalComponent(resolved)) {
52
+ resolved.slots = Object.fromEntries(Object.entries(resolved.slots ?? {}).map(([slotName, children])=>[
53
+ slotName,
54
+ children.map((child)=>resolveStringsInElement(child, dictionary))
55
+ ]));
56
+ }
57
+ if (elementKind.isContentControl(resolved) && resolved.content) {
58
+ resolved.content = resolveStringsInElement(resolved.content, dictionary);
59
+ }
60
+ if (elementKind.isItemsControl(resolved) && resolved.itemTemplate) {
61
+ resolved.itemTemplate = resolveStringsInElement(resolved.itemTemplate, dictionary);
62
+ }
63
+ if (elementKind.isPanel(resolved)) {
64
+ resolved.children = resolved.children.map((child)=>resolveStringsInElement(child, dictionary));
65
+ }
66
+ return resolved;
67
+ }
68
+
69
+ exports.isStringsReference = isStringsReference;
70
+ exports.resolveStringsInElement = resolveStringsInElement;
71
+ exports.resolveStringsValue = resolveStringsValue;
72
+ //# sourceMappingURL=resolveStrings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveStrings.js","sources":["../../resolveStrings.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { SceneElement } from '@cratis/scene.model';\nimport { isContentControl, isExternalComponent, isItemsControl, isPanel } from './elementKind';\n\n/**\n * A locale's flat key -> value table, as `.strings` files parse to: dotted keys such as `invoice.title`\n * mapped to their localized text.\n */\nexport type StringsDictionary = Record<string, string>;\n\nconst referencePrefix = '$strings.';\n\n/**\n * Whether a property value is a `$strings.<key>` reference rather than a literal value.\n *\n * A document prints `$strings.<key>` unquoted - see Screenplay's internationalization documentation - so\n * the reference survives into a compiled element's properties as this exact string shape, indistinguishable\n * from any other string property until something resolves it.\n */\nexport function isStringsReference(value: unknown): value is string {\n return typeof value === 'string' && value.startsWith(referencePrefix);\n}\n\n/**\n * Resolves a single property value against a locale's dictionary.\n *\n * A value that is not a `$strings.` reference passes through unchanged - resolving is a no-op on anything\n * else a screen might put in the same property. A reference whose key is missing from the dictionary is\n * left as the literal `$strings.<key>` text rather than blanked out - the same failure mode the frontend\n * already had before resolution existed, and one an author notices immediately rather than a silently\n * empty label.\n */\nexport function resolveStringsValue(value: unknown, dictionary: StringsDictionary): unknown {\n if (!isStringsReference(value)) {\n return value;\n }\n\n const key = value.slice(referencePrefix.length);\n return Object.hasOwn(dictionary, key) ? dictionary[key] : value;\n}\n\n/**\n * Resolves every `$strings.` reference in an element tree's `properties` against a locale's dictionary,\n * returning a new tree - the input is never mutated, so a caller holding the original (a cached scene,\n * a Studio design-time fixture) keeps seeing the unresolved symbolic form.\n *\n * Walks every shape an element tree actually nests content in: an `ExternalComponent`'s named `slots`, a\n * `ContentControl`'s single `content`, an `ItemsControl`'s `itemTemplate`, and a `Panel`'s `children`. This\n * is the same set {@link isExternalComponent}/{@link isContentControl}/{@link isItemsControl}/{@link isPanel}\n * already distinguish elsewhere in this package, so a new element kind that starts nesting content a new\n * way needs a matching type guard there before it can be walked here too.\n */\nexport function resolveStringsInElement(element: SceneElement, dictionary: StringsDictionary): SceneElement {\n const properties = Object.fromEntries(\n Object.entries(element.properties ?? {}).map(([key, value]) => [key, resolveStringsValue(value, dictionary)]),\n );\n\n const resolved: SceneElement = { ...element, properties };\n\n if (isExternalComponent(resolved)) {\n resolved.slots = Object.fromEntries(\n Object.entries(resolved.slots ?? {}).map(([slotName, children]) => [\n slotName,\n children.map(child => resolveStringsInElement(child, dictionary)),\n ]),\n );\n }\n\n if (isContentControl(resolved) && resolved.content) {\n resolved.content = resolveStringsInElement(resolved.content, dictionary);\n }\n\n if (isItemsControl(resolved) && resolved.itemTemplate) {\n resolved.itemTemplate = resolveStringsInElement(resolved.itemTemplate, dictionary);\n }\n\n if (isPanel(resolved)) {\n resolved.children = resolved.children.map(child => resolveStringsInElement(child, dictionary));\n }\n\n return resolved;\n}\n"],"names":["referencePrefix","isStringsReference","value","startsWith","resolveStringsValue","dictionary","key","slice","length","Object","hasOwn","resolveStringsInElement","element","properties","fromEntries","entries","map","resolved","isExternalComponent","slots","slotName","children","child","isContentControl","content","isItemsControl","itemTemplate","isPanel"],"mappings":";;;;AAAA;AACA;AAWA,MAAMA,eAAAA,GAAkB,WAAA;AAExB;;;;;;IAOO,SAASC,kBAAAA,CAAmBC,KAAc,EAAA;AAC7C,IAAA,OAAO,OAAOA,KAAAA,KAAU,QAAA,IAAYA,KAAAA,CAAMC,UAAU,CAACH,eAAAA,CAAAA;AACzD;AAEA;;;;;;;;AAQC,IACM,SAASI,mBAAAA,CAAoBF,KAAc,EAAEG,UAA6B,EAAA;IAC7E,IAAI,CAACJ,mBAAmBC,KAAAA,CAAAA,EAAQ;QAC5B,OAAOA,KAAAA;AACX,IAAA;AAEA,IAAA,MAAMI,GAAAA,GAAMJ,KAAAA,CAAMK,KAAK,CAACP,gBAAgBQ,MAAM,CAAA;IAC9C,OAAOC,MAAAA,CAAOC,MAAM,CAACL,UAAAA,EAAYC,OAAOD,UAAU,CAACC,IAAI,GAAGJ,KAAAA;AAC9D;AAEA;;;;;;;;;;AAUC,IACM,SAASS,uBAAAA,CAAwBC,OAAqB,EAAEP,UAA6B,EAAA;AACxF,IAAA,MAAMQ,aAAaJ,MAAAA,CAAOK,WAAW,CACjCL,MAAAA,CAAOM,OAAO,CAACH,OAAAA,CAAQC,UAAU,IAAI,IAAIG,GAAG,CAAC,CAAC,CAACV,GAAAA,EAAKJ,MAAM,GAAK;AAACI,YAAAA,GAAAA;AAAKF,YAAAA,mBAAAA,CAAoBF,KAAAA,EAAOG,UAAAA;AAAY,SAAA,CAAA,CAAA;AAGhH,IAAA,MAAMY,QAAAA,GAAyB;AAAE,QAAA,GAAGL,OAAO;AAAEC,QAAAA;AAAW,KAAA;AAExD,IAAA,IAAIK,gCAAoBD,QAAAA,CAAAA,EAAW;AAC/BA,QAAAA,QAAAA,CAASE,KAAK,GAAGV,MAAAA,CAAOK,WAAW,CAC/BL,MAAAA,CAAOM,OAAO,CAACE,QAAAA,CAASE,KAAK,IAAI,IAAIH,GAAG,CAAC,CAAC,CAACI,QAAAA,EAAUC,SAAS,GAAK;AAC/DD,gBAAAA,QAAAA;AACAC,gBAAAA,QAAAA,CAASL,GAAG,CAACM,CAAAA,KAAAA,GAASX,wBAAwBW,KAAAA,EAAOjB,UAAAA,CAAAA;AACxD,aAAA,CAAA,CAAA;AAET,IAAA;AAEA,IAAA,IAAIkB,4BAAAA,CAAiBN,QAAAA,CAAAA,IAAaA,QAAAA,CAASO,OAAO,EAAE;AAChDP,QAAAA,QAAAA,CAASO,OAAO,GAAGb,uBAAAA,CAAwBM,QAAAA,CAASO,OAAO,EAAEnB,UAAAA,CAAAA;AACjE,IAAA;AAEA,IAAA,IAAIoB,0BAAAA,CAAeR,QAAAA,CAAAA,IAAaA,QAAAA,CAASS,YAAY,EAAE;AACnDT,QAAAA,QAAAA,CAASS,YAAY,GAAGf,uBAAAA,CAAwBM,QAAAA,CAASS,YAAY,EAAErB,UAAAA,CAAAA;AAC3E,IAAA;AAEA,IAAA,IAAIsB,oBAAQV,QAAAA,CAAAA,EAAW;QACnBA,QAAAA,CAASI,QAAQ,GAAGJ,QAAAA,CAASI,QAAQ,CAACL,GAAG,CAACM,CAAAA,KAAAA,GAASX,uBAAAA,CAAwBW,KAAAA,EAAOjB,UAAAA,CAAAA,CAAAA;AACtF,IAAA;IAEA,OAAOY,QAAAA;AACX;;;;"}
@@ -22,4 +22,5 @@ export * from './incompatibleStarterThemes';
22
22
  export * from './ActionDispatcher';
23
23
  export * from './runActions';
24
24
  export * from './resolveBehaviors';
25
+ export * from './resolveStrings';
25
26
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../index.ts"],"names":[],"mappings":"AAGA,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC;AAClD,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../index.ts"],"names":[],"mappings":"AAGA,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC;AAClD,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC"}
package/dist/esm/index.js CHANGED
@@ -18,4 +18,5 @@ export { buildStarterProfile } from './buildStarterProfile.js';
18
18
  export { incompatibleStarterThemes } from './incompatibleStarterThemes.js';
19
19
  export { InteractionStop, runActions, runBindings } from './runActions.js';
20
20
  export { resolveApplicationTriggerBehaviors, resolveBehaviors, resolveEventBehaviors, resolveIntervalBehaviors } from './resolveBehaviors.js';
21
+ export { isStringsReference, resolveStringsInElement, resolveStringsValue } from './resolveStrings.js';
21
22
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,6 @@
1
+ import { SceneElement } from '@cratis/scene.model';
2
+ export type StringsDictionary = Record<string, string>;
3
+ export declare function isStringsReference(value: unknown): value is string;
4
+ export declare function resolveStringsValue(value: unknown, dictionary: StringsDictionary): unknown;
5
+ export declare function resolveStringsInElement(element: SceneElement, dictionary: StringsDictionary): SceneElement;
6
+ //# sourceMappingURL=resolveStrings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveStrings.d.ts","sourceRoot":"","sources":["../../resolveStrings.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAOnD,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAWvD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAElE;AAWD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,iBAAiB,GAAG,OAAO,CAO1F;AAaD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,iBAAiB,GAAG,YAAY,CA6B1G"}
@@ -0,0 +1,68 @@
1
+ import { isExternalComponent, isContentControl, isItemsControl, isPanel } from './elementKind.js';
2
+
3
+ // Copyright (c) Cratis. All rights reserved.
4
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
5
+ const referencePrefix = '$strings.';
6
+ /**
7
+ * Whether a property value is a `$strings.<key>` reference rather than a literal value.
8
+ *
9
+ * A document prints `$strings.<key>` unquoted - see Screenplay's internationalization documentation - so
10
+ * the reference survives into a compiled element's properties as this exact string shape, indistinguishable
11
+ * from any other string property until something resolves it.
12
+ */ function isStringsReference(value) {
13
+ return typeof value === 'string' && value.startsWith(referencePrefix);
14
+ }
15
+ /**
16
+ * Resolves a single property value against a locale's dictionary.
17
+ *
18
+ * A value that is not a `$strings.` reference passes through unchanged - resolving is a no-op on anything
19
+ * else a screen might put in the same property. A reference whose key is missing from the dictionary is
20
+ * left as the literal `$strings.<key>` text rather than blanked out - the same failure mode the frontend
21
+ * already had before resolution existed, and one an author notices immediately rather than a silently
22
+ * empty label.
23
+ */ function resolveStringsValue(value, dictionary) {
24
+ if (!isStringsReference(value)) {
25
+ return value;
26
+ }
27
+ const key = value.slice(referencePrefix.length);
28
+ return Object.hasOwn(dictionary, key) ? dictionary[key] : value;
29
+ }
30
+ /**
31
+ * Resolves every `$strings.` reference in an element tree's `properties` against a locale's dictionary,
32
+ * returning a new tree - the input is never mutated, so a caller holding the original (a cached scene,
33
+ * a Studio design-time fixture) keeps seeing the unresolved symbolic form.
34
+ *
35
+ * Walks every shape an element tree actually nests content in: an `ExternalComponent`'s named `slots`, a
36
+ * `ContentControl`'s single `content`, an `ItemsControl`'s `itemTemplate`, and a `Panel`'s `children`. This
37
+ * is the same set {@link isExternalComponent}/{@link isContentControl}/{@link isItemsControl}/{@link isPanel}
38
+ * already distinguish elsewhere in this package, so a new element kind that starts nesting content a new
39
+ * way needs a matching type guard there before it can be walked here too.
40
+ */ function resolveStringsInElement(element, dictionary) {
41
+ const properties = Object.fromEntries(Object.entries(element.properties ?? {}).map(([key, value])=>[
42
+ key,
43
+ resolveStringsValue(value, dictionary)
44
+ ]));
45
+ const resolved = {
46
+ ...element,
47
+ properties
48
+ };
49
+ if (isExternalComponent(resolved)) {
50
+ resolved.slots = Object.fromEntries(Object.entries(resolved.slots ?? {}).map(([slotName, children])=>[
51
+ slotName,
52
+ children.map((child)=>resolveStringsInElement(child, dictionary))
53
+ ]));
54
+ }
55
+ if (isContentControl(resolved) && resolved.content) {
56
+ resolved.content = resolveStringsInElement(resolved.content, dictionary);
57
+ }
58
+ if (isItemsControl(resolved) && resolved.itemTemplate) {
59
+ resolved.itemTemplate = resolveStringsInElement(resolved.itemTemplate, dictionary);
60
+ }
61
+ if (isPanel(resolved)) {
62
+ resolved.children = resolved.children.map((child)=>resolveStringsInElement(child, dictionary));
63
+ }
64
+ return resolved;
65
+ }
66
+
67
+ export { isStringsReference, resolveStringsInElement, resolveStringsValue };
68
+ //# sourceMappingURL=resolveStrings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveStrings.js","sources":["../../resolveStrings.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { SceneElement } from '@cratis/scene.model';\nimport { isContentControl, isExternalComponent, isItemsControl, isPanel } from './elementKind';\n\n/**\n * A locale's flat key -> value table, as `.strings` files parse to: dotted keys such as `invoice.title`\n * mapped to their localized text.\n */\nexport type StringsDictionary = Record<string, string>;\n\nconst referencePrefix = '$strings.';\n\n/**\n * Whether a property value is a `$strings.<key>` reference rather than a literal value.\n *\n * A document prints `$strings.<key>` unquoted - see Screenplay's internationalization documentation - so\n * the reference survives into a compiled element's properties as this exact string shape, indistinguishable\n * from any other string property until something resolves it.\n */\nexport function isStringsReference(value: unknown): value is string {\n return typeof value === 'string' && value.startsWith(referencePrefix);\n}\n\n/**\n * Resolves a single property value against a locale's dictionary.\n *\n * A value that is not a `$strings.` reference passes through unchanged - resolving is a no-op on anything\n * else a screen might put in the same property. A reference whose key is missing from the dictionary is\n * left as the literal `$strings.<key>` text rather than blanked out - the same failure mode the frontend\n * already had before resolution existed, and one an author notices immediately rather than a silently\n * empty label.\n */\nexport function resolveStringsValue(value: unknown, dictionary: StringsDictionary): unknown {\n if (!isStringsReference(value)) {\n return value;\n }\n\n const key = value.slice(referencePrefix.length);\n return Object.hasOwn(dictionary, key) ? dictionary[key] : value;\n}\n\n/**\n * Resolves every `$strings.` reference in an element tree's `properties` against a locale's dictionary,\n * returning a new tree - the input is never mutated, so a caller holding the original (a cached scene,\n * a Studio design-time fixture) keeps seeing the unresolved symbolic form.\n *\n * Walks every shape an element tree actually nests content in: an `ExternalComponent`'s named `slots`, a\n * `ContentControl`'s single `content`, an `ItemsControl`'s `itemTemplate`, and a `Panel`'s `children`. This\n * is the same set {@link isExternalComponent}/{@link isContentControl}/{@link isItemsControl}/{@link isPanel}\n * already distinguish elsewhere in this package, so a new element kind that starts nesting content a new\n * way needs a matching type guard there before it can be walked here too.\n */\nexport function resolveStringsInElement(element: SceneElement, dictionary: StringsDictionary): SceneElement {\n const properties = Object.fromEntries(\n Object.entries(element.properties ?? {}).map(([key, value]) => [key, resolveStringsValue(value, dictionary)]),\n );\n\n const resolved: SceneElement = { ...element, properties };\n\n if (isExternalComponent(resolved)) {\n resolved.slots = Object.fromEntries(\n Object.entries(resolved.slots ?? {}).map(([slotName, children]) => [\n slotName,\n children.map(child => resolveStringsInElement(child, dictionary)),\n ]),\n );\n }\n\n if (isContentControl(resolved) && resolved.content) {\n resolved.content = resolveStringsInElement(resolved.content, dictionary);\n }\n\n if (isItemsControl(resolved) && resolved.itemTemplate) {\n resolved.itemTemplate = resolveStringsInElement(resolved.itemTemplate, dictionary);\n }\n\n if (isPanel(resolved)) {\n resolved.children = resolved.children.map(child => resolveStringsInElement(child, dictionary));\n }\n\n return resolved;\n}\n"],"names":["referencePrefix","isStringsReference","value","startsWith","resolveStringsValue","dictionary","key","slice","length","Object","hasOwn","resolveStringsInElement","element","properties","fromEntries","entries","map","resolved","isExternalComponent","slots","slotName","children","child","isContentControl","content","isItemsControl","itemTemplate","isPanel"],"mappings":";;AAAA;AACA;AAWA,MAAMA,eAAAA,GAAkB,WAAA;AAExB;;;;;;IAOO,SAASC,kBAAAA,CAAmBC,KAAc,EAAA;AAC7C,IAAA,OAAO,OAAOA,KAAAA,KAAU,QAAA,IAAYA,KAAAA,CAAMC,UAAU,CAACH,eAAAA,CAAAA;AACzD;AAEA;;;;;;;;AAQC,IACM,SAASI,mBAAAA,CAAoBF,KAAc,EAAEG,UAA6B,EAAA;IAC7E,IAAI,CAACJ,mBAAmBC,KAAAA,CAAAA,EAAQ;QAC5B,OAAOA,KAAAA;AACX,IAAA;AAEA,IAAA,MAAMI,GAAAA,GAAMJ,KAAAA,CAAMK,KAAK,CAACP,gBAAgBQ,MAAM,CAAA;IAC9C,OAAOC,MAAAA,CAAOC,MAAM,CAACL,UAAAA,EAAYC,OAAOD,UAAU,CAACC,IAAI,GAAGJ,KAAAA;AAC9D;AAEA;;;;;;;;;;AAUC,IACM,SAASS,uBAAAA,CAAwBC,OAAqB,EAAEP,UAA6B,EAAA;AACxF,IAAA,MAAMQ,aAAaJ,MAAAA,CAAOK,WAAW,CACjCL,MAAAA,CAAOM,OAAO,CAACH,OAAAA,CAAQC,UAAU,IAAI,IAAIG,GAAG,CAAC,CAAC,CAACV,GAAAA,EAAKJ,MAAM,GAAK;AAACI,YAAAA,GAAAA;AAAKF,YAAAA,mBAAAA,CAAoBF,KAAAA,EAAOG,UAAAA;AAAY,SAAA,CAAA,CAAA;AAGhH,IAAA,MAAMY,QAAAA,GAAyB;AAAE,QAAA,GAAGL,OAAO;AAAEC,QAAAA;AAAW,KAAA;AAExD,IAAA,IAAIK,oBAAoBD,QAAAA,CAAAA,EAAW;AAC/BA,QAAAA,QAAAA,CAASE,KAAK,GAAGV,MAAAA,CAAOK,WAAW,CAC/BL,MAAAA,CAAOM,OAAO,CAACE,QAAAA,CAASE,KAAK,IAAI,IAAIH,GAAG,CAAC,CAAC,CAACI,QAAAA,EAAUC,SAAS,GAAK;AAC/DD,gBAAAA,QAAAA;AACAC,gBAAAA,QAAAA,CAASL,GAAG,CAACM,CAAAA,KAAAA,GAASX,wBAAwBW,KAAAA,EAAOjB,UAAAA,CAAAA;AACxD,aAAA,CAAA,CAAA;AAET,IAAA;AAEA,IAAA,IAAIkB,gBAAAA,CAAiBN,QAAAA,CAAAA,IAAaA,QAAAA,CAASO,OAAO,EAAE;AAChDP,QAAAA,QAAAA,CAASO,OAAO,GAAGb,uBAAAA,CAAwBM,QAAAA,CAASO,OAAO,EAAEnB,UAAAA,CAAAA;AACjE,IAAA;AAEA,IAAA,IAAIoB,cAAAA,CAAeR,QAAAA,CAAAA,IAAaA,QAAAA,CAASS,YAAY,EAAE;AACnDT,QAAAA,QAAAA,CAASS,YAAY,GAAGf,uBAAAA,CAAwBM,QAAAA,CAASS,YAAY,EAAErB,UAAAA,CAAAA;AAC3E,IAAA;AAEA,IAAA,IAAIsB,QAAQV,QAAAA,CAAAA,EAAW;QACnBA,QAAAA,CAASI,QAAQ,GAAGJ,QAAAA,CAASI,QAAQ,CAACL,GAAG,CAACM,CAAAA,KAAAA,GAASX,uBAAAA,CAAwBW,KAAAA,EAAOjB,UAAAA,CAAAA,CAAAA;AACtF,IAAA;IAEA,OAAOY,QAAAA;AACX;;"}