Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/embed-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]`. If you want the full line containing the fragment identifier you can add the option `:fragmentFullLine`.

Example:

Expand Down
1 change: 1 addition & 0 deletions src/core/render/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ export class Compiler {
}

embed.fragment = config.fragment;
embed.fragmentFullLine = config.fragmentFullLine;

return embed;
}
Expand Down
4 changes: 2 additions & 2 deletions src/core/render/compiler/media.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
26 changes: 20 additions & 6 deletions src/core/render/embed.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
* @param {boolean} fullLine - The fragment identifier to search for.
* @returns {string} - The extracted and demented 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 for fragment
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();
}
Expand Down Expand Up @@ -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.fragmentFullLine,
);
}

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.fragmentFullLine,
);
}

embedToken = compile.lexer(
Expand Down
42 changes: 42 additions & 0 deletions test/integration/example.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 :fragmentFullLine')
`,
},
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: {
Expand Down
Loading