@mark1russell7/render-biblo 0.0.0-stage → 0.2.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mark Russell
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,44 @@
1
- # Temporary Holding Version
1
+ # @mark1russell7/render-biblo
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ [![npm](https://img.shields.io/npm/v/@mark1russell7/render-biblo?color=2346c4)](https://www.npmjs.com/package/@mark1russell7/render-biblo) [![CI](https://github.com/mark1russell7/render/actions/workflows/ci.yml/badge.svg)](https://github.com/mark1russell7/render/actions/workflows/ci.yml) [![license: MIT](https://img.shields.io/badge/license-MIT-2346c4)](https://github.com/mark1russell7/render/blob/main/LICENSE)
4
+
5
+ The classes of render. A class is a template of nodes: cells with expressions, and methods. An instance is an ID and a scope. A change of a class reaches each instance that still follows it.
6
+
7
+ ```sh
8
+ npm i @mark1russell7/render-biblo @mark1russell7/render-node @mark1russell7/render-dsl
9
+ ```
10
+
11
+ ```ts
12
+ import { app, lit, ref } from "@mark1russell7/render-dsl";
13
+ import { biblo, classNodeOps, componentClass, instantiate, registerClass, updateClass } from "@mark1russell7/render-biblo";
14
+ import { nodeStore, readValue } from "@mark1russell7/render-node";
15
+
16
+ const ops = { concat: (...parts: unknown[]) => parts.join("") };
17
+ const badge = (label: string) =>
18
+ componentClass("Badge", {
19
+ label: { expr: lit(label) },
20
+ text: { expr: app("concat", lit("[ "), ref("self", "label"), lit(" ]")) },
21
+ });
22
+
23
+ const b = biblo();
24
+ const store = nodeStore({ nodeOps: classNodeOps(b), ops });
25
+ registerClass(b, badge("star"));
26
+ const inst = instantiate(b, store, "Badge");
27
+ const text = store.nodes.get(inst.id)!.slots.get("text")!;
28
+ readValue(store, text); // { tag: "some", value: "[ star ]" }
29
+
30
+ updateClass(b, store, badge("planet"));
31
+ readValue(store, text); // { tag: "some", value: "[ planet ]" }
32
+ ```
33
+
34
+ Traits give methods to each class with a set of cells. The fingerprint of a class is a product of primes, thus the match of a trait is one division.
35
+
36
+ A class is data: each expression is a [coeval](https://github.com/mark1russell7/coeval) document, thus a class from JSON text registers as it is. An instance scopes its cells with `mapRefs` of the kernel: `self` and `parent` become node IDs, and the parameters of a `fn` stay. `updateClass` compares the expressions with `docEquals`.
37
+
38
+ ## More
39
+
40
+ - [The site](https://mark1russell7.github.io/render/): the guide, live demos and the viewer.
41
+ - [The API reference](https://mark1russell7.github.io/render/reference/api/): the exports of each package.
42
+ - [The repository](https://github.com/mark1russell7/render): the source, the tests and the review of each known defect.
43
+
44
+ Each package of render is ESM, has TypeScript declarations, and works in Node.js 22.12 or later and in browsers. The license is MIT.
@@ -0,0 +1,209 @@
1
+ import { Expr } from "@mark1russell7/render-dsl";
2
+ import { NodeId, NodeOps, NodeStore } from "@mark1russell7/render-node";
3
+ //#region src/class.d.ts
4
+ /**
5
+ * A cell template of a class. It has an expression (a coeval document), and optionally a type: the name of
6
+ * another class. A typed cell holds an instance of that class, thus the class level knows the paths through its children.
7
+ */
8
+ type CellDef = {
9
+ readonly expr: Expr;
10
+ /** The class of the child instance that this cell holds. */
11
+ readonly type?: string | undefined;
12
+ /**
13
+ * The bindings of a typed cell: expressions that replace cells of the child.
14
+ * They are in the scope of the child. For example, `{ value: ref("parent", "key") }` binds the cell `value`
15
+ * of the child to the cell `key` of this instance.
16
+ */
17
+ readonly bindings?: Readonly<Record<string, Expr>> | undefined;
18
+ };
19
+ /**
20
+ * A class is a template. Instances share it, and nothing copies it.
21
+ *
22
+ * - `cells`: the reactive structure, which is the data that each instance holds.
23
+ * - `methods`: the behavior. The extends chain resolves them, and the most specific method wins.
24
+ * - `extends`: the parent class. Cells and methods both resolve through it.
25
+ *
26
+ * The values of `methods` are opaque. Each layer reads the method names that it knows, for example
27
+ * `render` for splay and `splash` for the node engine. The class `Top` gives the defaults. An expression method is
28
+ * a coeval document, thus a class is data from end to end.
29
+ */
30
+ type ComponentClass = {
31
+ readonly name: string;
32
+ readonly cells: Readonly<Record<string, CellDef>>;
33
+ readonly extends?: string | undefined;
34
+ readonly methods?: Readonly<Record<string, unknown>> | undefined;
35
+ };
36
+ /** This function makes a class. */
37
+ export declare const componentClass: (name: string, cells: Readonly<Record<string, CellDef>>, ext?: string, methods?: Readonly<Record<string, unknown>>) => ComponentClass;
38
+ /**
39
+ * This function gives a copy of a class with more cells and methods. The copy keeps the name.
40
+ * An override with the name of an existing cell or method replaces it.
41
+ */
42
+ export declare const extendClass: (base: ComponentClass, overrides: {
43
+ readonly cells?: Readonly<Record<string, CellDef>>;
44
+ readonly methods?: Readonly<Record<string, unknown>>;
45
+ }) => ComponentClass;
46
+ //#endregion
47
+ //#region src/instance.d.ts
48
+ /** The identity of an instance. It is also the ID of the root node of the instance. */
49
+ type InstanceId = string;
50
+ /**
51
+ * The scope of an instance: the names that its expressions can use.
52
+ * `ref("self", ...)` reads this instance, and `ref("parent", ...)` reads the parent instance.
53
+ */
54
+ type Scope = {
55
+ readonly self: InstanceId;
56
+ readonly parent: InstanceId | undefined;
57
+ /** The child instances, in order. Splay renders them, and dehydrate reads them. */
58
+ readonly children: readonly InstanceId[];
59
+ };
60
+ /**
61
+ * An instance is small: an ID, a class name and a scope. It copies no data of its class.
62
+ * The values of its cells are in the node store, in the slots of its root node.
63
+ */
64
+ type Instance = {
65
+ readonly id: InstanceId;
66
+ readonly classRef: string;
67
+ readonly scope: Scope;
68
+ };
69
+ //#endregion
70
+ //#region src/traits.d.ts
71
+ /**
72
+ * Structural traits with prime fingerprints: a granular polymorphism.
73
+ *
74
+ * Each atomic feature of a class gets a unique prime: a cell (`value`), or a typed cell (`kid:Point`).
75
+ * The fingerprint of a class is the product of the primes of its features. The product does not depend on
76
+ * the order of the features, thus two classes with the same features have the same fingerprint.
77
+ *
78
+ * A trait gives methods to each class that has the features of its list. Then the fingerprint of the trait
79
+ * divides the fingerprint of the class. Among the traits that apply, only the most specific ones count
80
+ * (a trait whose fingerprint divides the fingerprint of another applicable trait is dominated). When two of
81
+ * them give the same method, the method is ambiguous: no trait gives it, and the ambiguity is visible.
82
+ */
83
+ /** A trait: methods for each class that has the cells of its list. */
84
+ type Trait = {
85
+ readonly name: string;
86
+ /** The features that a class must have: a cell name (`label`), or a typed cell (`kid:Point`). */
87
+ readonly requires: readonly string[];
88
+ readonly methods: Readonly<Record<string, unknown>>;
89
+ };
90
+ /** The traits that apply to a class, and the names of the methods that two of them give. */
91
+ type TraitResolution = {
92
+ readonly applied: readonly Trait[];
93
+ readonly ambiguous: readonly string[];
94
+ };
95
+ /** This function gives the features of an item of the list of a trait: `kid:Point` is the cell `kid` with the type `Point`. */
96
+ export declare const requirementAtoms: (requirement: string) => string[];
97
+ //#endregion
98
+ //#region src/registry.d.ts
99
+ /**
100
+ * The biblo is the class registry and the instance store.
101
+ *
102
+ * Classes are shared templates. Instances are small (an ID and a scope), and the values of their cells
103
+ * are in the node store. A trait gives methods to each class that has the cells of its list.
104
+ * Change a biblo only through its functions, for example `registerClass`, `registerTrait` and `instantiate`.
105
+ */
106
+ type Biblo = {
107
+ readonly classes: ReadonlyMap<string, ComponentClass>;
108
+ readonly instances: ReadonlyMap<InstanceId, Instance>;
109
+ readonly traits: ReadonlyMap<string, Trait>;
110
+ };
111
+ /** This function makes an empty biblo. */
112
+ export declare const biblo: () => Biblo;
113
+ /**
114
+ * This function gives an independent copy of a biblo: the same classes, traits, instances and counters. The
115
+ * classes and the traits are immutable, thus the copy shares them. Pair the copy with a copy of its store
116
+ * (`forkStore`), with the class semantics of the copy (`classNodeOps`).
117
+ */
118
+ export declare const forkBiblo: (b: Biblo) => Biblo;
119
+ /**
120
+ * This function registers a class, or replaces the class with the same name. The live instances do not change.
121
+ * The expressions of the class are coeval documents, thus a class from JSON text registers as it is.
122
+ */
123
+ export declare const registerClass: (b: Biblo, cls: ComponentClass) => void;
124
+ /** This function registers a trait, or replaces the trait with the same name. The live instances use it at once. */
125
+ export declare const registerTrait: (b: Biblo, trait: Trait) => void;
126
+ /** This function removes a trait. */
127
+ export declare const unregisterTrait: (b: Biblo, name: string) => void;
128
+ /**
129
+ * This function renames a class. Its subclasses, the typed cells that use it and its live instances use the
130
+ * new name. A trait whose list has a typed cell of the class (`kid:Point`) also uses the new name. The function
131
+ * does nothing and gives `false` when the class is missing or the new name is in use.
132
+ */
133
+ export declare const renameClass: (b: Biblo, from: string, to: string) => boolean;
134
+ /** This function registers each class of a list, in order. */
135
+ export declare const registerClasses: (b: Biblo, classes: readonly ComponentClass[]) => void;
136
+ /** This function gives all cell templates of a class through its extends chain. A subclass cell replaces a parent cell. */
137
+ export declare const resolveCells: (b: Biblo, className: string) => Readonly<Record<string, CellDef>>;
138
+ /** This function gives the fingerprint of a class: the product of the primes of its cells and typed cells. */
139
+ export declare const classFingerprint: (b: Biblo, className: string) => bigint;
140
+ /** This function gives the prime of an atomic feature, for example `cell:value`. */
141
+ export declare const primeOf: (b: Biblo, atom: string) => bigint;
142
+ /** This function gives the traits that apply to a class (the most specific ones), and the ambiguous method names. */
143
+ export declare const resolveTraits: (b: Biblo, className: string) => TraitResolution;
144
+ /**
145
+ * This function gives all methods of a class. There are three layers, from the lowest to the highest.
146
+ * The first layer is the root of the extends chain, for example `Top`. The second layer is the traits that apply.
147
+ * The third layer is the other classes of the chain, to the class itself.
148
+ *
149
+ * Thus a trait changes the defaults of the root, and a class changes a trait.
150
+ * A method that two traits give is ambiguous: no trait gives it.
151
+ */
152
+ export declare const resolveMethods: (b: Biblo, className: string) => Readonly<Record<string, unknown>>;
153
+ /**
154
+ * This function makes an instance of a class. The class is not copied: the instance gets an ID, a scope,
155
+ * and a root node with one slot for each cell. All nodes are evaluated before the end of the function.
156
+ *
157
+ * - A typed cell becomes a child instance of its class, with the bindings of the cell. The slot of the cell
158
+ * holds the root node of the child, thus `ref("self", "kid", "value")` reads a cell of the child.
159
+ * A typed cell whose class is already above it on the chain of typed cells is a plain cell.
160
+ * - `bindings` replace cells of this instance. They are in the scope of this instance. A binding for a typed
161
+ * cell makes it a plain cell with the bound expression.
162
+ * - An unknown class gives an instance with no cells.
163
+ */
164
+ export declare const instantiate: (b: Biblo, store: NodeStore, className: string, parentId?: InstanceId, bindings?: Readonly<Record<string, Expr>>) => Instance;
165
+ /**
166
+ * This function moves a child instance to a position in the children of its parent. A position past the end
167
+ * moves it to the end. It does nothing for an instance without a parent.
168
+ */
169
+ export declare const moveChild: (b: Biblo, childId: InstanceId, index: number) => void;
170
+ /**
171
+ * This function destroys an instance, the inverse of `instantiate`. It destroys the children first, then
172
+ * removes the nodes of the instance and detaches it from its parent. The readers of the removed nodes
173
+ * become `none` in one epoch.
174
+ */
175
+ export declare const destroyInstance: (b: Biblo, store: NodeStore, instanceId: InstanceId) => void;
176
+ /**
177
+ * This function registers a new version of a class and updates the live instances: the class is a template,
178
+ * and the instances follow it. The update applies to each instance of the class and of its subclasses.
179
+ * When a cell of the resolved class changes, the instance cell changes too, if it still has the old expression.
180
+ *
181
+ * - A cell with an edit of its own keeps it. A cell that a binding gave keeps the binding.
182
+ * - A new cell is added, and a removed cell is removed. A shared cell node only loses its slot.
183
+ * - A typed cell that changes its type gets a new child instance. A change of its bindings reaches the cells of
184
+ * the child that still follow the old bindings. A change between a typed cell and a plain cell replaces the cell.
185
+ *
186
+ * All changes evaluate in one epoch.
187
+ */
188
+ export declare const updateClass: (b: Biblo, store: NodeStore, cls: ComponentClass) => void;
189
+ /**
190
+ * This function gives the instance that owns a node. For an instance root, it is the node itself.
191
+ * For another node, it is the nearest owner up the slot tree. A node outside all instances gives `undefined`.
192
+ */
193
+ export declare const ownerOf: (b: Biblo, store: NodeStore, nodeId: NodeId) => InstanceId | undefined;
194
+ //#endregion
195
+ //#region src/nodeops.d.ts
196
+ /**
197
+ * This function makes the class-level reactive semantics (the defaults of `Top`).
198
+ *
199
+ * The ops of the result use the `splash`, `flow`, `deref` and `targets` methods of the class that owns each node.
200
+ * The extends chain resolves them, thus the defaults of `Top` apply to all classes, and a class can
201
+ * change them. A node without an owner, or a class without the method, uses `fallback`.
202
+ *
203
+ * The node layer knows nothing of biblo. This factory is how the class layer gives semantics to the
204
+ * node layer without a dependency in the wrong direction. Give the result to `nodeStore`.
205
+ */
206
+ export declare const classNodeOps: (b: Biblo, fallback?: NodeOps) => NodeOps;
207
+ //#endregion
208
+ export type { Biblo, CellDef, ComponentClass, Instance, InstanceId, Scope, Trait, TraitResolution };
209
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/class.ts","../src/instance.ts","../src/traits.ts","../src/registry.ts","../src/nodeops.ts"],"mappings":";;;;;;;KAMY;WACD,MAAM;;WAEN;;;;;;WAMA,WAAW,SAAS,eAAe;;;;;;;;;;;;;KAclC;WACD;WACA,OAAO,SAAS,eAAe;WAC/B;WACA,UAAU,SAAS;;;qBAIjB,iBACX,cACA,OAAO,SAAS,eAAe,WAC/B,cACA,UAAU,SAAS,6BAClB;;;;;qBAWU,cACX,MAAM,gBACN;WACW,QAAQ,SAAS,eAAe;WAChC,UAAU,SAAS;MAE7B;;;;KC1DS;;;;;KAMA;WACD,MAAM;WACN,QAAQ;;WAER,mBAAmB;;;;;;KAOlB;WACD,IAAI;WACJ;WACA,OAAO;;;;;;;;;;;;;;;;;KCPN;WACD;;WAEA;WACA,SAAS,SAAS;;;KAIjB;WACD,kBAAkB;WAClB;;;qBAkDE,mBAAoB;;;;;;;;;;KCzDrB;WACD,SAAS,oBAAoB;WAC7B,WAAW,YAAY,YAAY;WACnC,QAAQ,oBAAoB;;;qBA+B1B,aAAY;;;;;;qBAoBZ,YAAa,GAAG,UAAQ;;;;;qBA+BxB,gBAAiB,GAAG,OAAO,KAAK;;qBAOhC,gBAAiB,GAAG,OAAO,OAAO;;qBAOlC,kBAAmB,GAAG,OAAO;;;;;;qBAW7B,cAAe,GAAG,OAAO,cAAc;;qBAiCvC,kBAAmB,GAAG,OAAO,kBAAkB;;qBAiC/C,eAAgB,GAAG,OAAO,sBAAoB,SAAS,eAAe;;qBAWtE,mBAAoB,GAAG,OAAO;;qBAU9B,UAAW,GAAG,OAAO;;qBAGrB,gBAAiB,GAAG,OAAO,sBAAoB;;;;;;;;;qBAkB/C,iBAAkB,GAAG,OAAO,sBAAoB,SAAS;;;;;;;;;;;;qBAuGzD,cACX,GAAG,OACH,OAAO,WACP,mBACA,WAAW,YACX,WAAW,SAAS,eAAe,WAClC;;;;;qBAqBU,YAAa,GAAG,OAAO,SAAS,YAAY;;;;;;qBAiB5C,kBAAmB,GAAG,OAAO,OAAO,WAAW,YAAY;;;;;;;;;;;;;qBAuE3D,cAAe,GAAG,OAAO,OAAO,WAAW,KAAK;;;;;qBAsDhD,UAAW,GAAG,OAAO,OAAO,WAAW,QAAQ,WAAS;;;;;;;;;;;;;qBC5exD,eAAgB,GAAG,OAAO,WAAU,YAAuB"}