@caelo-cms/shared 0.10.72 → 0.11.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 (204) hide show
  1. package/dist/ai-tools.d.ts +103 -142
  2. package/dist/ai-tools.d.ts.map +1 -1
  3. package/dist/ai-tools.js +79 -167
  4. package/dist/ai-tools.js.map +1 -1
  5. package/dist/build-page.d.ts +115 -35
  6. package/dist/build-page.d.ts.map +1 -1
  7. package/dist/build-page.js +31 -12
  8. package/dist/build-page.js.map +1 -1
  9. package/dist/content.d.ts +214 -102
  10. package/dist/content.d.ts.map +1 -1
  11. package/dist/content.js +219 -84
  12. package/dist/content.js.map +1 -1
  13. package/dist/css-scope-scan.js +1 -1
  14. package/dist/css-var-aliases.d.ts +20 -0
  15. package/dist/css-var-aliases.d.ts.map +1 -0
  16. package/dist/css-var-aliases.js +95 -0
  17. package/dist/css-var-aliases.js.map +1 -0
  18. package/dist/css-var-scan.d.ts +0 -16
  19. package/dist/css-var-scan.d.ts.map +1 -1
  20. package/dist/css-var-scan.js +24 -0
  21. package/dist/css-var-scan.js.map +1 -1
  22. package/dist/edit-markers.d.ts +41 -5
  23. package/dist/edit-markers.d.ts.map +1 -1
  24. package/dist/edit-markers.js +47 -50
  25. package/dist/edit-markers.js.map +1 -1
  26. package/dist/escaped-line-breaks.d.ts +44 -0
  27. package/dist/escaped-line-breaks.d.ts.map +1 -0
  28. package/dist/escaped-line-breaks.js +203 -0
  29. package/dist/escaped-line-breaks.js.map +1 -0
  30. package/dist/index.d.ts +4 -1
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +4 -1
  33. package/dist/index.js.map +1 -1
  34. package/dist/interactions.js +6 -6
  35. package/dist/interactions.js.map +1 -1
  36. package/dist/link-canonicalise.d.ts.map +1 -1
  37. package/dist/link-canonicalise.js +7 -1
  38. package/dist/link-canonicalise.js.map +1 -1
  39. package/dist/link-refs.d.ts +1 -1
  40. package/dist/link-refs.js +3 -3
  41. package/dist/lists/address.d.ts +34 -0
  42. package/dist/lists/address.d.ts.map +1 -0
  43. package/dist/lists/address.js +43 -0
  44. package/dist/lists/address.js.map +1 -0
  45. package/dist/lists/default-types.d.ts +22 -0
  46. package/dist/lists/default-types.d.ts.map +1 -0
  47. package/dist/lists/default-types.js +127 -0
  48. package/dist/lists/default-types.js.map +1 -0
  49. package/dist/lists/fields.d.ts +152 -0
  50. package/dist/lists/fields.d.ts.map +1 -0
  51. package/dist/lists/fields.js +259 -0
  52. package/dist/lists/fields.js.map +1 -0
  53. package/dist/lists/index.d.ts +14 -0
  54. package/dist/lists/index.d.ts.map +1 -0
  55. package/dist/lists/index.js +15 -0
  56. package/dist/lists/index.js.map +1 -0
  57. package/dist/lists/item-attr.d.ts +26 -0
  58. package/dist/lists/item-attr.d.ts.map +1 -0
  59. package/dist/lists/item-attr.js +31 -0
  60. package/dist/lists/item-attr.js.map +1 -0
  61. package/dist/lists/items.d.ts +105 -0
  62. package/dist/lists/items.d.ts.map +1 -0
  63. package/dist/lists/items.js +304 -0
  64. package/dist/lists/items.js.map +1 -0
  65. package/dist/lists/list-type.d.ts +401 -0
  66. package/dist/lists/list-type.d.ts.map +1 -0
  67. package/dist/lists/list-type.js +275 -0
  68. package/dist/lists/list-type.js.map +1 -0
  69. package/dist/lists/model.d.ts +14 -0
  70. package/dist/lists/model.d.ts.map +1 -0
  71. package/dist/lists/model.js +15 -0
  72. package/dist/lists/model.js.map +1 -0
  73. package/dist/lists/page-type.d.ts +115 -0
  74. package/dist/lists/page-type.d.ts.map +1 -0
  75. package/dist/lists/page-type.js +66 -0
  76. package/dist/lists/page-type.js.map +1 -0
  77. package/dist/lists/refs.d.ts +13 -0
  78. package/dist/lists/refs.d.ts.map +1 -0
  79. package/dist/lists/refs.js +18 -0
  80. package/dist/lists/refs.js.map +1 -0
  81. package/dist/lists/render-data.d.ts +123 -0
  82. package/dist/lists/render-data.d.ts.map +1 -0
  83. package/dist/lists/render-data.js +3 -0
  84. package/dist/lists/render-data.js.map +1 -0
  85. package/dist/lists/render-deps.d.ts +69 -0
  86. package/dist/lists/render-deps.d.ts.map +1 -0
  87. package/dist/lists/render-deps.js +93 -0
  88. package/dist/lists/render-deps.js.map +1 -0
  89. package/dist/lists/resolve-values.d.ts +63 -0
  90. package/dist/lists/resolve-values.d.ts.map +1 -0
  91. package/dist/lists/resolve-values.js +181 -0
  92. package/dist/lists/resolve-values.js.map +1 -0
  93. package/dist/lists/resolve.d.ts +119 -0
  94. package/dist/lists/resolve.d.ts.map +1 -0
  95. package/dist/lists/resolve.js +970 -0
  96. package/dist/lists/resolve.js.map +1 -0
  97. package/dist/lists/scope.d.ts +81 -0
  98. package/dist/lists/scope.d.ts.map +1 -0
  99. package/dist/lists/scope.js +3 -0
  100. package/dist/lists/scope.js.map +1 -0
  101. package/dist/markup-structure.d.ts +8 -0
  102. package/dist/markup-structure.d.ts.map +1 -1
  103. package/dist/markup-structure.js +2 -0
  104. package/dist/markup-structure.js.map +1 -1
  105. package/dist/media.d.ts +1 -1
  106. package/dist/nested-module-render.d.ts +38 -20
  107. package/dist/nested-module-render.d.ts.map +1 -1
  108. package/dist/nested-module-render.js +156 -31
  109. package/dist/nested-module-render.js.map +1 -1
  110. package/dist/page-log.d.ts +1 -1
  111. package/dist/preview-compose.d.ts +24 -21
  112. package/dist/preview-compose.d.ts.map +1 -1
  113. package/dist/preview-compose.js +34 -118
  114. package/dist/preview-compose.js.map +1 -1
  115. package/dist/redirect-plan.d.ts +13 -0
  116. package/dist/redirect-plan.d.ts.map +1 -1
  117. package/dist/redirect-plan.js +22 -0
  118. package/dist/redirect-plan.js.map +1 -1
  119. package/dist/seo.d.ts +21 -0
  120. package/dist/seo.d.ts.map +1 -1
  121. package/dist/seo.js +32 -0
  122. package/dist/seo.js.map +1 -1
  123. package/dist/source-text-transport.d.ts +43 -0
  124. package/dist/source-text-transport.d.ts.map +1 -0
  125. package/dist/source-text-transport.js +79 -0
  126. package/dist/source-text-transport.js.map +1 -0
  127. package/dist/template-engine.d.ts +44 -31
  128. package/dist/template-engine.d.ts.map +1 -1
  129. package/dist/template-engine.js +75 -174
  130. package/dist/template-engine.js.map +1 -1
  131. package/dist/template-sections.d.ts +69 -0
  132. package/dist/template-sections.d.ts.map +1 -0
  133. package/dist/template-sections.js +436 -0
  134. package/dist/template-sections.js.map +1 -0
  135. package/dist/version.d.ts +2 -2
  136. package/dist/version.d.ts.map +1 -1
  137. package/dist/version.js +1 -1
  138. package/dist/version.js.map +1 -1
  139. package/package.json +8 -1
  140. package/src/__tests__/redos-hardening.test.ts +51 -16
  141. package/src/ai-tools-add-module-modes.test.ts +51 -1
  142. package/src/ai-tools.test.ts +7 -10
  143. package/src/ai-tools.ts +90 -180
  144. package/src/bug-intake.test.ts +1 -1
  145. package/src/build-page.test.ts +34 -3
  146. package/src/build-page.ts +34 -11
  147. package/src/content.test.ts +137 -4
  148. package/src/content.ts +230 -85
  149. package/src/css-scope-scan.ts +1 -1
  150. package/src/css-var-aliases.test.ts +61 -0
  151. package/src/css-var-aliases.ts +109 -0
  152. package/src/css-var-scan.ts +9 -0
  153. package/src/edit-markers.test.ts +37 -21
  154. package/src/edit-markers.ts +52 -20
  155. package/src/escaped-line-breaks.ts +221 -0
  156. package/src/index.ts +4 -1
  157. package/src/interactions.ts +6 -6
  158. package/src/link-canonicalise.test.ts +36 -6
  159. package/src/link-canonicalise.ts +6 -1
  160. package/src/link-refs.test.ts +67 -42
  161. package/src/link-refs.ts +3 -3
  162. package/src/lists/address.ts +75 -0
  163. package/src/lists/default-types.ts +141 -0
  164. package/src/lists/fields.ts +286 -0
  165. package/src/lists/index.ts +16 -0
  166. package/src/lists/item-attr.test.ts +36 -0
  167. package/src/lists/item-attr.ts +49 -0
  168. package/src/lists/items.ts +402 -0
  169. package/src/lists/list-fixtures.test.ts +308 -0
  170. package/src/lists/list-type.ts +306 -0
  171. package/src/lists/lists.test.ts +328 -0
  172. package/src/lists/model.ts +16 -0
  173. package/src/lists/page-type.ts +71 -0
  174. package/src/lists/refs.ts +21 -0
  175. package/src/lists/render-data.ts +134 -0
  176. package/src/lists/render-deps.test.ts +132 -0
  177. package/src/lists/render-deps.ts +147 -0
  178. package/src/lists/resolve-values.ts +224 -0
  179. package/src/lists/resolve.test.ts +472 -0
  180. package/src/lists/resolve.ts +1246 -0
  181. package/src/lists/scope.ts +69 -0
  182. package/src/lists-compose-parity.test.ts +262 -0
  183. package/src/markup-structure.ts +10 -0
  184. package/src/nested-module-render.test.ts +147 -74
  185. package/src/nested-module-render.ts +120 -48
  186. package/src/preview-compose.test.ts +55 -19
  187. package/src/preview-compose.ts +59 -154
  188. package/src/redirect-plan.test.ts +25 -0
  189. package/src/redirect-plan.ts +24 -0
  190. package/src/seo.test.ts +58 -0
  191. package/src/seo.ts +49 -0
  192. package/src/source-text-transport.test.ts +158 -0
  193. package/src/source-text-transport.ts +81 -0
  194. package/src/template-engine-lists.test.ts +608 -0
  195. package/src/template-engine.test.ts +62 -80
  196. package/src/template-engine.ts +102 -245
  197. package/src/template-sections.ts +514 -0
  198. package/src/version.ts +1 -1
  199. package/dist/structured-sets.d.ts +0 -70
  200. package/dist/structured-sets.d.ts.map +0 -1
  201. package/dist/structured-sets.js +0 -92
  202. package/dist/structured-sets.js.map +0 -1
  203. package/src/structured-sets.ts +0 -114
  204. package/src/template-engine-data-lists.test.ts +0 -90
