@agentshouse/mdmodel 0.1.0-alpha.1 → 0.1.0-alpha.11

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 (156) hide show
  1. package/README.md +227 -7
  2. package/dist/blocks.d.ts +11 -0
  3. package/dist/blocks.d.ts.map +1 -0
  4. package/dist/blocks.js +63 -0
  5. package/dist/blocks.js.map +1 -0
  6. package/dist/definition.d.ts +8 -6
  7. package/dist/definition.d.ts.map +1 -1
  8. package/dist/definition.js +44 -38
  9. package/dist/definition.js.map +1 -1
  10. package/dist/divide.d.ts +3 -0
  11. package/dist/divide.d.ts.map +1 -0
  12. package/dist/divide.js +376 -0
  13. package/dist/divide.js.map +1 -0
  14. package/dist/document.d.ts +4 -1
  15. package/dist/document.d.ts.map +1 -1
  16. package/dist/document.js +95 -4
  17. package/dist/document.js.map +1 -1
  18. package/dist/index.d.ts +4 -2
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +3 -1
  21. package/dist/index.js.map +1 -1
  22. package/dist/links.d.ts +25 -1
  23. package/dist/links.d.ts.map +1 -1
  24. package/dist/links.js +289 -48
  25. package/dist/links.js.map +1 -1
  26. package/dist/paths.d.ts +1 -0
  27. package/dist/paths.d.ts.map +1 -1
  28. package/dist/paths.js +5 -0
  29. package/dist/paths.js.map +1 -1
  30. package/dist/profile.js.map +1 -1
  31. package/dist/project.d.ts +21 -0
  32. package/dist/project.d.ts.map +1 -0
  33. package/dist/project.js +158 -0
  34. package/dist/project.js.map +1 -0
  35. package/dist/refuse.js.map +1 -1
  36. package/dist/schema.d.ts.map +1 -1
  37. package/dist/schema.js +16 -38
  38. package/dist/schema.js.map +1 -1
  39. package/dist/sections.d.ts.map +1 -1
  40. package/dist/sections.js +14 -47
  41. package/dist/sections.js.map +1 -1
  42. package/dist/types.d.ts +44 -0
  43. package/dist/types.d.ts.map +1 -1
  44. package/dist/types.js.map +1 -1
  45. package/dist/validate.d.ts +2 -2
  46. package/dist/validate.d.ts.map +1 -1
  47. package/dist/validate.js +17 -8
  48. package/dist/validate.js.map +1 -1
  49. package/dist/version.d.ts +1 -1
  50. package/dist/version.d.ts.map +1 -1
  51. package/dist/version.js +1 -1
  52. package/dist/version.js.map +1 -1
  53. package/dist/yaml.d.ts +1 -0
  54. package/dist/yaml.d.ts.map +1 -1
  55. package/dist/yaml.js +6 -4
  56. package/dist/yaml.js.map +1 -1
  57. package/fixtures/README.md +88 -27
  58. package/fixtures/cases/any-without-type/context.json +1 -0
  59. package/fixtures/cases/binary-any-reference/context.json +5 -0
  60. package/fixtures/cases/binary-any-reference/expected.json +7 -0
  61. package/fixtures/cases/binary-any-reference/library/notes/draft.md +6 -0
  62. package/fixtures/cases/binary-any-reference/library/types/note.md +5 -0
  63. package/fixtures/cases/binary-document-collision/context.json +5 -0
  64. package/fixtures/cases/binary-document-collision/expected.json +6 -0
  65. package/fixtures/cases/binary-document-collision/library/notes/draft.md +3 -0
  66. package/fixtures/cases/binary-document-collision/library/types/note.md +3 -0
  67. package/fixtures/cases/binary-link-outside-collection/context.json +6 -0
  68. package/fixtures/cases/binary-link-outside-collection/expected.json +6 -0
  69. package/fixtures/cases/binary-link-outside-collection/library/notes/draft.md +5 -0
  70. package/fixtures/cases/binary-link-outside-collection/library/types/note.md +3 -0
  71. package/fixtures/cases/binary-prototype-reference/context.json +1 -0
  72. package/fixtures/cases/binary-prototype-reference/expected.json +7 -0
  73. package/fixtures/cases/binary-prototype-reference/library/notes/draft.md +6 -0
  74. package/fixtures/cases/binary-prototype-reference/library/types/note.md +5 -0
  75. package/fixtures/cases/binary-typed-reference/context.json +5 -0
  76. package/fixtures/cases/binary-typed-reference/expected.json +7 -0
  77. package/fixtures/cases/binary-typed-reference/library/notes/draft.md +6 -0
  78. package/fixtures/cases/binary-typed-reference/library/types/note.md +5 -0
  79. package/fixtures/cases/binary-typed-reference/library/types/person.md +3 -0
  80. package/fixtures/cases/bracketed-link-definition/context.json +1 -0
  81. package/fixtures/cases/bracketed-link-definition/expected.json +1 -0
  82. package/fixtures/cases/bracketed-link-definition/library/item.md +10 -0
  83. package/fixtures/cases/bracketed-link-definition/library/types/task.md +7 -0
  84. package/fixtures/cases/declared-binary-links/context.json +6 -0
  85. package/fixtures/cases/declared-binary-links/expected.json +1 -0
  86. package/fixtures/cases/declared-binary-links/library/notes/draft.md +7 -0
  87. package/fixtures/cases/declared-binary-links/library/types/note.md +3 -0
  88. package/fixtures/cases/duplicate-link-definition/context.json +1 -0
  89. package/fixtures/cases/duplicate-link-definition/expected.json +1 -0
  90. package/fixtures/cases/duplicate-link-definition/library/item.md +11 -0
  91. package/fixtures/cases/duplicate-link-definition/library/types/task.md +7 -0
  92. package/fixtures/cases/fenced-link-definition/context.json +1 -0
  93. package/fixtures/cases/fenced-link-definition/expected.json +1 -0
  94. package/fixtures/cases/fenced-link-definition/library/item.md +12 -0
  95. package/fixtures/cases/fenced-link-definition/library/types/task.md +7 -0
  96. package/fixtures/cases/field-enum/context.json +1 -0
  97. package/fixtures/cases/interrupted-link-definition/context.json +1 -0
  98. package/fixtures/cases/interrupted-link-definition/expected.json +1 -0
  99. package/fixtures/cases/interrupted-link-definition/library/notes/draft.md +8 -0
  100. package/fixtures/cases/interrupted-link-definition/library/types/note.md +3 -0
  101. package/fixtures/cases/long-fence-link-definition/context.json +1 -0
  102. package/fixtures/cases/long-fence-link-definition/expected.json +1 -0
  103. package/fixtures/cases/long-fence-link-definition/library/notes/draft.md +9 -0
  104. package/fixtures/cases/long-fence-link-definition/library/types/note.md +3 -0
  105. package/fixtures/cases/malformed-definition/context.json +1 -0
  106. package/fixtures/cases/missing-binary-image/context.json +6 -0
  107. package/fixtures/cases/missing-binary-image/expected.json +6 -0
  108. package/fixtures/cases/missing-binary-image/library/notes/draft.md +5 -0
  109. package/fixtures/cases/missing-binary-image/library/types/note.md +3 -0
  110. package/fixtures/cases/missing-binary-link/context.json +6 -0
  111. package/fixtures/cases/missing-binary-link/expected.json +6 -0
  112. package/fixtures/cases/missing-binary-link/library/notes/draft.md +5 -0
  113. package/fixtures/cases/missing-binary-link/library/types/note.md +3 -0
  114. package/fixtures/cases/missing-required-field/context.json +1 -0
  115. package/fixtures/cases/missing-section-item-kind/context.json +1 -0
  116. package/fixtures/cases/missing-section-item-kind/expected.json +7 -0
  117. package/fixtures/cases/missing-section-item-kind/library/types/task.md +7 -0
  118. package/fixtures/cases/paragraph-link-definition/context.json +5 -0
  119. package/fixtures/cases/paragraph-link-definition/expected.json +1 -0
  120. package/fixtures/cases/paragraph-link-definition/library/notes/draft.md +10 -0
  121. package/fixtures/cases/paragraph-link-definition/library/types/note.md +3 -0
  122. package/fixtures/cases/prd-definition/context.json +1 -0
  123. package/fixtures/cases/prd-definition/library/types/task.md +2 -1
  124. package/fixtures/cases/prototype-field/context.json +1 -0
  125. package/fixtures/cases/prototype-field/expected.json +7 -0
  126. package/fixtures/cases/prototype-field/library/item.md +9 -0
  127. package/fixtures/cases/prototype-field/library/types/task.md +7 -0
  128. package/fixtures/cases/quoted-link-definition/context.json +1 -0
  129. package/fixtures/cases/quoted-link-definition/expected.json +6 -0
  130. package/fixtures/cases/quoted-link-definition/library/notes/draft.md +7 -0
  131. package/fixtures/cases/quoted-link-definition/library/types/note.md +3 -0
  132. package/fixtures/cases/referenced-missing-file/context.json +1 -0
  133. package/fixtures/cases/structured-section/context.json +1 -0
  134. package/fixtures/cases/structured-section/library/types/task.md +1 -1
  135. package/fixtures/cases/truncated-link-definition/context.json +1 -0
  136. package/fixtures/cases/truncated-link-definition/expected.json +6 -0
  137. package/fixtures/cases/truncated-link-definition/library/notes/draft.md +7 -0
  138. package/fixtures/cases/truncated-link-definition/library/notes/other.md +5 -0
  139. package/fixtures/cases/truncated-link-definition/library/types/note.md +3 -0
  140. package/fixtures/cases/unclosed-frontmatter/context.json +1 -0
  141. package/fixtures/cases/undeclared-field/context.json +1 -0
  142. package/fixtures/cases/undeclared-field/expected.json +7 -0
  143. package/fixtures/cases/undeclared-field/library/item.md +9 -0
  144. package/fixtures/cases/undeclared-field/library/types/task.md +7 -0
  145. package/fixtures/cases/unresolved-link/context.json +1 -0
  146. package/fixtures/cases/valid-typed-document/context.json +1 -0
  147. package/fixtures/cases/valid-typed-document/library/tasks/one.md +1 -0
  148. package/fixtures/cases/valid-typed-document/library/types/task.md +2 -1
  149. package/fixtures/cases/wide-item-fence-link/context.json +1 -0
  150. package/fixtures/cases/wide-item-fence-link/expected.json +1 -0
  151. package/fixtures/cases/wide-item-fence-link/library/notes/draft.md +7 -0
  152. package/fixtures/cases/wide-item-fence-link/library/types/note.md +3 -0
  153. package/fixtures/division.json +431 -0
  154. package/fixtures/preamble.json +107 -0
  155. package/fixtures/projection.json +186 -0
  156. package/package.json +4 -5
