domma-cms 0.25.1 → 0.25.2
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/package.json +3 -2
- package/server/services/markdown.js +30 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "domma-cms",
|
|
3
|
-
"version": "0.25.
|
|
3
|
+
"version": "0.25.2",
|
|
4
4
|
"description": "File-based CMS powered by Domma and Fastify. Run npx domma-cms my-site to create a new project.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "server/server.js",
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
"scripts/",
|
|
24
24
|
"docs/",
|
|
25
25
|
"CHANGELOG.md",
|
|
26
|
-
"CLAUDE.md"
|
|
26
|
+
"CLAUDE.md",
|
|
27
|
+
"FEATURES.md"
|
|
27
28
|
],
|
|
28
29
|
"scripts": {
|
|
29
30
|
"test": "node --test --test-concurrency=1 'tests/**/*.test.js'",
|
|
@@ -1177,12 +1177,26 @@ export function parseShortcodeAttrs(attrStr) {
|
|
|
1177
1177
|
* @param {string} markdown
|
|
1178
1178
|
* @returns {{ scrubbed: string, restore: (s: string) => string }}
|
|
1179
1179
|
*/
|
|
1180
|
+
/**
|
|
1181
|
+
* Monotonic id namespacing each scrubCodeRegions call. Scrub/restore pairs
|
|
1182
|
+
* NEST: a shortcode handler may run nested processors (processCardBlocks,
|
|
1183
|
+
* processGridBlocks, …) on an already-scrubbed body, and each of those scrubs
|
|
1184
|
+
* again. Without a per-call id, the inner restore's regex also matched the
|
|
1185
|
+
* OUTER call's placeholders and looked them up in the wrong store —
|
|
1186
|
+
* `store[idx]` → undefined, which surfaced as literal "undefined" strings
|
|
1187
|
+
* wherever inline code appeared inside [reveal]/effects bodies. With the id,
|
|
1188
|
+
* each restore only touches its own placeholders and the outer restore picks
|
|
1189
|
+
* up the rest on the way out.
|
|
1190
|
+
*/
|
|
1191
|
+
let scrubCallId = 0;
|
|
1192
|
+
|
|
1180
1193
|
export function scrubCodeRegions(markdown) {
|
|
1194
|
+
const callId = ++scrubCallId;
|
|
1181
1195
|
const store = [];
|
|
1182
1196
|
const placeholder = (s) => {
|
|
1183
1197
|
const idx = store.length;
|
|
1184
1198
|
store.push(s);
|
|
1185
|
-
return `\x02SC${idx}\x03`;
|
|
1199
|
+
return `\x02SC${callId}:${idx}\x03`;
|
|
1186
1200
|
};
|
|
1187
1201
|
|
|
1188
1202
|
// HTML <pre><code>...</code></pre> blocks (rendered by earlier marked.parse calls inside accordion/carousel etc.)
|
|
@@ -1192,7 +1206,7 @@ export function scrubCodeRegions(markdown) {
|
|
|
1192
1206
|
// Inline code spans (single or multiple backticks, non-greedy)
|
|
1193
1207
|
scrubbed = scrubbed.replace(/`+[^`\n]+`+/g, placeholder);
|
|
1194
1208
|
|
|
1195
|
-
const restore = (s) => s.replace(
|
|
1209
|
+
const restore = (s) => s.replace(new RegExp(`\\x02SC${callId}:(\\d+)\\x03`, 'g'), (_, i) => store[parseInt(i, 10)]);
|
|
1196
1210
|
return {scrubbed, restore};
|
|
1197
1211
|
}
|
|
1198
1212
|
|
|
@@ -1306,7 +1320,9 @@ function processEffectsBlocks(markdown) {
|
|
|
1306
1320
|
if (attrs.continuous === 'true') classes.push('firework-continuous');
|
|
1307
1321
|
if (attrs.hover === 'true') classes.push('firework-on-hover');
|
|
1308
1322
|
if (body === null) return `<div class="${classes.join(' ')}"></div>`;
|
|
1309
|
-
|
|
1323
|
+
// Restore code placeholders before the nested parse (tabs-handler
|
|
1324
|
+
// pattern) so code spans/fences render as <code>, not raw backticks.
|
|
1325
|
+
const innerHtml = marked.parse(processCardBlocks(processGridBlocks(restore(body.trim()))));
|
|
1310
1326
|
return `<div class="${classes.join(' ')}">${innerHtml}</div>\n`;
|
|
1311
1327
|
});
|
|
1312
1328
|
|
|
@@ -1321,7 +1337,9 @@ function processEffectsBlocks(markdown) {
|
|
|
1321
1337
|
const dataAttrs = Object.entries(attrs).map(([k, v]) => ` data-fx-${k}="${escapeAttr(v)}"`).join('');
|
|
1322
1338
|
const hasActions = /\[\s*(render|wait|undo|redraw)\b/.test(body);
|
|
1323
1339
|
if (!hasActions) {
|
|
1324
|
-
|
|
1340
|
+
// Restore code placeholders before the nested parse (tabs-handler
|
|
1341
|
+
// pattern) so code spans/fences render as <code>, not raw backticks.
|
|
1342
|
+
const innerHtml = marked.parse(processCardBlocks(processGridBlocks(restore(body.trim()))));
|
|
1325
1343
|
return `<div class="dm-fx-scribe"${dataAttrs}>${innerHtml}</div>\n`;
|
|
1326
1344
|
}
|
|
1327
1345
|
const actions = [];
|
|
@@ -1358,7 +1376,9 @@ function processEffectsBlocks(markdown) {
|
|
|
1358
1376
|
if (body === null) return '';
|
|
1359
1377
|
const attrs = parseShortcodeAttrs(attrStr);
|
|
1360
1378
|
const dataAttrs = Object.entries(attrs).map(([k, v]) => ` data-fx-${k}="${v}"`).join('');
|
|
1361
|
-
|
|
1379
|
+
// Restore code placeholders before the nested parse (tabs-handler
|
|
1380
|
+
// pattern) so code spans/fences render as <code>, not raw backticks.
|
|
1381
|
+
const innerHtml = marked.parse(processCardBlocks(processGridBlocks(restore(body.trim()))));
|
|
1362
1382
|
return `<div class="dm-fx-${name}"${dataAttrs}>${innerHtml}</div>\n`;
|
|
1363
1383
|
});
|
|
1364
1384
|
}
|
|
@@ -1373,7 +1393,9 @@ function processEffectsBlocks(markdown) {
|
|
|
1373
1393
|
if (body === null) {
|
|
1374
1394
|
return `<div class="dm-fx-ticker-tape" data-fx-mode="page"${dataAttrs}></div>`;
|
|
1375
1395
|
}
|
|
1376
|
-
|
|
1396
|
+
// Restore code placeholders before the nested parse (tabs-handler
|
|
1397
|
+
// pattern) so code spans/fences render as <code>, not raw backticks.
|
|
1398
|
+
const innerHtml = marked.parse(processCardBlocks(processGridBlocks(restore(body.trim()))));
|
|
1377
1399
|
return `<div class="dm-fx-ticker-tape" data-fx-mode="container"${dataAttrs}>${innerHtml}</div>\n`;
|
|
1378
1400
|
});
|
|
1379
1401
|
|
|
@@ -1385,7 +1407,7 @@ function processEffectsBlocks(markdown) {
|
|
|
1385
1407
|
if (attrs.duration) classes.push(`animate-duration-${attrs.duration}`);
|
|
1386
1408
|
if (attrs.delay) classes.push(`animate-delay-${attrs.delay}`);
|
|
1387
1409
|
if (attrs.repeat) classes.push(`animate-${attrs.repeat}`);
|
|
1388
|
-
return `<div class="${classes.join(' ')}">${marked.parse(processCardBlocks(processGridBlocks(body.trim())))}</div>\n`;
|
|
1410
|
+
return `<div class="${classes.join(' ')}">${marked.parse(processCardBlocks(processGridBlocks(restore(body.trim()))))}</div>\n`;
|
|
1389
1411
|
});
|
|
1390
1412
|
|
|
1391
1413
|
apply('ambient', (attrStr, body) => {
|
|
@@ -1395,7 +1417,7 @@ function processEffectsBlocks(markdown) {
|
|
|
1395
1417
|
if (attrs.type) classes.push(`bg-ambient-${attrs.type}`);
|
|
1396
1418
|
if (attrs.speed) classes.push(`bg-ambient-${attrs.speed}`);
|
|
1397
1419
|
if (attrs.intensity) classes.push(`bg-ambient-${attrs.intensity}`);
|
|
1398
|
-
return `<div class="${classes.join(' ')}">${marked.parse(processCardBlocks(processGridBlocks(body.trim())))}</div>\n`;
|
|
1420
|
+
return `<div class="${classes.join(' ')}">${marked.parse(processCardBlocks(processGridBlocks(restore(body.trim()))))}</div>\n`;
|
|
1399
1421
|
});
|
|
1400
1422
|
|
|
1401
1423
|
return restore(result);
|