ferrovue 0.3.0 → 0.4.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.
Files changed (85) hide show
  1. package/README.md +32 -13
  2. package/dist/attrs.d.ts +2 -52
  3. package/dist/attrs.js +18 -448
  4. package/dist/calls.d.ts +4 -0
  5. package/dist/calls.js +219 -0
  6. package/dist/children.d.ts +9 -0
  7. package/dist/children.js +273 -0
  8. package/dist/classes.d.ts +13 -0
  9. package/dist/classes.js +176 -0
  10. package/dist/cli.js +0 -17
  11. package/dist/client.js +0 -12
  12. package/dist/compiler.js +25 -90
  13. package/dist/component.js +10 -86
  14. package/dist/context.d.ts +4 -66
  15. package/dist/context.js +2 -33
  16. package/dist/diff.d.ts +0 -3
  17. package/dist/diff.js +0 -9
  18. package/dist/emitter.d.ts +0 -8
  19. package/dist/emitter.js +0 -12
  20. package/dist/expr.d.ts +0 -70
  21. package/dist/expr.js +27 -890
  22. package/dist/fallthrough.d.ts +9 -0
  23. package/dist/fallthrough.js +78 -0
  24. package/dist/fixture.d.ts +2 -1
  25. package/dist/fixture.js +37 -22
  26. package/dist/index.d.ts +2 -0
  27. package/dist/index.js +1 -0
  28. package/dist/islands.d.ts +1 -0
  29. package/dist/islands.js +1 -0
  30. package/dist/lists.d.ts +0 -11
  31. package/dist/lists.js +4 -39
  32. package/dist/loops.d.ts +3 -0
  33. package/dist/loops.js +164 -0
  34. package/dist/model.d.ts +14 -143
  35. package/dist/model.js +27 -12
  36. package/dist/narrowing.d.ts +19 -0
  37. package/dist/narrowing.js +126 -0
  38. package/dist/numbers.d.ts +8 -0
  39. package/dist/numbers.js +73 -0
  40. package/dist/parens.d.ts +0 -27
  41. package/dist/parens.js +0 -44
  42. package/dist/plugin.d.ts +84 -0
  43. package/dist/plugin.js +26 -0
  44. package/dist/plugins/i18n.d.ts +23 -0
  45. package/dist/{i18n.js → plugins/i18n.js} +76 -19
  46. package/dist/plugins/index.d.ts +2 -0
  47. package/dist/plugins/index.js +8 -0
  48. package/dist/plugins/router-link.d.ts +8 -0
  49. package/dist/{router.js → plugins/router-link.js} +19 -61
  50. package/dist/plugins/router.d.ts +42 -0
  51. package/dist/plugins/router.js +256 -0
  52. package/dist/plugins/scoped.d.ts +12 -0
  53. package/dist/plugins/scoped.js +125 -0
  54. package/dist/plugins/shared-types.d.ts +2 -0
  55. package/dist/plugins/shared-types.js +7 -0
  56. package/dist/plugins/stores.d.ts +37 -0
  57. package/dist/plugins/stores.js +377 -0
  58. package/dist/plugins/teleport.d.ts +5 -0
  59. package/dist/plugins/teleport.js +55 -0
  60. package/dist/rust.d.ts +1 -7
  61. package/dist/rust.js +38 -160
  62. package/dist/script.d.ts +0 -6
  63. package/dist/script.js +13 -128
  64. package/dist/slots.d.ts +13 -0
  65. package/dist/slots.js +160 -0
  66. package/dist/strings.d.ts +13 -0
  67. package/dist/strings.js +208 -0
  68. package/dist/styles.d.ts +14 -0
  69. package/dist/styles.js +181 -0
  70. package/dist/template.d.ts +1 -42
  71. package/dist/template.js +14 -738
  72. package/dist/testing.d.ts +1 -0
  73. package/dist/testing.js +1 -8
  74. package/dist/types.d.ts +2 -0
  75. package/dist/typescript.d.ts +0 -13
  76. package/dist/typescript.js +8 -41
  77. package/dist/vite.d.ts +1 -0
  78. package/dist/vite.js +1 -23
  79. package/package.json +7 -2
  80. package/dist/i18n.d.ts +0 -27
  81. package/dist/router.d.ts +0 -17
  82. package/dist/scoped.d.ts +0 -24
  83. package/dist/scoped.js +0 -177
  84. package/dist/stores.d.ts +0 -6
  85. package/dist/stores.js +0 -229