package/dist/divide.js ADDED
@@ -0,0 +1,376 @@
1
+ import { blockRanges, headingLines } from './blocks.js';
2
+ import { projectionInput, rangeText } from './project.js';
3
+ import { refusal } from './refuse.js';
4
+ const SMALLEST_BUDGET = 2;
5
+ function node(draft) {
6
+ return {
7
+ start: draft.start,
8
+ end: draft.end,
9
+ bodyStart: draft.bodyStart,
10
+ heading: draft.heading,
11
+ children: draft.children.map(node)
12
+ };
13
+ }
14
+ function forest(state, range) {
15
+ const content = state.content;
16
+ const headings = headingLines(content, range.start, range.end);
17
+ const roots = [];
18
+ const open = [];
19
+ const first = headings[0]?.start ?? range.end;
20
+ if (first > range.start) {
21
+ roots.push({
22
+ level: 0,
23
+ start: range.start,
24
+ end: first,
25
+ bodyStart: range.start,
26
+ heading: '',
27
+ children: []
28
+ });
29
+ }
30
+ for (const heading of headings){
31
+ while((open[open.length - 1]?.level ?? 0) >= heading.level){
32
+ open.pop().end = heading.start;
33
+ }
34
+ const draft = {
35
+ level: heading.level,
36
+ start: heading.start,
37
+ end: range.end,
38
+ bodyStart: heading.next,
39
+ heading: `${textOf(state, {
40
+ start: heading.start,
41
+ end: heading.textEnd
42
+ })}\n\n`,
43
+ children: []
44
+ };
45
+ (open[open.length - 1]?.children ?? roots).push(draft);
46
+ open.push(draft);
47
+ }
48
+ return roots.map(node);
49
+ }
50
+ function isSpace(character) {
51
+ return character === ' ' || character === '\t' || character === '\n' || character === '\r';
52
+ }
53
+ const TERMINATORS = new Set([
54
+ '.',
55
+ '!',
56
+ '?',
57
+ '…',
58
+ '。',
59
+ '!',
60
+ '?'
61
+ ]);
62
+ function isTerminator(character) {
63
+ return TERMINATORS.has(character);
64
+ }
65
+ const CLOSERS = new Set([
66
+ '"',
67
+ "'",
68
+ ')',
69
+ ']',
70
+ '»',
71
+ '”'
72
+ ]);
73
+ function isCloser(character) {
74
+ return CLOSERS.has(character);
75
+ }
76
+ function sentenceBounds(text) {
77
+ const bounds = [
78
+ 0
79
+ ];
80
+ let i = 0;
81
+ while(i < text.length){
82
+ if (!isTerminator(text[i])) {
83
+ i += 1;
84
+ continue;
85
+ }
86
+ let after = i + 1;
87
+ while(after < text.length && isCloser(text[after]))after += 1;
88
+ if (after >= text.length || !isSpace(text[after])) {
89
+ i = after + 1;
90
+ continue;
91
+ }
92
+ while(after < text.length && isSpace(text[after]))after += 1;
93
+ if (after < text.length) bounds.push(after);
94
+ i = after;
95
+ }
96
+ bounds.push(text.length);
97
+ return bounds;
98
+ }
99
+ function isTrailingSurrogate(text, index) {
100
+ const code = text.charCodeAt(index);
101
+ return code >= 0xdc00 && code <= 0xdfff;
102
+ }
103
+ function characterLength(text, index) {
104
+ return isTrailingSurrogate(text, index + 1) ? 2 : 1;
105
+ }
106
+ function boundOf(cutting, from, to, budget) {
107
+ const limit = from + budget;
108
+ if (limit >= to) return to;
109
+ for(let index = limit; index > from + 1; index -= 1){
110
+ if (isSpace(cutting.text[index])) return index;
111
+ }
112
+ const inside = cutting.masks.find((mask)=>limit > mask.start && limit < mask.end);
113
+ if (inside !== undefined) return inside.start > from ? inside.start : Math.min(inside.end, to);
114
+ return isTrailingSurrogate(cutting.text, limit) ? limit - 1 : limit;
115
+ }
116
+ function utf8Size(code) {
117
+ if (code < 0x80) return 1;
118
+ if (code < 0x800) return 2;
119
+ if (code < 0x10000) return 3;
120
+ return 4;
121
+ }
122
+ function byteBounds(content, spans) {
123
+ const marks = [
124
+ ...new Set(spans.flatMap((span)=>[
125
+ span.start,
126
+ span.end
127
+ ]))
128
+ ].sort((left, right)=>left - right);
129
+ const bytes = new Map();
130
+ let index = 0;
131
+ let count = 0;
132
+ for (const mark of marks){
133
+ while(index < mark){
134
+ const code = content.codePointAt(index);
135
+ count += utf8Size(code);
136
+ index += code > 0xffff ? 2 : 1;
137
+ }
138
+ bytes.set(mark, count);
139
+ }
140
+ return spans.map((span)=>({
141
+ ...span,
142
+ start: bytes.get(span.start),
143
+ end: bytes.get(span.end)
144
+ }));
145
+ }
146
+ function textOf(state, extent) {
147
+ return rangeText(state.content, extent, state.edits);
148
+ }
149
+ function sourceCutting(state, extent) {
150
+ let text = state.content.slice(extent.start, extent.end);
151
+ const masks = [];
152
+ for (const edit of state.edits){
153
+ if (edit.start < extent.start || edit.end > extent.end) continue;
154
+ const from = edit.start - extent.start;
155
+ const to = edit.end - extent.start;
156
+ text = `${text.slice(0, from)}${'x'.repeat(to - from)}${text.slice(to)}`;
157
+ masks.push({
158
+ start: from,
159
+ end: to
160
+ });
161
+ }
162
+ return {
163
+ text,
164
+ masks,
165
+ piece: (from, to)=>{
166
+ const cut = {
167
+ start: extent.start + from,
168
+ end: extent.start + to
169
+ };
170
+ return {
171
+ ...cut,
172
+ text: textOf(state, cut)
173
+ };
174
+ }
175
+ };
176
+ }
177
+ function valueCutting(value) {
178
+ return {
179
+ text: value.text,
180
+ masks: [],
181
+ piece: (from, to)=>({
182
+ start: value.start,
183
+ end: value.end,
184
+ text: value.text.slice(from, to)
185
+ })
186
+ };
187
+ }
188
+ function prefixOf(state, body) {
189
+ if (body.emitted === 0 || body.heading.length >= state.budget) return '';
190
+ return body.heading;
191
+ }
192
+ function available(state, body) {
193
+ return state.budget - prefixOf(state, body).length;
194
+ }
195
+ function emit(state, body, piece, bare = false) {
196
+ if (piece.text.trim() === '') return;
197
+ const text = (bare ? '' : prefixOf(state, body)) + piece.text;
198
+ state.spans.push({
199
+ start: piece.start,
200
+ end: piece.end,
201
+ text
202
+ });
203
+ body.emitted += 1;
204
+ }
205
+ function merge(run) {
206
+ return {
207
+ start: Math.min(...run.map((unit)=>unit.start)),
208
+ end: Math.max(...run.map((unit)=>unit.end)),
209
+ text: run.map((unit)=>unit.text).join('')
210
+ };
211
+ }
212
+ function divideUnits(state, body, units) {
213
+ let run = [];
214
+ let length = 0;
215
+ const flush = ()=>{
216
+ if (run.length === 0) return;
217
+ emit(state, body, merge(run));
218
+ run = [];
219
+ length = 0;
220
+ };
221
+ for (const unit of units){
222
+ if (run.length > 0 && length + unit.text.length > available(state, body)) flush();
223
+ if (unit.text.length > available(state, body)) {
224
+ flush();
225
+ unit.descend();
226
+ continue;
227
+ }
228
+ run.push(unit);
229
+ length += unit.text.length;
230
+ }
231
+ flush();
232
+ }
233
+ function divideBound(state, body, cutting, range) {
234
+ let start = range.start;
235
+ while(start < range.end){
236
+ const bare = available(state, body) < characterLength(cutting.text, start);
237
+ const room = bare ? state.budget : available(state, body);
238
+ const stop = boundOf(cutting, start, range.end, room);
239
+ const piece = cutting.piece(start, stop);
240
+ if (cutting.masks.length === 0 || piece.text.length <= room) {
241
+ emit(state, body, piece, bare);
242
+ } else {
243
+ divideBound(state, body, valueCutting(piece), {
244
+ start: 0,
245
+ end: piece.text.length
246
+ });
247
+ }
248
+ start = stop;
249
+ }
250
+ }
251
+ function divideSentences(state, body, cutting) {
252
+ const cut = cutting.piece;
253
+ const bounds = sentenceBounds(cutting.text);
254
+ let index = 0;
255
+ while(index + 1 < bounds.length){
256
+ const alone = {
257
+ start: bounds[index],
258
+ end: bounds[index + 1]
259
+ };
260
+ if (cut(alone.start, alone.end).text.length > available(state, body)) {
261
+ divideBound(state, body, cutting, alone);
262
+ index += 1;
263
+ continue;
264
+ }
265
+ const carried = bounds[Math.max(index - 1, 0)];
266
+ const from = cut(carried, alone.end).text.length <= available(state, body) ? carried : alone.start;
267
+ let last = index;
268
+ while(last + 2 < bounds.length && cut(from, bounds[last + 2]).text.length <= available(state, body)){
269
+ last += 1;
270
+ }
271
+ emit(state, body, cut(from, bounds[last + 1]));
272
+ index = last + 1;
273
+ }
274
+ }
275
+ function blockUnit(state, body, block) {
276
+ return {
277
+ start: block.start,
278
+ end: block.end,
279
+ text: textOf(state, block),
280
+ descend: ()=>divideSentences(state, body, sourceCutting(state, block))
281
+ };
282
+ }
283
+ function valueUnit(state, body, value) {
284
+ return {
285
+ start: value.start,
286
+ end: value.end,
287
+ text: value.text,
288
+ descend: ()=>divideSentences(state, body, valueCutting(value))
289
+ };
290
+ }
291
+ function nodeUnit(state, subject) {
292
+ return {
293
+ start: subject.start,
294
+ end: subject.end,
295
+ text: textOf(state, subject),
296
+ descend: ()=>divideNode(state, subject)
297
+ };
298
+ }
299
+ function ownBlocks(subject, end, blocks) {
300
+ const first = blocks[0];
301
+ return first === undefined ? [
302
+ {
303
+ start: subject.start,
304
+ end
305
+ }
306
+ ] : [
307
+ {
308
+ start: subject.start,
309
+ end: first.end
310
+ },
311
+ ...blocks.slice(1)
312
+ ];
313
+ }
314
+ function divideNode(state, subject) {
315
+ const end = subject.children[0]?.start ?? subject.end;
316
+ const blocks = blockRanges(state.content, subject.bodyStart, end);
317
+ const children = {
318
+ heading: '',
319
+ emitted: 0
320
+ };
321
+ if (blocks.length === 0 && subject.children.length > 0) {
322
+ const [first, ...rest] = subject.children;
323
+ const led = [
324
+ {
325
+ ...first,
326
+ start: subject.start
327
+ },
328
+ ...rest
329
+ ];
330
+ divideUnits(state, children, led.map((child)=>nodeUnit(state, child)));
331
+ return;
332
+ }
333
+ const body = {
334
+ heading: subject.heading,
335
+ emitted: 0
336
+ };
337
+ const own = ownBlocks(subject, end, blocks);
338
+ divideUnits(state, body, own.map((block)=>blockUnit(state, body, block)));
339
+ divideUnits(state, children, subject.children.map((child)=>nodeUnit(state, child)));
340
+ }
341
+ function divideInput(state, input) {
342
+ const body = {
343
+ heading: '',
344
+ emitted: 0
345
+ };
346
+ divideUnits(state, body, [
347
+ ...input.values.map((value)=>valueUnit(state, body, value)),
348
+ ...input.ranges.flatMap((range)=>forest(state, range).map((subject)=>nodeUnit(state, subject)))
349
+ ]);
350
+ }
351
+ export function divide(document, file, context) {
352
+ if (!Number.isInteger(context.budget) || context.budget < SMALLEST_BUDGET) {
353
+ return {
354
+ ok: false,
355
+ refusal: refusal(file, 'division-budget')
356
+ };
357
+ }
358
+ const result = projectionInput(document, file, context);
359
+ if (!result.ok) return {
360
+ ok: false,
361
+ refusal: result.refusal
362
+ };
363
+ const state = {
364
+ content: document.content,
365
+ edits: result.input.edits,
366
+ budget: context.budget,
367
+ spans: []
368
+ };
369
+ divideInput(state, result.input);
370
+ return {
371
+ ok: true,
372
+ spans: byteBounds(document.content, state.spans)
373
+ };
374
+ }
375
+
376
+ //# sourceMappingURL=divide.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/workspace/packages/mdmodel/src/divide.ts"],"sourcesContent":["import { blockRanges, headingLines } from './blocks.js';\nimport { projectionInput, rangeText, type Edit, type Input, type Piece } from './project.js';\nimport { refusal } from './refuse.js';\nimport type { Division, DivisionContext, Document, Extent, Span } from './types.js';\n\nconst SMALLEST_BUDGET = 2;\n\ntype Node = {\n readonly start: number;\n readonly end: number;\n readonly bodyStart: number;\n readonly heading: string;\n readonly children: readonly Node[];\n};\n\ntype Draft = {\n readonly level: number;\n start: number;\n end: number;\n readonly bodyStart: number;\n readonly heading: string;\n readonly children: Draft[];\n};\n\ntype State = {\n readonly content: string;\n readonly edits: readonly Edit[];\n readonly budget: number;\n readonly spans: Span[];\n};\n\ntype Body = {\n readonly heading: string;\n emitted: number;\n};\n\ntype Unit = Piece & { readonly descend: () => void };\n\ntype Cutting = {\n readonly text: string;\n readonly masks: readonly Extent[];\n readonly piece: (from: number, to: number) => Piece;\n};\n\nfunction node(draft: Draft): Node {\n return {\n start: draft.start,\n end: draft.end,\n bodyStart: draft.bodyStart,\n heading: draft.heading,\n children: draft.children.map(node),\n };\n}\n\nfunction forest(state: State, range: Extent): Node[] {\n const content = state.content;\n const headings = headingLines(content, range.start, range.end);\n const roots: Draft[] = [];\n const open: Draft[] = [];\n const first = headings[0]?.start ?? range.end;\n if (first > range.start) {\n roots.push({\n level: 0,\n start: range.start,\n end: first,\n bodyStart: range.start,\n heading: '',\n children: [],\n });\n }\n for (const heading of headings) {\n while ((open[open.length - 1]?.level ?? 0) >= heading.level) {\n open.pop()!.end = heading.start;\n }\n const draft: Draft = {\n level: heading.level,\n start: heading.start,\n end: range.end,\n bodyStart: heading.next,\n heading: `${textOf(state, { start: heading.start, end: heading.textEnd })}\\n\\n`,\n children: [],\n };\n (open[open.length - 1]?.children ?? roots).push(draft);\n open.push(draft);\n }\n return roots.map(node);\n}\n\nfunction isSpace(character: string): boolean {\n return character === ' ' || character === '\\t' || character === '\\n' || character === '\\r';\n}\n\nconst TERMINATORS = new Set(['.', '!', '?', '…', '。', '!', '?']);\n\nfunction isTerminator(character: string): boolean {\n return TERMINATORS.has(character);\n}\n\nconst CLOSERS = new Set(['\"', \"'\", ')', ']', '»', '”']);\n\nfunction isCloser(character: string): boolean {\n return CLOSERS.has(character);\n}\n\nfunction sentenceBounds(text: string): number[] {\n const bounds = [0];\n let i = 0;\n while (i < text.length) {\n if (!isTerminator(text[i]!)) {\n i += 1;\n continue;\n }\n let after = i + 1;\n while (after < text.length && isCloser(text[after]!)) after += 1;\n if (after >= text.length || !isSpace(text[after]!)) {\n i = after + 1;\n continue;\n }\n while (after < text.length && isSpace(text[after]!)) after += 1;\n if (after < text.length) bounds.push(after);\n i = after;\n }\n bounds.push(text.length);\n return bounds;\n}\n\nfunction isTrailingSurrogate(text: string, index: number): boolean {\n const code = text.charCodeAt(index);\n return code >= 0xdc00 && code <= 0xdfff;\n}\n\nfunction characterLength(text: string, index: number): number {\n return isTrailingSurrogate(text, index + 1) ? 2 : 1;\n}\n\nfunction boundOf(cutting: Cutting, from: number, to: number, budget: number): number {\n const limit = from + budget;\n if (limit >= to) return to;\n for (let index = limit; index > from + 1; index -= 1) {\n if (isSpace(cutting.text[index]!)) return index;\n }\n const inside = cutting.masks.find((mask) => limit > mask.start && limit < mask.end);\n if (inside !== undefined) return inside.start > from ? inside.start : Math.min(inside.end, to);\n return isTrailingSurrogate(cutting.text, limit) ? limit - 1 : limit;\n}\n\nfunction utf8Size(code: number): number {\n if (code < 0x80) return 1;\n if (code < 0x800) return 2;\n if (code < 0x10000) return 3;\n return 4;\n}\n\nfunction byteBounds(content: string, spans: readonly Span[]): Span[] {\n const marks = [...new Set(spans.flatMap((span) => [span.start, span.end]))].sort(\n (left, right) => left - right,\n );\n const bytes = new Map<number, number>();\n let index = 0;\n let count = 0;\n for (const mark of marks) {\n while (index < mark) {\n const code = content.codePointAt(index)!;\n count += utf8Size(code);\n index += code > 0xffff ? 2 : 1;\n }\n bytes.set(mark, count);\n }\n return spans.map((span) => ({\n ...span,\n start: bytes.get(span.start)!,\n end: bytes.get(span.end)!,\n }));\n}\n\nfunction textOf(state: State, extent: Extent): string {\n return rangeText(state.content, extent, state.edits);\n}\n\nfunction sourceCutting(state: State, extent: Extent): Cutting {\n let text = state.content.slice(extent.start, extent.end);\n const masks: Extent[] = [];\n for (const edit of state.edits) {\n if (edit.start < extent.start || edit.end > extent.end) continue;\n const from = edit.start - extent.start;\n const to = edit.end - extent.start;\n text = `${text.slice(0, from)}${'x'.repeat(to - from)}${text.slice(to)}`;\n masks.push({ start: from, end: to });\n }\n return {\n text,\n masks,\n piece: (from, to) => {\n const cut = { start: extent.start + from, end: extent.start + to };\n return { ...cut, text: textOf(state, cut) };\n },\n };\n}\n\nfunction valueCutting(value: Piece): Cutting {\n return {\n text: value.text,\n masks: [],\n piece: (from, to) => ({ start: value.start, end: value.end, text: value.text.slice(from, to) }),\n };\n}\n\nfunction prefixOf(state: State, body: Body): string {\n if (body.emitted === 0 || body.heading.length >= state.budget) return '';\n return body.heading;\n}\n\nfunction available(state: State, body: Body): number {\n return state.budget - prefixOf(state, body).length;\n}\n\nfunction emit(state: State, body: Body, piece: Piece, bare = false): void {\n if (piece.text.trim() === '') return;\n const text = (bare ? '' : prefixOf(state, body)) + piece.text;\n state.spans.push({ start: piece.start, end: piece.end, text });\n body.emitted += 1;\n}\n\nfunction merge(run: readonly Unit[]): Piece {\n return {\n start: Math.min(...run.map((unit) => unit.start)),\n end: Math.max(...run.map((unit) => unit.end)),\n text: run.map((unit) => unit.text).join(''),\n };\n}\n\nfunction divideUnits(state: State, body: Body, units: readonly Unit[]): void {\n let run: Unit[] = [];\n let length = 0;\n const flush = (): void => {\n if (run.length === 0) return;\n emit(state, body, merge(run));\n run = [];\n length = 0;\n };\n for (const unit of units) {\n if (run.length > 0 && length + unit.text.length > available(state, body)) flush();\n if (unit.text.length > available(state, body)) {\n flush();\n unit.descend();\n continue;\n }\n run.push(unit);\n length += unit.text.length;\n }\n flush();\n}\n\nfunction divideBound(state: State, body: Body, cutting: Cutting, range: Extent): void {\n let start = range.start;\n while (start < range.end) {\n const bare = available(state, body) < characterLength(cutting.text, start);\n const room = bare ? state.budget : available(state, body);\n const stop = boundOf(cutting, start, range.end, room);\n const piece = cutting.piece(start, stop);\n if (cutting.masks.length === 0 || piece.text.length <= room) {\n emit(state, body, piece, bare);\n } else {\n divideBound(state, body, valueCutting(piece), { start: 0, end: piece.text.length });\n }\n start = stop;\n }\n}\n\nfunction divideSentences(state: State, body: Body, cutting: Cutting): void {\n const cut = cutting.piece;\n const bounds = sentenceBounds(cutting.text);\n let index = 0;\n while (index + 1 < bounds.length) {\n const alone = { start: bounds[index]!, end: bounds[index + 1]! };\n if (cut(alone.start, alone.end).text.length > available(state, body)) {\n divideBound(state, body, cutting, alone);\n index += 1;\n continue;\n }\n const carried = bounds[Math.max(index - 1, 0)]!;\n const from =\n cut(carried, alone.end).text.length <= available(state, body) ? carried : alone.start;\n let last = index;\n while (\n last + 2 < bounds.length &&\n cut(from, bounds[last + 2]!).text.length <= available(state, body)\n ) {\n last += 1;\n }\n emit(state, body, cut(from, bounds[last + 1]!));\n index = last + 1;\n }\n}\n\nfunction blockUnit(state: State, body: Body, block: Extent): Unit {\n return {\n start: block.start,\n end: block.end,\n text: textOf(state, block),\n descend: () => divideSentences(state, body, sourceCutting(state, block)),\n };\n}\n\nfunction valueUnit(state: State, body: Body, value: Piece): Unit {\n return {\n start: value.start,\n end: value.end,\n text: value.text,\n descend: () => divideSentences(state, body, valueCutting(value)),\n };\n}\n\nfunction nodeUnit(state: State, subject: Node): Unit {\n return {\n start: subject.start,\n end: subject.end,\n text: textOf(state, subject),\n descend: () => divideNode(state, subject),\n };\n}\n\nfunction ownBlocks(subject: Node, end: number, blocks: readonly Extent[]): Extent[] {\n const first = blocks[0];\n return first === undefined\n ? [{ start: subject.start, end }]\n : [{ start: subject.start, end: first.end }, ...blocks.slice(1)];\n}\n\nfunction divideNode(state: State, subject: Node): void {\n const end = subject.children[0]?.start ?? subject.end;\n const blocks = blockRanges(state.content, subject.bodyStart, end);\n const children: Body = { heading: '', emitted: 0 };\n if (blocks.length === 0 && subject.children.length > 0) {\n const [first, ...rest] = subject.children;\n const led = [{ ...first!, start: subject.start }, ...rest];\n divideUnits(\n state,\n children,\n led.map((child) => nodeUnit(state, child)),\n );\n return;\n }\n const body: Body = { heading: subject.heading, emitted: 0 };\n const own = ownBlocks(subject, end, blocks);\n divideUnits(\n state,\n body,\n own.map((block) => blockUnit(state, body, block)),\n );\n divideUnits(\n state,\n children,\n subject.children.map((child) => nodeUnit(state, child)),\n );\n}\n\nfunction divideInput(state: State, input: Input): void {\n const body: Body = { heading: '', emitted: 0 };\n divideUnits(state, body, [\n ...input.values.map((value) => valueUnit(state, body, value)),\n ...input.ranges.flatMap((range) =>\n forest(state, range).map((subject) => nodeUnit(state, subject)),\n ),\n ]);\n}\n\nexport function divide(document: Document, file: string, context: DivisionContext): Division {\n if (!Number.isInteger(context.budget) || context.budget < SMALLEST_BUDGET) {\n return { ok: false, refusal: refusal(file, 'division-budget') };\n }\n const result = projectionInput(document, file, context);\n if (!result.ok) return { ok: false, refusal: result.refusal };\n const state: State = {\n content: document.content,\n edits: result.input.edits,\n budget: context.budget,\n spans: [],\n };\n divideInput(state, result.input);\n return { ok: true, spans: byteBounds(document.content, state.spans) };\n}\n"],"names":["blockRanges","headingLines","projectionInput","rangeText","refusal","SMALLEST_BUDGET","node","draft","start","end","bodyStart","heading","children","map","forest","state","range","content","headings","roots","open","first","push","level","length","pop","next","textOf","textEnd","isSpace","character","TERMINATORS","Set","isTerminator","has","CLOSERS","isCloser","sentenceBounds","text","bounds","i","after","isTrailingSurrogate","index","code","charCodeAt","characterLength","boundOf","cutting","from","to","budget","limit","inside","masks","find","mask","undefined","Math","min","utf8Size","byteBounds","spans","marks","flatMap","span","sort","left","right","bytes","Map","count","mark","codePointAt","set","get","extent","edits","sourceCutting","slice","edit","repeat","piece","cut","valueCutting","value","prefixOf","body","emitted","available","emit","bare","trim","merge","run","unit","max","join","divideUnits","units","flush","descend","divideBound","room","stop","divideSentences","alone","carried","last","blockUnit","block","valueUnit","nodeUnit","subject","divideNode","ownBlocks","blocks","rest","led","child","own","divideInput","input","values","ranges","divide","document","file","context","Number","isInteger","ok","result"],"mappings":"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"}
@@ -1,5 +1,8 @@
1
- import type { ApplyResult, Change, Document, ParseResult } from './types.js';
1
+ import type { ApplyResult, Change, Document, Link, ParseResult } from './types.js';
2
+ import { type YamlMap } from './yaml.js';
2
3
  export declare function parse(content: string, file?: string): ParseResult;
