Skip to content

Commit ea52b2b

Browse files
committed
fix: Allow markdown escaping for nested special code blocks (#9265)
1 parent c8512b3 commit ea52b2b

2 files changed

Lines changed: 28 additions & 16 deletions

File tree

learn/guides/devindex/frontend/ContentEngine.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -196,47 +196,47 @@ The Markdown component supports several enhanced block types beyond standard Mar
196196
Standard fenced code blocks with a language identifier are automatically highlighted:
197197
198198
```markdown
199-
```javascript readonly
199+
\```javascript readonly
200200
const greeting = 'Hello, Neo.mjs!';
201201
console.log(greeting);
202-
` ` `
202+
\```
203203
```
204204

205205
### 2. Live Preview Blocks
206206

207207
Code blocks marked with `live-preview` render an interactive code editor with real-time output:
208208

209209
```markdown
210-
```javascript live-preview
210+
\```javascript live-preview
211211
Neo.create({
212212
module: Neo.button.Base,
213213
text : 'Click Me!'
214214
})
215-
` ` `
215+
\```
216216
```
217217

218218
### 3. Neo Component Blocks
219219

220220
Embed any Neo.mjs component directly in documentation using `neo-component`:
221221

222222
```markdown
223-
```json neo-component
223+
\```json neo-component
224224
{
225225
"module": "Neo.button.Base",
226226
"text": "I'm a real button!"
227227
}
228-
` ` `
228+
\```
229229
```
230230

231231
### 4. Mermaid Diagrams
232232

233233
Create flowcharts, sequence diagrams, and more using Mermaid syntax:
234234

235235
```markdown
236-
```mermaid
236+
\```mermaid
237237
flowchart LR
238238
A[Start] --> B[End]
239-
` ` `
239+
\```
240240
```
241241

242242
### 5. Ticket References

src/component/Markdown.mjs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ const
77
regexFrontMatter = /^---\r?\n([\s\S]*?)\r?\n---\r?\n/,
88
regexLabClose = /<!--\s*\/lab\s*-->/g,
99
regexLabOpen = /<!--\s*lab\s*-->/g,
10-
regexLivePreview = /```(javascript|html|css|json)\s+live-preview\s*\n([\s\S]*?)\n\s*```/g,
11-
regexMermaid = /```mermaid\s*\n([\s\S]*?)\n\s*```/g,
12-
regexNeoComponent = /```json\s+neo-component\s*\n([\s\S]*?)\n\s*```/g,
10+
regexLivePreview = /(?<!\\)```(javascript|html|css|json)\s+live-preview\s*\n([\s\S]*?)\n\s*```/g,
11+
regexMermaid = /(?<!\\)```mermaid\s*\n([\s\S]*?)\n\s*```/g,
12+
regexNeoComponent = /(?<!\\)```json\s+neo-component\s*\n([\s\S]*?)\n\s*```/g,
1313
regexNewLines = /^\n+|\n+$/g,
14-
regexCodeBlock = /```(\w*)(?:[^\n]*)?\n([\s\S]*?)\n\s*```/g,
14+
regexCodeBlock = /(?<!\\)(`{3,})(\w*)(?:[^\n]*)?\n([\s\S]*?)\n\s*\1/g,
1515
regexInlineCode = /`([^`]+)`/g,
1616
regexTicketId = /(^|[\s(])#(\d+)\b/g;
1717

@@ -439,9 +439,14 @@ class Markdown extends Component {
439439
*/
440440
processNeoComponentsBlocks(contentString, map) {
441441
return contentString.replace(regexNeoComponent, (match, code) => {
442-
const key = IdGenerator.getId('learn-content-component');
443-
map[key] = JSON.parse(code);
444-
return `<div id="${key}"></div>`
442+
try {
443+
const key = IdGenerator.getId('learn-content-component');
444+
map[key] = JSON.parse(code);
445+
return `<div id="${key}"></div>`
446+
} catch (e) {
447+
console.warn('Failed to parse neo-component block, returning original code.', e);
448+
return match;
449+
}
445450
})
446451
}
447452

@@ -455,10 +460,13 @@ class Markdown extends Component {
455460
count = 0,
456461
replacements;
457462

458-
let updatedContent = contentString.replace(regexCodeBlock, (match, language, code) => {
463+
let updatedContent = contentString.replace(regexCodeBlock, (match, backticks, language, code) => {
459464
const token = `__NEO-READONLY-TOKEN-${++count}__`;
460465
const lang = (!language || language.trim() === '' || language === 'text') ? 'plaintext' : language;
461466

467+
// Remove the backslash escape from special blocks so they display correctly
468+
code = code.replace(/\\```/g, '```');
469+
462470
replacementPromises.push(
463471
HighlightJs.highlight(code, lang, windowId)
464472
.catch(err => {
@@ -539,6 +547,10 @@ class Markdown extends Component {
539547

540548
// Parse the (now modified) markdown content into HTML
541549
// This content string now contains standard markdown PLUS the HTML divs/pres we injected.
550+
551+
// Remove the backslash escape from special blocks so marked.js treats them as normal markdown blocks
552+
content = content.replace(/\\```/g, '```');
553+
542554
html = marked.parse(content);
543555

544556
// Wrap raw HTML img tags in a scrollable container

0 commit comments

Comments
 (0)