Update markdown detection to avoid regex
Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
109
packages/prosemirror/src/hasMarkdown.ts
Normal file
109
packages/prosemirror/src/hasMarkdown.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
|
||||
// Use of this source code is governed by the ISC license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
function isTableSeparatorCell(cell: string): boolean {
|
||||
const trimmed = cell.trim();
|
||||
if (trimmed.length < 3) return false;
|
||||
|
||||
let start = 0;
|
||||
let end = trimmed.length;
|
||||
if (trimmed[0] === ":") start = 1;
|
||||
if (trimmed[end - 1] === ":") end -= 1;
|
||||
if (end - start < 3) return false;
|
||||
|
||||
for (let i = start; i < end; i++) {
|
||||
if (trimmed[i] !== "-") return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function isTableSeparatorLine(line: string): boolean {
|
||||
const trimmed = line.trim();
|
||||
if (trimmed.length < 3) return false;
|
||||
|
||||
let s = trimmed;
|
||||
if (s[0] === "|") s = s.slice(1);
|
||||
if (s[s.length - 1] === "|") s = s.slice(0, -1);
|
||||
if (s.trim().length === 0) return false;
|
||||
|
||||
const cells = s.split("|");
|
||||
for (const cell of cells) {
|
||||
if (!isTableSeparatorCell(cell)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function isWordChar(c: number): boolean {
|
||||
return (
|
||||
(c >= 48 && c <= 57) ||
|
||||
(c >= 65 && c <= 90) ||
|
||||
(c >= 97 && c <= 122) ||
|
||||
c === 95
|
||||
);
|
||||
}
|
||||
|
||||
function hasMarkdownLine(line: string): boolean {
|
||||
if (line.length === 0) return false;
|
||||
const ch = line[0];
|
||||
|
||||
if (ch === "`" && line.startsWith("```")) {
|
||||
for (let i = 3; i < line.length; i++) {
|
||||
if (!isWordChar(line.charCodeAt(i))) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ch === "#") {
|
||||
let i = 1;
|
||||
while (i < line.length && i < 6 && line[i] === "#") i++;
|
||||
return i <= 6 && i < line.length && (line[i] === " " || line[i] === "\t");
|
||||
}
|
||||
|
||||
if (ch === ">" && line.length > 1 && (line[1] === " " || line[1] === "\t")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (
|
||||
(ch === "-" || ch === "+" || ch === "*") &&
|
||||
line.length > 1 &&
|
||||
(line[1] === " " || line[1] === "\t")
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ch >= "0" && ch <= "9") {
|
||||
let i = 1;
|
||||
while (i < line.length && line[i] >= "0" && line[i] <= "9") i++;
|
||||
if (
|
||||
i < line.length &&
|
||||
line[i] === "." &&
|
||||
i + 1 < line.length &&
|
||||
(line[i + 1] === " " || line[i + 1] === "\t")
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
line.length >= 3 &&
|
||||
(ch === "-" || ch === "_" || ch === "*") &&
|
||||
line[1] === ch &&
|
||||
line[2] === ch
|
||||
) {
|
||||
for (let i = 3; i < line.length; i++) {
|
||||
if (line[i] !== " " && line[i] !== "\t") return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export function hasMarkdown(text: string): boolean {
|
||||
const lines = text.split("\n");
|
||||
for (const line of lines) {
|
||||
if (hasMarkdownLine(line) || isTableSeparatorLine(line)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -2,4 +2,5 @@
|
||||
// Use of this source code is governed by the ISC license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
export { hasMarkdown, parseInlineContent, parseMarkdown } from "./markdown";
|
||||
export { hasMarkdown } from "./hasMarkdown";
|
||||
export { parseInlineContent, parseMarkdown } from "./markdown";
|
||||
|
||||
@@ -15,11 +15,6 @@ import {
|
||||
safeLinkHref,
|
||||
} from "./htmlBlock";
|
||||
|
||||
const tableSeparatorPattern =
|
||||
/^\|?\s*:?-{3,}:?\s*(\|\s*:?-{3,}:?\s*)*\|?\s*$/m;
|
||||
const markdownLinePattern =
|
||||
/(?:^```\w*$|^#{1,6}\s|^>\s|^[-+*]\s|^\d+\.\s|^(?:---|___|\*\*\*)\s*$)/m;
|
||||
|
||||
function unescapeHtml(html: string): string {
|
||||
return html
|
||||
.replace(/</g, "<")
|
||||
@@ -412,10 +407,6 @@ class Converter {
|
||||
}
|
||||
}
|
||||
|
||||
export function hasMarkdown(text: string): boolean {
|
||||
return markdownLinePattern.test(text) || tableSeparatorPattern.test(text);
|
||||
}
|
||||
|
||||
export function parseInlineContent(
|
||||
schema: Schema,
|
||||
text: string,
|
||||
|
||||
Reference in New Issue
Block a user