poe-code 3.0.181 → 3.0.183

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 (187) hide show
  1. package/dist/bin/poe-agent.js +1 -1
  2. package/dist/cli/commands/config.js +3 -4
  3. package/dist/cli/commands/config.js.map +1 -1
  4. package/dist/cli/commands/configure.js +12 -3
  5. package/dist/cli/commands/configure.js.map +1 -1
  6. package/dist/cli/commands/dashboard-loop-shared.d.ts +7 -9
  7. package/dist/cli/commands/dashboard-loop-shared.js +16 -9
  8. package/dist/cli/commands/dashboard-loop-shared.js.map +1 -1
  9. package/dist/cli/commands/experiment.js +41 -32
  10. package/dist/cli/commands/experiment.js.map +1 -1
  11. package/dist/cli/commands/mcp.js +7 -2
  12. package/dist/cli/commands/mcp.js.map +1 -1
  13. package/dist/cli/commands/memory.d.ts +3 -0
  14. package/dist/cli/commands/memory.js +181 -0
  15. package/dist/cli/commands/memory.js.map +1 -0
  16. package/dist/cli/commands/pipeline-init.d.ts +17 -0
  17. package/dist/cli/commands/pipeline-init.js +166 -0
  18. package/dist/cli/commands/pipeline-init.js.map +1 -0
  19. package/dist/cli/commands/pipeline.js +187 -45
  20. package/dist/cli/commands/pipeline.js.map +1 -1
  21. package/dist/cli/commands/plan.d.ts +1 -0
  22. package/dist/cli/commands/plan.js +196 -39
  23. package/dist/cli/commands/plan.js.map +1 -1
  24. package/dist/cli/commands/ralph.js +24 -24
  25. package/dist/cli/commands/ralph.js.map +1 -1
  26. package/dist/cli/commands/shared.d.ts +3 -0
  27. package/dist/cli/commands/shared.js +27 -1
  28. package/dist/cli/commands/shared.js.map +1 -1
  29. package/dist/cli/commands/skill.js +21 -10
  30. package/dist/cli/commands/skill.js.map +1 -1
  31. package/dist/cli/commands/spawn-poe-agent.d.ts +2 -0
  32. package/dist/cli/commands/spawn-poe-agent.js +47 -0
  33. package/dist/cli/commands/spawn-poe-agent.js.map +1 -0
  34. package/dist/cli/commands/spawn.js +21 -1
  35. package/dist/cli/commands/spawn.js.map +1 -1
  36. package/dist/cli/commands/utils-symlink-agents.d.ts +6 -0
  37. package/dist/cli/commands/utils-symlink-agents.js +78 -0
  38. package/dist/cli/commands/utils-symlink-agents.js.map +1 -0
  39. package/dist/cli/commands/utils-symlink-ops.d.ts +29 -0
  40. package/dist/cli/commands/utils-symlink-ops.js +76 -0
  41. package/dist/cli/commands/utils-symlink-ops.js.map +1 -0
  42. package/dist/cli/commands/utils-symlink-skills.d.ts +15 -0
  43. package/dist/cli/commands/utils-symlink-skills.js +136 -0
  44. package/dist/cli/commands/utils-symlink-skills.js.map +1 -0
  45. package/dist/cli/commands/utils-symlink.d.ts +3 -0
  46. package/dist/cli/commands/utils-symlink.js +40 -0
  47. package/dist/cli/commands/utils-symlink.js.map +1 -0
  48. package/dist/cli/commands/utils.js +2 -0
  49. package/dist/cli/commands/utils.js.map +1 -1
  50. package/dist/cli/constants.d.ts +2 -2
  51. package/dist/cli/constants.js +1 -1
  52. package/dist/cli/constants.js.map +1 -1
  53. package/dist/cli/poe-agent-main.d.ts +10 -1
  54. package/dist/cli/poe-agent-main.js +89 -47
  55. package/dist/cli/poe-agent-main.js.map +1 -1
  56. package/dist/cli/program.js +13 -1
  57. package/dist/cli/program.js.map +1 -1
  58. package/dist/corpus/001-archaeoastronomy.md +479 -0
  59. package/dist/corpus/002-magnetohydrodynamics.md +475 -0
  60. package/dist/corpus/003-biosemiotics.md +483 -0
  61. package/dist/corpus/004-cryopedology.md +483 -0
  62. package/dist/corpus/005-geomicrobiology.md +479 -0
  63. package/dist/corpus/006-aeronomy.md +487 -0
  64. package/dist/corpus/007-paleoclimatology.md +479 -0
  65. package/dist/corpus/008-hydrogeophysics.md +479 -0
  66. package/dist/corpus/009-magnetostratigraphy.md +475 -0
  67. package/dist/corpus/010-isotope-hydrology.md +481 -0
  68. package/dist/corpus/011-speleothem-geochemistry.md +474 -0
  69. package/dist/corpus/012-astrobiogeochemistry.md +475 -0
  70. package/dist/corpus/013-neuroethology.md +483 -0
  71. package/dist/corpus/014-chronophysiology.md +483 -0
  72. package/dist/corpus/015-limnogeochemistry.md +475 -0
  73. package/dist/corpus/016-palynology.md +483 -0
  74. package/dist/corpus/017-volcanotectonics.md +473 -0
  75. package/dist/corpus/018-seismotectonics.md +473 -0
  76. package/dist/corpus/019-biogeomorphology.md +475 -0
  77. package/dist/corpus/020-geobiophysics.md +479 -0
  78. package/dist/corpus/021-phytolith-analysis.md +481 -0
  79. package/dist/corpus/022-archaeometallurgy.md +479 -0
  80. package/dist/corpus/023-paleomagnetism.md +479 -0
  81. package/dist/corpus/024-biocalorimetry.md +475 -0
  82. package/dist/corpus/025-atmospheric-chemiluminescence.md +473 -0
  83. package/dist/corpus/026-cryoseismology.md +479 -0
  84. package/dist/corpus/027-extremophile-radiobiology.md +475 -0
  85. package/dist/corpus/028-heliophysics.md +479 -0
  86. package/dist/corpus/029-astroparticle-geophysics.md +474 -0
  87. package/dist/corpus/030-glaciohydrology.md +479 -0
  88. package/dist/corpus/031-permafrost-microbiology.md +477 -0
  89. package/dist/corpus/032-ecoacoustics.md +479 -0
  90. package/dist/corpus/033-dendroclimatology.md +473 -0
  91. package/dist/corpus/034-ionospheric-tomography.md +477 -0
  92. package/dist/corpus/035-marine-geodesy.md +481 -0
  93. package/dist/corpus/036-sedimentary-ancient-dna.md +481 -0
  94. package/dist/corpus/037-myrmecochory-dynamics.md +474 -0
  95. package/dist/corpus/038-chemosensory-ecology.md +477 -0
  96. package/dist/corpus/039-spintronics-materials.md +479 -0
  97. package/dist/corpus/040-nanotoxicology.md +483 -0
  98. package/dist/corpus/041-cosmochemistry.md +483 -0
  99. package/dist/corpus/042-quaternary-geochronology.md +471 -0
  100. package/dist/corpus/043-biophotonics.md +479 -0
  101. package/dist/corpus/044-evolutionary-morphometrics.md +481 -0
  102. package/dist/corpus/045-cryovolcanology.md +475 -0
  103. package/dist/corpus/046-exoplanet-atmospheric-dynamics.md +479 -0
  104. package/dist/corpus/047-microbial-electrosynthesis.md +477 -0
  105. package/dist/corpus/048-paleoseismology.md +479 -0
  106. package/dist/corpus/049-actinide-geochemistry.md +477 -0
  107. package/dist/corpus/050-quantum-biology.md +489 -0
  108. package/dist/index.d.ts +3 -2
  109. package/dist/index.js +31666 -23440
  110. package/dist/index.js.map +4 -4
  111. package/dist/plan/document-schema.d.ts +21 -0
  112. package/dist/plan/document-schema.js +16 -0
  113. package/dist/plan/document-schema.js.map +1 -0
  114. package/dist/providers/claude-code.js +31 -13
  115. package/dist/providers/claude-code.js.map +4 -4
  116. package/dist/providers/codex.js +31 -13
  117. package/dist/providers/codex.js.map +4 -4
  118. package/dist/providers/goose.js +32 -14
  119. package/dist/providers/goose.js.map +4 -4
  120. package/dist/providers/kimi.js +31 -13
  121. package/dist/providers/kimi.js.map +4 -4
  122. package/dist/providers/opencode.js +32 -14
  123. package/dist/providers/opencode.js.map +4 -4
  124. package/dist/providers/poe-agent.d.ts +5 -0
  125. package/dist/providers/poe-agent.js +21214 -4016
  126. package/dist/providers/poe-agent.js.map +4 -4
  127. package/dist/sdk/container.js +4 -0
  128. package/dist/sdk/container.js.map +1 -1
  129. package/dist/sdk/pipeline.d.ts +27 -0
  130. package/dist/sdk/pipeline.js +91 -1
  131. package/dist/sdk/pipeline.js.map +1 -1
  132. package/dist/sdk/spawn.js +8 -2
  133. package/dist/sdk/spawn.js.map +1 -1
  134. package/dist/sdk/types.d.ts +5 -1
  135. package/dist/services/config.d.ts +47 -33
  136. package/dist/services/config.js +22 -20
  137. package/dist/services/config.js.map +1 -1
  138. package/dist/templates/pipeline/SKILL_plan.md +22 -8
  139. package/dist/templates/pipeline/steps.yaml.mustache +1 -1
  140. package/dist/templates/skill/poe-generate.md +47 -0
  141. package/dist/templates/skill/terminal-pilot.md +45 -0
  142. package/dist/utils/dry-run.d.ts +8 -0
  143. package/dist/utils/dry-run.js +16 -0
  144. package/dist/utils/dry-run.js.map +1 -1
  145. package/dist/utils/file-system.d.ts +4 -0
  146. package/package.json +19 -9
  147. package/packages/cmdkit/dist/cli.js +42 -22
  148. package/packages/cmdkit/dist/cli.js.map +3 -3
  149. package/packages/cmdkit/dist/index.js +52 -9
  150. package/packages/cmdkit/dist/index.js.map +2 -2
  151. package/packages/cmdkit/dist/mcp.d.ts +15 -0
  152. package/packages/cmdkit/dist/mcp.js +121 -20
  153. package/packages/cmdkit/dist/mcp.js.map +3 -3
  154. package/packages/cmdkit/dist/number-schema.d.ts +3 -0
  155. package/packages/cmdkit/dist/number-schema.js +8 -0
  156. package/packages/cmdkit/dist/schema-scope.d.ts +4 -0
  157. package/packages/cmdkit/dist/schema-scope.js +34 -0
  158. package/packages/cmdkit/dist/sdk.js +58 -3
  159. package/packages/cmdkit/dist/sdk.js.map +3 -3
  160. package/packages/cmdkit-schema/dist/index.compile-check.js +1 -0
  161. package/packages/cmdkit-schema/dist/index.d.ts +59 -16
  162. package/packages/cmdkit-schema/dist/index.js +53 -8
  163. package/packages/design-system/dist/dashboard/components/footer.js +2 -3
  164. package/packages/design-system/dist/dashboard/components/output-pane.d.ts +1 -10
  165. package/packages/design-system/dist/dashboard/components/output-pane.js +5 -74
  166. package/packages/design-system/dist/dashboard/dashboard.js +6 -26
  167. package/packages/design-system/dist/dashboard/index.d.ts +1 -0
  168. package/packages/design-system/dist/dashboard/index.js +1 -0
  169. package/packages/design-system/dist/dashboard/keymap.js +4 -19
  170. package/packages/design-system/dist/dashboard/should-use-dashboard.d.ts +10 -0
  171. package/packages/design-system/dist/dashboard/should-use-dashboard.js +7 -0
  172. package/packages/design-system/dist/dashboard/snapshot.js +1 -5
  173. package/packages/design-system/dist/dashboard/store.d.ts +1 -2
  174. package/packages/design-system/dist/dashboard/store.js +6 -62
  175. package/packages/design-system/dist/dashboard/terminal.d.ts +2 -0
  176. package/packages/design-system/dist/dashboard/terminal.js +18 -0
  177. package/packages/design-system/dist/dashboard/types.d.ts +1 -11
  178. package/packages/design-system/dist/index.d.ts +1 -1
  179. package/packages/design-system/dist/index.js +1 -1
  180. package/packages/design-system/dist/terminal-markdown/ast.d.ts +10 -2
  181. package/packages/design-system/dist/terminal-markdown/parser/block.d.ts +2 -1
  182. package/packages/design-system/dist/terminal-markdown/parser/block.js +400 -110
  183. package/packages/design-system/dist/terminal-markdown/parser/frontmatter.d.ts +2 -0
  184. package/packages/design-system/dist/terminal-markdown/parser/frontmatter.js +28 -11
  185. package/packages/design-system/dist/terminal-markdown/parser/inline.d.ts +4 -0
  186. package/packages/design-system/dist/terminal-markdown/parser/inline.js +134 -55
  187. package/packages/design-system/dist/terminal-markdown/parser.js +36 -7
