@flowview/runtime 0.1.2 → 0.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.
package/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # @flowview/runtime
2
+
3
+ The runtime contains the small HTML escaping and value helpers used by
4
+ FlowView-generated render functions. It does not parse templates, compile code,
5
+ or provide a sanitizer.
6
+
7
+ ```ts
8
+ import {
9
+ renderValue,
10
+ renderAttributeValue,
11
+ renderRawValue,
12
+ } from "@flowview/runtime";
13
+
14
+ renderValue("<script>"); // &lt;script&gt;
15
+ renderRawValue("<b>trusted</b>"); // <b>trusted</b>
16
+ ```
17
+
18
+ FlowView templates are trusted source. Ordinary interpolation (`{{ value }}`)
19
+ escapes HTML by default. Raw interpolation (`{{{ value }}}`) is explicit and
20
+ must receive an already trusted or sanitized string. Passing untrusted markup
21
+ to it can cause cross-site scripting. `@flowview/runtime` is not a sanitizer.
22
+
23
+ Mixed static text plus interpolation in one attribute value is unsupported by
24
+ the compiler. The optional `track` expression is accepted but has no rendering
25
+ effect; the compiler reports warning `FV0015`.
26
+
27
+ See the root [FlowView guide](../../README.md) and
28
+ [security model](../../SECURITY.md).
package/dist/index.d.ts CHANGED
@@ -1,6 +1,20 @@
1
1
  declare function escapeHtml(value: unknown): string;
2
2
 
3
3
  declare function renderValue(value: unknown): string;
4
+ declare function renderAttributeValue(value: unknown): string;
5
+ /**
6
+ * Insert an already-trusted HTML fragment verbatim. Backs `{{{ expression }}}`.
7
+ *
8
+ * This performs NO escaping and NO sanitization: the template author asserts
9
+ * the value is trusted or already sanitized HTML. Passing user-supplied markup
10
+ * here is a cross-site scripting vulnerability.
11
+ *
12
+ * Deliberately narrow contract: only strings are inserted. `null`, `undefined`
13
+ * and `false` render as an empty string (like {@link renderValue}). Every
14
+ * other value throws a `TypeError` rather than being stringified, so a number,
15
+ * array or object never turns into markup by accident.
16
+ */
17
+ declare function renderRawValue(value: unknown): string;
4
18
 
5
19
  /**
6
20
  * Generic shape of the context object passed to a generated render function.
@@ -11,4 +25,4 @@ type RenderContext = Record<string, unknown>;
11
25
  */
12
26
  type RenderFunction<C extends RenderContext = RenderContext> = (context: C) => string;
13
27
 
