@liveblocks/react-ui 3.3.3 → 3.4.0-alpha1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_private/index.d.cts +3 -4
- package/dist/_private/index.d.ts +3 -4
- package/dist/components/AiChat.cjs +3 -2
- package/dist/components/AiChat.cjs.map +1 -1
- package/dist/components/AiChat.js +3 -2
- package/dist/components/AiChat.js.map +1 -1
- package/dist/components/AiTool.cjs +15 -6
- package/dist/components/AiTool.cjs.map +1 -1
- package/dist/components/AiTool.js +15 -6
- package/dist/components/AiTool.js.map +1 -1
- package/dist/components/Thread.cjs +1 -2
- package/dist/components/Thread.cjs.map +1 -1
- package/dist/components/Thread.js +2 -3
- package/dist/components/Thread.js.map +1 -1
- package/dist/components/internal/AiChatAssistantMessage.cjs +1 -0
- package/dist/components/internal/AiChatAssistantMessage.cjs.map +1 -1
- package/dist/components/internal/AiChatAssistantMessage.js +1 -0
- package/dist/components/internal/AiChatAssistantMessage.js.map +1 -1
- package/dist/components/internal/AiChatUserMessage.cjs +16 -14
- package/dist/components/internal/AiChatUserMessage.cjs.map +1 -1
- package/dist/components/internal/AiChatUserMessage.js +16 -14
- package/dist/components/internal/AiChatUserMessage.js.map +1 -1
- package/dist/components/internal/CodeBlock.cjs +1 -1
- package/dist/components/internal/CodeBlock.cjs.map +1 -1
- package/dist/components/internal/CodeBlock.js +1 -1
- package/dist/components/internal/CodeBlock.js.map +1 -1
- package/dist/components/internal/Prose.cjs +3 -1
- package/dist/components/internal/Prose.cjs.map +1 -1
- package/dist/components/internal/Prose.js +3 -1
- package/dist/components/internal/Prose.js.map +1 -1
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/primitives/AiMessage/tool-invocation.cjs +5 -2
- package/dist/primitives/AiMessage/tool-invocation.cjs.map +1 -1
- package/dist/primitives/AiMessage/tool-invocation.js +5 -2
- package/dist/primitives/AiMessage/tool-invocation.js.map +1 -1
- package/dist/primitives/Composer/slate/plugins/custom-links.cjs +2 -9
- package/dist/primitives/Composer/slate/plugins/custom-links.cjs.map +1 -1
- package/dist/primitives/Composer/slate/plugins/custom-links.js +1 -8
- package/dist/primitives/Composer/slate/plugins/custom-links.js.map +1 -1
- package/dist/primitives/Markdown.cjs +409 -61
- package/dist/primitives/Markdown.cjs.map +1 -1
- package/dist/primitives/Markdown.js +410 -62
- package/dist/primitives/Markdown.js.map +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.cjs.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +9 -9
- package/src/styles/dark/index.css +26 -0
- package/src/styles/index.css +174 -45
- package/styles/dark/attributes.css +1 -1
- package/styles/dark/attributes.css.map +1 -1
- package/styles/dark/media-query.css +1 -1
- package/styles/dark/media-query.css.map +1 -1
- package/styles.css +1 -1
- package/styles.css.map +1 -1
- package/dist/utils/find-last-index.cjs +0 -16
- package/dist/utils/find-last-index.cjs.map +0 -1
- package/dist/utils/find-last-index.js +0 -14
- package/dist/utils/find-last-index.js.map +0 -1
|
@@ -1,9 +1,22 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import { assertNever, sanitizeUrl } from '@liveblocks/core';
|
|
2
|
+
import { assertNever, sanitizeUrl, isUrl } from '@liveblocks/core';
|
|
3
3
|
import { Slot } from '@radix-ui/react-slot';
|
|
4
4
|
import { Lexer } from 'marked';
|
|
5
5
|
import { forwardRef, useMemo, memo } from 'react';
|
|
6
6
|
|
|
7
|
+
const LIST_ITEM_CHECKBOX_REGEX = /^\[\s?(x)?\]?$/i;
|
|
8
|
+
const PARTIAL_LINK_IMAGE_REGEX = /(?<!\\)(?<image>!)?\[(?!\^)(?<text>[^\]]*)(?:\](?:\((?<url>[^)]*)?)?)?$/;
|
|
9
|
+
const PARTIAL_TABLE_HEADER_REGEX = /^\s*\|(?:[^|\n]+(?:\|[^|\n]+)*?)?\|?\s*(?:\n\s*\|\s*[-:|\s]*\s*)?$/;
|
|
10
|
+
const PARTIAL_EMOJI_REGEX = /(?:\u200D|\uFE0F|\u20E3|\p{Regional_Indicator}|\p{Emoji_Presentation}|\p{Emoji_Modifier_Base}|\p{Emoji_Modifier})+$/u;
|
|
11
|
+
const TRAILING_NON_WHITESPACE_REGEX = /^\S*/;
|
|
12
|
+
const WHITESPACE_REGEX = /\s/;
|
|
13
|
+
const NEWLINE_REGEX = /\r\n?/g;
|
|
14
|
+
const BUFFERED_CHARACTERS_REGEX = /(?<!\\)((\*+|_+|~+|`+|\++|-{0,2}|={0,2}|\\|!|<\/?)\s*)$/;
|
|
15
|
+
const SINGLE_CHARACTER_REGEX = /^\s*(\S\s*)$/;
|
|
16
|
+
const LEFT_ANGLE_BRACKET_REGEX = /</g;
|
|
17
|
+
const RIGHT_ANGLE_BRACKET_REGEX = />/g;
|
|
18
|
+
const AMPERSAND_REGEX = /&(?!#?[0-9A-Za-z]+;)/g;
|
|
19
|
+
const DEFAULT_PARTIAL_LINK_URL = "#";
|
|
7
20
|
const defaultComponents = {
|
|
8
21
|
Paragraph: ({ children }) => {
|
|
9
22
|
return /* @__PURE__ */ jsx("p", {
|
|
@@ -99,20 +112,8 @@ const defaultComponents = {
|
|
|
99
112
|
const List = type === "ordered" ? "ol" : "ul";
|
|
100
113
|
return /* @__PURE__ */ jsx(List, {
|
|
101
114
|
start: start === 1 ? void 0 : start,
|
|
102
|
-
children: items.map((item, index) => /* @__PURE__ */
|
|
103
|
-
children:
|
|
104
|
-
item.checked !== void 0 && /* @__PURE__ */ jsxs(Fragment, {
|
|
105
|
-
children: [
|
|
106
|
-
/* @__PURE__ */ jsx("input", {
|
|
107
|
-
type: "checkbox",
|
|
108
|
-
disabled: true,
|
|
109
|
-
checked: item.checked
|
|
110
|
-
}),
|
|
111
|
-
" "
|
|
112
|
-
]
|
|
113
|
-
}),
|
|
114
|
-
item.children
|
|
115
|
-
]
|
|
115
|
+
children: items.map((item, index) => /* @__PURE__ */ jsx("li", {
|
|
116
|
+
children: item.children
|
|
116
117
|
}, index))
|
|
117
118
|
});
|
|
118
119
|
},
|
|
@@ -121,18 +122,22 @@ const defaultComponents = {
|
|
|
121
122
|
}
|
|
122
123
|
};
|
|
123
124
|
const Markdown = forwardRef(
|
|
124
|
-
({ content, components, asChild, ...props }, forwardedRef) => {
|
|
125
|
+
({ content, partial, components, asChild, ...props }, forwardedRef) => {
|
|
125
126
|
const Component = asChild ? Slot : "div";
|
|
126
127
|
const tokens = useMemo(() => {
|
|
127
|
-
|
|
128
|
-
|
|
128
|
+
if (!content) {
|
|
129
|
+
return [];
|
|
130
|
+
}
|
|
131
|
+
return partial ? tokenizePartial(content) : tokenize(content);
|
|
132
|
+
}, [content, partial]);
|
|
129
133
|
return /* @__PURE__ */ jsx(Component, {
|
|
130
134
|
...props,
|
|
131
135
|
ref: forwardedRef,
|
|
132
136
|
children: tokens.map((token, index) => {
|
|
133
137
|
return /* @__PURE__ */ jsx(MemoizedMarkdownToken, {
|
|
134
138
|
token,
|
|
135
|
-
components
|
|
139
|
+
components,
|
|
140
|
+
partial
|
|
136
141
|
}, index);
|
|
137
142
|
})
|
|
138
143
|
});
|
|
@@ -151,22 +156,25 @@ const MemoizedMarkdownToken = memo(
|
|
|
151
156
|
(previousProps, nextProps) => {
|
|
152
157
|
const previousToken = previousProps.token;
|
|
153
158
|
const nextToken = nextProps.token;
|
|
154
|
-
if (previousToken.
|
|
159
|
+
if (previousToken.type !== nextToken.type || previousProps.partial !== nextProps.partial) {
|
|
155
160
|
return false;
|
|
156
161
|
}
|
|
157
|
-
|
|
162
|
+
let previousContent = previousToken.raw;
|
|
163
|
+
let nextContent = nextToken.raw;
|
|
164
|
+
if ("text" in previousToken && "text" in nextToken) {
|
|
165
|
+
previousContent = previousToken.text;
|
|
166
|
+
nextContent = nextToken.text;
|
|
167
|
+
}
|
|
168
|
+
if (previousContent.length !== nextContent.length) {
|
|
158
169
|
return false;
|
|
159
170
|
}
|
|
160
|
-
return
|
|
171
|
+
return previousContent === nextContent;
|
|
161
172
|
}
|
|
162
173
|
);
|
|
163
174
|
function MarkdownToken({
|
|
164
175
|
token,
|
|
165
176
|
components
|
|
166
177
|
}) {
|
|
167
|
-
if (!isMarkedToken(token)) {
|
|
168
|
-
return null;
|
|
169
|
-
}
|
|
170
178
|
switch (token.type) {
|
|
171
179
|
case "escape": {
|
|
172
180
|
return token.text;
|
|
@@ -264,12 +272,12 @@ function MarkdownToken({
|
|
|
264
272
|
case "code": {
|
|
265
273
|
let language = void 0;
|
|
266
274
|
if (token.lang !== void 0) {
|
|
267
|
-
language = token.lang.match(
|
|
275
|
+
language = token.lang.match(TRAILING_NON_WHITESPACE_REGEX)?.[0] ?? void 0;
|
|
268
276
|
}
|
|
269
277
|
const CodeBlock = components?.CodeBlock ?? defaultComponents.CodeBlock;
|
|
270
278
|
return /* @__PURE__ */ jsx(CodeBlock, {
|
|
271
279
|
language,
|
|
272
|
-
code: token.text
|
|
280
|
+
code: token.text || " "
|
|
273
281
|
});
|
|
274
282
|
}
|
|
275
283
|
case "blockquote": {
|
|
@@ -285,12 +293,23 @@ function MarkdownToken({
|
|
|
285
293
|
case "list": {
|
|
286
294
|
const List = components?.List ?? defaultComponents.List;
|
|
287
295
|
const items = token.items.map((item) => {
|
|
296
|
+
let tokens = item.tokens;
|
|
297
|
+
if (item.task) {
|
|
298
|
+
tokens = [
|
|
299
|
+
{
|
|
300
|
+
type: "checkbox",
|
|
301
|
+
checked: Boolean(item.checked),
|
|
302
|
+
raw: `[${item.checked ? "x" : " "}]`
|
|
303
|
+
},
|
|
304
|
+
...tokens
|
|
305
|
+
];
|
|
306
|
+
}
|
|
288
307
|
return {
|
|
289
308
|
checked: item.task ? item.checked : void 0,
|
|
290
309
|
children: /* @__PURE__ */ jsx(MarkdownTokens, {
|
|
291
|
-
tokens
|
|
310
|
+
tokens,
|
|
292
311
|
components,
|
|
293
|
-
normalizeToBlockTokens: item.loose
|
|
312
|
+
normalizeToBlockTokens: item.tokens.length > 0 ? item.loose : false
|
|
294
313
|
})
|
|
295
314
|
};
|
|
296
315
|
});
|
|
@@ -299,6 +318,18 @@ function MarkdownToken({
|
|
|
299
318
|
...props
|
|
300
319
|
});
|
|
301
320
|
}
|
|
321
|
+
case "checkbox": {
|
|
322
|
+
return /* @__PURE__ */ jsxs(Fragment, {
|
|
323
|
+
children: [
|
|
324
|
+
/* @__PURE__ */ jsx("input", {
|
|
325
|
+
type: "checkbox",
|
|
326
|
+
disabled: true,
|
|
327
|
+
checked: token.checked
|
|
328
|
+
}),
|
|
329
|
+
" "
|
|
330
|
+
]
|
|
331
|
+
});
|
|
332
|
+
}
|
|
302
333
|
case "table": {
|
|
303
334
|
const Table = components?.Table ?? defaultComponents.Table;
|
|
304
335
|
const headings = token.header.map(
|
|
@@ -340,7 +371,9 @@ function MarkdownToken({
|
|
|
340
371
|
const Separator = components?.Separator ?? defaultComponents.Separator;
|
|
341
372
|
return /* @__PURE__ */ jsx(Separator, {});
|
|
342
373
|
}
|
|
343
|
-
case "html":
|
|
374
|
+
case "html": {
|
|
375
|
+
return parseHtmlEntities(token.text);
|
|
376
|
+
}
|
|
344
377
|
default: {
|
|
345
378
|
return null;
|
|
346
379
|
}
|
|
@@ -351,64 +384,379 @@ function MarkdownTokens({
|
|
|
351
384
|
components,
|
|
352
385
|
normalizeToBlockTokens = false
|
|
353
386
|
}) {
|
|
354
|
-
|
|
387
|
+
assertTokens(tokens);
|
|
388
|
+
let normalizedTokens = [];
|
|
355
389
|
if (normalizeToBlockTokens) {
|
|
390
|
+
let leadingCheckboxToken = tokens[0]?.type === "checkbox" ? tokens[0] : null;
|
|
356
391
|
for (let i = 0; i < tokens.length; i++) {
|
|
357
392
|
const token = tokens[i];
|
|
358
393
|
switch (token.type) {
|
|
359
394
|
case "text": {
|
|
360
|
-
const
|
|
395
|
+
const paragraphTextTokens = [token];
|
|
361
396
|
while (i + 1 < tokens.length && tokens[i + 1].type === "text") {
|
|
362
397
|
i++;
|
|
363
|
-
|
|
398
|
+
paragraphTextTokens.push(tokens[i]);
|
|
364
399
|
}
|
|
400
|
+
const paragraphRaw = paragraphTextTokens.map((text) => text.raw).join("");
|
|
401
|
+
const paragraphText = paragraphTextTokens.map((text) => text.text).join("");
|
|
365
402
|
normalizedTokens.push({
|
|
366
403
|
type: "paragraph",
|
|
367
|
-
tokens:
|
|
368
|
-
raw:
|
|
369
|
-
text:
|
|
404
|
+
tokens: leadingCheckboxToken ? [leadingCheckboxToken, ...paragraphTextTokens] : paragraphTextTokens,
|
|
405
|
+
raw: paragraphRaw,
|
|
406
|
+
text: paragraphText
|
|
370
407
|
});
|
|
408
|
+
leadingCheckboxToken = null;
|
|
371
409
|
break;
|
|
372
410
|
}
|
|
411
|
+
case "checkbox":
|
|
412
|
+
break;
|
|
373
413
|
default: {
|
|
374
414
|
normalizedTokens.push(token);
|
|
375
415
|
}
|
|
376
416
|
}
|
|
377
417
|
}
|
|
418
|
+
} else {
|
|
419
|
+
normalizedTokens = tokens;
|
|
378
420
|
}
|
|
379
|
-
return
|
|
421
|
+
return normalizedTokens.map((token, index) => /* @__PURE__ */ jsx(MarkdownToken, {
|
|
380
422
|
token,
|
|
381
423
|
components
|
|
382
424
|
}, index));
|
|
383
425
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
"
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
426
|
+
function assertTokens(_) {
|
|
427
|
+
}
|
|
428
|
+
function isBlockToken(token) {
|
|
429
|
+
return token.type === "paragraph" || token.type === "heading" || token.type === "blockquote" || token.type === "list_item";
|
|
430
|
+
}
|
|
431
|
+
function tokenize(markdown) {
|
|
432
|
+
return new Lexer().lex(markdown);
|
|
433
|
+
}
|
|
434
|
+
function tokenizePartial(markdown) {
|
|
435
|
+
const preprocessedContent = trimPartialMarkdown(normalizeNewlines(markdown));
|
|
436
|
+
const tokens = tokenize(preprocessedContent);
|
|
437
|
+
try {
|
|
438
|
+
return completePartialTokens(tokens);
|
|
439
|
+
} catch {
|
|
440
|
+
return tokens;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
function findPotentiallyPartialToken(tokens, parentToken) {
|
|
444
|
+
if (tokens.length === 0) {
|
|
445
|
+
return parentToken;
|
|
446
|
+
}
|
|
447
|
+
assertTokens(tokens);
|
|
448
|
+
const lastIndex = tokens.length - 1;
|
|
449
|
+
let lastToken = tokens[lastIndex];
|
|
450
|
+
if (lastToken.type === "space") {
|
|
451
|
+
const penultimateToken = tokens[lastIndex - 1];
|
|
452
|
+
if (!penultimateToken) {
|
|
453
|
+
return parentToken;
|
|
454
|
+
}
|
|
455
|
+
lastToken = penultimateToken;
|
|
456
|
+
}
|
|
457
|
+
if (lastToken.type === "list") {
|
|
458
|
+
const listToken = lastToken;
|
|
459
|
+
const lastListItem = listToken.items[listToken.items.length - 1];
|
|
460
|
+
if (!lastListItem) {
|
|
461
|
+
return parentToken;
|
|
462
|
+
}
|
|
463
|
+
const lastListItemTokens = lastListItem.tokens;
|
|
464
|
+
if (lastListItemTokens.some((token) => token.type === "space") && lastListItemTokens.length > 0) {
|
|
465
|
+
const lastListItemLastToken = lastListItemTokens[lastListItemTokens.length - 1];
|
|
466
|
+
if (lastListItemLastToken) {
|
|
467
|
+
if (lastListItemLastToken.type === "text") {
|
|
468
|
+
return lastListItemLastToken;
|
|
469
|
+
}
|
|
470
|
+
if (isBlockToken(lastListItemLastToken)) {
|
|
471
|
+
return findPotentiallyPartialToken(
|
|
472
|
+
lastListItemLastToken.tokens,
|
|
473
|
+
lastListItemLastToken
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
return void 0;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
return findPotentiallyPartialToken(lastListItem.tokens, lastListItem);
|
|
480
|
+
}
|
|
481
|
+
if (lastToken.type === "table") {
|
|
482
|
+
const tableToken = lastToken;
|
|
483
|
+
const lastTableRow = tableToken.rows[tableToken.rows.length - 1];
|
|
484
|
+
if (!lastTableRow) {
|
|
485
|
+
return parentToken;
|
|
486
|
+
}
|
|
487
|
+
const firstEmptyTableCellIndex = lastTableRow.findIndex(
|
|
488
|
+
(cell) => cell.tokens.length === 0
|
|
489
|
+
);
|
|
490
|
+
const lastNonEmptyTableCell = firstEmptyTableCellIndex === -1 ? void 0 : firstEmptyTableCellIndex === 0 ? lastTableRow[firstEmptyTableCellIndex] : lastTableRow[firstEmptyTableCellIndex - 1];
|
|
491
|
+
if (!lastNonEmptyTableCell) {
|
|
492
|
+
return parentToken;
|
|
493
|
+
}
|
|
494
|
+
return findPotentiallyPartialToken(
|
|
495
|
+
lastNonEmptyTableCell.tokens,
|
|
496
|
+
lastNonEmptyTableCell
|
|
497
|
+
);
|
|
498
|
+
}
|
|
499
|
+
if (isBlockToken(lastToken)) {
|
|
500
|
+
return findPotentiallyPartialToken(lastToken.tokens, lastToken);
|
|
501
|
+
}
|
|
502
|
+
return parentToken;
|
|
503
|
+
}
|
|
504
|
+
function normalizeNewlines(string) {
|
|
505
|
+
return string.replace(NEWLINE_REGEX, "\n");
|
|
506
|
+
}
|
|
507
|
+
function trimPartialMarkdown(markdown) {
|
|
508
|
+
const lines = markdown.split("\n");
|
|
509
|
+
if (lines.length === 0) {
|
|
510
|
+
return markdown;
|
|
511
|
+
}
|
|
512
|
+
const [singleCharacterMatch] = lines[lines.length - 1].match(SINGLE_CHARACTER_REGEX) ?? [];
|
|
513
|
+
if (singleCharacterMatch) {
|
|
514
|
+
lines[lines.length - 1] = lines[lines.length - 1].slice(
|
|
515
|
+
0,
|
|
516
|
+
-singleCharacterMatch.length
|
|
517
|
+
);
|
|
518
|
+
return lines.join("\n");
|
|
519
|
+
}
|
|
520
|
+
const [bufferedCharactersMatch] = lines[lines.length - 1].match(BUFFERED_CHARACTERS_REGEX) ?? [];
|
|
521
|
+
if (bufferedCharactersMatch) {
|
|
522
|
+
lines[lines.length - 1] = lines[lines.length - 1].slice(
|
|
523
|
+
0,
|
|
524
|
+
-bufferedCharactersMatch.length
|
|
525
|
+
);
|
|
526
|
+
return lines.join("\n");
|
|
527
|
+
}
|
|
528
|
+
return markdown;
|
|
529
|
+
}
|
|
530
|
+
function completePartialInlineMarkdown(markdown, options = {}) {
|
|
531
|
+
const stack = [];
|
|
532
|
+
const allowLinksImages = options.allowLinksImages ?? true;
|
|
533
|
+
let completedMarkdown = markdown;
|
|
534
|
+
const partialEmojiMatch = completedMarkdown.match(PARTIAL_EMOJI_REGEX);
|
|
535
|
+
if (partialEmojiMatch) {
|
|
536
|
+
const partialEmoji = partialEmojiMatch[0];
|
|
537
|
+
completedMarkdown = completedMarkdown.slice(0, -partialEmoji.length);
|
|
538
|
+
if (partialEmoji.includes("\uFE0F") || partialEmoji.includes("\u20E3")) {
|
|
539
|
+
const codepoints = Array.from(completedMarkdown);
|
|
540
|
+
if (codepoints.length > 0) {
|
|
541
|
+
completedMarkdown = codepoints.slice(0, -1).join("");
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
for (let i = 0; i < completedMarkdown.length; i++) {
|
|
546
|
+
const character = completedMarkdown[i];
|
|
547
|
+
const isEscaped = i > 0 ? completedMarkdown[i - 1] === "\\" : false;
|
|
548
|
+
if (isEscaped) {
|
|
549
|
+
continue;
|
|
550
|
+
}
|
|
551
|
+
if (character === "`") {
|
|
552
|
+
const lastDelimiter = stack[stack.length - 1];
|
|
553
|
+
const isClosingPreviousDelimiter = lastDelimiter?.string === "`" && i > lastDelimiter.index;
|
|
554
|
+
if (isClosingPreviousDelimiter) {
|
|
555
|
+
stack.pop();
|
|
556
|
+
} else {
|
|
557
|
+
const characterAfterDelimiter = completedMarkdown[i + 1];
|
|
558
|
+
if (characterAfterDelimiter && !WHITESPACE_REGEX.test(characterAfterDelimiter)) {
|
|
559
|
+
stack.push({ string: "`", length: 1, index: i });
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
continue;
|
|
563
|
+
}
|
|
564
|
+
if (character === "*" || character === "_" || character === "~") {
|
|
565
|
+
const isInsideInlineCode = stack[stack.length - 1]?.string === "`";
|
|
566
|
+
let j = i;
|
|
567
|
+
while (j < completedMarkdown.length && completedMarkdown[j] === character) {
|
|
568
|
+
j++;
|
|
569
|
+
}
|
|
570
|
+
const consecutiveDelimiterCharacters = j - i;
|
|
571
|
+
if (isInsideInlineCode) {
|
|
572
|
+
i += consecutiveDelimiterCharacters - 1;
|
|
573
|
+
continue;
|
|
574
|
+
}
|
|
575
|
+
let remainingConsecutiveDelimiterCharacters = consecutiveDelimiterCharacters;
|
|
576
|
+
let consecutiveDelimiterCharacterIndex = 0;
|
|
577
|
+
while (remainingConsecutiveDelimiterCharacters > 0) {
|
|
578
|
+
const lastDelimiter = stack[stack.length - 1];
|
|
579
|
+
if (!lastDelimiter || lastDelimiter.string[0] !== character) {
|
|
580
|
+
break;
|
|
581
|
+
}
|
|
582
|
+
if (remainingConsecutiveDelimiterCharacters >= lastDelimiter.length) {
|
|
583
|
+
stack.pop();
|
|
584
|
+
remainingConsecutiveDelimiterCharacters -= lastDelimiter.length;
|
|
585
|
+
consecutiveDelimiterCharacterIndex += lastDelimiter.length;
|
|
586
|
+
continue;
|
|
587
|
+
}
|
|
588
|
+
break;
|
|
589
|
+
}
|
|
590
|
+
if (remainingConsecutiveDelimiterCharacters > 0) {
|
|
591
|
+
if (i + consecutiveDelimiterCharacters >= completedMarkdown.length) {
|
|
592
|
+
completedMarkdown = completedMarkdown.slice(
|
|
593
|
+
0,
|
|
594
|
+
completedMarkdown.length - remainingConsecutiveDelimiterCharacters
|
|
595
|
+
);
|
|
596
|
+
break;
|
|
597
|
+
}
|
|
598
|
+
const characterAfterDelimiters = completedMarkdown[i + consecutiveDelimiterCharacters];
|
|
599
|
+
if (characterAfterDelimiters && !WHITESPACE_REGEX.test(characterAfterDelimiters)) {
|
|
600
|
+
let delimiterStartIndex = i + consecutiveDelimiterCharacterIndex;
|
|
601
|
+
if (remainingConsecutiveDelimiterCharacters % 2 === 1) {
|
|
602
|
+
stack.push({
|
|
603
|
+
string: character,
|
|
604
|
+
length: 1,
|
|
605
|
+
index: delimiterStartIndex
|
|
606
|
+
});
|
|
607
|
+
delimiterStartIndex += 1;
|
|
608
|
+
remainingConsecutiveDelimiterCharacters -= 1;
|
|
609
|
+
}
|
|
610
|
+
while (remainingConsecutiveDelimiterCharacters >= 2) {
|
|
611
|
+
stack.push({
|
|
612
|
+
string: character + character,
|
|
613
|
+
length: 2,
|
|
614
|
+
index: delimiterStartIndex
|
|
615
|
+
});
|
|
616
|
+
delimiterStartIndex += 2;
|
|
617
|
+
remainingConsecutiveDelimiterCharacters -= 2;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
i += consecutiveDelimiterCharacters - 1;
|
|
622
|
+
continue;
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
if (allowLinksImages) {
|
|
626
|
+
const partialLinkImageMatch = completedMarkdown.match(
|
|
627
|
+
PARTIAL_LINK_IMAGE_REGEX
|
|
628
|
+
);
|
|
629
|
+
if (partialLinkImageMatch) {
|
|
630
|
+
const linkImageStartIndex = partialLinkImageMatch.index;
|
|
631
|
+
const linkImageEndIndex = linkImageStartIndex + partialLinkImageMatch[0].length;
|
|
632
|
+
const isInsideInlineCode = stack.some(
|
|
633
|
+
(delimiter) => delimiter.string === "`" && delimiter.index < linkImageStartIndex
|
|
634
|
+
);
|
|
635
|
+
if (!isInsideInlineCode) {
|
|
636
|
+
const partialLinkImageContent = partialLinkImageMatch[0];
|
|
637
|
+
const {
|
|
638
|
+
text: partialLinkText,
|
|
639
|
+
url: partialLinkUrl,
|
|
640
|
+
image: isImage
|
|
641
|
+
} = partialLinkImageMatch.groups;
|
|
642
|
+
if (isImage) {
|
|
643
|
+
completedMarkdown = completedMarkdown.slice(
|
|
644
|
+
0,
|
|
645
|
+
-partialLinkImageContent.length
|
|
646
|
+
);
|
|
647
|
+
} else {
|
|
648
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
649
|
+
const delimiter = stack[i];
|
|
650
|
+
if (delimiter.index >= linkImageStartIndex && delimiter.index < linkImageEndIndex) {
|
|
651
|
+
stack.splice(i, 1);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
const completedLinkText = partialLinkText ? partialLinkUrl ? partialLinkText : completePartialInlineMarkdown(partialLinkText, {
|
|
655
|
+
allowLinksImages: false
|
|
656
|
+
}) : "";
|
|
657
|
+
const completedLinkUrl = partialLinkUrl && !WHITESPACE_REGEX.test(partialLinkUrl) && isUrl(partialLinkUrl) ? partialLinkUrl : DEFAULT_PARTIAL_LINK_URL;
|
|
658
|
+
const completedLink = `[${completedLinkText}](${completedLinkUrl})`;
|
|
659
|
+
completedMarkdown = completedMarkdown.slice(
|
|
660
|
+
0,
|
|
661
|
+
-partialLinkImageContent.length
|
|
662
|
+
);
|
|
663
|
+
completedMarkdown += completedLink;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
669
|
+
const delimiter = stack[i];
|
|
670
|
+
if (delimiter.index + delimiter.length >= completedMarkdown.length) {
|
|
671
|
+
completedMarkdown = completedMarkdown.slice(0, delimiter.index);
|
|
672
|
+
continue;
|
|
673
|
+
}
|
|
674
|
+
if (delimiter.string !== "`") {
|
|
675
|
+
completedMarkdown = completedMarkdown.trimEnd();
|
|
676
|
+
}
|
|
677
|
+
completedMarkdown += delimiter.string;
|
|
678
|
+
}
|
|
679
|
+
return completedMarkdown;
|
|
680
|
+
}
|
|
681
|
+
function completePartialTableMarkdown(markdown) {
|
|
682
|
+
const tableLines = markdown.split("\n");
|
|
683
|
+
if (tableLines.length === 0) {
|
|
684
|
+
return void 0;
|
|
685
|
+
}
|
|
686
|
+
const tableHeader = tableLines[0];
|
|
687
|
+
if (tableHeader === "|") {
|
|
688
|
+
return void 0;
|
|
689
|
+
}
|
|
690
|
+
const tableHeadings = tableHeader.split("|").map((cell) => cell.trim()).filter((cell) => cell !== "");
|
|
691
|
+
if (tableHeadings.length === 0) {
|
|
692
|
+
return void 0;
|
|
693
|
+
}
|
|
694
|
+
if (!tableHeader.endsWith("|")) {
|
|
695
|
+
const lastTableHeading = tableHeadings[tableHeadings.length - 1];
|
|
696
|
+
const completedLastTableHeading = completePartialInlineMarkdown(lastTableHeading);
|
|
697
|
+
tableHeadings[tableHeadings.length - 1] = completedLastTableHeading;
|
|
698
|
+
}
|
|
699
|
+
return `| ${tableHeadings.join(" | ")} |
|
|
700
|
+
| ${tableHeadings.map(() => "---").join(" | ")} |`;
|
|
701
|
+
}
|
|
702
|
+
function completePartialTokens(tokens) {
|
|
703
|
+
const potentiallyPartialToken = findPotentiallyPartialToken(tokens);
|
|
704
|
+
if (!potentiallyPartialToken) {
|
|
705
|
+
return tokens;
|
|
706
|
+
}
|
|
707
|
+
if (potentiallyPartialToken.type === "paragraph" || potentiallyPartialToken.type === "text") {
|
|
708
|
+
if (PARTIAL_TABLE_HEADER_REGEX.test(potentiallyPartialToken.raw)) {
|
|
709
|
+
const completedTableMarkdown = completePartialTableMarkdown(
|
|
710
|
+
potentiallyPartialToken.raw
|
|
711
|
+
);
|
|
712
|
+
if (completedTableMarkdown) {
|
|
713
|
+
const completedTable = tokenize(completedTableMarkdown)[0];
|
|
714
|
+
if (completedTable) {
|
|
715
|
+
const table = potentiallyPartialToken;
|
|
716
|
+
table.type = "table";
|
|
717
|
+
table.header = completedTable.header;
|
|
718
|
+
table.align = completedTable.align;
|
|
719
|
+
table.rows = completedTable.rows;
|
|
720
|
+
return tokens;
|
|
721
|
+
}
|
|
722
|
+
} else {
|
|
723
|
+
potentiallyPartialToken.text = "";
|
|
724
|
+
potentiallyPartialToken.tokens = [];
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
if (potentiallyPartialToken.type === "list_item") {
|
|
729
|
+
const listItem = potentiallyPartialToken;
|
|
730
|
+
const listItemTokens = listItem.tokens;
|
|
731
|
+
if (!listItem.task && listItemTokens.length === 1 && listItemTokens[0].type === "text") {
|
|
732
|
+
const listItemText = listItemTokens[0];
|
|
733
|
+
const checkboxMatch = listItemText.text.match(LIST_ITEM_CHECKBOX_REGEX);
|
|
734
|
+
if (checkboxMatch) {
|
|
735
|
+
listItem.task = true;
|
|
736
|
+
if (checkboxMatch[1] === "x") {
|
|
737
|
+
listItem.checked = true;
|
|
738
|
+
} else {
|
|
739
|
+
listItem.checked = false;
|
|
740
|
+
}
|
|
741
|
+
listItem.text = "";
|
|
742
|
+
listItem.tokens = [];
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
if (potentiallyPartialToken.text.length === 0) {
|
|
747
|
+
return tokens;
|
|
748
|
+
}
|
|
749
|
+
const completedMarkdown = completePartialInlineMarkdown(
|
|
750
|
+
potentiallyPartialToken.text
|
|
751
|
+
);
|
|
752
|
+
const completedMarkdownTokens = tokenize(completedMarkdown)[0]?.tokens ?? [];
|
|
753
|
+
potentiallyPartialToken.text = completedMarkdown;
|
|
754
|
+
potentiallyPartialToken.tokens = completedMarkdownTokens;
|
|
755
|
+
return tokens;
|
|
408
756
|
}
|
|
409
757
|
function parseHtmlEntities(input) {
|
|
410
758
|
const document = new DOMParser().parseFromString(
|
|
411
|
-
`<!doctype html><body>${input}`,
|
|
759
|
+
`<!doctype html><body>${input.replace(AMPERSAND_REGEX, "&").replace(LEFT_ANGLE_BRACKET_REGEX, "<").replace(RIGHT_ANGLE_BRACKET_REGEX, ">")}`,
|
|
412
760
|
"text/html"
|
|
413
761
|
);
|
|
414
762
|
return document.body.textContent;
|