@effected/markdown 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/Frontmatter.js +272 -0
  2. package/FrontmatterResolver.js +273 -0
  3. package/JsonFrontmatter.js +46 -0
  4. package/LICENSE +21 -0
  5. package/Markdown.js +251 -0
  6. package/MarkdownDiagnostic.js +85 -0
  7. package/MarkdownDocument.js +248 -0
  8. package/MarkdownEdit.js +52 -0
  9. package/MarkdownFormat.js +380 -0
  10. package/MarkdownNode.js +641 -0
  11. package/MarkdownVisitor.js +88 -0
  12. package/Mdast.js +384 -0
  13. package/README.md +255 -0
  14. package/TomlFrontmatter.js +44 -0
  15. package/YamlFrontmatter.js +45 -0
  16. package/index.d.ts +2190 -0
  17. package/index.js +15 -0
  18. package/internal/blockParser.js +419 -0
  19. package/internal/blockRegistry.js +90 -0
  20. package/internal/blockTypes.js +27 -0
  21. package/internal/blocks/atxHeading.js +54 -0
  22. package/internal/blocks/blockquote.js +40 -0
  23. package/internal/blocks/code.js +90 -0
  24. package/internal/blocks/document.js +17 -0
  25. package/internal/blocks/fencedCode.js +26 -0
  26. package/internal/blocks/footnoteDefinition.js +84 -0
  27. package/internal/blocks/frontmatter.js +56 -0
  28. package/internal/blocks/htmlBlock.js +72 -0
  29. package/internal/blocks/indentedCode.js +16 -0
  30. package/internal/blocks/linkReferenceDefinition.js +72 -0
  31. package/internal/blocks/list.js +159 -0
  32. package/internal/blocks/paragraph.js +27 -0
  33. package/internal/blocks/setextHeading.js +24 -0
  34. package/internal/blocks/table.js +378 -0
  35. package/internal/blocks/taskListItem.js +36 -0
  36. package/internal/blocks/thematicBreak.js +35 -0
  37. package/internal/carriers.js +42 -0
  38. package/internal/entities.js +26 -0
  39. package/internal/entityMap.js +7 -0
  40. package/internal/htmlTags.js +18 -0
  41. package/internal/inlineNode.js +54 -0
  42. package/internal/inlineParser.js +403 -0
  43. package/internal/inlineRegistry.js +68 -0
  44. package/internal/inlines/autolink.js +36 -0
  45. package/internal/inlines/autolinkLiteral.js +374 -0
  46. package/internal/inlines/codeSpan.js +32 -0
  47. package/internal/inlines/emphasis.js +79 -0
  48. package/internal/inlines/entity.js +21 -0
  49. package/internal/inlines/escape.js +34 -0
  50. package/internal/inlines/footnoteReference.js +63 -0
  51. package/internal/inlines/lineBreak.js +25 -0
  52. package/internal/inlines/link.js +212 -0
  53. package/internal/inlines/rawHtml.js +27 -0
  54. package/internal/inlines/strikethrough.js +81 -0
  55. package/internal/inlines/text.js +22 -0
  56. package/internal/lineIndex.js +76 -0
  57. package/internal/patterns.js +26 -0
  58. package/internal/preprocess.js +58 -0
  59. package/internal/rawInline.js +57 -0
  60. package/internal/references.js +160 -0
  61. package/internal/segments.js +36 -0
  62. package/internal/stringify.js +519 -0
  63. package/internal/unescape.js +18 -0
  64. package/package.json +61 -0
  65. package/tsdoc-metadata.json +11 -0
