From 5ccf910c2ec1c5dca406da528c3d0442c168d4db Mon Sep 17 00:00:00 2001
From: sy-records <52o@qq52o.cn>
Date: Fri, 7 Nov 2025 12:07:25 +0800
Subject: [PATCH 1/5] fix: removing unnecessary empty paragraph check
---
src/core/render/compiler/blockquote.js | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/src/core/render/compiler/blockquote.js b/src/core/render/compiler/blockquote.js
index 5f00951de..e249623b9 100644
--- a/src/core/render/compiler/blockquote.js
+++ b/src/core/render/compiler/blockquote.js
@@ -20,17 +20,10 @@ export const blockquoteCompiler = ({ renderer }) =>
token[key] = token[key].replace(calloutMark, '').trimStart();
});
- // Remove empty paragraph
- if (tokens.length > 1 && !token.raw.trim()) {
- tokens = tokens.slice(1);
- }
-
openTag = `
`;
closeTag = `
`;
}
const body = this.parser.parse(tokens);
- const html = `${openTag}${body}${closeTag}`;
-
- return html;
+ return `${openTag}${body}${closeTag}`;
});
From 8245bda775e1bafa718d3bfccbb53bc779acc963 Mon Sep 17 00:00:00 2001
From: Luffy <52o@qq52o.cn>
Date: Tue, 11 Nov 2025 14:15:39 +0800
Subject: [PATCH 2/5] feat: enhance blockquoteCompiler to support callouts with
empty lines
---
src/core/render/compiler/blockquote.js | 44 ++++++++++++++++----------
1 file changed, 27 insertions(+), 17 deletions(-)
diff --git a/src/core/render/compiler/blockquote.js b/src/core/render/compiler/blockquote.js
index e249623b9..5cafc66ee 100644
--- a/src/core/render/compiler/blockquote.js
+++ b/src/core/render/compiler/blockquote.js
@@ -1,27 +1,37 @@
export const blockquoteCompiler = ({ renderer }) =>
(renderer.blockquote = function ({ tokens }) {
- const calloutData =
- tokens[0].type === 'paragraph' &&
- // 0: Match "[!TIP] My Title"
- // 1: Mark "[!TIP]"
- // 2: Type "TIP"
- tokens[0].raw.match(/^(\[!(\w+)\])/);
-
let openTag = '';
let closeTag = '
';
- if (calloutData) {
- const calloutMark = calloutData[1]; // "[!TIP]"
- const calloutType = calloutData[2].toLowerCase(); // "tip"
- const token = tokens[0].tokens[0];
+ // Find the first paragraph token in the blockquote
+ const firstParagraphIndex = tokens.findIndex(t => t.type === 'paragraph');
+ const firstParagraph = tokens[firstParagraphIndex];
+
+ if (firstParagraph) {
+ // Check if the paragraph starts with a callout like [!TIP] or [!NOTE]
+ const calloutData = firstParagraph.raw.match(/^(\[!(\w+)\])/);
+
+ if (calloutData) {
+ const calloutMark = calloutData[1]; // "[!TIP]"
+ const calloutType = calloutData[2].toLowerCase(); // "tip"
+
+ // Remove the callout mark from the paragraph raw text
+ firstParagraph.raw = firstParagraph.raw.replace(calloutMark, '').trimStart();
+ if (firstParagraph.tokens && firstParagraph.tokens.length > 0) {
+ firstParagraph.tokens.forEach(t => {
+ if (t.raw) {t.raw = t.raw.replace(calloutMark, '').trimStart();}
+ if (t.text) {t.text = t.text.replace(calloutMark, '').trimStart();}
+ });
+ }
- // Remove callout mark from tokens
- ['raw', 'text'].forEach(key => {
- token[key] = token[key].replace(calloutMark, '').trimStart();
- });
+ // If the first paragraph is now empty after removing [!TIP], remove it
+ if (!firstParagraph.raw.trim()) {
+ tokens.splice(firstParagraphIndex, 1);
+ }
- openTag = ``;
- closeTag = `
`;
+ openTag = ``;
+ closeTag = `
`;
+ }
}
const body = this.parser.parse(tokens);
From b5f180c2bbb67975358b52bbb1f3129a4c4ddd8d Mon Sep 17 00:00:00 2001
From: Luffy <52o@qq52o.cn>
Date: Tue, 11 Nov 2025 14:17:59 +0800
Subject: [PATCH 3/5] fix: lint
---
src/core/render/compiler/blockquote.js | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/src/core/render/compiler/blockquote.js b/src/core/render/compiler/blockquote.js
index 5cafc66ee..2bc1bce82 100644
--- a/src/core/render/compiler/blockquote.js
+++ b/src/core/render/compiler/blockquote.js
@@ -16,11 +16,17 @@ export const blockquoteCompiler = ({ renderer }) =>
const calloutType = calloutData[2].toLowerCase(); // "tip"
// Remove the callout mark from the paragraph raw text
- firstParagraph.raw = firstParagraph.raw.replace(calloutMark, '').trimStart();
+ firstParagraph.raw = firstParagraph.raw
+ .replace(calloutMark, '')
+ .trimStart();
if (firstParagraph.tokens && firstParagraph.tokens.length > 0) {
firstParagraph.tokens.forEach(t => {
- if (t.raw) {t.raw = t.raw.replace(calloutMark, '').trimStart();}
- if (t.text) {t.text = t.text.replace(calloutMark, '').trimStart();}
+ if (t.raw) {
+ t.raw = t.raw.replace(calloutMark, '').trimStart();
+ }
+ if (t.text) {
+ t.text = t.text.replace(calloutMark, '').trimStart();
+ }
});
}
From f313859a8f45bad3fcde8b7ae296d31ba11cdc6f Mon Sep 17 00:00:00 2001
From: Luffy <52o@qq52o.cn>
Date: Wed, 12 Nov 2025 11:04:47 +0800
Subject: [PATCH 4/5] fix: remove unnecessary trimming of callout marks in
blockquote processing
---
src/core/render/compiler/blockquote.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/core/render/compiler/blockquote.js b/src/core/render/compiler/blockquote.js
index 2bc1bce82..8fc2607e1 100644
--- a/src/core/render/compiler/blockquote.js
+++ b/src/core/render/compiler/blockquote.js
@@ -22,10 +22,10 @@ export const blockquoteCompiler = ({ renderer }) =>
if (firstParagraph.tokens && firstParagraph.tokens.length > 0) {
firstParagraph.tokens.forEach(t => {
if (t.raw) {
- t.raw = t.raw.replace(calloutMark, '').trimStart();
+ t.raw = t.raw.replace(calloutMark, '');
}
if (t.text) {
- t.text = t.text.replace(calloutMark, '').trimStart();
+ t.text = t.text.replace(calloutMark, '');
}
});
}
From 44dae254a7828a4238580f23c75e8477e6e58b3e Mon Sep 17 00:00:00 2001
From: Luffy <52o@qq52o.cn>
Date: Wed, 12 Nov 2025 11:24:23 +0800
Subject: [PATCH 5/5] test: update snapshot
---
test/integration/render.test.js | 35 +++++++++++++++++++--------------
1 file changed, 20 insertions(+), 15 deletions(-)
diff --git a/test/integration/render.test.js b/test/integration/render.test.js
index ff8182779..22442ebcc 100644
--- a/test/integration/render.test.js
+++ b/test/integration/render.test.js
@@ -15,41 +15,46 @@ describe('render', function () {
test('caution', () => {
const output = window.marked('> [!CAUTION]\n> Text');
- expect(output).toMatchInlineSnapshot(
- `""`,
- );
+ expect(output).toMatchInlineSnapshot(`
+""
+`);
});
test('important', () => {
const output = window.marked('> [!IMPORTANT]\n> Text');
- expect(output).toMatchInlineSnapshot(
- `""`,
- );
+ expect(output).toMatchInlineSnapshot(`
+""
+`);
});
test('note', () => {
const output = window.marked('> [!NOTE]\n> Text');
- expect(output).toMatchInlineSnapshot(
- `""`,
- );
+ expect(output).toMatchInlineSnapshot(`
+""
+`);
});
test('tip', () => {
const output = window.marked('> [!TIP]\n> Text');
- expect(output).toMatchInlineSnapshot(
- `""`,
- );
+ expect(output).toMatchInlineSnapshot(`
+""
+`);
});
test('warning', () => {
const output = window.marked('> [!WARNING]\n> Text');
- expect(output).toMatchInlineSnapshot(
- `""`,
- );
+ expect(output).toMatchInlineSnapshot(`
+""
+`);
});
test('important (legacy)', () => {