@@ -0,0 +1,158 @@
1
+ // SPDX-License-Identifier: MPL-2.0
2
+
3
+ import { describe, expect, it } from "bun:test";
4
+ import { addModuleToolInput, createTemplateToolInput } from "./ai-tools.js";
5
+ import { decodeEscapedLineBreaks } from "./escaped-line-breaks.js";
6
+ import {
7
+ decodeHtmlEscapedSource,
8
+ decodeJsonEncodedSource,
9
+ decodeSourceTextTransport,
10
+ } from "./source-text-transport.js";
11
+
12
+ const markup = '<main class="simple-page-main"><caelo-slot name="content"></caelo-slot></main>';
13
+
14
+ describe("decodeHtmlEscapedSource", () => {
15
+ it("decodes markup escaped as a whole (e2e-livedit run 40344374447)", () => {
16
+ const sent =
17
+ '&lt;main class="simple-page-main"&gt;&lt;caelo-slot name="content"&gt;&lt;/caelo-slot&gt;&lt;/main&gt;';
18
+ expect(decodeHtmlEscapedSource(sent)).toBe(markup);
19
+ expect(
20
+ decodeHtmlEscapedSource("&lt;p class=&quot;x&quot;&gt;Tom &amp;amp; Jerry&lt;/p&gt;"),
21
+ ).toBe('<p class="x">Tom &amp; Jerry</p>');
22
+ });
23
+
24
+ it("leaves real markup and text that only mentions an entity untouched", () => {
25
+ const withEntity = "<p>Use &lt;div&gt; for blocks</p>";
26
+ expect(decodeHtmlEscapedSource(withEntity)).toBe(withEntity);
27
+ expect(decodeHtmlEscapedSource("a &lt; b")).toBe("a &lt; b");
28
+ expect(decodeHtmlEscapedSource(".a > .b { color: red }")).toBe(".a > .b { color: red }");
29
+ });
30
+ });
31
+
32
+ describe("decodeJsonEncodedSource", () => {
33
+ it("decodes a whole-value JSON string literal with escapes", () => {
34
+ expect(decodeJsonEncodedSource(JSON.stringify(markup))).toBe(markup);
35
+ expect(decodeJsonEncodedSource('".a {\\n color: red;\\n}"')).toBe(".a {\n color: red;\n}");
36
+ });
37
+
38
+ it("leaves a literal without escapes and non-literals untouched", () => {
39
+ expect(decodeJsonEncodedSource('"use strict"')).toBe('"use strict"');
40
+ expect(decodeJsonEncodedSource(markup)).toBe(markup);
41
+ expect(decodeJsonEncodedSource('"broken \\" literal')).toBe('"broken \\" literal');
42
+ });
43
+ });
44
+
45
+ describe("decodeSourceTextTransport", () => {
46
+ it("unwraps CDATA, then a JSON literal, then HTML escaping", () => {
47
+ expect(decodeSourceTextTransport(`<![CDATA[${markup}]]>`, "html")).toBe(markup);
48
+ expect(
49
+ decodeSourceTextTransport(
50
+ JSON.stringify(markup.replaceAll("<", "&lt;").replaceAll(">", "&gt;")),
51
+ "html",
52
+ ),
53
+ ).toBe(markup);
54
+ expect(decodeSourceTextTransport(42, "html")).toBe(42);
55
+ });
56
+
57
+ it("is what create_template's html argument goes through", () => {
58
+ const r = createTemplateToolInput.parse({
59
+ slug: "page-template",
60
+ displayName: "Simple Page",
61
+ html: markup.replaceAll("<", "&lt;").replaceAll(">", "&gt;"),
62
+ });
63
+ expect(r.html).toBe(markup);
64
+ });
65
+ });
66
+
67
+ // e2e-livedit run 40532297620 (release gate v0.11.1): add_module's html, css
68
+ // and js arrived with every line break as the two characters `\` `n`. The
69
+ // stored footer showed literal `\n` text and the shared module <script>
70
+ // threw `SyntaxError: Invalid or unexpected token` on every preview. These
71
+ // are the exact values the AI sent.
72
+ describe("decodeEscapedLineBreaks", () => {
73
+ const sentJs =
74
+ "(function () {\\n document.querySelectorAll('.site-footer__year').forEach(function (el) {\\n el.textContent = new Date().getFullYear();\\n });\\n})();";
75
+ const sentCss =
76
+ ".site-footer {\\n padding: 2rem 1.5rem;\\n text-align: center;\\n}\\n.site-footer__link:hover {\\n text-decoration: underline;\\n}";
77
+ const sentHtml =
78
+ '<footer class="site-footer">\\n <nav class="site-footer__nav" aria-label="Footer">\\n <ul class="site-footer__list">\\n {{#nav}}\\n <li class="site-footer__item"><a class="site-footer__link" href="{{link.href}}">{{label}}</a></li>\\n {{/nav}}\\n </ul>\\n </nav>\\n</footer>';
79
+
80
+ it("turns escaped line breaks back into real ones (the run's exact values)", () => {
81
+ expect(decodeEscapedLineBreaks(sentJs, "js")).toBe(
82
+ "(function () {\n document.querySelectorAll('.site-footer__year').forEach(function (el) {\n el.textContent = new Date().getFullYear();\n });\n})();",
83
+ );
84
+ expect(decodeEscapedLineBreaks(sentCss, "css")).toBe(
85
+ ".site-footer {\n padding: 2rem 1.5rem;\n text-align: center;\n}\n.site-footer__link:hover {\n text-decoration: underline;\n}",
86
+ );
87
+ const html = decodeEscapedLineBreaks(sentHtml, "html") as string;
88
+ expect(html).not.toContain("\\n");
89
+ expect(html.split("\n")).toHaveLength(9);
90
+ expect(html).toContain('<footer class="site-footer">\n <nav');
91
+ });
92
+
93
+ it("decodes escaped CRLF and escaped tab indentation", () => {
94
+ expect(decodeEscapedLineBreaks(".a {\\r\\n\\tcolor: red;\\r\\n\\t\\tx: y;\\r\\n}", "css")).toBe(
95
+ ".a {\n\tcolor: red;\n\t\tx: y;\n}",
96
+ );
97
+ });
98
+
99
+ it("leaves source with real line breaks, single-line code and escaped backslashes alone", () => {
100
+ const multiLine = "const s = 'a\\n b';\nconsole.log(s.split('\\n '));";
101
+ expect(decodeEscapedLineBreaks(multiLine, "js")).toBe(multiLine);
102
+ const minified = "var t=a.join('\\n');console.log(t.split('\\n'))";
103
+ expect(decodeEscapedLineBreaks(minified, "js")).toBe(minified);
104
+ const oneHit = "el.textContent = lines.join('\\n ');";
105
+ expect(decodeEscapedLineBreaks(oneHit, "js")).toBe(oneHit);
106
+ const escapedBackslash = "a('\\\\n x'); b('\\\\n y');";
107
+ expect(decodeEscapedLineBreaks(escapedBackslash, "js")).toBe(escapedBackslash);
108
+ expect(decodeEscapedLineBreaks(7, "js")).toBe(7);
109
+ });
110
+
111
+ // PR #1189 review: an escape inside a literal is meaningful, so a value
112
+ // holding one is ambiguous and left exactly as sent — decoding it would
113
+ // turn valid source into broken source.
114
+ it("leaves values alone when an escaped line break sits inside a literal", () => {
115
+ const jsString = 'document.querySelector("pre").textContent = "Title\\n Detail\\n More";';
116
+ expect(decodeEscapedLineBreaks(jsString, "js")).toBe(jsString);
117
+ const jsTemplate = "(function () {\\n el.title = `a\\n b`;\\n})();";
118
+ expect(decodeEscapedLineBreaks(jsTemplate, "js")).toBe(jsTemplate);
119
+ const jsRegex = "(function () {\\n var ok = /a\\n b/.test(x);\\n})();";
120
+ expect(decodeEscapedLineBreaks(jsRegex, "js")).toBe(jsRegex);
121
+ const cssContent = '.a::after {\\n content: "x\\n y";\\n}';
122
+ expect(decodeEscapedLineBreaks(cssContent, "css")).toBe(cssContent);
123
+ const htmlAttr = '<div>\\n <span title="a\\n b">x</span>\\n</div>';
124
+ expect(decodeEscapedLineBreaks(htmlAttr, "html")).toBe(htmlAttr);
125
+ const htmlPre = '<div>\\n <pre>printf("a\\n");</pre>\\n</div>';
126
+ expect(decodeEscapedLineBreaks(htmlPre, "html")).toBe(htmlPre);
127
+ });
128
+
129
+ it("decodes structural escapes around literals and comments that hold none", () => {
130
+ expect(
131
+ decodeEscapedLineBreaks(
132
+ "// it's the footer\\n(function () {\\n var s = 'a\\\\n';\\n /x/.test(s);\\n})();",
133
+ "js",
134
+ ),
135
+ ).toBe("// it's the footer\n(function () {\n var s = 'a\\\\n';\n /x/.test(s);\n})();");
136
+ expect(
137
+ decodeEscapedLineBreaks('<p>It\'s ours</p>\\n<p>\\n <a href="/">Home</a>\\n</p>', "html"),
138
+ ).toBe('<p>It\'s ours</p>\n<p>\n <a href="/">Home</a>\n</p>');
139
+ });
140
+
141
+ it("is what add_module's html / css / js arguments go through", () => {
142
+ const r = addModuleToolInput.parse({
143
+ target: "layout",
144
+ targetRef: "site-default",
145
+ blockName: "footer",
146
+ position: "bottom",
147
+ displayName: "Site Footer",
148
+ html: sentHtml,
149
+ css: sentCss,
150
+ js: sentJs,
151
+ });
152
+ for (const v of [r.html, r.css, r.js]) {
153
+ expect(v).toBeString();
154
+ expect(v).not.toContain("\\n");
155
+ expect(v).toContain("\n");
156
+ }
157
+ });
158
+ });
@@ -0,0 +1,81 @@
1
+ // SPDX-License-Identifier: MPL-2.0
2
+
3
+ /**
4
+ * Decoding of whole-value transport encodings around AI tool arguments that
5
+ * carry source text (module / template / layout html, css, js).
6
+ *
7
+ * The model sometimes encodes a long markup string as a whole before it
8
+ * sends it: as a CDATA section (`unwrapCdataEnvelope`), as a JSON string
9
+ * literal (`"<footer class=\"x\">…"`), HTML-escaped (`&lt;main&gt;…`), or
10
+ * with its line breaks string-escaped (`{\n color: red;\n}`, see
11
+ * `escaped-line-breaks.ts`).
12
+ * Each is an encoding of a value the caller did supply, never content:
13
+ * a JSON string literal is not valid markup, CSS or JS as a whole, and
14
+ * markup without a single `<` but with `&lt;tag` has no element at all.
15
+ * Refusing them cost a tool round-trip each time (e2e-livedit runs of
16
+ * PR #1121 and #1143); describing them in every tool cost tokens on every
17
+ * call and still did not stop them. So the boundary decodes them, once,
18
+ * here. Anything not clearly a whole-value encoding is left untouched and
19
+ * the op validator still refuses it (shared `content.ts`), which also
20
+ * keeps human and import writes strict. This is input normalisation, not
21
+ * a fallback for missing data (CLAUDE.md §2).
22
+ */
23
+
24
+ import { decodeEscapedLineBreaks, type SourceLanguage } from "./escaped-line-breaks.js";
25
+ import { unwrapCdataEnvelope } from "./strip-cdata.js";
26
+
27
+ /**
28
+ * The body of a whole-value JSON string literal, or the input unchanged.
29
+ * Only decoded when the literal carries an escape (`\"`, `\n`, `\t`, `\\`,
30
+ * `\/`, `\u…`): a bare `"use strict"` stays as it is.
31
+ */
32
+ export function decodeJsonEncodedSource(value: unknown): unknown {
33
+ if (typeof value !== "string") return value;
34
+ const t = value.trim();
35
+ if (t.length < 2 || !t.startsWith('"') || !t.endsWith('"')) return value;
36
+ if (!/\\["ntr\\/u]/.test(t)) return value;
37
+ try {
38
+ const decoded: unknown = JSON.parse(t);
39
+ return typeof decoded === "string" ? decoded : value;
40
+ } catch {
41
+ return value;
42
+ }
43
+ }
44
+
45
+ const ENTITIES: Readonly<Record<string, string>> = {
46
+ "&lt;": "<",
47
+ "&gt;": ">",
48
+ "&quot;": '"',
49
+ "&#34;": '"',
50
+ "&#39;": "'",
51
+ "&#x27;": "'",
52
+ "&apos;": "'",
53
+ };
54
+
55
+ /**
56
+ * Markup sent HTML-escaped as a whole, decoded once; the input unchanged
57
+ * otherwise. "As a whole" = no raw `<` anywhere and at least one escaped
58
+ * tag (`&lt;div`, `&lt;/div`) — the same test the op's refusal uses.
59
+ * `&amp;` is decoded last, so an entity the author meant (`&amp;nbsp;`
60
+ * sent for `&nbsp;`) comes out as the author wrote it.
61
+ */
62
+ export function decodeHtmlEscapedSource(value: unknown): unknown {
63
+ if (typeof value !== "string") return value;
64
+ if (value.includes("<") || !/&lt;\/?[a-zA-Z]/.test(value)) return value;
65
+ return value
66
+ .replace(/&lt;|&gt;|&quot;|&#34;|&#39;|&#x27;|&apos;/g, (e) => ENTITIES[e] ?? e)
67
+ .replace(/&amp;/g, "&");
68
+ }
69
+
70
+ /**
71
+ * Every whole-value transport encoding, outermost first.
72
+ *
73
+ * @param language - the grammar of the value; escaped line breaks are only
74
+ * decoded where they cannot belong to a literal of it.
75
+ */
76
+ export function decodeSourceTextTransport(value: unknown, language: SourceLanguage): unknown {
77
+ return decodeEscapedLineBreaks(
78
+ decodeHtmlEscapedSource(decodeJsonEncodedSource(unwrapCdataEnvelope(value))),
79
+ language,
80
+ );
81
+ }