Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Markdown: Added support for code blocks #1562

Merged
merged 12 commits into from
Dec 1, 2018
88 changes: 88 additions & 0 deletions components/prism-markdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,24 @@ Prism.languages.insertBefore('markdown', 'prolog', {
// ``code``
pattern: /``.+?``|`[^`\n]+`/,
alias: 'keyword'
},
{
// ```optional language
// code block
// ```
pattern: /^```[\s\S]*?^```$/m,
greedy: true,
inside: {
'code-block': {
pattern: /^(```.*(?:\r?\n|\r))[\s\S]+?(?=(?:\r?\n|\r)^```$)/m,
lookbehind: true
},
'code-language': {
pattern: /^(```).+/,
lookbehind: true
},
'punctuation': /```/
}
}
],
'title': [
Expand Down Expand Up @@ -137,3 +155,73 @@ Prism.languages.markdown['italic'].inside['bold'] = Prism.languages.markdown['bo
Prism.languages.markdown['italic'].inside['strike'] = Prism.languages.markdown['strike'];
Prism.languages.markdown['strike'].inside['bold'] = Prism.languages.markdown['bold'];
Prism.languages.markdown['strike'].inside['italic'] = Prism.languages.markdown['italic'];

Prism.hooks.add('after-tokenize', function (env) {
if (env.language !== 'markdown') {
return;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what our style policy is on this, but I generally prefer {} around if blocks like this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, looks like core uses {} with if blocks. Otherwise, code looks good. Love this improvement.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right!

}

function walkTokens(tokens) {
if (!tokens || typeof tokens === 'string') {
return;
}

for (var i = 0, l = tokens.length; i < l; i++) {
var token = tokens[i];

if (token.type !== 'code') {
walkTokens(token.content);
continue;
}

var codeLang = token.content[1];
var codeBlock = token.content[3];

if (codeLang && codeBlock &&
codeLang.type === 'code-language' && codeBlock.type === 'code-block' &&
typeof codeLang.content === 'string') {

// this might be a language that Prism does not support
var alias = 'language-' + codeLang.content.trim().split(/\s+/)[0].toLowerCase();

// add alias
if (!codeBlock.alias) {
codeBlock.alias = [alias];
} else if (typeof codeBlock.alias === 'string') {
codeBlock.alias = [codeBlock.alias, alias];
} else {
codeBlock.alias.push(alias);
}
}
}
}

walkTokens(env.tokens);
});

Prism.hooks.add('wrap', function (env) {
if (env.type !== 'code-block') {
return;
}

var codeLang = '';
for (var i = 0, l = env.classes.length; i < l; i++) {
var cls = env.classes[i];
var match = /language-(\w+)/.exec(cls);
if (match) {
codeLang = match[1];
break;
}
}

var grammar = Prism.languages[codeLang];

if (!grammar) {
return;
}

// reverse Prism.util.encode
var code = env.content.replace(/&lt;/g, '<').replace(/&amp;/g, '&');

env.content = Prism.highlight(code, grammar, codeLang);
});
2 changes: 1 addition & 1 deletion components/prism-markdown.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 13 additions & 2 deletions tests/languages/markdown/code_feature.test
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,29 @@

foobar

``` js
var a = 0;
```

----------------------------------------------------

[
["code", "`foo bar baz`"],
["code", "``foo `bar` baz``"],
["code", " foobar"],
["code", "\tfoobar"]
["code", "\tfoobar"],

["code", [
["punctuation", "```"],
["code-language", " js"],
["code-block", "var a = 0;"],
["punctuation", "```"]
]]
]

----------------------------------------------------

Checks for code blocks and inline code. The first code block is
indented with 4 spaces, the second one is indented with 1 tab.
The initial dot is necessary because of the first part being trimmed
by the test runner.
by the test runner.