@@ -1,6 +1,8 @@
1
+ import type { MdRange } from "../ast.js";
1
2
  type ExtractedFrontmatter = {
2
3
  frontmatter?: Record<string, unknown>;
3
4
  body: string;
5
+ range?: MdRange;
4
6
  };
5
7
  export declare function extractFrontmatter(markdown: string): ExtractedFrontmatter;
6
8
  export {};
@@ -100,22 +100,24 @@ class YamlSubsetParser {
100
100
  }
101
101
  }
102
102
  export function extractFrontmatter(markdown) {
103
- const content = stripBom(markdown);
104
- if (!startsWithFrontmatterFence(content)) {
103
+ if (!startsWithFrontmatterFence(markdown)) {
104
+ return { body: markdown };
105
+ }
106
+ const openingLine = readLine(markdown, 0);
107
+ if (stripBom(openingLine.text) !== "---") {
105
108
  return { body: markdown };
106
109
  }
107
- const openingLine = readLine(content, 0);
108
110
  let position = openingLine.nextPosition;
109
111
  let closingFenceStart;
110
112
  let closingFenceNextPosition;
111
- while (position <= content.length) {
112
- const line = readLine(content, position);
113
+ while (position <= markdown.length) {
114
+ const line = readLine(markdown, position);
113
115
  if (line.text === "---") {
114
116
  closingFenceStart = line.start;
115
117
  closingFenceNextPosition = line.nextPosition;
116
118
  break;
117
119
  }
118
- if (line.nextPosition >= content.length) {
120
+ if (line.nextPosition >= markdown.length) {
119
121
  break;
120
122
  }
121
123
  position = line.nextPosition;
@@ -123,12 +125,15 @@ export function extractFrontmatter(markdown) {
123
125
  if (closingFenceStart === undefined || closingFenceNextPosition === undefined) {
124
126
  return { body: markdown };
125
127
  }
126
- const rawFrontmatter = sliceFrontmatterBlock(content, openingLine.nextPosition, closingFenceStart);
128
+ const rawFrontmatter = sliceFrontmatterBlock(markdown, openingLine.nextPosition, closingFenceStart);
127
129
  const frontmatter = parseFrontmatterBlock(rawFrontmatter);
128
- return {
130
+ return withRange({
129
131
  frontmatter,
130
- body: content.slice(closingFenceNextPosition)
131
- };
132
+ body: markdown.slice(closingFenceNextPosition)
133
+ }, {
134
+ start: 0,
135
+ end: Buffer.byteLength(markdown.slice(0, closingFenceNextPosition), "utf8")
136
+ });
132
137
  }
133
138
  function parseFrontmatterBlock(yamlBlock) {
134
139
  if (yamlBlock.length === 0) {
@@ -338,11 +343,23 @@ function sliceFrontmatterBlock(content, start, end) {
338
343
  return content.slice(start, sliceEnd);
339
344
  }
340
345
  function startsWithFrontmatterFence(value) {
341
- return value.startsWith("---\n") || value.startsWith("---\r\n");
346
+ return (value.startsWith("---\n") ||
347
+ value.startsWith("---\r\n") ||
348
+ value.startsWith("\uFEFF---\n") ||
349
+ value.startsWith("\uFEFF---\r\n"));
342
350
  }
343
351
  function stripBom(value) {
344
352
  return value.startsWith("\uFEFF") ? value.slice(1) : value;
345
353
  }
354
+ function withRange(value, range) {
355
+ Object.defineProperty(value, "range", {
356
+ value: range,
357
+ enumerable: false,
358
+ configurable: true,
359
+ writable: true
360
+ });
361
+ return value;
362
+ }
346
363
  function readLine(input, position) {
347
364
  let end = position;
348
365
  while (end < input.length && input[end] !== "\n" && input[end] !== "\r") {
@@ -1,6 +1,10 @@
1
1
  import type { MdNode } from "../ast.js";
2
+ type OffsetMap = readonly number[];
2
3
  export type ParseInlineOptions = {
3
4
  footnoteLabels?: ReadonlySet<string>;
4
5
  allowLiteralAutolinks?: boolean;
6
+ offset?: number;
7
+ offsets?: OffsetMap;
5
8
  };
6
9
  export declare function parseInline(raw: string, options?: ParseInlineOptions): MdNode[];
10
+ export {};
@@ -96,24 +96,32 @@ export function parseInline(raw, options = {}) {
96
96
  const delimiters = [];
97
97
  const footnoteLabels = options.footnoteLabels;
98
98
  const allowLiteralAutolinks = options.allowLiteralAutolinks ?? true;
99
+ const offsets = options.offsets ?? createOffsetMap(raw, options.offset ?? 0);
99
100
  let textBuffer = "";
101
+ let textStart = 0;
100
102
  let index = 0;
101
- const flushText = () => {
103
+ const appendText = (value, start) => {
104
+ if (textBuffer.length === 0) {
105
+ textStart = start;
106
+ }
107
+ textBuffer += value;
108
+ };
109
+ const flushText = (end = index) => {
102
110
  if (textBuffer.length === 0) {
103
111
  return;
104
112
  }
105
- nodes.push({ type: "text", value: textBuffer });
113
+ nodes.push(createTextNode(textBuffer, createRange(offsets, textStart, end)));
106
114
  textBuffer = "";
107
115
  };
108
116
  while (index < raw.length) {
109
117
  const char = raw[index];
110
118
  if (char === "\\" && index + 1 < raw.length && isEscapable(raw[index + 1])) {
111
- textBuffer += raw[index + 1];
119
+ appendText(raw[index + 1], index);
112
120
  index += 2;
113
121
  continue;
114
122
  }
115
123
  if (char === "`") {
116
- const code = parseInlineCode(raw, index);
124
+ const code = parseInlineCode(raw, index, offsets);
117
125
  if (code !== null) {
118
126
  flushText();
119
127
  nodes.push(code.node);
@@ -122,7 +130,7 @@ export function parseInline(raw, options = {}) {
122
130
  }
123
131
  }
124
132
  if (char === "!" && index + 1 < raw.length && raw[index + 1] === "[") {
125
- const image = parseImage(raw, index);
133
+ const image = parseImage(raw, index, offsets);
126
134
  if (image !== null) {
127
135
  flushText();
128
136
  nodes.push(image.node);
@@ -131,14 +139,14 @@ export function parseInline(raw, options = {}) {
131
139
  }
132
140
  }
133
141
  if (char === "[") {
134
- const footnoteReference = parseFootnoteReference(raw, index, footnoteLabels);
142
+ const footnoteReference = parseFootnoteReference(raw, index, footnoteLabels, offsets);
135
143
  if (footnoteReference !== null) {
136
144
  flushText();
137
145
  nodes.push(footnoteReference.node);
138
146
  index = footnoteReference.end;
139
147
  continue;
140
148
  }
141
- const link = parseLink(raw, index, footnoteLabels);
149
+ const link = parseLink(raw, index, footnoteLabels, offsets);
142
150
  if (link !== null) {
143
151
  flushText();
144
152
  nodes.push(link.node);
@@ -147,14 +155,14 @@ export function parseInline(raw, options = {}) {
147
155
  }
148
156
  }
149
157
  if (char === "<") {
150
- const autolink = parseAutolink(raw, index);
158
+ const autolink = parseAutolink(raw, index, offsets);
151
159
  if (autolink !== null) {
152
160
  flushText();
153
161
  nodes.push(autolink.node);
154
162
  index = autolink.end;
155
163
  continue;
156
164
  }
157
- const html = parseInlineHtmlTag(raw, index);
165
+ const html = parseInlineHtmlTag(raw, index, offsets);
158
166
  if (html !== null) {
159
167
  flushText();
160
168
  nodes.push(html.node);
@@ -165,22 +173,23 @@ export function parseInline(raw, options = {}) {
165
173
  if (char === "\n") {
166
174
  if (textBuffer.endsWith("\\")) {
167
175
  textBuffer = textBuffer.slice(0, -1);
168
- flushText();
169
- nodes.push({ type: "break" });
176
+ flushText(index - 1);
177
+ nodes.push(withRange({ type: "break" }, createRange(offsets, index, index + 1)));
170
178
  index += 1;
171
179
  continue;
172
180
  }
173
181
  const trailingSpaceStart = findTrailingHardBreakSpaceStart(textBuffer);
174
182
  if (trailingSpaceStart !== -1) {
183
+ const trailingSpaceCount = textBuffer.length - trailingSpaceStart;
175
184
  textBuffer = textBuffer.slice(0, trailingSpaceStart);
176
- flushText();
177
- nodes.push({ type: "break" });
185
+ flushText(index - trailingSpaceCount);
186
+ nodes.push(withRange({ type: "break" }, createRange(offsets, index, index + 1)));
178
187
  index += 1;
179
188
  continue;
180
189
  }
181
190
  }
182
191
  if (allowLiteralAutolinks) {
183
- const literalAutolink = parseLiteralAutolink(raw, index);
192
+ const literalAutolink = parseLiteralAutolink(raw, index, offsets);
184
193
  if (literalAutolink !== null) {
185
194
  flushText();
186
195
  nodes.push(literalAutolink.node);
@@ -192,10 +201,10 @@ export function parseInline(raw, options = {}) {
192
201
  const delimiter = parseDelimiter(raw, index, char);
193
202
  if (delimiter !== null) {
194
203
  flushText();
195
- const node = {
196
- type: "text",
197
- value: raw.slice(index, index + delimiter.length)
198
- };
204
+ const node = createTextNode(raw.slice(index, index + delimiter.length), {
205
+ start: offsets[index] ?? 0,
206
+ end: offsets[index + delimiter.length] ?? offsets[offsets.length - 1] ?? 0
207
+ });
199
208
  nodes.push(node);
200
209
  delimiters.push({
201
210
  ...delimiter,
@@ -206,7 +215,7 @@ export function parseInline(raw, options = {}) {
206
215
  continue;
207
216
  }
208
217
  }
209
- textBuffer += char;
218
+ appendText(char, index);
210
219
  index += 1;
211
220
  }
212
221
  flushText();
@@ -407,14 +416,14 @@ function buildInlineNodes(nodes, delimiters, pairs) {
407
416
  }
408
417
  }
409
418
  if (delimiterEntry.delimiter.length > 0) {
410
- appendNode({
411
- type: "text",
412
- value: delimiterEntry.delimiter.marker.repeat(delimiterEntry.delimiter.length)
413
- });
419
+ appendNode(createTextNode(delimiterEntry.delimiter.marker.repeat(delimiterEntry.delimiter.length), node.range));
414
420
  }
415
421
  delimiterEntry.opens.sort((left, right) => right.sequence - left.sequence);
416
422
  for (const pair of delimiterEntry.opens) {
417
- const wrapper = createDelimiterNode(pair.kind);
423
+ const wrapper = withRange(createDelimiterNode(pair.kind), {
424
+ start: pair.opener.node.range?.start ?? pair.opener.position,
425
+ end: pair.closer.node.range?.end ?? pair.closer.position
426
+ });
418
427
  appendNode(wrapper);
419
428
  stack.push({ pair, children: wrapper.children });
420
429
  }
@@ -424,6 +433,30 @@ function buildInlineNodes(nodes, delimiters, pairs) {
424
433
  function createDelimiterNode(kind) {
425
434
  return { type: kind, children: [] };
426
435
  }
436
+ function createTextNode(value, range) {
437
+ return range === undefined ? { type: "text", value } : withRange({ type: "text", value }, range);
438
+ }
439
+ function withRange(node, range) {
440
+ Object.defineProperty(node, "range", {
441
+ value: range,
442
+ enumerable: false,
443
+ configurable: true,
444
+ writable: true
445
+ });
446
+ return node;
447
+ }
448
+ function mergeRanges(left, right) {
449
+ if (left === undefined) {
450
+ return right;
451
+ }
452
+ if (right === undefined) {
453
+ return left;
454
+ }
455
+ return {
456
+ start: Math.min(left.start, right.start),
457
+ end: Math.max(left.end, right.end)
458
+ };
459
+ }
427
460
  function normalizeInlineNodes(nodes) {
428
461
  const normalized = [];
429
462
  for (const node of nodes) {
@@ -434,6 +467,10 @@ function normalizeInlineNodes(nodes) {
434
467
  const previousNode = normalized[normalized.length - 1];
435
468
  if (previousNode?.type === "text" && nextNode.type === "text") {
436
469
  previousNode.value += nextNode.value;
470
+ const range = mergeRanges(previousNode.range, nextNode.range);
471
+ if (range !== undefined) {
472
+ withRange(previousNode, range);
473
+ }
437
474
  continue;
438
475
  }
439
476
  normalized.push(nextNode);
@@ -448,11 +485,12 @@ function normalizeInlineNode(node) {
448
485
  node.type === "strong" ||
449
486
  node.type === "strikethrough" ||
450
487
  node.type === "link") {
451
- return { ...node, children: normalizeInlineNodes(node.children) };
488
+ const nextNode = { ...node, children: normalizeInlineNodes(node.children) };
489
+ return node.range === undefined ? nextNode : withRange(nextNode, node.range);
452
490
  }
453
491
  return node;
454
492
  }
455
- function parseInlineCode(input, start) {
493
+ function parseInlineCode(input, start, offsets) {
456
494
  const fenceLength = readRunLength(input, start, "`");
457
495
  let index = start + fenceLength;
458
496
  while (index < input.length) {
@@ -463,10 +501,15 @@ function parseInlineCode(input, start) {
463
501
  const closingFenceLength = readRunLength(input, index, "`");
464
502
  if (closingFenceLength === fenceLength) {
465
503
  return {
466
- node: {
467
- type: "inlineCode",
468
- value: input.slice(start + fenceLength, index)
469
- },
504
+ node: offsets === undefined
505
+ ? {
506
+ type: "inlineCode",
507
+ value: input.slice(start + fenceLength, index)
508
+ }
509
+ : withRange({
510
+ type: "inlineCode",
511
+ value: input.slice(start + fenceLength, index)
512
+ }, createRange(offsets, start, index + fenceLength)),
470
513
  end: index + fenceLength
471
514
  };
472
515
  }
@@ -474,7 +517,7 @@ function parseInlineCode(input, start) {
474
517
  }
475
518
  return null;
476
519
  }
477
- function parseLink(input, start, footnoteLabels) {
520
+ function parseLink(input, start, footnoteLabels, offsets) {
478
521
  const label = parseBracketedLabel(input, start);
479
522
  if (label === null || label.end >= input.length || input[label.end] !== "(") {
480
523
  return null;
@@ -484,19 +527,22 @@ function parseLink(input, start, footnoteLabels) {
484
527
  return null;
485
528
  }
486
529
  return {
487
- node: {
530
+ node: withRange({
488
531
  type: "link",
489
532
  url: destination.url,
490
533
  ...(destination.title === undefined ? {} : { title: destination.title }),
491
534
  children: parseInline(label.value, {
492
535
  footnoteLabels,
493
- allowLiteralAutolinks: false
536
+ allowLiteralAutolinks: false,
537
+ ...(offsets === undefined
538
+ ? {}
539
+ : { offsets: sliceOffsetMap(offsets, label.contentStart, label.end - 1) })
494
540
  })
495
- },
541
+ }, offsets === undefined ? { start, end: destination.end } : createRange(offsets, start, destination.end)),
496
542
  end: destination.end
497
543
  };
498
544
  }
499
- function parseImage(input, start) {
545
+ function parseImage(input, start, offsets) {
500
546
  const label = parseBracketedLabel(input, start + 1);
501
547
  if (label === null || label.end >= input.length || input[label.end] !== "(") {
502
548
  return null;
@@ -506,12 +552,12 @@ function parseImage(input, start) {
506
552
  return null;
507
553
  }
508
554
  return {
509
- node: {
555
+ node: withRange({
510
556
  type: "image",
511
557
  url: destination.url,
512
558
  alt: decodeEscapes(label.value),
513
559
  ...(destination.title === undefined ? {} : { title: destination.title })
514
- },
560
+ }, offsets === undefined ? { start, end: destination.end } : createRange(offsets, start, destination.end)),
515
561
  end: destination.end
516
562
  };
517
563
  }
@@ -544,6 +590,7 @@ function parseBracketedLabel(input, start) {
544
590
  if (depth === 0) {
545
591
  return {
546
592
  value: input.slice(start + 1, index),
593
+ contentStart: start + 1,
547
594
  end: index + 1
548
595
  };
549
596
  }
@@ -631,7 +678,7 @@ function findTrailingQuotedSegmentStart(content, end, quote) {
631
678
  }
632
679
  return -1;
633
680
  }
634
- function parseAutolink(input, start) {
681
+ function parseAutolink(input, start, offsets) {
635
682
  let index = start + 1;
636
683
  while (index < input.length && input[index] !== ">") {
637
684
  const char = input[index];
@@ -648,15 +695,17 @@ function parseAutolink(input, start) {
648
695
  return null;
649
696
  }
650
697
  return {
651
- node: {
698
+ node: withRange({
652
699
  type: "link",
653
700
  url,
654
- children: [{ type: "text", value: url }]
655
- },
701
+ children: [
702
+ createTextNode(url, offsets === undefined ? { start: start + 1, end: index } : createRange(offsets, start + 1, index))
703
+ ]
704
+ }, offsets === undefined ? { start, end: index + 1 } : createRange(offsets, start, index + 1)),
656
705
  end: index + 1
657
706
  };
658
707
  }
659
- function parseFootnoteReference(input, start, footnoteLabels) {
708
+ function parseFootnoteReference(input, start, footnoteLabels, offsets) {
660
709
  if (footnoteLabels === undefined ||
661
710
  start + 3 >= input.length ||
662
711
  input[start] !== "[" ||
@@ -678,35 +727,35 @@ function parseFootnoteReference(input, start, footnoteLabels) {
678
727
  return null;
679
728
  }
680
729
  return {
681
- node: { type: "footnoteReference", label },
730
+ node: withRange({ type: "footnoteReference", label }, offsets === undefined ? { start, end: labelEnd + 1 } : createRange(offsets, start, labelEnd + 1)),
682
731
  end: labelEnd + 1
683
732
  };
684
733
  }
685
- function parseLiteralAutolink(input, start) {
734
+ function parseLiteralAutolink(input, start, offsets) {
686
735
  if (!isLiteralAutolinkBoundaryBefore(input, start)) {
687
736
  return null;
688
737
  }
689
738
  const urlLiteral = parseLiteralUrlAutolink(input, start);
690
739
  if (urlLiteral !== null) {
691
- return createLiteralAutolinkNode(urlLiteral.text, urlLiteral.url, urlLiteral.end);
740
+ return createLiteralAutolinkNode(urlLiteral.text, urlLiteral.url, start, urlLiteral.end, offsets);
692
741
  }
693
742
  const wwwLiteral = parseLiteralWwwAutolink(input, start);
694
743
  if (wwwLiteral !== null) {
695
- return createLiteralAutolinkNode(wwwLiteral.text, `http://${wwwLiteral.text}`, wwwLiteral.end);
744
+ return createLiteralAutolinkNode(wwwLiteral.text, `http://${wwwLiteral.text}`, start, wwwLiteral.end, offsets);
696
745
  }
697
746
  const emailLiteral = parseLiteralEmailAutolink(input, start);
698
747
  if (emailLiteral !== null) {
699
- return createLiteralAutolinkNode(emailLiteral.text, `mailto:${emailLiteral.text}`, emailLiteral.end);
748
+ return createLiteralAutolinkNode(emailLiteral.text, `mailto:${emailLiteral.text}`, start, emailLiteral.end, offsets);
700
749
  }
701
750
  return null;
702
751
  }
703
- function createLiteralAutolinkNode(text, url, end) {
752
+ function createLiteralAutolinkNode(text, url, start, end, offsets) {
704
753
  return {
705
- node: {
754
+ node: withRange({
706
755
  type: "link",
707
756
  url,
708
- children: [{ type: "text", value: text }]
709
- },
757
+ children: [createTextNode(text, offsets === undefined ? { start, end } : createRange(offsets, start, end))]
758
+ }, offsets === undefined ? { start, end } : createRange(offsets, start, end)),
710
759
  end
711
760
  };
712
761
  }
@@ -746,7 +795,7 @@ function parseLiteralEmailAutolink(input, start) {
746
795
  }
747
796
  return { text, end: start + text.length };
748
797
  }
749
- function parseInlineHtmlTag(input, start) {
798
+ function parseInlineHtmlTag(input, start, offsets) {
750
799
  if (input[start] !== "<") {
751
800
  return null;
752
801
  }
@@ -773,7 +822,7 @@ function parseInlineHtmlTag(input, start) {
773
822
  return null;
774
823
  }
775
824
  return {
776
- node: { type: "html", value: input.slice(start, index + 1) },
825
+ node: withRange({ type: "html", value: input.slice(start, index + 1) }, offsets === undefined ? { start, end: index + 1 } : createRange(offsets, start, index + 1)),
777
826
  end: index + 1
778
827
  };
779
828
  }
@@ -784,7 +833,7 @@ function parseInlineHtmlTag(input, start) {
784
833
  }
785
834
  if (input[index] === ">") {
786
835
  return {
787
- node: { type: "html", value: input.slice(start, index + 1) },
836
+ node: withRange({ type: "html", value: input.slice(start, index + 1) }, offsets === undefined ? { start, end: index + 1 } : createRange(offsets, start, index + 1)),
788
837
  end: index + 1
789
838
  };
790
839
  }
@@ -794,7 +843,9 @@ function parseInlineHtmlTag(input, start) {
794
843
  return null;
795
844
  }
796
845
  return {
797
- node: { type: "html", value: input.slice(start, selfClosingEnd + 1) },
846
+ node: withRange({ type: "html", value: input.slice(start, selfClosingEnd + 1) }, offsets === undefined
847
+ ? { start, end: selfClosingEnd + 1 }
848
+ : createRange(offsets, start, selfClosingEnd + 1)),
798
849
  end: selfClosingEnd + 1
799
850
  };
800
851
  }
@@ -1085,3 +1136,31 @@ function isHtmlAttributeNameChar(value) {
1085
1136
  value === "-" ||
1086
1137
  value === ".");
1087
1138
  }
1139
+ function createRange(offsets, start, end) {
1140
+ return {
1141
+ start: offsets[start] ?? offsets[offsets.length - 1] ?? 0,
1142
+ end: offsets[end] ?? offsets[offsets.length - 1] ?? 0
1143
+ };
1144
+ }
1145
+ function sliceOffsetMap(offsets, start, end) {
1146
+ return offsets.slice(start, end + 1);
1147
+ }
1148
+ function createOffsetMap(input, absoluteStart = 0) {
1149
+ const offsets = new Array(input.length + 1).fill(absoluteStart);
1150
+ let byteOffset = absoluteStart;
1151
+ let index = 0;
1152
+ while (index < input.length) {
1153
+ offsets[index] = byteOffset;
1154
+ const codePoint = input.codePointAt(index) ?? 0;
1155
+ const codeUnitLength = codePoint > 0xffff ? 2 : 1;
1156
+ const byteLength = codePoint <= 0x7f ? 1 : codePoint <= 0x7ff ? 2 : codePoint <= 0xffff ? 3 : 4;
1157
+ for (let offsetIndex = 1; offsetIndex < codeUnitLength; offsetIndex += 1) {
1158
+ offsets[index + offsetIndex] = byteOffset;
1159
+ }
1160
+ byteOffset += byteLength;
1161
+ index += codeUnitLength;
1162
+ offsets[index] = byteOffset;
1163
+ }
1164
+ offsets[input.length] = byteOffset;
1165
+ return offsets;
1166
+ }
@@ -1,13 +1,42 @@
1
1
  import { parseBlockDocument } from "./parser/block.js";
2
2
  export function parse(markdown) {
3
- const { frontmatter, children } = parseBlockDocument(markdown);
3
+ const { frontmatter, frontmatterRange, children } = parseBlockDocument(markdown);
4
+ const ast = withRange({
5
+ type: "root",
6
+ children: frontmatter === undefined
7
+ ? children
8
+ : [createFrontmatterNode(frontmatter, frontmatterRange), ...children]
9
+ }, {
10
+ start: 0,
11
+ end: Buffer.byteLength(markdown, "utf8")
12
+ });
4
13
  return {
5
14
  ...(frontmatter === undefined ? {} : { frontmatter }),
6
- ast: {
7
- type: "root",
8
- children: frontmatter === undefined
9
- ? children
10
- : [{ type: "frontmatter", data: frontmatter }, ...children]
11
- }
15
+ ast
12
16
  };
13
17
  }
18
+ function createFrontmatterNode(data, range) {
19
+ const node = {
20
+ type: "frontmatter",
21
+ data
22
+ };
23
+ if (range === undefined) {
24
+ return node;
25
+ }
26
+ Object.defineProperty(node, "range", {
27
+ value: range,
28
+ enumerable: false,
29
+ configurable: true,
30
+ writable: true
31
+ });
32
+ return node;
33
+ }
34
+ function withRange(node, range) {
35
+ Object.defineProperty(node, "range", {
36
+ value: range,
37
+ enumerable: false,
38
+ configurable: true,
39
+ writable: true
40
+ });
41
+ return node;
42
+ }