svelte-streamdown 1.0.7 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +11 -5
  2. package/dist/Block.svelte +26 -10
  3. package/dist/Elements/Code.svelte +1 -1
  4. package/dist/Elements/Element.svelte +120 -37
  5. package/dist/Elements/FootnoteRef.svelte +113 -0
  6. package/dist/Elements/FootnoteRef.svelte.d.ts +7 -0
  7. package/dist/Elements/Image.svelte +3 -3
  8. package/dist/Elements/{A.svelte → Link.svelte} +3 -3
  9. package/dist/Elements/{A.svelte.d.ts → Link.svelte.d.ts} +3 -3
  10. package/dist/Elements/Math.svelte +3 -2
  11. package/dist/Elements/index.d.ts +5 -25
  12. package/dist/Elements/index.js +5 -25
  13. package/dist/Streamdown.d.ts +1 -1
  14. package/dist/Streamdown.svelte +7 -1
  15. package/dist/Streamdown.svelte.d.ts +6 -0
  16. package/dist/marked/index.d.ts +18 -5
  17. package/dist/marked/index.js +4 -0
  18. package/dist/marked/marked-alert.d.ts +2 -2
  19. package/dist/marked/marked-alert.js +18 -18
  20. package/dist/marked/marked-footnotes.d.ts +1 -0
  21. package/dist/marked/marked-footnotes.js +28 -8
  22. package/dist/marked/marked-list.d.ts +36 -0
  23. package/dist/marked/marked-list.js +215 -0
  24. package/dist/marked/marked-math.js +0 -3
  25. package/dist/marked/marked-subsup.d.ts +28 -0
  26. package/dist/marked/marked-subsup.js +44 -0
  27. package/dist/theme.d.ts +48 -42
  28. package/dist/theme.js +47 -43
  29. package/dist/utils/parse-incomplete-markdown.js +157 -0
  30. package/dist/utils/useClickOutside.svelte.d.ts +8 -0
  31. package/dist/utils/useClickOutside.svelte.js +42 -0
  32. package/dist/utils/useKeyDown.svelte.d.ts +5 -0
  33. package/dist/utils/useKeyDown.svelte.js +20 -0
  34. package/package.json +3 -1
  35. package/dist/Elements/Blockquote.svelte +0 -28
  36. package/dist/Elements/Blockquote.svelte.d.ts +0 -9
  37. package/dist/Elements/Del.svelte +0 -28
  38. package/dist/Elements/Del.svelte.d.ts +0 -9
  39. package/dist/Elements/Em.svelte +0 -28
  40. package/dist/Elements/Em.svelte.d.ts +0 -9
  41. package/dist/Elements/Heading.svelte +0 -25
  42. package/dist/Elements/Heading.svelte.d.ts +0 -9
  43. package/dist/Elements/Hr.svelte +0 -26
  44. package/dist/Elements/Hr.svelte.d.ts +0 -9
  45. package/dist/Elements/InlineCode.svelte +0 -28
  46. package/dist/Elements/InlineCode.svelte.d.ts +0 -9
  47. package/dist/Elements/Li.svelte +0 -28
  48. package/dist/Elements/Li.svelte.d.ts +0 -9
  49. package/dist/Elements/Ol.svelte +0 -30
  50. package/dist/Elements/Ol.svelte.d.ts +0 -9
  51. package/dist/Elements/P.svelte +0 -28
  52. package/dist/Elements/P.svelte.d.ts +0 -9
  53. package/dist/Elements/Strong.svelte +0 -28
  54. package/dist/Elements/Strong.svelte.d.ts +0 -9
  55. package/dist/Elements/Sub.svelte +0 -27
  56. package/dist/Elements/Sub.svelte.d.ts +0 -8
  57. package/dist/Elements/Sup.svelte +0 -28
  58. package/dist/Elements/Sup.svelte.d.ts +0 -8
  59. package/dist/Elements/Tbody.svelte +0 -24
  60. package/dist/Elements/Tbody.svelte.d.ts +0 -7
  61. package/dist/Elements/Td.svelte +0 -28
  62. package/dist/Elements/Td.svelte.d.ts +0 -9
  63. package/dist/Elements/Th.svelte +0 -28
  64. package/dist/Elements/Th.svelte.d.ts +0 -9
  65. package/dist/Elements/Thead.svelte +0 -27
  66. package/dist/Elements/Thead.svelte.d.ts +0 -9
  67. package/dist/Elements/Tr.svelte +0 -27
  68. package/dist/Elements/Tr.svelte.d.ts +0 -9
  69. package/dist/Elements/Ul.svelte +0 -28
  70. package/dist/Elements/Ul.svelte.d.ts +0 -9
  71. /package/dist/{hightlighter.svelte.d.ts → utils/hightlighter.svelte.d.ts} +0 -0
  72. /package/dist/{hightlighter.svelte.js → utils/hightlighter.svelte.js} +0 -0
