mirror of
https://github.com/docsifyjs/docsify.git
synced 2025-12-08 19:55:52 +00:00
feat: Fragment identifier full line ignore (#2626)
This commit is contained in:
parent
f793e26215
commit
e8117563ea
@ -65,7 +65,7 @@ Sometimes you don't want to embed a whole file. Maybe because you need just a fe
|
||||
```
|
||||
|
||||
In your code file you need to surround the fragment between `/// [demo]` lines (before and after the fragment).
|
||||
Alternatively you can use `### [demo]`.
|
||||
Alternatively you can use `### [demo]`. By default, only identifiers are omitted. To omit the entire line containing the identifier in the fragment output, you can add the `:omitFragmentLine` option.
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
@ -135,6 +135,7 @@ export class Compiler {
|
||||
}
|
||||
|
||||
embed.fragment = config.fragment;
|
||||
embed.omitFragmentLine = config.omitFragmentLine;
|
||||
|
||||
return embed;
|
||||
}
|
||||
|
||||
@ -18,12 +18,12 @@ export const compileMedia = {
|
||||
},
|
||||
video(url, title) {
|
||||
return {
|
||||
html: `<video src="${url}" ${title || 'controls'}>Not Support</video>`,
|
||||
html: `<video src="${url}" ${title || 'controls'}>Not Supported</video>`,
|
||||
};
|
||||
},
|
||||
audio(url, title) {
|
||||
return {
|
||||
html: `<audio src="${url}" ${title || 'controls'}>Not Support</audio>`,
|
||||
html: `<audio src="${url}" ${title || 'controls'}>Not Supported</audio>`,
|
||||
};
|
||||
},
|
||||
code(url, title) {
|
||||
|
||||
@ -12,16 +12,22 @@ const cached = {};
|
||||
*
|
||||
* @param {string} text - The input text that may contain embedded fragments.
|
||||
* @param {string} fragment - The fragment identifier to search for.
|
||||
* @returns {string} - The extracted and demented content, or an empty string if not found.
|
||||
* @param {boolean} fullLine - Boolean flag to enable full-line matching of fragment identifiers.
|
||||
* @returns {string} - The extracted and dedented content, or an empty string if not found.
|
||||
*/
|
||||
function extractFragmentContent(text, fragment) {
|
||||
function extractFragmentContent(text, fragment, fullLine) {
|
||||
if (!fragment) {
|
||||
return text;
|
||||
}
|
||||
|
||||
let fragmentRegex = `(?:###|\\/\\/\\/)\\s*\\[${fragment}\\]`;
|
||||
const contentRegex = `[\\s\\S]*?`;
|
||||
if (fullLine) {
|
||||
// Match full line containing fragment identifier (e.g. /// [demo])
|
||||
fragmentRegex = `.*${fragmentRegex}.*\n`;
|
||||
}
|
||||
const pattern = new RegExp(
|
||||
`(?:###|\\/\\/\\/)\\s*\\[${fragment}\\]([\\s\\S]*?)(?:###|\\/\\/\\/)\\s*\\[${fragment}\\]`,
|
||||
);
|
||||
`(?:${fragmentRegex})(${contentRegex})(?:${fragmentRegex})`,
|
||||
); // content is the capture group
|
||||
const match = text.match(pattern);
|
||||
return stripIndent((match || [])[1] || '').trim();
|
||||
}
|
||||
@ -68,13 +74,21 @@ function walkFetchEmbed({ embedTokens, compile, fetch }, cb) {
|
||||
}
|
||||
|
||||
if (currentToken.embed.fragment) {
|
||||
text = extractFragmentContent(text, currentToken.embed.fragment);
|
||||
text = extractFragmentContent(
|
||||
text,
|
||||
currentToken.embed.fragment,
|
||||
currentToken.embed.omitFragmentLine,
|
||||
);
|
||||
}
|
||||
|
||||
embedToken = compile.lexer(text);
|
||||
} else if (currentToken.embed.type === 'code') {
|
||||
if (currentToken.embed.fragment) {
|
||||
text = extractFragmentContent(text, currentToken.embed.fragment);
|
||||
text = extractFragmentContent(
|
||||
text,
|
||||
currentToken.embed.fragment,
|
||||
currentToken.embed.omitFragmentLine,
|
||||
);
|
||||
}
|
||||
|
||||
embedToken = compile.lexer(
|
||||
|
||||
@ -173,6 +173,48 @@ describe('Creating a Docsify site (integration tests in Jest)', function () {
|
||||
);
|
||||
});
|
||||
|
||||
test('embed file full line fragment identifier', async () => {
|
||||
await docsifyInit({
|
||||
markdown: {
|
||||
homepage: `
|
||||
# Embed Test
|
||||
|
||||
[filename](_media/example1.html ':include :type=code :fragment=demo :omitFragmentLine')
|
||||
`,
|
||||
},
|
||||
routes: {
|
||||
'_media/example1.html': `
|
||||
<script>
|
||||
let myURL = 'https://api.example.com/data';
|
||||
/// [demo] Full line fragment identifier (all of these words here should not be included in fragment)
|
||||
const result = fetch(myURL)
|
||||
.then(response => {
|
||||
return response.json();
|
||||
})
|
||||
.then(myJson => {
|
||||
console.log(JSON.stringify(myJson));
|
||||
});
|
||||
<!-- /// [demo] -->
|
||||
result.then(console.log).catch(console.error);
|
||||
</script>
|
||||
`,
|
||||
},
|
||||
});
|
||||
|
||||
// Wait for the embedded fragment to be fetched and rendered into #main
|
||||
expect(
|
||||
await waitForText('#main', 'console.log(JSON.stringify(myJson));'),
|
||||
).toBeTruthy();
|
||||
|
||||
const mainText = document.querySelector('#main').textContent;
|
||||
expect(mainText).not.toContain('https://api.example.com/data');
|
||||
expect(mainText).not.toContain('Full line fragment identifier');
|
||||
expect(mainText).not.toContain('-->');
|
||||
expect(mainText).not.toContain(
|
||||
'result.then(console.log).catch(console.error);',
|
||||
);
|
||||
});
|
||||
|
||||
test('embed multiple file code fragments', async () => {
|
||||
await docsifyInit({
|
||||
markdown: {
|
||||
@ -186,7 +228,9 @@ describe('Creating a Docsify site (integration tests in Jest)', function () {
|
||||
# Text between
|
||||
|
||||
[filename](_media/example3.js ':include :fragment=something_else_not_code')
|
||||
|
||||
|
||||
[filename](_media/example4.js ':include :fragment=demo')
|
||||
|
||||
# Text after
|
||||
`,
|
||||
},
|
||||
@ -209,6 +253,12 @@ describe('Creating a Docsify site (integration tests in Jest)', function () {
|
||||
example3 += 10;
|
||||
/// [something_else_not_code]
|
||||
console.log(example3);`,
|
||||
'_media/example4.js': `
|
||||
let example4 = 1;
|
||||
### No fragment here
|
||||
example4 += 10;
|
||||
/// No fragment here
|
||||
console.log(example4);`,
|
||||
},
|
||||
});
|
||||
|
||||
@ -225,6 +275,9 @@ describe('Creating a Docsify site (integration tests in Jest)', function () {
|
||||
expect(mainText).not.toContain('console.log(example1);');
|
||||
expect(mainText).not.toContain('console.log(example2);');
|
||||
expect(mainText).not.toContain('console.log(example3);');
|
||||
expect(mainText).not.toContain('console.log(example4);');
|
||||
expect(mainText).not.toContain('example4 += 10;');
|
||||
expect(mainText).not.toContain('No fragment here');
|
||||
});
|
||||
|
||||
test('embed file table cell', async () => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user