Skip to content

Commit a2f734f

Browse files
feat: support config helper multi keys if supported (#2571)
* update: support config helper multi keys --------- Co-authored-by: Luffy <lufei@docsifyjs.org>
1 parent 3709947 commit a2f734f

File tree

6 files changed

+76
-6
lines changed

6 files changed

+76
-6
lines changed

docs/helpers.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ You will get `<a href="/demo/">link</a>`html. Do not worry, you can still set th
9393

9494
```md
9595
![logo](https://docsify.js.org/_media/icon.svg ':class=someCssClass')
96+
97+
<!-- Multiple class names -->
98+
99+
![logo](https://docsify.js.org/_media/icon.svg ':class=someCssClass :class=anotherCssClass')
96100
```
97101

98102
### IDs

src/core/render/compiler/image.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@ export const imageCompiler = ({ renderer, contentBase, router }) =>
2727
}
2828

2929
if (config.class) {
30-
attrs.push(`class="${config.class}"`);
30+
let classes = config.class;
31+
if (Array.isArray(config.class)) {
32+
classes = config.class.join(' ');
33+
}
34+
attrs.push(`class="${classes}"`);
3135
}
3236

3337
if (config.id) {

src/core/render/compiler/link.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,11 @@ export const linkCompiler = ({
5454
}
5555

5656
if (config.class) {
57-
attrs.push(`class="${config.class}"`);
57+
let classes = config.class;
58+
if (Array.isArray(config.class)) {
59+
classes = config.class.join(' ');
60+
}
61+
attrs.push(`class="${classes}"`);
5862
}
5963

6064
if (config.id) {

src/core/render/utils.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,21 @@ export function getAndRemoveConfig(str = '') {
2626
.replace(/^('|")/, '')
2727
.replace(/('|")$/, '')
2828
.replace(/(?:^|\s):([\w-]+:?)=?([\w-%]+)?/g, (m, key, value) => {
29-
if (key.indexOf(':') === -1) {
30-
config[key] = (value && value.replace(/&quot;/g, '')) || true;
31-
return '';
29+
if (key.indexOf(':') !== -1) {
30+
return m;
3231
}
3332

34-
return m;
33+
value = (value && value.replace(/&quot;/g, '')) || true;
34+
35+
if (value !== true && config[key] !== undefined) {
36+
if (!Array.isArray(config[key]) && value !== config[key]) {
37+
config[key] = [config[key]];
38+
}
39+
config[key].includes(value) || config[key].push(value);
40+
} else {
41+
config[key] = value;
42+
}
43+
return '';
3544
})
3645
.trim();
3746
}

test/integration/render.test.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,16 @@ describe('render', function () {
279279
);
280280
});
281281

282+
test('multi class config', async function () {
283+
const output = window.marked(
284+
"[alt text](http://url ':class=someCssClass :class=anotherCssClass')",
285+
);
286+
287+
expect(output).toMatchInlineSnapshot(
288+
`"<p><a href="http://url" target="_blank" rel="noopener" class="someCssClass anotherCssClass">alt text</a></p>"`,
289+
);
290+
});
291+
282292
test('id', async function () {
283293
const output = window.marked("[alt text](http://url ':id=someCssID')");
284294

test/unit/render-util.test.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,45 @@ describe('core/render/utils', () => {
8787
});
8888
});
8989

90+
test('parse config with key arguments img', () => {
91+
const result = getAndRemoveConfig(
92+
"![logo](https://docsify.js.org/_media/icon.svg ' :size=50x100 ')",
93+
);
94+
95+
expect(result).toMatchObject({
96+
config: {
97+
size: '50x100',
98+
},
99+
str: "![logo](https://docsify.js.org/_media/icon.svg ' ')",
100+
});
101+
});
102+
103+
test('parse config with key arguments', () => {
104+
const result = getAndRemoveConfig(
105+
"[filename](_media/example.md ' :class=foo ')",
106+
);
107+
108+
expect(result).toMatchObject({
109+
config: {
110+
class: 'foo',
111+
},
112+
str: "[filename](_media/example.md ' ')",
113+
});
114+
});
115+
116+
test('parse config with same key arguments', () => {
117+
const result = getAndRemoveConfig(
118+
"[filename](_media/example.md ' :class=foo :class=bar :bb=aa ')",
119+
);
120+
121+
expect(result).toMatchObject({
122+
config: {
123+
class: ['foo', 'bar'],
124+
},
125+
str: "[filename](_media/example.md ' ')",
126+
});
127+
});
128+
90129
test('parse config with double quotes', () => {
91130
const result = getAndRemoveConfig(
92131
'[filename](_media/example.md ":include")',

0 commit comments

Comments
 (0)