4
+ export declare function links(document: Document, file: string): readonly Link[];
3
5
  export declare function apply(document: Document, change: Change): ApplyResult;
4
6
  export declare function serialize(document: Document): string;
7
+ export declare function frontmatter(document: Document): YamlMap | null;
5
8
  //# sourceMappingURL=document.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../src/document.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAmD7E,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,SAAK,GAAG,WAAW,CA0C7D;AAkDD,wBAAgB,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,CAWrE;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAEpD"}
1
+ {"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../src/document.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACnF,OAAO,EAYL,KAAK,OAAO,EACb,MAAM,WAAW,CAAC;AAwCnB,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,SAAK,GAAG,WAAW,CAkD7D;AAyGD,wBAAgB,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,IAAI,EAAE,CAWvE;AAED,wBAAgB,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,CAarE;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAEpD;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,GAAG,IAAI,CAE9D"}
package/dist/document.js CHANGED
@@ -1,17 +1,20 @@
1
+ import { hrefOccurrences } from './links.js';
2
+ import { classifyHref, hrefSuffix } from './paths.js';
1
3
  import { headingSpans, sectionsRecord } from './sections.js';
2
4
  import { refusal } from './refuse.js';
3
- import { bodyStartAfterYaml, equalValue, extractFrontmatter, jsValue, lineEnding, mapEntry, parseYamlMapping, serializeJs, serializeKey, YamlError } from './yaml.js';
5
+ import { bodyStartAfterYaml, bodyStartOf, equalValue, extractFrontmatter, jsValue, lineEnding, mapEntry, parseYamlMapping, serializeJs, serializeKey, YamlError } from './yaml.js';
4
6
  const internals = new WeakMap();
