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.
@@ -1,4 +1,4 @@
1
1
  // Function to get the Version
2
2
  export function version() {
3
- return "1.7.6";
3
+ return "1.7.8";
4
4
  }
@@ -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
- "\\\\": "\x00ESC_BACKSLASH\x00",
41
- "\\[": "\x00ESC_LBRACKET\x00",
42
- "\\]": "\x00ESC_RBRACKET\x00",
43
- "\\(": "\x00ESC_LPAREN\x00",
44
- "\\)": "\x00ESC_RPAREN\x00",
45
- "\\|": "\x00ESC_PIPE\x00",
46
- '\\"': "\x00ESC_QUOTE\x00",
47
- "\\*": "\x00ESC_STAR\x00",
48
- "\\_": "\x00ESC_UNDERSCORE\x00",
49
- "\\`": "\x00ESC_BACKTICK\x00",
50
- "\\~": "\x00ESC_TILDE\x00"
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 `\x00HTML${idx}\x00`;
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(/\x00HTML(\d+)\x00/g, (_, i) => htmlPlaceholders[+i]);
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
- .replace(/\\\|/g, "|")
201
- .replace(/\\\[/g, "[")
202
- .replace(/\\\]/g, "]"));
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
- .replace(/\\\|/g, "|")
227
- .replace(/\\\[/g, "[")
228
- .replace(/\\\]/g, "]"));
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(/^\x00CODEBLOCK\d+\x00/);
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 `\x00CODEBLOCK${idx}\x00\n`;
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(/\x00CODEBLOCK(\d+)\x00/g, (_, i) => codeBlockPlaceholders[+i]);
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "samengine",
3
- "version": "1.7.7",
3
+ "version": "1.7.9",
4
4
  "description": "A TypeScript game library to make HTML Games",
5
5
  "sideEffects": false,
6
6
  "files": [