@monimesl/dot-renderer-react 0.1.0-alpha.34 → 0.1.0-alpha.36

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 (2) hide show
  1. package/dist/markdown.js +35 -10
  2. package/package.json +4 -4
package/dist/markdown.js CHANGED
@@ -1,5 +1,5 @@
1
1
  //#region src/markdown.ts
2
- const HEADING = /^(#{1,6})\s+(.*?)\s*#*\s*$/;
2
+ const HEADING = /^(#{1,6})\s+(.*)$/;
3
3
  const RULE = /^ {0,3}([-*_])( *\1){2,} *$/;
4
4
  const QUOTE = /^ {0,3}> ?/;
5
5
  const LIST_ITEM = /^ {0,3}([-*+]|\d{1,9}[.)])\s+/;
@@ -7,6 +7,7 @@ const LINK = /^(!?)\[([^\]]*)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/;
7
7
  const AUTOLINK = /^<(https?:\/\/[^>\s]+)>/;
8
8
  const PUNCTUATION = /[!-/:-@[-`{-~]/;
9
9
  const ITEM_INDENT = " ";
10
+ const MAX_INLINE_LENGTH = 2e4;
10
11
  function parseMarkdown(markdown) {
11
12
  return parseBlocks(markdown.replace(/\r\n?/g, "\n").split("\n"));
12
13
  }
@@ -56,7 +57,7 @@ function oneLineBlock(line) {
56
57
  if (heading) return {
57
58
  kind: "heading",
58
59
  level: Math.min(heading[1].length, 3),
59
- content: parseInline(heading[2])
60
+ content: parseInline(withoutClosingHashes(heading[2]))
60
61
  };
61
62
  if (RULE.test(line)) return { kind: "rule" };
62
63
  const trimmed = line.trim();
@@ -68,6 +69,11 @@ function oneLineBlock(line) {
68
69
  };
69
70
  return null;
70
71
  }
72
+ function withoutClosingHashes(text) {
73
+ let end = text.trimEnd().length;
74
+ while (end > 0 && text[end - 1] === "#") end -= 1;
75
+ return text.slice(0, end).trimEnd();
76
+ }
71
77
  function endsParagraph(line) {
72
78
  return line.trim() === "" || HEADING.test(line) || RULE.test(line) || QUOTE.test(line) || LIST_ITEM.test(line);
73
79
  }
@@ -118,7 +124,12 @@ function withoutIndent(line, indent) {
118
124
  return line.slice(Math.min(spaces, indent));
119
125
  }
120
126
  function parseInline(text) {
127
+ if (text.length > MAX_INLINE_LENGTH) return [{
128
+ kind: "text",
129
+ text
130
+ }];
121
131
  const inlines = [];
132
+ const closingSearches = /* @__PURE__ */ new Map();
122
133
  let plain = "";
123
134
  let index = 0;
124
135
  const flush = () => {
@@ -185,7 +196,7 @@ function parseInline(text) {
185
196
  continue;
186
197
  }
187
198
  if (char === "*" || char === "_") {
188
- const strong = between(text, index, char + char);
199
+ const strong = between(text, index, char + char, closingSearches);
189
200
  if (strong) {
190
201
  take({
191
202
  kind: "strong",
@@ -193,7 +204,7 @@ function parseInline(text) {
193
204
  }, strong.length);
194
205
  continue;
195
206
  }
196
- const emphasis = between(text, index, char);
207
+ const emphasis = between(text, index, char, closingSearches);
197
208
  if (emphasis) {
198
209
  take({
199
210
  kind: "emphasis",
@@ -208,23 +219,37 @@ function parseInline(text) {
208
219
  flush();
209
220
  return inlines;
210
221
  }
211
- function between(text, start, delimiter) {
222
+ function between(text, start, delimiter, closingSearches) {
212
223
  const open = start + delimiter.length;
213
224
  if (!text.startsWith(delimiter, start) || open >= text.length || /\s/.test(text[open])) return null;
214
225
  const underscore = delimiter.startsWith("_");
215
226
  if (underscore && /\w/.test(text[start - 1] ?? "")) return null;
227
+ let searchEnds = closingSearches.get(delimiter);
228
+ if (!searchEnds) {
229
+ searchEnds = /* @__PURE__ */ new Map();
230
+ closingSearches.set(delimiter, searchEnds);
231
+ }
232
+ const placesLookedAt = [];
216
233
  let close = text.indexOf(delimiter, open + 1);
217
234
  while (close !== -1) {
235
+ const earlierEnd = searchEnds.get(close);
236
+ if (earlierEnd !== void 0) {
237
+ close = earlierEnd;
238
+ break;
239
+ }
240
+ placesLookedAt.push(close);
218
241
  const touchesSpace = /\s/.test(text[close - 1]);
219
242
  const insideWord = underscore && /\w/.test(text[close + delimiter.length] ?? "");
220
243
  const startsPair = delimiter.length === 1 && text[close + 1] === delimiter;
221
- if (!touchesSpace && !insideWord && !startsPair) return {
222
- inner: text.slice(open, close),
223
- length: close + delimiter.length - start
224
- };
244
+ if (!touchesSpace && !insideWord && !startsPair) break;
225
245
  close = text.indexOf(delimiter, close + (startsPair ? 2 : 1));
226
246
  }
227
- return null;
247
+ for (const place of placesLookedAt) searchEnds.set(place, close);
248
+ if (close === -1) return null;
249
+ return {
250
+ inner: text.slice(open, close),
251
+ length: close + delimiter.length - start
252
+ };
228
253
  }
229
254
  //#endregion
230
255
  export { parseInline, parseMarkdown };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monimesl/dot-renderer-react",
3
- "version": "0.1.0-alpha.34",
3
+ "version": "0.1.0-alpha.36",
4
4
  "description": "React renderer for Dot webviews",
5
5
  "type": "module",
6
6
  "repository": {
@@ -29,8 +29,8 @@
29
29
  "react": "19.3.0",
30
30
  "react-dom": "19.3.0",
31
31
  "uqr": "^0.1.3",
32
- "@monimesl/dot-core": "0.1.0-alpha.34",
33
- "@monimesl/dot-webview": "0.1.0-alpha.34"
32
+ "@monimesl/dot-core": "0.1.0-alpha.36",
33
+ "@monimesl/dot-webview": "0.1.0-alpha.36"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@base-ui/react": "1.8.0",
@@ -46,7 +46,7 @@
46
46
  "tsdown": "^0.23.0",
47
47
  "typescript": "^5.9.3",
48
48
  "vitest": "^5.0.1",
49
- "@monimesl/dot-service": "0.1.0-alpha.34"
49
+ "@monimesl/dot-service": "0.1.0-alpha.36"
50
50
  },
51
51
  "publishConfig": {
52
52
  "access": "public"