14
- export { type RenderContext, type RenderFunction, escapeHtml, renderValue };
28
+ export { type RenderContext, type RenderFunction, escapeHtml, renderAttributeValue, renderRawValue, renderValue };
package/dist/index.js CHANGED
@@ -21,8 +21,28 @@ function escapeHtml(value) {
21
21
  function renderValue(value) {
22
22
  return escapeHtml(value);
23
23
  }
24
+ function renderAttributeValue(value) {
25
+ if (value === null || value === void 0) {
26
+ return "";
27
+ }
28
+ return escapeHtml(String(value));
29
+ }
30
+ function renderRawValue(value) {
31
+ if (typeof value === "string") {
32
+ return value;
33
+ }
34
+ if (value === null || value === void 0 || value === false) {
35
+ return "";
36
+ }
37
+ const kind = Array.isArray(value) ? "array" : typeof value;
38
+ throw new TypeError(
39
+ `Raw interpolation {{{ }}} requires a string, null, undefined or false, but received a value of type ${kind}.`
40
+ );
41
+ }
24
42
  export {
25
43
  escapeHtml,
44
+ renderAttributeValue,
45
+ renderRawValue,
26
46
  renderValue
27
47
  };
28
48
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/escape-html.ts","../src/render-value.ts"],"sourcesContent":["const HTML_ESCAPE_REPLACEMENTS: Record<string, string> = {\n \"&\": \"&amp;\",\n \"<\": \"&lt;\",\n \">\": \"&gt;\",\n '\"': \"&quot;\",\n \"'\": \"&#39;\",\n};\n\nconst HTML_ESCAPE_PATTERN = /[&<>\"']/g;\n\nexport function escapeHtml(value: unknown): string {\n if (value === null || value === undefined || value === false) {\n return \"\";\n }\n\n return String(value).replace(\n HTML_ESCAPE_PATTERN,\n (character) => HTML_ESCAPE_REPLACEMENTS[character],\n );\n}\n","import { escapeHtml } from \"./escape-html\";\n\nexport function renderValue(value: unknown): string {\n return escapeHtml(value);\n}\n"],"mappings":";AAAA,IAAM,2BAAmD;AAAA,EACvD,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AACP;AAEA,IAAM,sBAAsB;AAErB,SAAS,WAAW,OAAwB;AACjD,MAAI,UAAU,QAAQ,UAAU,UAAa,UAAU,OAAO;AAC5D,WAAO;AAAA,EACT;AAEA,SAAO,OAAO,KAAK,EAAE;AAAA,IACnB;AAAA,IACA,CAAC,cAAc,yBAAyB,SAAS;AAAA,EACnD;AACF;;;ACjBO,SAAS,YAAY,OAAwB;AAClD,SAAO,WAAW,KAAK;AACzB;","names":[]}
1
+ {"version":3,"sources":["../src/escape-html.ts","../src/render-value.ts"],"sourcesContent":["const HTML_ESCAPE_REPLACEMENTS: Record<string, string> = {\n \"&\": \"&amp;\",\n \"<\": \"&lt;\",\n \">\": \"&gt;\",\n '\"': \"&quot;\",\n \"'\": \"&#39;\",\n};\n\nconst HTML_ESCAPE_PATTERN = /[&<>\"']/g;\n\nexport function escapeHtml(value: unknown): string {\n if (value === null || value === undefined || value === false) {\n return \"\";\n }\n\n return String(value).replace(\n HTML_ESCAPE_PATTERN,\n (character) => HTML_ESCAPE_REPLACEMENTS[character],\n );\n}\n","import { escapeHtml } from \"./escape-html\";\n\nexport function renderValue(value: unknown): string {\n return escapeHtml(value);\n}\n\nexport function renderAttributeValue(value: unknown): string {\n if (value === null || value === undefined) {\n return \"\";\n }\n\n return escapeHtml(String(value));\n}\n\n/**\n * Insert an already-trusted HTML fragment verbatim. Backs `{{{ expression }}}`.\n *\n * This performs NO escaping and NO sanitization: the template author asserts\n * the value is trusted or already sanitized HTML. Passing user-supplied markup\n * here is a cross-site scripting vulnerability.\n *\n * Deliberately narrow contract: only strings are inserted. `null`, `undefined`\n * and `false` render as an empty string (like {@link renderValue}). Every\n * other value throws a `TypeError` rather than being stringified, so a number,\n * array or object never turns into markup by accident.\n */\nexport function renderRawValue(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n\n if (value === null || value === undefined || value === false) {\n return \"\";\n }\n\n const kind = Array.isArray(value) ? \"array\" : typeof value;\n throw new TypeError(\n `Raw interpolation {{{ }}} requires a string, null, undefined or false, but received a value of type ${kind}.`,\n );\n}\n"],"mappings":";AAAA,IAAM,2BAAmD;AAAA,EACvD,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AACP;AAEA,IAAM,sBAAsB;AAErB,SAAS,WAAW,OAAwB;AACjD,MAAI,UAAU,QAAQ,UAAU,UAAa,UAAU,OAAO;AAC5D,WAAO;AAAA,EACT;AAEA,SAAO,OAAO,KAAK,EAAE;AAAA,IACnB;AAAA,IACA,CAAC,cAAc,yBAAyB,SAAS;AAAA,EACnD;AACF;;;ACjBO,SAAS,YAAY,OAAwB;AAClD,SAAO,WAAW,KAAK;AACzB;AAEO,SAAS,qBAAqB,OAAwB;AAC3D,MAAI,UAAU,QAAQ,UAAU,QAAW;AACzC,WAAO;AAAA,EACT;AAEA,SAAO,WAAW,OAAO,KAAK,CAAC;AACjC;AAcO,SAAS,eAAe,OAAwB;AACrD,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AAEA,MAAI,UAAU,QAAQ,UAAU,UAAa,UAAU,OAAO;AAC5D,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,MAAM,QAAQ,KAAK,IAAI,UAAU,OAAO;AACrD,QAAM,IAAI;AAAA,IACR,uGAAuG,IAAI;AAAA,EAC7G;AACF;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowview/runtime",
3
- "version": "0.1.2",
3
+ "version": "0.2.1",
4
4
  "description": "Tiny runtime for flowview-generated render functions.",
5
5
  "license": "MIT",
6
6
  "type": "module",