5
7
  function refuse(file, rule, location) {
6
8
  return location === undefined ? refusal(file, rule) : refusal(file, rule, {
7
9
  location
8
10
  });
9
11
  }
10
- function freezeDocument(content, type, fields, sections, internal) {
12
+ function freezeDocument(content, type, fields, preamble, sections, internal) {
11
13
  const document = Object.freeze({
12
14
  content,
13
15
  type,
14
16
  fields: Object.freeze(fields),
17
+ preamble,
15
18
  sections: Object.freeze(sections)
16
19
  });
17
20
  internals.set(document, internal);
@@ -29,7 +32,7 @@ export function parse(content, file = '') {
29
32
  const spans = headingSpans(content, 0);
30
33
  return {
31
34
  ok: true,
32
- document: freezeDocument(content, undefined, {}, sectionsRecord(spans, content), {
35
+ document: freezeDocument(content, undefined, {}, content.slice(0, spans[0]?.headingStart), sectionsRecord(spans, content), {
33
36
  root: null,
34
37
  yamlEnd: 0,
35
38
  bodyStart: 0
@@ -54,7 +57,7 @@ export function parse(content, file = '') {
54
57
  const record = fields;
55
58
  return {
56
59
  ok: true,
57
- document: freezeDocument(content, declaredType(record), record, sectionsRecord(spans, content), {
60
+ document: freezeDocument(content, declaredType(record), record, content.slice(bodyStart, spans[0]?.headingStart), sectionsRecord(spans, content), {
58
61
  root,
59
62
  yamlEnd: fence.yamlEnd,
60
63
  bodyStart
@@ -133,7 +136,92 @@ function applySection(document, name, value, prior) {
133
136
  document: parsed.document
134
137
  };
135
138
  }
139
+ function applyPreamble(document, value, prior) {
140
+ if (document.preamble !== prior) return {
141
+ outcome: 'stale',
142
+ document
143
+ };
144
+ const start = bodyStartOf(document.content);
145
+ const parsed = parse(splice(document.content, start, start + document.preamble.length, value));
146
+ if (!parsed.ok) return {
147
+ outcome: 'refuse',
148
+ refusal: parsed.refusal
149
+ };
150
+ return {
151
+ outcome: 'applied',
152
+ document: parsed.document
153
+ };
154
+ }
155
+ function fitsBare(to) {
156
+ if (to === '' || to.startsWith('<')) return false;
157
+ let depth = 0;
158
+ for (const character of to){
159
+ if (/[\s\u0000-\u001f\u007f]/.test(character)) return false;
160
+ if (character === '(') depth += 1;
161
+ else if (character === ')') {
162
+ if (depth === 0) return false;
163
+ depth -= 1;
164
+ }
165
+ }
166
+ return depth === 0;
167
+ }
168
+ function fitsBrackets(to) {
169
+ return to !== '' && !/[<>\n\r]/.test(to);
170
+ }
171
+ function destinationText(to, bracketed) {
172
+ if (fitsBare(to)) return bracketed && fitsBrackets(to) ? `<${to}>` : to;
173
+ if (fitsBrackets(to)) return `<${to}>`;
174
+ return null;
175
+ }
176
+ function applyLink(document, href, to) {
177
+ const content = document.content;
178
+ const bodyStart = bodyStartOf(content);
179
+ const matches = hrefOccurrences(content.slice(bodyStart)).filter((occurrence)=>occurrence.href === href);
180
+ if (matches.length === 0) return {
181
+ outcome: 'stale',
182
+ document
183
+ };
184
+ const written = to + hrefSuffix(href);
185
+ let rewritten = '';
186
+ let cursor = 0;
187
+ for (const match of matches){
188
+ const text = destinationText(written, match.bracketed);
189
+ if (text === null) return {
190
+ outcome: 'refuse',
191
+ refusal: refuse('', 'unwritable-link', written)
192
+ };
193
+ rewritten += content.slice(cursor, bodyStart + match.start);
194
+ rewritten += text;
195
+ cursor = bodyStart + match.end;
196
+ }
197
+ const parsed = parse(rewritten + content.slice(cursor));
198
+ if (!parsed.ok) return {
199
+ outcome: 'refuse',
200
+ refusal: parsed.refusal
201
+ };
202
+ return {
203
+ outcome: 'applied',
204
+ document: parsed.document
205
+ };
206
+ }
207
+ export function links(document, file) {
208
+ const found = [];
209
+ const seen = new Set();
210
+ for (const occurrence of hrefOccurrences(document.content.slice(bodyStartOf(document.content)))){
211
+ if (seen.has(occurrence.href)) continue;
212
+ const resolved = classifyHref(file, occurrence.href);
213
+ if (resolved.kind !== 'path') continue;
214
+ seen.add(occurrence.href);
215
+ found.push({
216
+ href: occurrence.href,
217
+ target: resolved.path
218
+ });
219
+ }
220
+ return found;
221
+ }
136
222
  export function apply(document, change) {
223
+ if (change.kind === 'link') return applyLink(document, change.href, change.to);
224
+ if (change.kind === 'preamble') return applyPreamble(document, change.value, change.prior);
137
225
  try {
138
226
  if (change.kind === 'field') return applyField(document, change.name, change.value, change.prior);
139
227
  return applySection(document, change.name, change.value, change.prior);
@@ -150,5 +238,8 @@ export function apply(document, change) {
150
238
  export function serialize(document) {
151
239
  return document.content;
152
240
  }
241
+ export function frontmatter(document) {
242
+ return internals.get(document)?.root ?? null;
243
+ }
153
244
 
154
245
  //# sourceMappingURL=document.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/executor/code/agents.house/mdmodel/packages/mdmodel/src/document.ts"],"sourcesContent":["import { headingSpans, sectionsRecord } from './sections.js';\nimport { refusal } from './refuse.js';\nimport type { ApplyResult, Change, Document, ParseResult } from './types.js';\nimport {\n bodyStartAfterYaml,\n equalValue,\n extractFrontmatter,\n jsValue,\n lineEnding,\n mapEntry,\n parseYamlMapping,\n serializeJs,\n serializeKey,\n YamlError,\n type YamlMap,\n} from './yaml.js';\n\ntype Internal = {\n readonly root: YamlMap | null;\n readonly yamlEnd: number;\n readonly bodyStart: number;\n};\n\nconst internals = new WeakMap<Document, Internal>();\n\nfunction refuse(file: string, rule: string, location?: string) {\n return location === undefined ? refusal(file, rule) : refusal(file, rule, { location });\n}\n\nfunction freezeDocument(\n content: string,\n type: string | undefined,\n fields: Record<string, unknown>,\n sections: Record<string, string>,\n internal: Internal,\n): Document {\n const document: Document = Object.freeze({\n content,\n type,\n fields: Object.freeze(fields),\n sections: Object.freeze(sections),\n });\n internals.set(document, internal);\n return document;\n}\n\nfunction declaredType(fields: Record<string, unknown>): string | undefined {\n const value = fields.type;\n if (value === undefined || value === null) return undefined;\n if (typeof value !== 'string' || value === '') return undefined;\n return value;\n}\n\nexport function parse(content: string, file = ''): ParseResult {\n const fence = extractFrontmatter(content);\n if (fence.kind === 'none') {\n const spans = headingSpans(content, 0);\n return {\n ok: true,\n document: freezeDocument(content, undefined, {}, sectionsRecord(spans, content), {\n root: null,\n yamlEnd: 0,\n bodyStart: 0,\n }),\n };\n }\n if (fence.kind === 'unclosed') return { ok: false, refusal: refuse(file, 'frontmatter-fence') };\n try {\n const root = parseYamlMapping(content, fence.yamlStart, fence.yamlEnd);\n const fields = jsValue(root);\n if (fields === null || typeof fields !== 'object' || Array.isArray(fields)) {\n return { ok: false, refusal: refuse(file, 'frontmatter-fence') };\n }\n const bodyStart = bodyStartAfterYaml(content, fence.yamlEnd);\n const spans = headingSpans(content, bodyStart);\n const record = fields as Record<string, unknown>;\n return {\n ok: true,\n document: freezeDocument(\n content,\n declaredType(record),\n record,\n sectionsRecord(spans, content),\n {\n root,\n yamlEnd: fence.yamlEnd,\n bodyStart,\n },\n ),\n };\n } catch (error) {\n if (error instanceof YamlError)\n return { ok: false, refusal: refuse(file, 'frontmatter-fence') };\n throw error;\n }\n}\n\nfunction splice(content: string, start: number, end: number, insert: string): string {\n return content.slice(0, start) + insert + content.slice(end);\n}\n\nfunction applyField(document: Document, name: string, value: unknown, prior: unknown): ApplyResult {\n const internal = internals.get(document);\n if (internal === undefined || internal.root === null) {\n return { outcome: 'refuse', refusal: refuse('', 'frontmatter-fence', name) };\n }\n if (!equalValue(document.fields[name], prior)) {\n return { outcome: 'stale', document };\n }\n let nextContent: string;\n const existing = mapEntry(internal.root, name);\n if (existing !== undefined) {\n nextContent = splice(\n document.content,\n existing.value.start,\n existing.value.end,\n serializeJs(value),\n );\n } else {\n const nl = lineEnding(document.content);\n const line = `${serializeKey(name)}: ${serializeJs(value)}${nl}`;\n const before = document.content.slice(0, internal.yamlEnd);\n const prefix = before.endsWith('\\n') || before.endsWith('\\r\\n') ? '' : nl;\n nextContent = splice(document.content, internal.yamlEnd, internal.yamlEnd, `${prefix}${line}`);\n }\n const parsed = parse(nextContent);\n if (!parsed.ok) return { outcome: 'refuse', refusal: parsed.refusal };\n return { outcome: 'applied', document: parsed.document };\n}\n\nfunction applySection(document: Document, name: string, value: string, prior: string): ApplyResult {\n const internal = internals.get(document);\n if (internal === undefined)\n return { outcome: 'refuse', refusal: refuse('', 'required-section', name) };\n const spans = headingSpans(document.content, internal.bodyStart);\n const span = spans.find((item) => item.name === name);\n if (span === undefined)\n return { outcome: 'refuse', refusal: refuse('', 'required-section', name) };\n const current = document.content.slice(span.bodyStart, span.bodyEnd);\n if (current !== prior) return { outcome: 'stale', document };\n const parsed = parse(splice(document.content, span.bodyStart, span.bodyEnd, value));\n if (!parsed.ok) return { outcome: 'refuse', refusal: parsed.refusal };\n return { outcome: 'applied', document: parsed.document };\n}\n\nexport function apply(document: Document, change: Change): ApplyResult {\n try {\n if (change.kind === 'field')\n return applyField(document, change.name, change.value, change.prior);\n return applySection(document, change.name, change.value, change.prior);\n } catch (error) {\n if (error instanceof YamlError) {\n return { outcome: 'refuse', refusal: refuse('', 'frontmatter-fence', change.name) };\n }\n throw error;\n }\n}\n\nexport function serialize(document: Document): string {\n return document.content;\n}\n"],"names":["headingSpans","sectionsRecord","refusal","bodyStartAfterYaml","equalValue","extractFrontmatter","jsValue","lineEnding","mapEntry","parseYamlMapping","serializeJs","serializeKey","YamlError","internals","WeakMap","refuse","file","rule","location","undefined","freezeDocument","content","type","fields","sections","internal","document","Object","freeze","set","declaredType","value","parse","fence","kind","spans","ok","root","yamlEnd","bodyStart","yamlStart","Array","isArray","record","error","splice","start","end","insert","slice","applyField","name","prior","get","outcome","nextContent","existing","nl","line","before","prefix","endsWith","parsed","applySection","span","find","item","current","bodyEnd","apply","change","serialize"],"mappings":"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"}
1
+ {"version":3,"sources":["/workspace/packages/mdmodel/src/document.ts"],"sourcesContent":["import { hrefOccurrences } from './links.js';\nimport { classifyHref, hrefSuffix } from './paths.js';\nimport { headingSpans, sectionsRecord } from './sections.js';\nimport { refusal } from './refuse.js';\nimport type { ApplyResult, Change, Document, Link, ParseResult } from './types.js';\nimport {\n bodyStartAfterYaml,\n bodyStartOf,\n equalValue,\n extractFrontmatter,\n jsValue,\n lineEnding,\n mapEntry,\n parseYamlMapping,\n serializeJs,\n serializeKey,\n YamlError,\n type YamlMap,\n} from './yaml.js';\n\ntype Internal = {\n readonly root: YamlMap | null;\n readonly yamlEnd: number;\n readonly bodyStart: number;\n};\n\nconst internals = new WeakMap<Document, Internal>();\n\nfunction refuse(file: string, rule: string, location?: string) {\n return location === undefined ? refusal(file, rule) : refusal(file, rule, { location });\n}\n\nfunction freezeDocument(\n content: string,\n type: string | undefined,\n fields: Record<string, unknown>,\n preamble: string,\n sections: Record<string, string>,\n internal: Internal,\n): Document {\n const document: Document = Object.freeze({\n content,\n type,\n fields: Object.freeze(fields),\n preamble,\n sections: Object.freeze(sections),\n });\n internals.set(document, internal);\n return document;\n}\n\nfunction declaredType(fields: Record<string, unknown>): string | undefined {\n const value = fields.type;\n if (value === undefined || value === null) return undefined;\n if (typeof value !== 'string' || value === '') return undefined;\n return value;\n}\n\nexport function parse(content: string, file = ''): ParseResult {\n const fence = extractFrontmatter(content);\n if (fence.kind === 'none') {\n const spans = headingSpans(content, 0);\n return {\n ok: true,\n document: freezeDocument(\n content,\n undefined,\n {},\n content.slice(0, spans[0]?.headingStart),\n sectionsRecord(spans, content),\n {\n root: null,\n yamlEnd: 0,\n bodyStart: 0,\n },\n ),\n };\n }\n if (fence.kind === 'unclosed') return { ok: false, refusal: refuse(file, 'frontmatter-fence') };\n try {\n const root = parseYamlMapping(content, fence.yamlStart, fence.yamlEnd);\n const fields = jsValue(root);\n if (fields === null || typeof fields !== 'object' || Array.isArray(fields)) {\n return { ok: false, refusal: refuse(file, 'frontmatter-fence') };\n }\n const bodyStart = bodyStartAfterYaml(content, fence.yamlEnd);\n const spans = headingSpans(content, bodyStart);\n const record = fields as Record<string, unknown>;\n return {\n ok: true,\n document: freezeDocument(\n content,\n declaredType(record),\n record,\n content.slice(bodyStart, spans[0]?.headingStart),\n sectionsRecord(spans, content),\n {\n root,\n yamlEnd: fence.yamlEnd,\n bodyStart,\n },\n ),\n };\n } catch (error) {\n if (error instanceof YamlError)\n return { ok: false, refusal: refuse(file, 'frontmatter-fence') };\n throw error;\n }\n}\n\nfunction splice(content: string, start: number, end: number, insert: string): string {\n return content.slice(0, start) + insert + content.slice(end);\n}\n\nfunction applyField(document: Document, name: string, value: unknown, prior: unknown): ApplyResult {\n const internal = internals.get(document);\n if (internal === undefined || internal.root === null) {\n return { outcome: 'refuse', refusal: refuse('', 'frontmatter-fence', name) };\n }\n if (!equalValue(document.fields[name], prior)) {\n return { outcome: 'stale', document };\n }\n let nextContent: string;\n const existing = mapEntry(internal.root, name);\n if (existing !== undefined) {\n nextContent = splice(\n document.content,\n existing.value.start,\n existing.value.end,\n serializeJs(value),\n );\n } else {\n const nl = lineEnding(document.content);\n const line = `${serializeKey(name)}: ${serializeJs(value)}${nl}`;\n const before = document.content.slice(0, internal.yamlEnd);\n const prefix = before.endsWith('\\n') || before.endsWith('\\r\\n') ? '' : nl;\n nextContent = splice(document.content, internal.yamlEnd, internal.yamlEnd, `${prefix}${line}`);\n }\n const parsed = parse(nextContent);\n if (!parsed.ok) return { outcome: 'refuse', refusal: parsed.refusal };\n return { outcome: 'applied', document: parsed.document };\n}\n\nfunction applySection(document: Document, name: string, value: string, prior: string): ApplyResult {\n const internal = internals.get(document);\n if (internal === undefined)\n return { outcome: 'refuse', refusal: refuse('', 'required-section', name) };\n const spans = headingSpans(document.content, internal.bodyStart);\n const span = spans.find((item) => item.name === name);\n if (span === undefined)\n return { outcome: 'refuse', refusal: refuse('', 'required-section', name) };\n const current = document.content.slice(span.bodyStart, span.bodyEnd);\n if (current !== prior) return { outcome: 'stale', document };\n const parsed = parse(splice(document.content, span.bodyStart, span.bodyEnd, value));\n if (!parsed.ok) return { outcome: 'refuse', refusal: parsed.refusal };\n return { outcome: 'applied', document: parsed.document };\n}\n\nfunction applyPreamble(document: Document, value: string, prior: string): ApplyResult {\n if (document.preamble !== prior) return { outcome: 'stale', document };\n const start = bodyStartOf(document.content);\n const parsed = parse(splice(document.content, start, start + document.preamble.length, value));\n if (!parsed.ok) return { outcome: 'refuse', refusal: parsed.refusal };\n return { outcome: 'applied', document: parsed.document };\n}\n\nfunction fitsBare(to: string): boolean {\n if (to === '' || to.startsWith('<')) return false;\n let depth = 0;\n for (const character of to) {\n if (/[\\s\\u0000-\\u001f\\u007f]/.test(character)) return false;\n if (character === '(') depth += 1;\n else if (character === ')') {\n if (depth === 0) return false;\n depth -= 1;\n }\n }\n return depth === 0;\n}\n\nfunction fitsBrackets(to: string): boolean {\n return to !== '' && !/[<>\\n\\r]/.test(to);\n}\n\nfunction destinationText(to: string, bracketed: boolean): string | null {\n if (fitsBare(to)) return bracketed && fitsBrackets(to) ? `<${to}>` : to;\n if (fitsBrackets(to)) return `<${to}>`;\n return null;\n}\n\nfunction applyLink(document: Document, href: string, to: string): ApplyResult {\n const content = document.content;\n const bodyStart = bodyStartOf(content);\n const matches = hrefOccurrences(content.slice(bodyStart)).filter(\n (occurrence) => occurrence.href === href,\n );\n if (matches.length === 0) return { outcome: 'stale', document };\n const written = to + hrefSuffix(href);\n let rewritten = '';\n let cursor = 0;\n for (const match of matches) {\n const text = destinationText(written, match.bracketed);\n if (text === null)\n return { outcome: 'refuse', refusal: refuse('', 'unwritable-link', written) };\n rewritten += content.slice(cursor, bodyStart + match.start);\n rewritten += text;\n cursor = bodyStart + match.end;\n }\n const parsed = parse(rewritten + content.slice(cursor));\n if (!parsed.ok) return { outcome: 'refuse', refusal: parsed.refusal };\n return { outcome: 'applied', document: parsed.document };\n}\n\nexport function links(document: Document, file: string): readonly Link[] {\n const found: Link[] = [];\n const seen = new Set<string>();\n for (const occurrence of hrefOccurrences(document.content.slice(bodyStartOf(document.content)))) {\n if (seen.has(occurrence.href)) continue;\n const resolved = classifyHref(file, occurrence.href);\n if (resolved.kind !== 'path') continue;\n seen.add(occurrence.href);\n found.push({ href: occurrence.href, target: resolved.path });\n }\n return found;\n}\n\nexport function apply(document: Document, change: Change): ApplyResult {\n if (change.kind === 'link') return applyLink(document, change.href, change.to);\n if (change.kind === 'preamble') return applyPreamble(document, change.value, change.prior);\n try {\n if (change.kind === 'field')\n return applyField(document, change.name, change.value, change.prior);\n return applySection(document, change.name, change.value, change.prior);\n } catch (error) {\n if (error instanceof YamlError) {\n return { outcome: 'refuse', refusal: refuse('', 'frontmatter-fence', change.name) };\n }\n throw error;\n }\n}\n\nexport function serialize(document: Document): string {\n return document.content;\n}\n\nexport function frontmatter(document: Document): YamlMap | null {\n return internals.get(document)?.root ?? null;\n}\n"],"names":["hrefOccurrences","classifyHref","hrefSuffix","headingSpans","sectionsRecord","refusal","bodyStartAfterYaml","bodyStartOf","equalValue","extractFrontmatter","jsValue","lineEnding","mapEntry","parseYamlMapping","serializeJs","serializeKey","YamlError","internals","WeakMap","refuse","file","rule","location","undefined","freezeDocument","content","type","fields","preamble","sections","internal","document","Object","freeze","set","declaredType","value","parse","fence","kind","spans","ok","slice","headingStart","root","yamlEnd","bodyStart","yamlStart","Array","isArray","record","error","splice","start","end","insert","applyField","name","prior","get","outcome","nextContent","existing","nl","line","before","prefix","endsWith","parsed","applySection","span","find","item","current","bodyEnd","applyPreamble","length","fitsBare","to","startsWith","depth","character","test","fitsBrackets","destinationText","bracketed","applyLink","href","matches","filter","occurrence","written","rewritten","cursor","match","text","links","found","seen","Set","has","resolved","add","push","target","path","apply","change","serialize","frontmatter"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
- export { apply, parse, serialize } from './document.js';
1
+ export { divide } from './divide.js';
2
+ export { apply, links, parse, serialize } from './document.js';
2
3
  export { MARKDOWN_SYNTAX_PROFILE } from './profile.js';
3
- export type { ApplyResult, Change, Document, Library, ParseResult, Refusal, Validation, } from './types.js';
4
+ export { project } from './project.js';
5
+ export type { ApplyResult, Change, Division, DivisionContext, Document, Library, Link, ParseResult, Projection, ProjectionContext, Refusal, Span, Validation, ValidationContext, } from './types.js';
4
6
  export { validate } from './validate.js';
5
7
  export { VERSION } from './version.js';
6
8
  //# sourceMappingURL=index.d.ts.map