@@ -2,6 +2,8 @@ import { Lexer, marked } from 'marked';
2
2
  import markedAlert, {} from './marked-alert.js';
3
3
  import markedFootnote, {} from './marked-footnotes.js';
4
4
  import { markedMath } from './marked-math.js';
5
+ import markedSubSup, {} from './marked-subsup.js';
6
+ import { markedList } from './marked-list.js';
5
7
  export const lex = (markdown) => {
6
8
  return marked
7
9
  .use({
@@ -10,6 +12,8 @@ export const lex = (markdown) => {
10
12
  .use(markedAlert())
11
13
  .use(markedFootnote())
12
14
  .use(markedMath())
15
+ .use(markedSubSup())
16
+ .use(markedList())
13
17
  .lexer(markdown)
14
18
  .filter((token) => token.type !== 'space' && token.type !== 'footnote');
15
19
  };
@@ -1,4 +1,4 @@
1
- import type { Token } from 'marked';
1
+ import type { Token, Tokenizer } from 'marked';
2
2
  import type { TokenizerExtensionFunction } from 'marked';
3
3
  type variantType = 'note' | 'tip' | 'important' | 'warning' | 'caution';
4
4
  export declare function createSyntaxPattern(type: variantType): string;
@@ -9,7 +9,7 @@ export default function markedAlert(): {
9
9
  tokenizer: TokenizerExtensionFunction;
10
10
  }>;
11
11
  };
12
- export declare function processAlertToken(token: Token): void;
12
+ export declare function processAlertToken(token: Token, tokenizer: Tokenizer): void;
13
13
  export type AlertToken = {
14
14
  type: 'alert';
15
15
  variant: variantType;
@@ -15,7 +15,7 @@ export default function markedAlert() {
15
15
  const cap = defaultTokenizer.rules.block.blockquote.exec(src);
16
16
  if (cap) {
17
17
  const blockquoteToken = defaultTokenizer.blockquote(src);
18
- blockquoteToken && processAlertToken(blockquoteToken);
18
+ blockquoteToken && processAlertToken(blockquoteToken, this.lexer.options.tokenizer);
19
19
  return blockquoteToken;
20
20
  }
21
21
  }
@@ -23,7 +23,7 @@ export default function markedAlert() {
23
23
  ]
24
24
  };
25
25
  }
26
- export function processAlertToken(token) {
26
+ export function processAlertToken(token, tokenizer) {
27
27
  const matchedVariant = variants.find((type) => new RegExp(createSyntaxPattern(type)).test(('text' in token && token.text) || ''));
28
28
  if (!matchedVariant)
29
29
  return;
@@ -35,20 +35,20 @@ export function processAlertToken(token) {
35
35
  });
36
36
  const firstLine = ('tokens' in token && token.tokens?.[0]);
37
37
  const firstLineText = firstLine.raw?.replace(typeRegexp, '').trim();
38
- firstLine.text = firstLineText;
39
- if (firstLineText) {
40
- const patternToken = firstLine.tokens[0];
41
- if (patternToken) {
42
- Object.assign(patternToken, {
43
- raw: patternToken.raw.replace(typeRegexp, ''),
44
- text: patternToken.text.replace(typeRegexp, '')
45
- });
46
- }
47
- if (firstLine.tokens[1]?.type === 'br') {
48
- firstLine.tokens.splice(1, 1);
49
- }
50
- }
51
- else if ('tokens' in token && token.tokens) {
52
- token.tokens?.shift();
53
- }
38
+ const lines = token.raw
39
+ .split('>')
40
+ .filter((line) => line.trim().replace(typeRegexp, '').length > 0);
41
+ const tokens = lines.map((line) => {
42
+ const lineTokens = tokenizer.lexer.inlineTokens(line);
43
+ return {
44
+ type: 'paragraph',
45
+ tokens: lineTokens
46
+ };
47
+ });
48
+ // Transform the token into an alert token
49
+ Object.assign(token, {
50
+ type: 'alert',
51
+ variant: matchedVariant,
52
+ tokens
53
+ });
54
54
  }
@@ -15,6 +15,7 @@ export type Footnote = {
15
15
  raw: string;
16
16
  label: string;
17
17
  tokens: StreamdownToken[];
18
+ lines: string[];
18
19
  };
19
20
  /**
20
21
  * Represents a reference to a footnote.
@@ -1,14 +1,30 @@
1
1
  import { lex } from './index.js';
2
+ import { StreamdownContext } from '../Streamdown.svelte';
3
+ import { getContext } from 'svelte';
4
+ const safeGetContext = () => {
5
+ try {
6
+ return getContext('streamdown');
7
+ }
8
+ catch (e) {
9
+ return null;
10
+ }
11
+ };
2
12
  export default function markedFootnote() {
3
13
  const ensureMaps = (tokenizer) => {
4
- if (!tokenizer.lexer.hasFootnotes) {
5
- tokenizer.lexer.footnotes = {
6
- refs: new Map(),
7
- footnotes: new Map()
8
- };
9
- tokenizer.lexer.hasFootnotes = true;
14
+ const streamdown = safeGetContext();
15
+ if (!streamdown) {
16
+ if (!tokenizer.lexer.hasFootnotes) {
17
+ tokenizer.lexer.footnotes = {
18
+ refs: new Map(),
19
+ footnotes: new Map()
20
+ };
21
+ tokenizer.lexer.hasFootnotes = true;
22
+ }
23
+ return tokenizer.lexer.footnotes;
24
+ }
25
+ else {
26
+ return streamdown.footnotes;
10
27
  }
11
- return tokenizer.lexer.footnotes;
12
28
  };
13
29
  return {
14
30
  extensions: [
@@ -30,11 +46,13 @@ export default function markedFootnote() {
30
46
  /^[ \t]*?[>\-*][ ]|[`]{3,}$|^[ \t]*?[|].+[|]$/.test(contentLastLine)
31
47
  ? '\n\n'
32
48
  : '';
49
+ const lines = content.split('\n');
33
50
  const token = {
34
51
  type: 'footnote',
35
52
  raw,
36
53
  label,
37
- tokens: lex(content)
54
+ lines,
55
+ tokens: []
38
56
  };
39
57
  maps.footnotes.set(label, token);
40
58
  const ref = maps.refs.get(label);
@@ -54,6 +72,7 @@ export default function markedFootnote() {
54
72
  if (match) {
55
73
  const [raw, label] = match;
56
74
  const footnote = maps.footnotes.get(label);
75
+ console.log({ footnote });
57
76
  const token = {
58
77
  type: 'footnoteRef',
59
78
  raw,
@@ -62,6 +81,7 @@ export default function markedFootnote() {
62
81
  type: 'footnote',
63
82
  raw,
64
83
  label,
84
+ lines: [],
65
85
  tokens: []
66
86
  }
67
87
  };
@@ -0,0 +1,36 @@
1
+ import type { TokenizerExtensionFunction } from 'marked';
2
+ export declare function letterToInt(letter: string): number;
3
+ export declare function romanToInt(roman: string): number;
4
+ export declare const romanUpper = "(?:C|XC|L?X{0,3}(?:IX|IV|V?I{0,3}))";
5
+ export declare const romanLower = "(?:c|xc|l?x{0,3}(?:ix|iv|v?i{0,3}))";
6
+ export declare const bulletPattern = "(?:[*+-]|(?:\\d{1,9}|[a-zA-Z]|(?:C|XC|L?X{0,3}(?:IX|IV|V?I{0,3}))|(?:c|xc|l?x{0,3}(?:ix|iv|v?i{0,3})))[.)])";
7
+ export declare const rule = "^( {0,3}(?:[*+-]|(?:\\d{1,9}|[a-zA-Z]|(?:C|XC|L?X{0,3}(?:IX|IV|V?I{0,3}))|(?:c|xc|l?x{0,3}(?:ix|iv|v?i{0,3})))[.)]))([ \\t][^\\n]+?)?(?:\\n|$)";
8
+ export declare function markedList(): {
9
+ extensions: Array<{
10
+ name: string;
11
+ level: 'block' | 'inline';
12
+ tokenizer: TokenizerExtensionFunction;
13
+ }>;
14
+ };
15
+ export interface ListToken {
16
+ type: 'list';
17
+ raw: string;
18
+ ordered: boolean;
19
+ listType: 'decimal' | 'lower-alpha' | 'upper-alpha' | 'lower-roman' | 'upper-roman';
20
+ loose: boolean;
21
+ items: ListItemToken[];
22
+ }
23
+ /**
24
+ * Token representing an item in an extended list.
25
+ */
26
+ export interface ListItemToken {
27
+ type: 'list_item';
28
+ raw: string;
29
+ task: boolean;
30
+ checked: boolean;
31
+ loose: boolean;
32
+ text: string;
33
+ value: number | null;
34
+ skipped: boolean;
35
+ tokens: unknown[];
36
+ }
@@ -0,0 +1,215 @@
1
+ export function letterToInt(letter) {
2
+ return letter.toLowerCase().charCodeAt(0) - 96;
3
+ }
4
+ const romanMap = {
5
+ I: 1,
6
+ V: 5,
7
+ X: 10,
8
+ L: 50,
9
+ C: 100,
10
+ D: 500,
11
+ M: 1000
12
+ };
13
+ export function romanToInt(roman) {
14
+ roman = roman.toUpperCase();
15
+ let total = 0;
16
+ for (let i = 0; i < roman.length; i++) {
17
+ const current = romanMap[roman[i]];
18
+ const next = romanMap[roman[i + 1]];
19
+ total += next && current < next ? -current : current;
20
+ }
21
+ return total;
22
+ }
23
+ // Regular expression patterns for list detection
24
+ export const romanUpper = '(?:C|XC|L?X{0,3}(?:IX|IV|V?I{0,3}))';
25
+ export const romanLower = '(?:c|xc|l?x{0,3}(?:ix|iv|v?i{0,3}))';
26
+ // Fixed regex pattern - carefully balanced parentheses
27
+ export const bulletPattern = `(?:[*+-]|(?:\\d{1,9}|[a-zA-Z]|${romanUpper}|${romanLower})[.)])`;
28
+ export const rule = `^( {0,3}${bulletPattern})([ \\t][^\\n]+?)?(?:\\n|$)`;
29
+ function finalizeList(list, lexer) {
30
+ if (list.items.length === 0)
31
+ return;
32
+ // Trim trailing newline from last item
33
+ const lastItem = list.items[list.items.length - 1];
34
+ lastItem.raw = lastItem.raw.trimEnd();
35
+ lastItem.text = lastItem.text.trimEnd();
36
+ list.raw = list.raw.trimEnd();
37
+ // Handle child tokens
38
+ for (const item of list.items) {
39
+ lexer.state.top = false;
40
+ item.tokens = lexer.blockTokens(item.text, []);
41
+ }
42
+ // Mark list as loose if needed
43
+ if (list.loose) {
44
+ for (const item of list.items) {
45
+ item.loose = true;
46
+ }
47
+ }
48
+ }
49
+ export function markedList() {
50
+ return {
51
+ extensions: [
52
+ {
53
+ name: 'list',
54
+ level: 'block',
55
+ tokenizer(src) {
56
+ let cap = new RegExp(rule).exec(src);
57
+ if (!cap)
58
+ return null;
59
+ const bullet = cap[1].trim();
60
+ const isOrdered = bullet !== '*' && bullet !== '-' && bullet !== '+';
61
+ let bull;
62
+ let type = '';
63
+ let expectedValue = 1;
64
+ // Detect list type (Roman, alphabetic, numeric)
65
+ if (isOrdered) {
66
+ if (bullet.match(new RegExp(`^${romanUpper}[.)]$`))) {
67
+ type = 'upper-roman';
68
+ bull = `${romanUpper}\\${bullet.slice(-1)}`;
69
+ }
70
+ else if (bullet.match(new RegExp(`^${romanLower}[.)]$`))) {
71
+ type = 'lower-roman';
72
+ bull = `${romanLower}\\${bullet.slice(-1)}`;
73
+ }
74
+ else if (bullet.match(/^[a-z][.)]$/)) {
75
+ type = 'lower-alpha';
76
+ bull = `[a-z]\\${bullet.slice(-1)}`;
77
+ }
78
+ else if (bullet.match(/^[A-Z][.)]$/)) {
79
+ type = 'upper-alpha';
80
+ bull = `[A-Z]\\${bullet.slice(-1)}`;
81
+ }
82
+ else {
83
+ type = 'decimal';
84
+ bull = `\\d{1,9}\\${bullet.slice(-1)}`;
85
+ }
86
+ }
87
+ else {
88
+ bull = this.lexer.options.pedantic ? bullet : '[*+-]';
89
+ }
90
+ const list = {
91
+ type: 'list',
92
+ raw: '',
93
+ ordered: isOrdered,
94
+ listType: type,
95
+ loose: false,
96
+ items: []
97
+ };
98
+ // Get next list item
99
+ const itemRegex = new RegExp(`^( {0,3}${bull})((?:[\t ][^\\n]*)?(?:\\n|$))`);
100
+ let endsWithBlankLine = false;
101
+ // Check if current bullet point can start a new List Item
102
+ while (src) {
103
+ let raw = '';
104
+ let itemContents = '';
105
+ let endEarly = false;
106
+ if (!(cap = itemRegex.exec(src)))
107
+ break;
108
+ raw = cap[0];
109
+ const bullet = cap[1].trim();
110
+ src = src.substring(raw.length);
111
+ const line = cap[2].split('\n', 1)[0].replace(/^\t+/, (t) => ' '.repeat(3 * t.length));
112
+ const nextLine = src.split('\n', 1)[0];
113
+ const blankLine = !line.trim();
114
+ let indent = 0;
115
+ if (this.lexer.options.pedantic) {
116
+ indent = 2;
117
+ itemContents = line.trimStart();
118
+ }
119
+ else if (blankLine) {
120
+ indent = cap[1].length + 1;
121
+ }
122
+ else {
123
+ indent = cap[2].search(/[^ ]/); // Find first non-space char
124
+ indent = indent > 4 ? 1 : indent; // Treat indented code blocks (> 4 spaces) as having only 1 indent
125
+ itemContents = line.slice(indent);
126
+ indent += cap[1].length;
127
+ }
128
+ if (blankLine && /^[ \t]*$/.test(nextLine)) {
129
+ // Items begin with at most one blank line
130
+ raw += nextLine + '\n';
131
+ src = src.substring(nextLine.length + 1);
132
+ endEarly = true;
133
+ }
134
+ if (!endEarly) {
135
+ const nextBulletRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:[*+-]|(?:\\d{1,9}|[a-zA-Z]|${romanUpper}|${romanLower})[.)])((?:[ \t][^\\n]*)?(?:\\n|$))`);
136
+ const hrRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`);
137
+ const fencesBeginRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:\`\`\`|~~~)`);
138
+ const headingBeginRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}#`);
139
+ const htmlBeginRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}<[a-z].*>`, 'i');
140
+ // Check if following lines should be included in List Item
141
+ while (src) {
142
+ const rawLine = src.split('\n', 1)[0];
143
+ const nextLineWithoutTabs = rawLine.replace(/\t/g, ' ');
144
+ if (fencesBeginRegex.test(nextLineWithoutTabs) ||
145
+ headingBeginRegex.test(nextLineWithoutTabs) ||
146
+ htmlBeginRegex.test(nextLineWithoutTabs) ||
147
+ nextBulletRegex.test(nextLineWithoutTabs) ||
148
+ hrRegex.test(nextLineWithoutTabs))
149
+ break;
150
+ if (nextLineWithoutTabs.search(/[^ ]/) >= indent || !nextLineWithoutTabs.trim()) {
151
+ itemContents += '\n' + nextLineWithoutTabs.slice(indent);
152
+ }
153
+ else {
154
+ itemContents += '\n' + nextLineWithoutTabs;
155
+ }
156
+ raw += rawLine + '\n';
157
+ src = src.substring(rawLine.length + 1);
158
+ }
159
+ }
160
+ if (!list.loose) {
161
+ // If the previous item ended with a blank line, the list is loose
162
+ if (endsWithBlankLine) {
163
+ list.loose = true;
164
+ }
165
+ else if (/\n[ \t]*\n[ \t]*$/.test(raw)) {
166
+ endsWithBlankLine = true;
167
+ }
168
+ }
169
+ let isTask = null;
170
+ let isChecked = false;
171
+ // Check for task list items
172
+ if (this.lexer.options.gfm) {
173
+ isTask = /^\[[ xX]] /.exec(itemContents);
174
+ if (isTask) {
175
+ isChecked = isTask[0] !== '[ ] ';
176
+ itemContents = itemContents.replace(/^\[[ xX]] +/, '');
177
+ }
178
+ }
179
+ let value = null;
180
+ if (!isOrdered) {
181
+ // Do nothing for unordered lists
182
+ }
183
+ else if (type === 'decimal') {
184
+ value = parseInt(bullet.slice(0, -1), 10);
185
+ }
186
+ else if (type === 'lower-alpha' || type === 'upper-alpha') {
187
+ value = letterToInt(bullet.slice(0, -1));
188
+ }
189
+ else if (type === 'lower-roman' || type === 'upper-roman') {
190
+ value = romanToInt(bullet.slice(0, -1));
191
+ }
192
+ list.items.push({
193
+ type: 'list_item',
194
+ raw,
195
+ task: !!isTask,
196
+ checked: isChecked,
197
+ loose: false,
198
+ text: itemContents,
199
+ value,
200
+ skipped: isOrdered && value !== expectedValue,
201
+ tokens: []
202
+ });
203
+ expectedValue = (value ?? 0) + 1;
204
+ list.raw += raw;
205
+ }
206
+ if (list.items.length === 0)
207
+ return null;
208
+ // Finalize the list
209
+ finalizeList(list, this.lexer);
210
+ return list;
211
+ }
212
+ }
213
+ ]
214
+ };
215
+ }
@@ -27,9 +27,6 @@ export function markedMath() {
27
27
  },
28
28
  tokenizer(src) {
29
29
  const match = src.match(inlineRuleNonStandard);
30
- if (match) {
31
- console.log('match', match);
32
- }
33
30
  if (match) {
34
31
  return {
35
32
  type: 'math',
@@ -0,0 +1,28 @@
1
+ import type { TokenizerExtensionFunction } from 'marked';
2
+ export default function markedSubSup(): {
3
+ extensions: {
4
+ name: string;
5
+ level: 'inline';
6
+ tokenizer: TokenizerExtensionFunction;
7
+ start?: (src: string) => number | void;
8
+ }[];
9
+ };
10
+ /**
11
+ * Represents a subscript token.
12
+ */
13
+ export type SubToken = {
14
+ type: 'sub';
15
+ raw: string;
16
+ text: string;
17
+ tokens: any[];
18
+ };
19
+ /**
20
+ * Represents a superscript token.
21
+ */
22
+ export type SupToken = {
23
+ type: 'sup';
24
+ raw: string;
25
+ text: string;
26
+ tokens: any[];
27
+ };
28
+ export type SubSupToken = SubToken | SupToken;
@@ -0,0 +1,44 @@
1
+ const subRule = /^~([^~\s](?:[^~]*[^~\s])?)~/; // ~text~
2
+ const supRule = /^\^([^\^\s](?:[^\^]*[^\^\s])?)\^/; // ^text^
3
+ export default function markedSubSup() {
4
+ return {
5
+ extensions: [
6
+ {
7
+ name: 'sub',
8
+ level: 'inline',
9
+ start(src) {
10
+ return src.indexOf('~');
11
+ },
12
+ tokenizer(src) {
13
+ const match = src.match(subRule);
14
+ if (match) {
15
+ return {
16
+ type: 'sub',
17
+ raw: match[0],
18
+ text: match[1],
19
+ tokens: this.lexer.inlineTokens(match[1])
20
+ };
21
+ }
22
+ }
23
+ },
24
+ {
25
+ name: 'sup',
26
+ level: 'inline',
27
+ start(src) {
28
+ return src.indexOf('^');
29
+ },
30
+ tokenizer(src) {
31
+ const match = src.match(supRule);
32
+ if (match) {
33
+ return {
34
+ type: 'sup',
35
+ raw: match[0],
36
+ text: match[1],
37
+ tokens: this.lexer.inlineTokens(match[1])
38
+ };
39
+ }
40
+ }
41
+ }
42
+ ]
43
+ };
44
+ }