package/README.md CHANGED
@@ -26,7 +26,7 @@ The project has two halves:
26
26
  | | What it is | Published as |
27
27
  |---|---|---|
28
28
  | `packages/ferrovue` | The compiler and the `ferrovue` command (TypeScript, runs on Node) | npm: [`ferrovue`](https://www.npmjs.com/package/ferrovue) |
29
- | `crates/ferrovue` | The runtime the generated Rust calls: escaping, slots, islands, `<RouterLink>` matching | crates.io: [`ferrovue`](https://crates.io/crates/ferrovue) ([API docs](https://docs.rs/ferrovue)) |
29
+ | `crates/ferrovue` | The runtime the generated Rust calls: escaping, slots, islands, `<RouterLink>` matching. The router, vue-i18n and the escaping and number primitives they share are crates of their own (`crates/ferrovue-router`, `ferrovue-i18n`, `ferrovue-core`), which `ferrovue` re-exports | crates.io: [`ferrovue`](https://crates.io/crates/ferrovue) ([API docs](https://docs.rs/ferrovue)) |
30
30
 
31
31
  ## Quick start
32
32
 
@@ -118,6 +118,10 @@ With `routes` configured, the generated `route_table::router()` builds the route
118
118
  each request's location with `router.at(path)` and pass the result to the components that take a
119
119
  route.
120
120
 
121
+ The router and vue-i18n are features of the crate, `router` and `i18n`, both on by default. An
122
+ application with neither routes nor translations can leave them out, and build neither
123
+ `ferrovue-router` nor `ferrovue-i18n`: `ferrovue = { version = "0.4", default-features = false }`.
124
+
121
125
  With the `maud` feature, `ferrovue::Html` implements `maud::Render`, so `(greeting::html(&props))` can go
122
126
  straight into a `maud::html!` page.
123
127
 
@@ -248,7 +252,7 @@ gives the ids that other component inherits.
248
252
  String methods count as JavaScript counts: in UTF-16 code units, so `"🦀".length` is 2 and
249
253
  `"🦀 crab".slice(3)` is `"crab"`. Strings are ordered by code unit too, which puts every character
250
254
  from U+E000 to U+FFFF after one beyond U+FFFF. Each runtime routine is held to vectors recorded from
251
- JavaScript (`crates/ferrovue/tests/vectors/`).
255
+ JavaScript (`crates/*/tests/vectors/`).
252
256
 
253
257
  A JavaScript string can hold half of a surrogate pair — `"🦀".slice(0, 1)`, `.charAt(1)`,
254
258
  `.split("")` — and a Rust string cannot. ferrovue writes U+FFFD in its place, which is exactly what
@@ -319,12 +323,12 @@ data_list::render(&mut page, &props, data_list::Slots { row: Some(&row), ..Defau
319
323
 
320
324
  ### Hydrating islands
321
325
 
322
- `mountIslands` from `ferrovue/client` hydrates every `data-island` element on the page with the
326
+ `mountIslands` from `ferrovue` hydrates every `data-island` element on the page with the
323
327
  component of that name, from the props the server wrote. With the Vite plugin, `ferrovue/islands`
324
328
  gives it every island there is, so nothing has to be listed by hand:
325
329
 
326
330
  ```ts
327
- import { hydrateState, mountIslands } from "ferrovue/client";
331
+ import { hydrateState, mountIslands } from "ferrovue";
328
332
  import islands from "ferrovue/islands"; // written by `ferrovue()` from `ferrovue/vite`
329
333
 
330
334
  hydrateState(pinia);
@@ -355,7 +359,7 @@ ferrovue::state_script_into(&mut page, "__pinia", &stores); // a <script type=
355
359
  ```
356
360
 
357
361
  ```ts
358
- import { hydrateState } from "ferrovue/client";
362
+ import { hydrateState } from "ferrovue";
359
363
  hydrateState(pinia); // before app.mount(): every store starts from what the server rendered
360
364
  ```
361
365
 
@@ -428,18 +432,33 @@ ferrovue version.
428
432
  ## Repository layout
429
433
 
430
434
  ```text
431
- crates/ferrovue/ the Rust runtime crate
432
- src/ runtime (escaping, JS numbers, router, i18n, teleports) + unit tests
435
+ crates/ferrovue/ the Rust runtime crate, which generated code calls
436
+ src/ a module per part (`Html`, slots, class and style, the state script,
437
+ strings, teleports, fallthrough attributes), each module's unit tests
438
+ beside it in <module>/tests.rs; lib.rs re-exports them all, and the
439
+ three crates below
433
440
  tests/conformance/ components, fixtures, recorded HTML, generated Rust
434
- tests/vectors/ vectors recorded from JavaScript, vue-router and vue-i18n
441
+ tests/vectors/ vectors recorded from JavaScript and Vue
435
442
  tests/properties.rs property-based tests of the runtime
436
443
  benches/ criterion benchmarks of generated renderers (see Performance)
444
+ crates/ferrovue-core/ escaping and JavaScript's numbers, which the other crates share
445
+ tests/vectors/ vectors recorded from escapeHtml, String(n), Math and toFixed
446
+ crates/ferrovue-router/ vue-router's matching and links (the `router` feature)
447
+ tests/vectors/ vectors recorded from vue-router
448
+ crates/ferrovue-i18n/ vue-i18n's t() (the `i18n` feature)
437
449
  packages/ferrovue/ the compiler (npm package)
438
- src/compiler.ts the API: `generate`, `write`
439
- src/script.ts, template.ts, expr.ts, attrs.ts
440
- <script setup>, the compiled template, expressions, class/style
441
- src/router.ts, stores.ts, i18n.ts
442
- vue-router, Pinia and vue-i18n
450
+ src/index.ts `ferrovue`: the browser API, `mountIslands`, `hydrateState` and the types
451
+ src/compiler.ts `ferrovue/compiler`: `generate`, `write`
452
+ src/component.ts, script.ts, typescript.ts
453
+ a `.vue` file read, <script setup>, TypeScript types
454
+ src/template.ts, children.ts, slots.ts, loops.ts
455
+ the compiled template: statements, child components, slots, v-for
456
+ src/expr.ts, strings.ts, numbers.ts, narrowing.ts, calls.ts, lists.ts
457
+ expressions: operators, strings, numbers, narrowing, calls, lists
458
+ src/attrs.ts, classes.ts, styles.ts, fallthrough.ts
459
+ attributes, class and style, attributes a parent passes on
460
+ src/plugin.ts the plugin interface (see CONTRIBUTING.md)
461
+ src/plugins/ vue-router, Pinia, vue-i18n, scoped styles, <Teleport>, shared types
443
462
  src/rust.ts, emitter.ts the Rust source written out
444
463
  src/cli.ts, vite.ts the `ferrovue` command and the Vite plugin
445
464
  src/client.ts browser-side helpers: `mountIslands`, `hydrateState`
package/dist/attrs.d.ts CHANGED
@@ -1,67 +1,17 @@
1
1
  import { type N, type Scope, type Val } from "./model.ts";
2
2
  import { Emitter } from "./emitter.ts";
3
- /** `toDisplayString`, escaped. */
3
+ export declare function display(e: Emitter, v: Val): boolean;
4
4
  export declare function interpolate(e: Emitter, v: Val): void;
5
- /** The value half of `key="value"`, escaped. */
6
5
  export declare function attrValue(e: Emitter, v: Val): void;
7
- /** `ssrRenderAttr(key, value)`: absent for null/undefined, `key="value"` for anything else. */
8
6
  export declare function renderAttr(s: Scope, e: Emitter, key: string, v: Val, n: N): void;
9
- /** `ssrRenderDynamicAttr(key, value)`: as `renderAttr`, but a boolean attribute is present or
10
- * absent, and an empty string renders the name alone. */
11
7
  export declare function renderDynamicAttr(s: Scope, e: Emitter, key: string, v: Val, n: N): void;
12
- /** One item of a class list once it is flattened: literal text, known now, or a Rust `&str`
13
- * expression evaluated at run time — empty when the item contributes nothing. */
14
- export type ClassItem = {
15
- lit: string;
16
- } | {
17
- code: string;
18
- };
19
- /** `normalizeClass`'s view of a class binding, flattened: a string, an array of items, an object
20
- * of `name: condition`, `cond && "name"`, `cond ? "a" : null`. Every item is trimmed and the empty
21
- * ones dropped before they are joined with one space, which is what `class_into` does too, so an
22
- * object's keys become items of their own. */
23
- export declare function classItems(s: Scope, n: N): ClassItem[];
24
- /** `ssrRenderClass(value)`: normalised, then escaped. `after` says a class was already written. */
25
- export declare function renderClass(s: Scope, e: Emitter, n: N, after?: boolean): void;
26
8
  export declare const IGNORED_PROPS: Set<string>;
27
- /** `ssrGetDirectiveProps(_ctx, dir)`: a custom directive's server props, which are none for a
28
- * directive the configuration declares client-only. `false` when `n` is not such a call. */
29
9
  export declare function directiveProps(s: Scope, n: N): boolean;
30
- /** Whether `n` is the root's `_attrs`: what a parent passes, then the scope ids. */
31
10
  export declare function isAttrs(n: N): boolean;
32
- /** Whether `n` is `$attrs` — `_ctx.$attrs`, or a `useAttrs()` binding — which a component whose
33
- * root is another's would find holding scope ids as well. */
34
11
  export declare function dollarAttrs(s: Scope, n: N): boolean;
35
- /** The parts `_mergeProps(…)` merges, or the one object that is not merged. */
36
12
  export declare function mergedParts(n: N): N[];
37
- /** `ssrRenderAttrs(obj)`, key by key in the object's order, and the inherited scope ids where the
38
- * root's `_attrs` is merged in. When a parent may pass attributes, which only the run time knows,
39
- * `$attrs` and the root's `_attrs` are merged with the element's own by `fv::attrs_into` — but only
40
- * when some were passed: with none, the element is written as it is without. */
41
13
  export declare function renderAttrs(s: Scope, e: Emitter, n: N): void;
42
- /** `mergeProps(a, _attrs, b, …)` as one object literal, without `_attrs` and `$attrs`, which hold
43
- * what only the run time knows. Of the rest, `class` and `style` values are merged as an array —
44
- * unless a class equals the one so far, which Vue then keeps once — and any other key keeps the
45
- * place it first had with the last value given. */
46
14
  export declare function mergeProps(s: Scope, n: N): N;
47
- /** The attributes of an object literal as `fv::Attr` entries, `("name", value)`, for a merge at run
48
- * time: given to a child component (`vnode`), whose virtual node normalises a class array or object
49
- * to a string, or an element's own (`own`), which `mergeProps` keeps as an object. */
50
15
  export declare function attrEntries(s: Scope, obj: N, side: "vnode" | "own"): string[];
51
- /** One attribute's value as an `fv::Attr`. */
52
16
  export declare function attrOf(s: Scope, key: string, n: N, side: "vnode" | "own"): string;
53
- /** One object of a style binding, and the run-time condition under which it is part of it. */
54
- export interface StyleItem {
55
- cond: string | null;
56
- entries: {
57
- key: string;
58
- css: string;
59
- value: N;
60
- }[];
61
- }
62
- /** The objects a style binding merges, in order: an object literal, a static `style` the compiler
63
- * parsed, `v-show`'s `cond ? null : { display: "none" }`, and arrays of those. */
64
- export declare function styleItems(s: Scope, n: N, when: string | null): StyleItem[];
65
- /** `ssrRenderStyle(value)`: a string as it is, or the objects merged — each property where it first
66
- * appears, with the last value given — and written `name:value;`, all escaped. */
67
- export declare function renderStyle(s: Scope, e: Emitter, n: N): void;
17
+ export declare function valueAttr(s: Scope, v: Val, n: N): string;