@microsoft/fast-build 0.6.0 → 0.8.0-fast-element-v3-rc-20260615
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
CHANGED
|
@@ -38,9 +38,10 @@ fast build [options]
|
|
|
38
38
|
| `--entry="<path>"` | `index.html` | Entry HTML template to render |
|
|
39
39
|
| `--state="<path>"` | `{}` when omitted | JSON file containing the template state. If omitted, no state file is loaded and rendering uses an empty state object. If `--state` is provided, the file must exist. |
|
|
40
40
|
| `--output="<path>"` | `output.html` | Where to write the rendered HTML |
|
|
41
|
-
| `--templates="<glob>"` | _(none)_ | Glob pattern(s) for custom element template HTML files. Separate multiple patterns with commas. A warning is printed if not provided or if no files match a pattern. |
|
|
41
|
+
| `--templates="<glob>"` | _(none)_ | Glob pattern(s) for custom element template HTML files. Separate multiple patterns with commas. A warning is printed if not provided in non-streaming mode or if no files match a pattern. |
|
|
42
42
|
| `--attribute-name-strategy="<strategy>"` | `camelCase` | Strategy for mapping HTML attribute names to state property names on custom elements. `"camelCase"` converts dashes to camelCase (e.g. `foo-bar` → `fooBar`). `"none"` preserves dashes (e.g. `foo-bar` → `foo-bar`). See [Attribute name strategy](#attribute-name-strategy). |
|
|
43
43
|
| `--config="<path>"` | `fast-build.config.json` | Path to a JSON configuration file. If omitted, `fast-build.config.json` in the current directory is used when present. CLI arguments take precedence over config values. See [Configuration file](#configuration-file). |
|
|
44
|
+
| `--stream[=true/false]` | `false` | Write rendered HTML chunks directly to stdout instead of writing `--output`. Valueless `--stream` is treated as `true`. |
|
|
44
45
|
|
|
45
46
|
### Example
|
|
46
47
|
|
|
@@ -81,6 +82,32 @@ Produces `output.html`:
|
|
|
81
82
|
</html>
|
|
82
83
|
```
|
|
83
84
|
|
|
85
|
+
### Streaming output
|
|
86
|
+
|
|
87
|
+
Pass `--stream`, `--stream=true`, or `--stream=false`, or set
|
|
88
|
+
`"stream": true` in `fast-build.config.json`, to control stdout streaming. When
|
|
89
|
+
streaming is enabled, the CLI writes raw rendered HTML chunks to stdout, does
|
|
90
|
+
not write the `--output` file, and does not print the normal `Built: ...`
|
|
91
|
+
message.
|
|
92
|
+
|
|
93
|
+
```shell
|
|
94
|
+
fast build --entry=index.html --state=state.json --stream
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Streaming is simulated by the WebAssembly renderer: chunks are prepared in
|
|
98
|
+
memory, returned to JavaScript as a JSON array, parsed by the CLI, and then
|
|
99
|
+
written to stdout. `--stream` uses the same entry renderer with its stream flag
|
|
100
|
+
enabled and passes an empty templates map when no `--templates` glob is
|
|
101
|
+
provided. Chunk boundaries are safe for HTML parsing:
|
|
102
|
+
|
|
103
|
+
- Attribute bindings stay within complete opening tag chunks.
|
|
104
|
+
- Custom element opening chunks include the complete Declarative Shadow DOM
|
|
105
|
+
template.
|
|
106
|
+
- Streamed output uses the same renderer preprocessing and custom-element host
|
|
107
|
+
attribute propagation as normal output.
|
|
108
|
+
- Empty chunks are omitted.
|
|
109
|
+
- Concatenating all chunks matches the normal non-streamed render.
|
|
110
|
+
|
|
84
111
|
### Missing or omitted state
|
|
85
112
|
|
|
86
113
|
State is optional. When `--state` is omitted and no `state` path is provided by config, `fast build` does not look for `state.json`; rendering uses an empty object (`{}`). An explicit `--state` path, or a `state` path from config, must exist or the command exits with an error.
|
|
@@ -117,7 +144,7 @@ Template files must use the following format:
|
|
|
117
144
|
</f-template>
|
|
118
145
|
```
|
|
119
146
|
|
|
120
|
-
If an `<f-template>` element has no `name` attribute, a warning is printed and it is ignored. Exact file paths (no wildcards) are also accepted as patterns, making it possible to register a single template file.
|
|
147
|
+
If an `<f-template>` element has no `name` attribute, a warning is printed and it is ignored. Exact file paths (no wildcards) are also accepted as patterns, making it possible to register a single template file. The parser follows browser tag boundaries for the `<f-template>` and inner `<template>` wrappers, including ASCII whitespace before `>` in opening and closing tags.
|
|
121
148
|
|
|
122
149
|
Any `shadowroot*` attributes on `<f-template>` are forwarded to the rendered Declarative Shadow DOM `<template>`. The CLI normalizes `shadowrootmode` and legacy `shadowroot` for compatibility: when neither has a non-empty value, it emits `shadowrootmode="open" shadowroot="open"`; when exactly one has a non-empty value, that value is mirrored to the other; when both have explicit non-empty values, both are preserved as authored, even if they conflict.
|
|
123
150
|
|
|
@@ -167,8 +194,10 @@ fast build --config=configs/my-build.json
|
|
|
167
194
|
|
|
168
195
|
**Path resolution:** File paths in the config file (`entry`, `state`, `output`, `templates`) are resolved relative to the config file's directory, not the current working directory. This ensures the config works correctly regardless of where the CLI is invoked.
|
|
169
196
|
|
|
170
|
-
All keys are optional. Only the following keys are allowed: `entry`, `state`, `output`, `templates`, `attribute-name-strategy`. Unknown keys
|
|
197
|
+
All keys are optional. Only the following keys are allowed: `entry`, `state`, `output`, `templates`, `attribute-name-strategy`, and `stream`. Unknown keys produce an error. Values must be strings except `stream`, which must be a JSON boolean (`true` or `false`). If `state` is omitted, rendering uses `{}`; if `state` is present, the referenced file must exist. CLI arguments always override config values, including `--stream=false` overriding `"stream": true`.
|
|
171
198
|
|
|
172
199
|
## Template syntax
|
|
173
200
|
|
|
174
|
-
Template syntax follows the FAST declarative HTML format. See the
|
|
201
|
+
Template syntax follows the FAST declarative HTML format. See the
|
|
202
|
+
[`@microsoft/fast-element` declarative documentation](../fast-element/DECLARATIVE_HTML.md)
|
|
203
|
+
for full documentation on bindings, conditionals, repeats, and directives.
|
package/bin/fast.js
CHANGED
|
@@ -7,16 +7,21 @@ const path = require("path");
|
|
|
7
7
|
|
|
8
8
|
const WASM_MODULE = path.join(__dirname, "../wasm/microsoft_fast_build.js");
|
|
9
9
|
const DEFAULT_CONFIG_FILENAME = "fast-build.config.json";
|
|
10
|
+
const VALUELESS_CLI_FLAGS = new Set(["stream"]);
|
|
10
11
|
const ALLOWED_CONFIG_KEYS = new Set([
|
|
11
12
|
"entry",
|
|
12
13
|
"state",
|
|
13
14
|
"output",
|
|
14
15
|
"templates",
|
|
15
16
|
"attribute-name-strategy",
|
|
17
|
+
"stream",
|
|
16
18
|
]);
|
|
17
19
|
|
|
20
|
+
/** @typedef {Record<string, string | boolean>} FastBuildConfig */
|
|
21
|
+
|
|
18
22
|
/**
|
|
19
|
-
* Parse CLI arguments of the form --key="value"
|
|
23
|
+
* Parse CLI arguments of the form --key="value", --key=value, or supported
|
|
24
|
+
* valueless flags like --stream.
|
|
20
25
|
* @param {string[]} argv
|
|
21
26
|
* @returns {Record<string, string>}
|
|
22
27
|
*/
|
|
@@ -26,11 +31,48 @@ function parseArgs(argv) {
|
|
|
26
31
|
const match = arg.match(/^--([^=]+)=(.*)$/s);
|
|
27
32
|
if (match) {
|
|
28
33
|
args[match[1]] = match[2].replace(/^"|"$/g, "");
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const flag = arg.match(/^--([^=]+)$/s);
|
|
38
|
+
if (flag && VALUELESS_CLI_FLAGS.has(flag[1])) {
|
|
39
|
+
args[flag[1]] = "true";
|
|
29
40
|
}
|
|
30
41
|
}
|
|
31
42
|
return args;
|
|
32
43
|
}
|
|
33
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Resolve a boolean option, preferring CLI args over config values.
|
|
47
|
+
* CLI values accept true, false, or an empty valueless flag.
|
|
48
|
+
* @param {Record<string, string>} args - Parsed CLI arguments.
|
|
49
|
+
* @param {FastBuildConfig} config - Parsed config file values.
|
|
50
|
+
* @param {string} key - The option key.
|
|
51
|
+
* @returns {boolean}
|
|
52
|
+
*/
|
|
53
|
+
function resolveBooleanOption(args, config, key) {
|
|
54
|
+
if (Object.prototype.hasOwnProperty.call(args, key)) {
|
|
55
|
+
const value = args[key].trim().toLowerCase();
|
|
56
|
+
if (value === "true" || value === "") {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
if (value === "false") {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
process.stderr.write(
|
|
64
|
+
`Error: Invalid --${key} value "${args[key]}". Expected "true" or "false".\n`
|
|
65
|
+
);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (Object.prototype.hasOwnProperty.call(config, key)) {
|
|
70
|
+
return config[key] === true;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
|
|
34
76
|
/**
|
|
35
77
|
* Load and validate a fast-build config file.
|
|
36
78
|
*
|
|
@@ -42,7 +84,7 @@ function parseArgs(argv) {
|
|
|
42
84
|
* file's directory so that the caller can use them directly.
|
|
43
85
|
*
|
|
44
86
|
* @param {string | undefined} configPath - Explicit path from --config, if any.
|
|
45
|
-
* @returns {{ config:
|
|
87
|
+
* @returns {{ config: FastBuildConfig, configDir: string | null }}
|
|
46
88
|
*/
|
|
47
89
|
function loadConfig(configPath) {
|
|
48
90
|
/** @type {string} */
|
|
@@ -92,6 +134,16 @@ function loadConfig(configPath) {
|
|
|
92
134
|
);
|
|
93
135
|
process.exit(1);
|
|
94
136
|
}
|
|
137
|
+
if (key === "stream") {
|
|
138
|
+
if (typeof raw[key] !== "boolean") {
|
|
139
|
+
process.stderr.write(
|
|
140
|
+
`Error: Value for "${key}" in config file "${resolvedPath}" must be a boolean.\n`
|
|
141
|
+
);
|
|
142
|
+
process.exit(1);
|
|
143
|
+
}
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
|
|
95
147
|
if (typeof raw[key] !== "string") {
|
|
96
148
|
process.stderr.write(
|
|
97
149
|
`Error: Value for "${key}" in config file "${resolvedPath}" must be a string.\n`
|
|
@@ -110,7 +162,7 @@ function loadConfig(configPath) {
|
|
|
110
162
|
* CLI-derived paths are resolved relative to CWD (the default behaviour).
|
|
111
163
|
*
|
|
112
164
|
* @param {Record<string, string>} args - Parsed CLI arguments.
|
|
113
|
-
* @param {
|
|
165
|
+
* @param {FastBuildConfig} config - Parsed config file values.
|
|
114
166
|
* @param {string | null} configDir - Directory of the config file, or null.
|
|
115
167
|
* @param {string} key - The option key.
|
|
116
168
|
* @param {string} [defaultValue] - Fallback when neither source provides a value.
|
|
@@ -122,6 +174,9 @@ function resolveOption(args, config, configDir, key, defaultValue) {
|
|
|
122
174
|
}
|
|
123
175
|
if (Object.prototype.hasOwnProperty.call(config, key)) {
|
|
124
176
|
const value = config[key];
|
|
177
|
+
if (typeof value !== "string") {
|
|
178
|
+
return defaultValue;
|
|
179
|
+
}
|
|
125
180
|
const isFilePath = key === "entry" || key === "state" || key === "output" || key === "templates";
|
|
126
181
|
if (isFilePath && configDir !== null) {
|
|
127
182
|
return path.resolve(configDir, value);
|
|
@@ -223,13 +278,13 @@ function staticPrefixDir(pattern) {
|
|
|
223
278
|
* @param {string} html
|
|
224
279
|
* @param {string} filePath - used in warning messages
|
|
225
280
|
* @param {object} wasm - the loaded WASM module
|
|
226
|
-
* @returns {{ name: string, content: string, shadowrootAttributes: { name: string, value: string | null }[] }[]}
|
|
281
|
+
* @returns {{ name: string, content: string, shadowrootAttributes: { name: string, value: string | null }[], hostAttributes: { name: string, value: string | null }[] }[]}
|
|
227
282
|
*/
|
|
228
283
|
function parseFTemplates(html, filePath, wasm) {
|
|
229
|
-
/** @type {{ name: string | null, content: string, shadowrootAttributes?: { name: string, value: string | null }[] }[]} */
|
|
284
|
+
/** @type {{ name: string | null, content: string, shadowrootAttributes?: { name: string, value: string | null }[], hostAttributes?: { name: string, value: string | null }[] }[]} */
|
|
230
285
|
const parsed = JSON.parse(wasm.parse_f_templates(html));
|
|
231
286
|
const results = [];
|
|
232
|
-
for (const { name, content, shadowrootAttributes } of parsed) {
|
|
287
|
+
for (const { name, content, shadowrootAttributes, hostAttributes } of parsed) {
|
|
233
288
|
if (name === null) {
|
|
234
289
|
process.stderr.write(
|
|
235
290
|
`Warning: <f-template> without a 'name' attribute in '${filePath}': ${content.trim()}\n`
|
|
@@ -239,6 +294,7 @@ function parseFTemplates(html, filePath, wasm) {
|
|
|
239
294
|
name,
|
|
240
295
|
content,
|
|
241
296
|
shadowrootAttributes: shadowrootAttributes || [],
|
|
297
|
+
hostAttributes: hostAttributes || [],
|
|
242
298
|
});
|
|
243
299
|
}
|
|
244
300
|
}
|
|
@@ -252,7 +308,7 @@ function parseFTemplates(html, filePath, wasm) {
|
|
|
252
308
|
* Warns (but does not error) if the base directory does not exist.
|
|
253
309
|
* @param {string} pattern
|
|
254
310
|
* @param {object} wasm - the loaded WASM module
|
|
255
|
-
* @returns {{ name: string, content: string, shadowrootAttributes: { name: string, value: string | null }[] }[]}
|
|
311
|
+
* @returns {{ name: string, content: string, shadowrootAttributes: { name: string, value: string | null }[], hostAttributes: { name: string, value: string | null }[] }[]}
|
|
256
312
|
*/
|
|
257
313
|
function resolvePattern(pattern, wasm) {
|
|
258
314
|
const baseDir = staticPrefixDir(pattern);
|
|
@@ -266,8 +322,8 @@ function resolvePattern(pattern, wasm) {
|
|
|
266
322
|
if (globMatch(pattern, file)) {
|
|
267
323
|
const html = fs.readFileSync(file, "utf8");
|
|
268
324
|
const templates = parseFTemplates(html, file, wasm);
|
|
269
|
-
for (const { name, content, shadowrootAttributes } of templates) {
|
|
270
|
-
results.push({ name, content, shadowrootAttributes });
|
|
325
|
+
for (const { name, content, shadowrootAttributes, hostAttributes } of templates) {
|
|
326
|
+
results.push({ name, content, shadowrootAttributes, hostAttributes });
|
|
271
327
|
}
|
|
272
328
|
}
|
|
273
329
|
}
|
|
@@ -287,6 +343,7 @@ async function runBuild(args) {
|
|
|
287
343
|
Object.prototype.hasOwnProperty.call(args, "state") ||
|
|
288
344
|
Object.prototype.hasOwnProperty.call(config, "state");
|
|
289
345
|
const attributeNameStrategy = resolveOption(args, config, configDir, "attribute-name-strategy");
|
|
346
|
+
const stream = resolveBooleanOption(args, config, "stream");
|
|
290
347
|
|
|
291
348
|
if (attributeNameStrategy && attributeNameStrategy !== "none" && attributeNameStrategy !== "camelCase") {
|
|
292
349
|
process.stderr.write(
|
|
@@ -301,9 +358,11 @@ async function runBuild(args) {
|
|
|
301
358
|
// Resolve template files
|
|
302
359
|
const templatesMap = {};
|
|
303
360
|
if (!templatesArg) {
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
361
|
+
if (!stream) {
|
|
362
|
+
process.stderr.write(
|
|
363
|
+
"Warning: --templates was not provided. No custom element templates will be loaded.\n"
|
|
364
|
+
);
|
|
365
|
+
}
|
|
307
366
|
} else {
|
|
308
367
|
const patterns = templatesArg.split(",").map((p) => p.trim());
|
|
309
368
|
for (const pattern of patterns) {
|
|
@@ -313,13 +372,13 @@ async function runBuild(args) {
|
|
|
313
372
|
`Warning: No template files found for pattern "${pattern}".\n`
|
|
314
373
|
);
|
|
315
374
|
}
|
|
316
|
-
for (const { name, content, shadowrootAttributes } of matches) {
|
|
375
|
+
for (const { name, content, shadowrootAttributes, hostAttributes } of matches) {
|
|
317
376
|
if (name in templatesMap) {
|
|
318
377
|
process.stderr.write(
|
|
319
378
|
`Warning: Duplicate template name "${name}" — later file overwrites earlier.\n`
|
|
320
379
|
);
|
|
321
380
|
}
|
|
322
|
-
templatesMap[name] = { content, shadowrootAttributes };
|
|
381
|
+
templatesMap[name] = { content, shadowrootAttributes, hostAttributes };
|
|
323
382
|
}
|
|
324
383
|
}
|
|
325
384
|
}
|
|
@@ -346,6 +405,49 @@ async function runBuild(args) {
|
|
|
346
405
|
}
|
|
347
406
|
|
|
348
407
|
// Render
|
|
408
|
+
if (stream) {
|
|
409
|
+
if (typeof wasm.render_entry_with_templates !== "function") {
|
|
410
|
+
process.stderr.write(
|
|
411
|
+
"Error: Streaming requires render_entry_with_templates to be exported by the WASM module.\n"
|
|
412
|
+
);
|
|
413
|
+
process.exit(1);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
const renderedChunks = wasm.render_entry_with_templates(
|
|
417
|
+
entryContent,
|
|
418
|
+
JSON.stringify(templatesMap),
|
|
419
|
+
stateContent,
|
|
420
|
+
attributeNameStrategy || "",
|
|
421
|
+
true,
|
|
422
|
+
);
|
|
423
|
+
|
|
424
|
+
/** @type {unknown} */
|
|
425
|
+
let chunks;
|
|
426
|
+
try {
|
|
427
|
+
chunks = JSON.parse(renderedChunks);
|
|
428
|
+
} catch (e) {
|
|
429
|
+
process.stderr.write(
|
|
430
|
+
`Error: Streaming renderer returned invalid JSON: ${e.message}\n`
|
|
431
|
+
);
|
|
432
|
+
process.exit(1);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
if (
|
|
436
|
+
!Array.isArray(chunks) ||
|
|
437
|
+
chunks.some((chunk) => typeof chunk !== "string")
|
|
438
|
+
) {
|
|
439
|
+
process.stderr.write(
|
|
440
|
+
"Error: Streaming renderer must return a JSON array of strings.\n"
|
|
441
|
+
);
|
|
442
|
+
process.exit(1);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
for (const chunk of chunks) {
|
|
446
|
+
process.stdout.write(chunk);
|
|
447
|
+
}
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
|
|
349
451
|
let rendered;
|
|
350
452
|
if (Object.keys(templatesMap).length > 0) {
|
|
351
453
|
rendered = wasm.render_entry_with_templates(
|
|
@@ -375,6 +477,8 @@ async function main() {
|
|
|
375
477
|
' --entry="index.html" Entry HTML template file (default: index.html)\n' +
|
|
376
478
|
' --state="state.json" State JSON file. If omitted, rendering uses\n' +
|
|
377
479
|
' an empty state object.\n' +
|
|
480
|
+
' --stream[=true|false] Write rendered HTML chunks to stdout instead\n' +
|
|
481
|
+
' of writing an output file.\n' +
|
|
378
482
|
' --attribute-name-strategy="camelCase"\n' +
|
|
379
483
|
' Strategy for mapping attribute names to property names.\n' +
|
|
380
484
|
' "camelCase" (default) or "none".\n' +
|
package/package.json
CHANGED
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
/* tslint:disable */
|
|
2
2
|
/* eslint-disable */
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Apply the FAST code-sample escape to an HTML string.
|
|
6
|
+
*
|
|
7
|
+
* Walks the input HTML and, for every `<code>` element, escapes:
|
|
8
|
+
*
|
|
9
|
+
* * curly braces (`{` → `{`, `}` → `}`) in text content and
|
|
10
|
+
* attribute values — so the FAST template parser does not interpret
|
|
11
|
+
* `{{ ... }}` / `{ ... }` inside code samples as bindings;
|
|
12
|
+
* * angle brackets of FAST directive tags (`<f-when>`, `</f-when>`,
|
|
13
|
+
* `<f-repeat>`, `</f-repeat>`, case-insensitive) — so those directive
|
|
14
|
+
* tags surface as literal text instead of being activated as real
|
|
15
|
+
* elements. Angle brackets of any other tag (`<button>`, custom
|
|
16
|
+
* elements, …) are left untouched so they keep rendering as live DOM.
|
|
17
|
+
*
|
|
18
|
+
* Non-`<code>` regions of the input are returned verbatim. The function
|
|
19
|
+
* is idempotent — running it on an already-escaped string is a no-op.
|
|
20
|
+
*
|
|
21
|
+
* Intended for build-time tooling that needs to inject author-written
|
|
22
|
+
* HTML containing `<code>` samples into a rendered page without going
|
|
23
|
+
* through the full `render_*` pipeline.
|
|
24
|
+
*/
|
|
25
|
+
export function escape_code_samples(html: string): string;
|
|
26
|
+
|
|
4
27
|
/**
|
|
5
28
|
* Parse all `<f-template>` elements from an HTML string.
|
|
6
29
|
* Returns a JSON array of template metadata objects,
|
|
@@ -28,9 +51,11 @@ export function render(entry: string, state?: string | null): string;
|
|
|
28
51
|
* e.g. `{"my-button": "<template>...</template>"}`, or template metadata objects.
|
|
29
52
|
* `attribute_name_strategy` controls attribute-to-property mapping: `"camelCase"` (default)
|
|
30
53
|
* or `"none"`. Pass an empty string for the default.
|
|
31
|
-
*
|
|
54
|
+
* Pass `stream: true` to return a JSON array string of stream chunks; in
|
|
55
|
+
* stream mode, `templates_json` may be `{}`. Omitted or `false` stream
|
|
56
|
+
* preserves the rendered HTML behavior.
|
|
32
57
|
*/
|
|
33
|
-
export function render_entry_with_templates(entry: string, templates_json: string, state?: string | null, attribute_name_strategy?: string | null): string;
|
|
58
|
+
export function render_entry_with_templates(entry: string, templates_json: string, state?: string | null, attribute_name_strategy?: string | null, stream?: boolean | null): string;
|
|
34
59
|
|
|
35
60
|
/**
|
|
36
61
|
* Render a FAST HTML template with custom element templates and an optional JSON state string.
|
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
/* @ts-self-types="./microsoft_fast_build.d.ts" */
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Apply the FAST code-sample escape to an HTML string.
|
|
5
|
+
*
|
|
6
|
+
* Walks the input HTML and, for every `<code>` element, escapes:
|
|
7
|
+
*
|
|
8
|
+
* * curly braces (`{` → `{`, `}` → `}`) in text content and
|
|
9
|
+
* attribute values — so the FAST template parser does not interpret
|
|
10
|
+
* `{{ ... }}` / `{ ... }` inside code samples as bindings;
|
|
11
|
+
* * angle brackets of FAST directive tags (`<f-when>`, `</f-when>`,
|
|
12
|
+
* `<f-repeat>`, `</f-repeat>`, case-insensitive) — so those directive
|
|
13
|
+
* tags surface as literal text instead of being activated as real
|
|
14
|
+
* elements. Angle brackets of any other tag (`<button>`, custom
|
|
15
|
+
* elements, …) are left untouched so they keep rendering as live DOM.
|
|
16
|
+
*
|
|
17
|
+
* Non-`<code>` regions of the input are returned verbatim. The function
|
|
18
|
+
* is idempotent — running it on an already-escaped string is a no-op.
|
|
19
|
+
*
|
|
20
|
+
* Intended for build-time tooling that needs to inject author-written
|
|
21
|
+
* HTML containing `<code>` samples into a rendered page without going
|
|
22
|
+
* through the full `render_*` pipeline.
|
|
23
|
+
* @param {string} html
|
|
24
|
+
* @returns {string}
|
|
25
|
+
*/
|
|
26
|
+
function escape_code_samples(html) {
|
|
27
|
+
let deferred2_0;
|
|
28
|
+
let deferred2_1;
|
|
29
|
+
try {
|
|
30
|
+
const ptr0 = passStringToWasm0(html, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
31
|
+
const len0 = WASM_VECTOR_LEN;
|
|
32
|
+
const ret = wasm.escape_code_samples(ptr0, len0);
|
|
33
|
+
deferred2_0 = ret[0];
|
|
34
|
+
deferred2_1 = ret[1];
|
|
35
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
36
|
+
} finally {
|
|
37
|
+
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.escape_code_samples = escape_code_samples;
|
|
41
|
+
|
|
3
42
|
/**
|
|
4
43
|
* Parse all `<f-template>` elements from an HTML string.
|
|
5
44
|
* Returns a JSON array of template metadata objects,
|
|
@@ -68,14 +107,17 @@ exports.render = render;
|
|
|
68
107
|
* e.g. `{"my-button": "<template>...</template>"}`, or template metadata objects.
|
|
69
108
|
* `attribute_name_strategy` controls attribute-to-property mapping: `"camelCase"` (default)
|
|
70
109
|
* or `"none"`. Pass an empty string for the default.
|
|
71
|
-
*
|
|
110
|
+
* Pass `stream: true` to return a JSON array string of stream chunks; in
|
|
111
|
+
* stream mode, `templates_json` may be `{}`. Omitted or `false` stream
|
|
112
|
+
* preserves the rendered HTML behavior.
|
|
72
113
|
* @param {string} entry
|
|
73
114
|
* @param {string} templates_json
|
|
74
115
|
* @param {string | null} [state]
|
|
75
116
|
* @param {string | null} [attribute_name_strategy]
|
|
117
|
+
* @param {boolean | null} [stream]
|
|
76
118
|
* @returns {string}
|
|
77
119
|
*/
|
|
78
|
-
function render_entry_with_templates(entry, templates_json, state, attribute_name_strategy) {
|
|
120
|
+
function render_entry_with_templates(entry, templates_json, state, attribute_name_strategy, stream) {
|
|
79
121
|
let deferred6_0;
|
|
80
122
|
let deferred6_1;
|
|
81
123
|
try {
|
|
@@ -87,7 +129,7 @@ function render_entry_with_templates(entry, templates_json, state, attribute_nam
|
|
|
87
129
|
var len2 = WASM_VECTOR_LEN;
|
|
88
130
|
var ptr3 = isLikeNone(attribute_name_strategy) ? 0 : passStringToWasm0(attribute_name_strategy, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
89
131
|
var len3 = WASM_VECTOR_LEN;
|
|
90
|
-
const ret = wasm.render_entry_with_templates(ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3);
|
|
132
|
+
const ret = wasm.render_entry_with_templates(ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3, isLikeNone(stream) ? 0xFFFFFF : stream ? 1 : 0);
|
|
91
133
|
var ptr5 = ret[0];
|
|
92
134
|
var len5 = ret[1];
|
|
93
135
|
if (ret[3]) {
|
|
Binary file
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/* tslint:disable */
|
|
2
2
|
/* eslint-disable */
|
|
3
3
|
export const memory: WebAssembly.Memory;
|
|
4
|
+
export const escape_code_samples: (a: number, b: number) => [number, number];
|
|
4
5
|
export const parse_f_templates: (a: number, b: number) => [number, number];
|
|
5
6
|
export const render: (a: number, b: number, c: number, d: number) => [number, number, number, number];
|
|
6
|
-
export const render_entry_with_templates: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => [number, number, number, number];
|
|
7
|
+
export const render_entry_with_templates: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => [number, number, number, number];
|
|
7
8
|
export const render_with_templates: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => [number, number, number, number];
|
|
8
9
|
export const __wbindgen_externrefs: WebAssembly.Table;
|
|
9
10
|
export const __wbindgen_malloc: (a: number, b: number) => number;
|