@@ -0,0 +1,403 @@
1
+ import { Break, Delete, Emphasis, FootnoteReference, Html, Image, ImageReference, InlineCode, Link, LinkReference, Strong, Text } from "../MarkdownNode.js";
2
+ import { globalOf, stickyOf } from "./patterns.js";
3
+ import { sourceOffsetAt } from "./segments.js";
4
+ import { GuardExceeded } from "./carriers.js";
5
+ import { appendChild, childrenOf, insertAfter, makeInlineNode, unlink } from "./inlineNode.js";
6
+ import { insertStrikethrough } from "./inlines/strikethrough.js";
7
+ import { inlineDialect } from "./inlineRegistry.js";
8
+
9
+ //#region src/internal/inlineParser.ts
10
+ const C_UNDERSCORE = 95;
11
+ const C_ASTERISK = 42;
12
+ const reTrailingSpaces = / +$/;
13
+ const C_BACKTICK = 96;
14
+ /**
15
+ * Every backtick run in `subject`, as start offsets grouped by run length.
16
+ *
17
+ * One forward scan, so a code span's search for its closing run is a binary
18
+ * search rather than a walk over every run in between.
19
+ */
20
+ const indexBacktickRuns = (subject) => {
21
+ const runs = /* @__PURE__ */ new Map();
22
+ let index = 0;
23
+ while (index < subject.length) {
24
+ if (subject.charCodeAt(index) !== C_BACKTICK) {
25
+ index += 1;
26
+ continue;
27
+ }
28
+ const start = index;
29
+ while (index < subject.length && subject.charCodeAt(index) === C_BACKTICK) index += 1;
30
+ const length = index - start;
31
+ const starts = runs.get(length);
32
+ if (starts === void 0) runs.set(length, [start]);
33
+ else starts.push(start);
34
+ }
35
+ return runs;
36
+ };
37
+ var InlineParser = class {
38
+ subject;
39
+ pos = 0;
40
+ refmap;
41
+ footnoteLabels;
42
+ delimiters;
43
+ brackets;
44
+ /** How many link openers on the stack are still active (see `deactivateLinkOpeners`). */
45
+ activeLinkOpeners = 0;
46
+ /** Per-needle memo of the offset from which it no longer occurs. */
47
+ absentAfter = /* @__PURE__ */ new Map();
48
+ /** Backtick run starts, by run length; built on first use. */
49
+ backtickRuns;
50
+ source;
51
+ dialect;
52
+ positionOf;
53
+ /** The output list's root; only ever a container for the children. */
54
+ root;
55
+ constructor(source, dialect, positionOf, refmap, footnoteLabels) {
56
+ this.source = source;
57
+ this.subject = source.text;
58
+ this.dialect = dialect;
59
+ this.positionOf = positionOf;
60
+ this.refmap = refmap;
61
+ this.footnoteLabels = footnoteLabels;
62
+ this.root = makeInlineNode("text", 0, source.text.length);
63
+ }
64
+ peek() {
65
+ return this.pos < this.subject.length ? this.subject.charCodeAt(this.pos) : -1;
66
+ }
67
+ /**
68
+ * Match `pattern` AT the cursor, advancing past it on success.
69
+ *
70
+ * A match that starts later is not a match: every construct here asks
71
+ * "does this begin at the cursor". Upstream adds `m.index` to its position
72
+ * instead, which is safe only because its dispatch guarantees index zero —
73
+ * a guarantee the trigger table does not make (see `inlines/text.ts`).
74
+ */
75
+ match(pattern) {
76
+ const sticky = stickyOf(pattern);
77
+ sticky.lastIndex = this.pos;
78
+ const found = sticky.exec(this.subject);
79
+ if (found === null) return;
80
+ this.pos = sticky.lastIndex;
81
+ return found[0];
82
+ }
83
+ matchAhead(pattern) {
84
+ const forward = globalOf(pattern);
85
+ forward.lastIndex = this.pos;
86
+ const found = forward.exec(this.subject);
87
+ if (found === null) return;
88
+ this.pos = found.index + found[0].length;
89
+ return found[0];
90
+ }
91
+ hasAhead(needle) {
92
+ const known = this.absentAfter.get(needle);
93
+ if (known !== void 0 && this.pos >= known) return false;
94
+ if (this.subject.indexOf(needle, this.pos) !== -1) return true;
95
+ this.absentAfter.set(needle, Math.min(known ?? this.pos, this.pos));
96
+ return false;
97
+ }
98
+ closingBacktickRun(from, length) {
99
+ if (this.backtickRuns === void 0) this.backtickRuns = indexBacktickRuns(this.subject);
100
+ const starts = this.backtickRuns.get(length);
101
+ if (starts === void 0) return;
102
+ let low = 0;
103
+ let high = starts.length;
104
+ while (low < high) {
105
+ const mid = low + high >> 1;
106
+ if ((starts[mid] ?? 0) < from) low = mid + 1;
107
+ else high = mid;
108
+ }
109
+ return starts[low];
110
+ }
111
+ append(node) {
112
+ appendChild(this.root, node);
113
+ }
114
+ appendText(value, from, to) {
115
+ const node = makeInlineNode("text", from, to, value);
116
+ appendChild(this.root, node);
117
+ return node;
118
+ }
119
+ lastChild() {
120
+ return this.root.lastChild;
121
+ }
122
+ unputText(count) {
123
+ if (count === 0) return true;
124
+ let available = 0;
125
+ for (let node = this.root.lastChild; node !== void 0 && available < count; node = node.prev) {
126
+ if (node.type !== "text") break;
127
+ available += node.value.length;
128
+ }
129
+ if (available < count) return false;
130
+ let remaining = count;
131
+ while (remaining > 0) {
132
+ const last = this.root.lastChild;
133
+ if (last === void 0) return false;
134
+ if (last.value.length > remaining) {
135
+ last.value = last.value.slice(0, last.value.length - remaining);
136
+ last.end -= remaining;
137
+ return true;
138
+ }
139
+ remaining -= last.value.length;
140
+ unlink(last);
141
+ }
142
+ return true;
143
+ }
144
+ trimTrailingSpaces() {
145
+ const last = this.root.lastChild;
146
+ if (last === void 0 || last.type !== "text") return 0;
147
+ const trimmed = last.value.replace(reTrailingSpaces, "");
148
+ const removed = last.value.length - trimmed.length;
149
+ if (removed === 0) return 0;
150
+ if (trimmed.length === 0) {
151
+ unlink(last);
152
+ return removed;
153
+ }
154
+ last.value = trimmed;
155
+ last.end = Math.max(last.end - removed, last.start);
156
+ return removed;
157
+ }
158
+ removeDelimiter(delimiter) {
159
+ if (delimiter.previous !== void 0) delimiter.previous.next = delimiter.next;
160
+ if (delimiter.next === void 0) this.delimiters = delimiter.previous;
161
+ else delimiter.next.previous = delimiter.previous;
162
+ }
163
+ removeDelimitersBetween(bottom, top) {
164
+ if (bottom.next !== top) {
165
+ bottom.next = top;
166
+ top.previous = bottom;
167
+ }
168
+ }
169
+ addBracket(node, index, image) {
170
+ if (this.brackets !== void 0) this.brackets.bracketAfter = true;
171
+ this.brackets = {
172
+ node,
173
+ previous: this.brackets,
174
+ previousDelimiter: this.delimiters,
175
+ index,
176
+ image,
177
+ active: true
178
+ };
179
+ if (!image) this.activeLinkOpeners += 1;
180
+ }
181
+ removeBracket() {
182
+ const popped = this.brackets;
183
+ if (popped !== void 0 && !popped.image && popped.active) this.activeLinkOpeners -= 1;
184
+ this.brackets = popped?.previous;
185
+ }
186
+ deactivateLinkOpeners() {
187
+ if (this.activeLinkOpeners === 0) return;
188
+ for (let opener = this.brackets; opener !== void 0; opener = opener.previous) if (!opener.image && opener.active) {
189
+ opener.active = false;
190
+ this.activeLinkOpeners -= 1;
191
+ }
192
+ }
193
+ /**
194
+ * Pair up the delimiter stack above `stackBottom` into emphasis and strong
195
+ * nodes — upstream's `processEmphasis`, including the two rules that make
196
+ * the algorithm terminate in linear time: `openers_bottom`, which records
197
+ * how far back a failed search already looked, and the multiple-of-three
198
+ * rule for runs that can both open and close.
199
+ */
200
+ processEmphasis(stackBottom) {
201
+ const openersBottom = new Array(20).fill(stackBottom);
202
+ let closer = this.delimiters;
203
+ while (closer !== void 0 && closer.previous !== stackBottom) closer = closer.previous;
204
+ while (closer !== void 0) {
205
+ if (!closer.canClose) {
206
+ closer = closer.next;
207
+ continue;
208
+ }
209
+ const closercc = closer.cc;
210
+ const openersBottomIndex = (closercc === C_UNDERSCORE ? 2 : closercc === 126 ? 14 : 8) + (closer.canOpen ? 3 : 0) + closer.origdelims % 3;
211
+ let opener = closer.previous;
212
+ let openerFound = false;
213
+ while (opener !== void 0 && opener !== stackBottom && opener !== openersBottom[openersBottomIndex]) {
214
+ const oddMatch = (closer.canOpen || opener.canClose) && closer.origdelims % 3 !== 0 && (opener.origdelims + closer.origdelims) % 3 === 0;
215
+ if (opener.cc === closer.cc && opener.canOpen && !oddMatch) {
216
+ openerFound = true;
217
+ break;
218
+ }
219
+ opener = opener.previous;
220
+ }
221
+ const oldCloser = closer;
222
+ if (closercc === C_ASTERISK || closercc === C_UNDERSCORE) if (!openerFound || opener === void 0) closer = closer.next;
223
+ else {
224
+ const useDelims = closer.numdelims >= 2 && opener.numdelims >= 2 ? 2 : 1;
225
+ const openerNode = opener.node;
226
+ const closerNode = closer.node;
227
+ opener.numdelims -= useDelims;
228
+ closer.numdelims -= useDelims;
229
+ openerNode.value = openerNode.value.slice(0, openerNode.value.length - useDelims);
230
+ openerNode.end -= useDelims;
231
+ closerNode.value = closerNode.value.slice(0, closerNode.value.length - useDelims);
232
+ closerNode.start += useDelims;
233
+ const emphasis = makeInlineNode(useDelims === 1 ? "emphasis" : "strong", openerNode.end, closerNode.start);
234
+ emphasis.data.markerChar = closercc === C_UNDERSCORE ? "_" : "*";
235
+ let between = openerNode.next;
236
+ while (between !== void 0 && between !== closerNode) {
237
+ const following = between.next;
238
+ appendChild(emphasis, between);
239
+ between = following;
240
+ }
241
+ insertAfter(openerNode, emphasis);
242
+ this.removeDelimitersBetween(opener, closer);
243
+ if (opener.numdelims === 0) {
244
+ unlink(openerNode);
245
+ this.removeDelimiter(opener);
246
+ }
247
+ if (closer.numdelims === 0) {
248
+ unlink(closerNode);
249
+ const next = closer.next;
250
+ this.removeDelimiter(closer);
251
+ closer = next;
252
+ }
253
+ }
254
+ else if (closercc === 126) closer = !openerFound || opener === void 0 ? closer.next : insertStrikethrough(this, opener, closer);
255
+ else closer = closer.next;
256
+ if (!openerFound) {
257
+ openersBottom[openersBottomIndex] = oldCloser.previous;
258
+ if (!oldCloser.canOpen) this.removeDelimiter(oldCloser);
259
+ }
260
+ }
261
+ while (this.delimiters !== void 0 && this.delimiters !== stackBottom) this.removeDelimiter(this.delimiters);
262
+ }
263
+ offsetAt(index) {
264
+ return sourceOffsetAt(this.source.segments, index, this.source.startOffset);
265
+ }
266
+ position(from, to) {
267
+ const start = this.offsetAt(from);
268
+ const end = to > from ? this.offsetAt(to - 1) + 1 : this.offsetAt(to);
269
+ return this.positionOf(start, Math.max(end, start));
270
+ }
271
+ /**
272
+ * Turn the mutable list into mdast nodes, coalescing adjacent text runs.
273
+ *
274
+ * Depth is emphasis nesting, which the input controls, so the same cap the
275
+ * block pass applies to containers applies here.
276
+ */
277
+ materialize(parent, depth) {
278
+ if (depth > 256) throw new GuardExceeded("NestingDepthExceeded", 256, depth, this.offsetAt(parent.start));
279
+ const children = [];
280
+ let pendingText;
281
+ const flushText = () => {
282
+ if (pendingText === void 0) return;
283
+ if (pendingText.value.length > 0) children.push(Text.make({
284
+ value: pendingText.value,
285
+ position: this.position(pendingText.start, pendingText.end)
286
+ }));
287
+ pendingText = void 0;
288
+ };
289
+ for (const node of childrenOf(parent)) {
290
+ if (node.type === "text") {
291
+ if (pendingText === void 0) pendingText = makeInlineNode("text", node.start, node.end, node.value);
292
+ else {
293
+ pendingText.value += node.value;
294
+ pendingText.end = node.end;
295
+ }
296
+ continue;
297
+ }
298
+ flushText();
299
+ const built = this.materializeNode(node, depth);
300
+ if (built !== void 0) children.push(built);
301
+ }
302
+ flushText();
303
+ return children;
304
+ }
305
+ materializeNode(node, depth) {
306
+ const position = this.position(node.start, node.end);
307
+ const { url, title, identifier, label, referenceType, markerChar, breakStyle } = node.data;
308
+ switch (node.type) {
309
+ case "inlineCode": return InlineCode.make({
310
+ value: node.value,
311
+ position
312
+ });
313
+ case "html": return Html.make({
314
+ value: node.value,
315
+ position
316
+ });
317
+ case "break": return Break.make({
318
+ position,
319
+ ...breakStyle === void 0 ? {} : { breakStyle }
320
+ });
321
+ case "emphasis": return Emphasis.make({
322
+ children: this.materialize(node, depth + 1),
323
+ position,
324
+ ...markerChar === void 0 ? {} : { markerChar }
325
+ });
326
+ case "delete": return Delete.make({
327
+ children: this.materialize(node, depth + 1),
328
+ position
329
+ });
330
+ case "strong": return Strong.make({
331
+ children: this.materialize(node, depth + 1),
332
+ position,
333
+ ...markerChar === void 0 ? {} : { markerChar }
334
+ });
335
+ case "link": return Link.make({
336
+ url: url ?? "",
337
+ children: this.materialize(node, depth + 1),
338
+ position,
339
+ ...title === void 0 ? {} : { title }
340
+ });
341
+ case "image": return Image.make({
342
+ url: url ?? "",
343
+ position,
344
+ ...title === void 0 ? {} : { title },
345
+ ...node.value === "" ? {} : { alt: node.value }
346
+ });
347
+ case "linkReference": return LinkReference.make({
348
+ identifier: identifier ?? "",
349
+ referenceType: referenceType ?? "shortcut",
350
+ children: this.materialize(node, depth + 1),
351
+ position,
352
+ ...label === void 0 ? {} : { label }
353
+ });
354
+ case "footnoteReference": return FootnoteReference.make({
355
+ identifier: identifier ?? "",
356
+ position,
357
+ ...label === void 0 ? {} : { label }
358
+ });
359
+ case "imageReference": return ImageReference.make({
360
+ identifier: identifier ?? "",
361
+ referenceType: referenceType ?? "shortcut",
362
+ position,
363
+ ...label === void 0 ? {} : { label },
364
+ ...node.value === "" ? {} : { alt: node.value }
365
+ });
366
+ default: return;
367
+ }
368
+ }
369
+ /**
370
+ * One construct at the cursor. Upstream's `parseInline`: try the
371
+ * constructs this character triggers, then ordinary text, and failing both
372
+ * take the character literally.
373
+ */
374
+ parseOne() {
375
+ const code = this.peek();
376
+ if (code === -1) return false;
377
+ for (const construct of this.dialect.byTrigger.get(code) ?? []) if (construct.parse(this)) return true;
378
+ if (this.dialect.text.parse(this)) return true;
379
+ const from = this.pos;
380
+ this.pos += 1;
381
+ this.appendText(String.fromCodePoint(code), from, this.pos);
382
+ return true;
383
+ }
384
+ parse() {
385
+ while (this.parseOne());
386
+ this.processEmphasis(void 0);
387
+ for (const pass of this.dialect.postprocess) pass(this.root);
388
+ return this.materialize(this.root, 0);
389
+ }
390
+ };
391
+ /**
392
+ * Parse a leaf block's raw text into phrasing content.
393
+ *
394
+ * A reference only forms when `refmap` holds its normalized label — a
395
+ * dangling `[foo]` is literal text, per the spec — and when one does form it
396
+ * is emitted as a `linkReference` carrying the identifier rather than an
397
+ * eagerly resolved link. `position` comes from the block pass, which owns the
398
+ * line index.
399
+ */
400
+ const parseInlines = (source, refmap, position, dialect = "commonmark", footnoteLabels = /* @__PURE__ */ new Set()) => new InlineParser(source, inlineDialect(dialect), position, refmap, footnoteLabels).parse();
401
+
402
+ //#endregion
403
+ export { parseInlines };
@@ -0,0 +1,68 @@
1
+ import { autolinkConstruct } from "./inlines/autolink.js";
2
+ import { linkifyEmails, urlAutolinkConstruct, wwwAutolinkConstruct } from "./inlines/autolinkLiteral.js";
3
+ import { codeSpanConstruct } from "./inlines/codeSpan.js";
4
+ import { emphasisConstruct } from "./inlines/emphasis.js";
5
+ import { entityConstruct } from "./inlines/entity.js";
6
+ import { escapeConstruct } from "./inlines/escape.js";
7
+ import { imageOpenConstruct, linkCloseConstruct, linkOpenConstruct } from "./inlines/link.js";
8
+ import { gfmImageOpenConstruct, gfmLinkCloseConstruct } from "./inlines/footnoteReference.js";
9
+ import { lineBreakConstruct } from "./inlines/lineBreak.js";
10
+ import { rawHtmlConstruct } from "./inlines/rawHtml.js";
11
+ import { strikethroughConstruct } from "./inlines/strikethrough.js";
12
+ import { gfmTextConstruct, textConstruct } from "./inlines/text.js";
13
+
14
+ //#region src/internal/inlineRegistry.ts
15
+ const triggerTable = (constructs) => {
16
+ const table = /* @__PURE__ */ new Map();
17
+ for (const construct of constructs) for (const trigger of construct.triggers) {
18
+ const bucket = table.get(trigger);
19
+ if (bucket === void 0) table.set(trigger, [construct]);
20
+ else bucket.push(construct);
21
+ }
22
+ return table;
23
+ };
24
+ /** The CommonMark construct set, which every dialect starts from. */
25
+ const COMMONMARK_CONSTRUCTS = [
26
+ lineBreakConstruct,
27
+ escapeConstruct,
28
+ codeSpanConstruct,
29
+ emphasisConstruct,
30
+ linkOpenConstruct,
31
+ imageOpenConstruct,
32
+ linkCloseConstruct,
33
+ autolinkConstruct,
34
+ rawHtmlConstruct,
35
+ entityConstruct
36
+ ];
37
+ const commonmarkDialect = {
38
+ byTrigger: triggerTable(COMMONMARK_CONSTRUCTS),
39
+ text: textConstruct,
40
+ postprocess: []
41
+ };
42
+ const gfmDialect = {
43
+ byTrigger: triggerTable([
44
+ ...COMMONMARK_CONSTRUCTS.filter((construct) => construct !== linkCloseConstruct && construct !== imageOpenConstruct),
45
+ gfmLinkCloseConstruct,
46
+ gfmImageOpenConstruct,
47
+ strikethroughConstruct,
48
+ wwwAutolinkConstruct,
49
+ urlAutolinkConstruct
50
+ ]),
51
+ text: gfmTextConstruct,
52
+ postprocess: [linkifyEmails]
53
+ };
54
+ const dialects = /* @__PURE__ */ new Map([["commonmark", commonmarkDialect], ["gfm", gfmDialect]]);
55
+ /**
56
+ * The inline tables for `dialect`.
57
+ *
58
+ * An unknown dialect cannot arrive through the schema-typed public surface,
59
+ * so it is programmer error and dies as a defect.
60
+ */
61
+ const inlineDialect = (dialect) => {
62
+ const found = dialects.get(dialect);
63
+ if (found === void 0) throw new TypeError(`unknown markdown dialect: ${String(dialect)}`);
64
+ return found;
65
+ };
66
+
67
+ //#endregion
68
+ export { inlineDialect };
@@ -0,0 +1,36 @@
1
+ import { appendChild, makeInlineNode } from "../inlineNode.js";
2
+
3
+ //#region src/internal/inlines/autolink.ts
4
+ const C_LESSTHAN = 60;
5
+ const reEmailAutolink = /^<([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)>/;
6
+ const reAutolink = /^<[A-Za-z][A-Za-z0-9.+-]{1,31}:[^<>\0- ]*>/i;
7
+ /** An absolute-URI or email autolink. */
8
+ const autolinkConstruct = {
9
+ name: "autolink",
10
+ triggers: [C_LESSTHAN],
11
+ parse: (scanner) => {
12
+ const from = scanner.pos;
13
+ const email = scanner.match(reEmailAutolink);
14
+ if (email !== void 0) {
15
+ const destination = email.slice(1, -1);
16
+ const node = makeInlineNode("link", from, scanner.pos);
17
+ node.data.url = `mailto:${destination}`;
18
+ appendChild(node, makeInlineNode("text", from + 1, scanner.pos - 1, destination));
19
+ scanner.append(node);
20
+ return true;
21
+ }
22
+ const uri = scanner.match(reAutolink);
23
+ if (uri !== void 0) {
24
+ const destination = uri.slice(1, -1);
25
+ const node = makeInlineNode("link", from, scanner.pos);
26
+ node.data.url = destination;
27
+ appendChild(node, makeInlineNode("text", from + 1, scanner.pos - 1, destination));
28
+ scanner.append(node);
29
+ return true;
30
+ }
31
+ return false;
32
+ }
33
+ };
34
+
35
+ //#endregion
36
+ export { autolinkConstruct };