samengine 1.7.7 → 1.7.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.
- package/dist/build/index.js +1 -1
- package/dist/utils/markdown.js +43 -34
- package/package.json +1 -1
package/dist/build/index.js
CHANGED
package/dist/utils/markdown.js
CHANGED
|
@@ -37,17 +37,17 @@ function renderInline(text, opts) {
|
|
|
37
37
|
// Escaped Zeichen sichern (wichtig für Markdown-Sonderzeichen)
|
|
38
38
|
// ---------------------------------------------------------------------
|
|
39
39
|
const ESCAPES = {
|
|
40
|
-
"\\\\": "
|
|
41
|
-
"\\[": "
|
|
42
|
-
"\\]": "
|
|
43
|
-
"\\(": "
|
|
44
|
-
"\\)": "
|
|
45
|
-
"\\|": "
|
|
46
|
-
'\\"': "
|
|
47
|
-
"\\*": "
|
|
48
|
-
"\\_": "
|
|
49
|
-
"\\`": "
|
|
50
|
-
"\\~": "
|
|
40
|
+
"\\\\": "@@ESC-BACKSLASH@@",
|
|
41
|
+
"\\[": "@@ESC-LBRACKET@@",
|
|
42
|
+
"\\]": "@@ESC-RBRACKET@@",
|
|
43
|
+
"\\(": "@@ESC-LPAREN@@",
|
|
44
|
+
"\\)": "@@ESC-RPAREN@@",
|
|
45
|
+
"\\|": "@@ESC-PIPE@@",
|
|
46
|
+
'\\"': "@@ESC-QUOTE@@",
|
|
47
|
+
"\\*": "@@ESC-STAR@@",
|
|
48
|
+
"\\_": "@@ESC-UNDERSCORE@@",
|
|
49
|
+
"\\`": "@@ESC-BACKTICK@@",
|
|
50
|
+
"\\~": "@@ESC-TILDE@@"
|
|
51
51
|
};
|
|
52
52
|
for (const [char, placeholder] of Object.entries(ESCAPES)) {
|
|
53
53
|
const regex = new RegExp(char.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&"), "g");
|
|
@@ -58,9 +58,17 @@ function renderInline(text, opts) {
|
|
|
58
58
|
if (!opts.sanitize) {
|
|
59
59
|
text = text.replace(/<[^>]+>/g, (match) => {
|
|
60
60
|
const idx = htmlPlaceholders.push(match) - 1;
|
|
61
|
-
return
|
|
61
|
+
return `@@HTML${idx}@@`;
|
|
62
62
|
});
|
|
63
63
|
}
|
|
64
|
+
// Links [text](url "title")
|
|
65
|
+
text = text.replace(/\[([^\]]+)\]\(([^)]+?)(?:\s+"([^"]*)")?\)/g, (_, linkText, url, title) => {
|
|
66
|
+
const t = title ? ` title="${escapeHtml(title)}"` : "";
|
|
67
|
+
const ext = opts.externalLinks && isExternalUrl(url)
|
|
68
|
+
? ' target="_blank" rel="noopener noreferrer"'
|
|
69
|
+
: "";
|
|
70
|
+
return `<a href="${url}"${t}${ext}>${linkText}</a>`;
|
|
71
|
+
});
|
|
64
72
|
// Code-Spans (höchste Priorität, vor allem anderen)
|
|
65
73
|
text = text.replace(/`{2}([^`]+)`{2}|`([^`\n]+)`/g, (_, a, b) => {
|
|
66
74
|
return `<code>${escapeHtml(a ?? b)}</code>`;
|
|
@@ -70,14 +78,6 @@ function renderInline(text, opts) {
|
|
|
70
78
|
const t = title ? ` title="${escapeHtml(title)}"` : "";
|
|
71
79
|
return `<img src="${url}" alt="${escapeHtml(alt)}"${t}>`;
|
|
72
80
|
});
|
|
73
|
-
// Links [text](url "title")
|
|
74
|
-
text = text.replace(/\[([^\]]+)\]\(([^)]+?)(?:\s+"([^"]*)")?\)/g, (_, linkText, url, title) => {
|
|
75
|
-
const t = title ? ` title="${escapeHtml(title)}"` : "";
|
|
76
|
-
const ext = opts.externalLinks && isExternalUrl(url)
|
|
77
|
-
? ' target="_blank" rel="noopener noreferrer"'
|
|
78
|
-
: "";
|
|
79
|
-
return `<a href="${url}"${t}${ext}>${renderInline(linkText, opts)}</a>`;
|
|
80
|
-
});
|
|
81
81
|
// Autolinks <https://…>
|
|
82
82
|
text = text.replace(/<(https?:\/\/[^\s>]+)>/g, (_, url) => {
|
|
83
83
|
const ext = opts.externalLinks
|
|
@@ -115,12 +115,19 @@ function renderInline(text, opts) {
|
|
|
115
115
|
}
|
|
116
116
|
// HTML-Platzhalter wiederherstellen
|
|
117
117
|
if (!opts.sanitize) {
|
|
118
|
-
text = text.replace(
|
|
119
|
-
}
|
|
120
|
-
// <<< HIER rein
|
|
121
|
-
for (const [char, placeholder] of Object.entries(ESCAPES)) {
|
|
122
|
-
text = text.replace(new RegExp(placeholder, "g"), char.replace("\\", ""));
|
|
118
|
+
text = text.replace(/@@HTML(\d+)@@/g, (_, i) => htmlPlaceholders[+i]);
|
|
123
119
|
}
|
|
120
|
+
text = text.replace(/@@ESC-BACKSLASH@@/g, "\\");
|
|
121
|
+
text = text.replace(/@@ESC-LPAREN@@/g, "(");
|
|
122
|
+
text = text.replace(/@@ESC-RPAREN@@/g, ")");
|
|
123
|
+
text = text.replace(/@@ESC-PIPE@@/g, "|");
|
|
124
|
+
text = text.replace(/@@ESC-QUOTE@@/g, '"');
|
|
125
|
+
text = text.replace(/@@ESC-STAR@@/g, "*");
|
|
126
|
+
text = text.replace(/@@ESC-UNDERSCORE@@/g, "_");
|
|
127
|
+
text = text.replace(/@@ESC-BACKTICK@@/g, "`");
|
|
128
|
+
text = text.replace(/@@ESC-TILDE@@/g, "~");
|
|
129
|
+
text = text.replace(/@@ESC-RBRACKET@@/g, "]");
|
|
130
|
+
text = text.replace(/@@ESC-LBRACKET@@/g, "[");
|
|
124
131
|
return text;
|
|
125
132
|
}
|
|
126
133
|
function parseListItems(lines, baseIndent) {
|
|
@@ -197,9 +204,10 @@ function parseTable(block, opts) {
|
|
|
197
204
|
.filter((_, i, a) => !(i === 0 && _ === "") && !(i === a.length - 1 && _ === ""))
|
|
198
205
|
.map((c) => c
|
|
199
206
|
.trim()
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
207
|
+
// .replace(/\\\|/g, "|")
|
|
208
|
+
// .replace(/\\\[/g, "[")
|
|
209
|
+
// .replace(/\\\]/g, "]")
|
|
210
|
+
);
|
|
203
211
|
const alignRow = rows[1].split(/(?<!\\)\|/).filter((c) => /[-:]/.test(c));
|
|
204
212
|
const aligns = alignRow.map((c) => {
|
|
205
213
|
c = c.trim();
|
|
@@ -223,9 +231,10 @@ function parseTable(block, opts) {
|
|
|
223
231
|
.filter((_, i, a) => !(i === 0 && _ === "") && !(i === a.length - 1 && _ === ""))
|
|
224
232
|
.map((c) => c
|
|
225
233
|
.trim()
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
234
|
+
// .replace(/\\\|/g, "|")
|
|
235
|
+
// .replace(/\\\[/g, "[")
|
|
236
|
+
// .replace(/\\\]/g, "]")
|
|
237
|
+
);
|
|
229
238
|
return `<tr>\n${cells
|
|
230
239
|
.map((c, i) => {
|
|
231
240
|
const align = aligns[i] ? ` style="text-align:${aligns[i]}"` : "";
|
|
@@ -299,7 +308,7 @@ function parseBlocks(markdown, opts) {
|
|
|
299
308
|
// -----------------------------------------------------------------------
|
|
300
309
|
// Code-Block-Platzhalter (bereits in parse() extrahiert)
|
|
301
310
|
{
|
|
302
|
-
const m = remaining.match(
|
|
311
|
+
const m = remaining.match(/^@@CODEBLOCK\d+@@/);
|
|
303
312
|
if (m) {
|
|
304
313
|
output.push(m[0]); // wird später in parse() ersetzt
|
|
305
314
|
remaining = remaining.slice(m[0].length);
|
|
@@ -609,7 +618,7 @@ export function parse(markdown, options = {}) {
|
|
|
609
618
|
const codeBlockPlaceholders = [];
|
|
610
619
|
text = text.replace(/^(`{3,}|~{3,})([^\n]*)\n([\s\S]*?)\n?\1[ \t]*(?:\n|$)/gm, (_, fence, lang, code) => {
|
|
611
620
|
const idx = codeBlockPlaceholders.push(renderCodeBlock(lang.trim(), code)) - 1;
|
|
612
|
-
return
|
|
621
|
+
return `@@CODEBLOCK${idx}@@\n`;
|
|
613
622
|
});
|
|
614
623
|
// Fußnoten-Definitionen einsammeln
|
|
615
624
|
const { text: cleaned, notes } = collectFootnotes(text);
|
|
@@ -619,7 +628,7 @@ export function parse(markdown, options = {}) {
|
|
|
619
628
|
// Block-Parsing
|
|
620
629
|
let html = parseBlocks(text, opts);
|
|
621
630
|
// Platzhalter durch gerenderte Code-Blöcke ersetzen
|
|
622
|
-
html = html.replace(
|
|
631
|
+
html = html.replace(/@@CODEBLOCK(\d+)@@/g, (_, i) => codeBlockPlaceholders[+i]);
|
|
623
632
|
// Fußnoten-Liste anhängen
|
|
624
633
|
html += renderFootnoteList(notes, opts);
|
|
625
634
|
return html;
|