@dtmd/temper 0.0.7 → 0.0.9
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 +84 -53
- package/bin/temper.js +0 -0
- package/dist/src/assembly.d.ts +15 -1
- package/dist/src/assembly.js +2 -1
- package/dist/src/builtins.d.ts +682 -66
- package/dist/src/builtins.js +664 -92
- package/dist/src/claude-code.d.ts +2 -2
- package/dist/src/claude-code.js +1 -1
- package/dist/src/contract.d.ts +180 -29
- package/dist/src/contract.js +128 -15
- package/dist/src/declarations.d.ts +72 -5
- package/dist/src/declarations.js +389 -107
- package/dist/src/dial.d.ts +75 -0
- package/dist/src/dial.js +82 -0
- package/dist/src/emit.d.ts +35 -1
- package/dist/src/emit.js +369 -63
- package/dist/src/generated/AssemblyFactRow.d.ts +2 -2
- package/dist/src/generated/BoundRow.d.ts +2 -2
- package/dist/src/generated/ClauseRow.d.ts +73 -3
- package/dist/src/generated/CollectionAddressRow.d.ts +4 -0
- package/dist/src/generated/EmbeddedMember.d.ts +3 -3
- package/dist/src/generated/FeatureValue.d.ts +2 -2
- package/dist/src/generated/Features.d.ts +52 -3
- package/dist/src/generated/KindFactRow.d.ts +24 -7
- package/dist/src/generated/MentionRow.d.ts +5 -3
- package/dist/src/generated/NestedMemberRow.d.ts +32 -0
- package/dist/src/generated/PayloadMember.d.ts +6 -0
- package/dist/src/generated/RequirementRow.d.ts +4 -2
- package/dist/src/generated/SatisfiesRow.d.ts +2 -1
- package/dist/src/generated/Shape.d.ts +15 -0
- package/dist/src/generated/Shape.js +2 -0
- package/dist/src/generated/TemplateRow.d.ts +24 -0
- package/dist/src/generated/TemplateRow.js +2 -0
- package/dist/src/generated/ValueType.d.ts +11 -2
- package/dist/src/generated/Verifier.d.ts +20 -0
- package/dist/src/generated/Verifier.js +2 -0
- package/dist/src/generated/index.d.ts +3 -0
- package/dist/src/index.d.ts +8 -8
- package/dist/src/index.js +3 -3
- package/dist/src/kind.d.ts +135 -29
- package/dist/src/kind.js +35 -8
- package/dist/src/prose.d.ts +81 -25
- package/dist/src/prose.js +91 -21
- package/package.json +4 -4
package/dist/src/prose.js
CHANGED
|
@@ -1,14 +1,54 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Prose — three constructors, one field type. A member's words are data the
|
|
3
3
|
* member declares: `file()` for a document that keeps its medium, `` text`…` ``
|
|
4
|
-
* for short inline prose, `blocks()` for
|
|
5
|
-
*
|
|
4
|
+
* for short inline prose, `blocks()` for a composed body that interleaves verbatim
|
|
5
|
+
* prose spans with embedded-member values in authored order. Whatever
|
|
6
|
+
* the constructor, the words land byte-identical to their authored text.
|
|
6
7
|
* Interpolations in `` text`…` `` are references, two intents apart: a **mention**
|
|
7
8
|
* (a {@link Mentionable}) is a declared one-way edge that moves no content, and an
|
|
8
9
|
* **include** (an {@link Include}) pulls the target file's bytes into the host's emitted
|
|
9
|
-
* projection. Both are authored per word and resolution-checked at emit, never mined
|
|
10
|
-
* (law 8).
|
|
10
|
+
* projection. Both are authored per word and resolution-checked at emit, never mined.
|
|
11
11
|
*/
|
|
12
|
+
/**
|
|
13
|
+
* Spell a top-level member as the {@link Mentionable} a mention carries: its
|
|
14
|
+
* `kind:name` address, its bare name the display text — the convention every
|
|
15
|
+
* corpus repeats to cite a member from prose, captured once here.
|
|
16
|
+
*/
|
|
17
|
+
export function mentionOf(member) {
|
|
18
|
+
return { address: `${member.kind}:${member.name}`, display: member.name };
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Whether a mention's unresolved address **defers to the gate** rather than refusing at
|
|
22
|
+
* emit: a top-level `kind:name` address whose kind is one the program declares at a
|
|
23
|
+
* discovery locus (an `at`-locus kind) may name a member discovered on disk, so `check`
|
|
24
|
+
* owns the verdict. An embedded leaf address (a `<host>/<kind>/<key>` form, carrying a
|
|
25
|
+
* `/`), a bare requirement name (no `:`), or a kind the program does not declare has no
|
|
26
|
+
* discovery locus and stays a dangling refusal.
|
|
27
|
+
*/
|
|
28
|
+
export function defersToGate(address, deferrableKinds) {
|
|
29
|
+
if (address.includes("/"))
|
|
30
|
+
return false;
|
|
31
|
+
const colon = address.indexOf(":");
|
|
32
|
+
return colon > 0 && deferrableKinds.has(address.slice(0, colon));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Refuse a mention whose address neither resolves against the scope's `mentionable`
|
|
36
|
+
* set nor defers to the gate ({@link defersToGate}) — the one dangling-mention refusal,
|
|
37
|
+
* shared by a member-level `Text` body, a composed body's prose span, and an embedded
|
|
38
|
+
* `Text` leaf. `context` prefixes the error so it names the host.
|
|
39
|
+
*
|
|
40
|
+
* # Throws
|
|
41
|
+
* If a mention names no declared value and its address has no discovery locus.
|
|
42
|
+
*/
|
|
43
|
+
export function checkMentions(mentions, scope, context) {
|
|
44
|
+
for (const mention of mentions) {
|
|
45
|
+
const { address } = mention.target;
|
|
46
|
+
if (!scope.mentionable.has(address) && !defersToGate(address, scope.deferrableKinds)) {
|
|
47
|
+
throw new Error(`${context}: mention of \`${address}\` resolves to no declared value — ` +
|
|
48
|
+
`a mention cannot dangle (specs/model/contract.md).`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
12
52
|
/** Whether an interpolation target is an include rather than a mention. */
|
|
13
53
|
function isInclude(reference) {
|
|
14
54
|
return reference.kind === "include";
|
|
@@ -40,8 +80,8 @@ function dedent(text) {
|
|
|
40
80
|
.replace(/\n[ \t]*$/, "\n");
|
|
41
81
|
}
|
|
42
82
|
/**
|
|
43
|
-
* Declare a document whose medium is preserved — read in whole at emit
|
|
44
|
-
*
|
|
83
|
+
* Declare a document whose medium is preserved — read in whole at emit.
|
|
84
|
+
* `moduleUrl` is the declaring module's own `import.meta.url`,
|
|
45
85
|
* so `path` resolves relative to that module, never the process cwd:
|
|
46
86
|
* `file(import.meta.url, "./long.md")`.
|
|
47
87
|
*/
|
|
@@ -52,7 +92,7 @@ export function file(moduleUrl, path) {
|
|
|
52
92
|
* The inline dedenting prose constructor. Interpolate {@link Reference} values — a
|
|
53
93
|
* {@link Mentionable} is a mention (moves no content), an {@link Include} pulls the
|
|
54
94
|
* target's bytes in; either is opt-in per word, and plain prose with zero references is
|
|
55
|
-
* fully legal forever
|
|
95
|
+
* fully legal forever.
|
|
56
96
|
*
|
|
57
97
|
* # Throws
|
|
58
98
|
* If an authored chunk carries {@link MENTION_SLOT} or {@link INCLUDE_SLOT} — the markers
|
|
@@ -89,14 +129,48 @@ export function text(strings, ...targets) {
|
|
|
89
129
|
export function include(moduleUrl, path) {
|
|
90
130
|
return { kind: "include", path, moduleUrl };
|
|
91
131
|
}
|
|
92
|
-
/**
|
|
132
|
+
/**
|
|
133
|
+
* Compose a member's body from ordered children: verbatim prose spans
|
|
134
|
+
* ({@link text}) and embedded-member values interleaved in authored order. A prose
|
|
135
|
+
* span rides as prose — no wrapper member is minted to carry a narrative.
|
|
136
|
+
*
|
|
137
|
+
* # Throws
|
|
138
|
+
* If a child is a {@link File} — the parameter type excludes one, so only a JS or
|
|
139
|
+
* cast caller arrives here, and the alternative is a raw crash downstream on the
|
|
140
|
+
* `leaves` a `File` has no reason to carry.
|
|
141
|
+
*/
|
|
93
142
|
export function blocks(...values) {
|
|
143
|
+
values.forEach((value, index) => {
|
|
144
|
+
if (isFileValue(value)) {
|
|
145
|
+
throw new Error(`blocks(): block ${index} is a \`file()\` value — a composed body admits a ` +
|
|
146
|
+
`\`text\` span or an embedded member value. A document is a member's whole ` +
|
|
147
|
+
`\`prose\` body (\`prose: file(…)\`); to pull its bytes into a composed body, ` +
|
|
148
|
+
`interpolate \`include()\` into a \`text\` span (specs/model/pipeline.md, "The SDK").`);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
94
151
|
return { kind: "blocks", values };
|
|
95
152
|
}
|
|
153
|
+
/**
|
|
154
|
+
* Whether a composed-body child is a {@link File}. A child kind may itself be named
|
|
155
|
+
* `file`, so the kind tag alone is ambiguous — an embedded value always carries
|
|
156
|
+
* `leaves`, and only a `File` anchors a `moduleUrl`.
|
|
157
|
+
*/
|
|
158
|
+
function isFileValue(value) {
|
|
159
|
+
const candidate = value;
|
|
160
|
+
return candidate.kind === "file" && typeof candidate.moduleUrl === "string";
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Whether a composed-body child is a verbatim prose span rather than an embedded
|
|
164
|
+
* member value — the discriminant emit and the row builders branch on to render a
|
|
165
|
+
* span as prose and count its refs at host level, never as a nested member.
|
|
166
|
+
*/
|
|
167
|
+
export function isTextSpan(value) {
|
|
168
|
+
return value.kind === "text";
|
|
169
|
+
}
|
|
96
170
|
/**
|
|
97
171
|
* Render an inline body to its final text — the display rule applied: each
|
|
98
172
|
* mention slot becomes its target's display form, the surrounding words
|
|
99
|
-
* untouched
|
|
173
|
+
* untouched. The chunk count is `mentions.length + 1` by {@link text}'s
|
|
100
174
|
* construction, so the walk consumes every slot.
|
|
101
175
|
*/
|
|
102
176
|
export function renderText(prose) {
|
|
@@ -109,26 +183,22 @@ export function renderText(prose) {
|
|
|
109
183
|
}
|
|
110
184
|
/**
|
|
111
185
|
* Resolve a leaf's authored value to its stored/rendered string: a bare string
|
|
112
|
-
* is unchanged; a `Text` leaf is mention-resolution-checked against
|
|
113
|
-
*
|
|
114
|
-
* — the same rule a member-level
|
|
115
|
-
* the dangling-mention error so it
|
|
186
|
+
* is unchanged; a `Text` leaf is mention-resolution-checked against `scope`
|
|
187
|
+
* ({@link checkMentions}: loud on a dangling address, a discovery-locus one
|
|
188
|
+
* deferred) and rendered by {@link renderText} — the same rule a member-level
|
|
189
|
+
* `Text` body resolves by. `context` prefixes the dangling-mention error so it
|
|
190
|
+
* names the leaf, not just the mention.
|
|
116
191
|
*
|
|
117
192
|
* # Throws
|
|
118
|
-
* If a mention names no declared value.
|
|
193
|
+
* If a mention names no declared value and has no discovery locus.
|
|
119
194
|
*/
|
|
120
|
-
export function resolveLeaf(value,
|
|
195
|
+
export function resolveLeaf(value, scope, context) {
|
|
121
196
|
if (typeof value === "string")
|
|
122
197
|
return value;
|
|
123
198
|
if (value.includes.length > 0) {
|
|
124
199
|
throw new Error(`${context}: an embedded-member leaf cannot carry an include — a content pull is a ` +
|
|
125
200
|
`member-body intent, not a fenced-value one (specs/model/pipeline.md, "The SDK").`);
|
|
126
201
|
}
|
|
127
|
-
|
|
128
|
-
if (!mentionable.has(mention.target.address)) {
|
|
129
|
-
throw new Error(`${context}: mention of \`${mention.target.address}\` resolves to no declared value — ` +
|
|
130
|
-
`a mention cannot dangle (specs/model/contract.md).`);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
202
|
+
checkMentions(value.mentions, scope, context);
|
|
133
203
|
return renderText(value);
|
|
134
204
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dtmd/temper",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"description": "The temper authoring face — the six-noun model as typed modules: harness(), kind<T>(), clause values, needs, and file()/text/blocks(). Emit compiles to the declaration rows the engine reads, a byte-faithful projection, and the lock.",
|
|
5
5
|
"license": "(MIT OR Apache-2.0)",
|
|
6
6
|
"repository": {
|
|
@@ -45,14 +45,14 @@
|
|
|
45
45
|
"prepublishOnly": "npm run test"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@types/node": "^22.
|
|
48
|
+
"@types/node": "^22.20.1",
|
|
49
49
|
"typescript": "^5.6.0"
|
|
50
50
|
},
|
|
51
51
|
"bin": {
|
|
52
52
|
"temper": "bin/temper.js"
|
|
53
53
|
},
|
|
54
54
|
"optionalDependencies": {
|
|
55
|
-
"@dtmd/temper-linux-x64": "0.0.
|
|
56
|
-
"@dtmd/temper-win32-x64": "0.0.
|
|
55
|
+
"@dtmd/temper-linux-x64": "0.0.9",
|
|
56
|
+
"@dtmd/temper-win32-x64": "0.0.9"
|
|
57
57
|
}
|
|
58
58
|
}
|