89 lines
2.9 KiB
JavaScript
89 lines
2.9 KiB
JavaScript
(function (root, factory) {
|
|
const normalize = factory();
|
|
if (typeof module === 'object' && module.exports) module.exports = normalize;
|
|
if (root) root.ccNormalizeMarkdownText = normalize;
|
|
})(typeof globalThis !== 'undefined' ? globalThis : this, function () {
|
|
const CODE_LIKE_PATTERN = /(?:=>|[{};]|^\s*(?:const|let|var|function|class|return|import|export|def|print|console\.)\b|<\/?[a-z][^>]*>)/im;
|
|
const FENCE_PATTERN = /^ {0,3}(`{3,}|~{3,})/;
|
|
|
|
function indentationWidth(line) {
|
|
let width = 0;
|
|
for (const character of line.match(/^[ \t]*/)?.[0] || '') {
|
|
width = character === '\t' ? width + (4 - (width % 4)) : width + 1;
|
|
}
|
|
return width;
|
|
}
|
|
|
|
function removeIndent(line, width) {
|
|
let column = 0;
|
|
let index = 0;
|
|
while (index < line.length && column < width) {
|
|
const character = line[index];
|
|
if (character !== ' ' && character !== '\t') break;
|
|
const nextColumn = character === '\t' ? column + (4 - (column % 4)) : column + 1;
|
|
index += 1;
|
|
if (nextColumn > width) return `${' '.repeat(nextColumn - width)}${line.slice(index)}`;
|
|
column = nextColumn;
|
|
}
|
|
return line.slice(index);
|
|
}
|
|
|
|
function isNaturalLanguage(lines) {
|
|
const text = lines.map((line) => line.trim()).join(' ').trim();
|
|
if (!text || CODE_LIKE_PATTERN.test(text)) return false;
|
|
|
|
const cjkCount = (text.match(/[\u3400-\u9fff]/g) || []).length;
|
|
if (cjkCount >= 4) return /[。!?;:]/.test(text);
|
|
|
|
const wordCount = (text.match(/[a-z][a-z'-]*/gi) || []).length;
|
|
return wordCount >= 8 && /[.!?]/.test(text);
|
|
}
|
|
|
|
function normalizeParagraph(lines) {
|
|
const contentLines = lines.filter((line) => line.trim());
|
|
if (contentLines.length === 0) return lines;
|
|
|
|
const commonIndent = Math.min(...contentLines.map(indentationWidth));
|
|
if (commonIndent < 4 || !isNaturalLanguage(contentLines)) return lines;
|
|
|
|
return lines.map((line) => (line.trim() ? removeIndent(line, commonIndent) : line));
|
|
}
|
|
|
|
return function normalizeMarkdownText(value) {
|
|
const lines = String(value ?? '').split('\n');
|
|
const output = [];
|
|
let paragraph = [];
|
|
let fence = null;
|
|
|
|
function flushParagraph() {
|
|
if (paragraph.length > 0) output.push(...normalizeParagraph(paragraph));
|
|
paragraph = [];
|
|
}
|
|
|
|
for (const line of lines) {
|
|
const fenceMatch = line.match(FENCE_PATTERN);
|
|
if (fence) {
|
|
output.push(line);
|
|
if (fenceMatch && fenceMatch[1][0] === fence.character && fenceMatch[1].length >= fence.length) {
|
|
fence = null;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (fenceMatch) {
|
|
flushParagraph();
|
|
fence = { character: fenceMatch[1][0], length: fenceMatch[1].length };
|
|
output.push(line);
|
|
} else if (!line.trim() || /^\s{0,3}<\/?[a-z][^>]*>/i.test(line)) {
|
|
flushParagraph();
|
|
output.push(line);
|
|
} else {
|
|
paragraph.push(line);
|
|
}
|
|
}
|
|
|
|
flushParagraph();
|
|
return output.join('\n');
|
|
};
|
|
});
|