diff --git a/CHANGES.md b/CHANGES.md index e64932fdc4..c0fadbf799 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -15,6 +15,8 @@ Core Changes: Language Improvements: +- (markdown) much improved code block support (#2382) [Josh Goebel][] +- (markdown) improve bold/italic nesting (#2382) [Josh Goebel][] - enh(csharp) Support `where` keyword as class constraint (#2378) [Josh Goebel][] - enh(csharp) Allow reference path in class inheritance lists (#2378) [Josh Goebel][] - enh(csharp) Add generic modifiers (in, out) (#2378) [Josh Goebel][] diff --git a/src/languages/dart.js b/src/languages/dart.js index cf198cc8ca..bbaa94760a 100644 --- a/src/languages/dart.js +++ b/src/languages/dart.js @@ -92,7 +92,8 @@ function(hljs) { hljs.COMMENT( '/\\*\\*', '\\*/', { - subLanguage: 'markdown' + subLanguage: 'markdown', + relevance:0 } ), hljs.COMMENT( @@ -102,6 +103,7 @@ function(hljs) { subLanguage: 'markdown', begin: '.', end: '$', + relevance:0 }] } ), diff --git a/src/languages/markdown.js b/src/languages/markdown.js index 7f56f771e0..e84cf9bc35 100644 --- a/src/languages/markdown.js +++ b/src/languages/markdown.js @@ -7,109 +7,148 @@ Category: common, markup */ function(hljs) { - return { - aliases: ['md', 'mkdown', 'mkd'], - contains: [ - // highlight headers - { - className: 'section', - variants: [ - { begin: '^#{1,6}', end: '$' }, - { begin: '^.+?\\n[=-]{2,}$' } - ] - }, - // inline html + INLINE_HTML = { + begin: '<', end: '>', + subLanguage: 'xml', + relevance: 0 + }; + HORIZONTAL_RULE = { + begin: '^[-\\*]{3,}', end: '$' + }; + CODE = { + className: 'code', + variants: [ + // TODO: fix to allow these to work with sublanguage also + { begin: '(`{3,})(.|\\n)*?\\1`*[ ]*', }, + { begin: '(~{3,})(.|\\n)*?\\1~*[ ]*', }, + // needed to allow markdown as a sublanguage to work + { begin: '```', end: '```+[ ]*$' }, + { begin: '~~~', end: '~~~+[ ]*$' }, + { begin: '`.+?`' }, { - begin: '<', end: '>', - subLanguage: 'xml', + begin: '(?=^( {4}|\\t))', + // use contains to gobble up multiple lines to allow the block to be whatever size + // but only have a single open/close tag vs one per line + contains: [ + { begin: '^( {4}|\\t)', end: '(\\n)$' } + ], relevance: 0 - }, - // lists (indicators only) + } + ] + }; + LIST = { + className: 'bullet', + begin: '^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)', + end: '\\s+', + excludeEnd: true + }; + LINK_REFERENCE = { + begin: /^\[[^\n]+\]:/, + returnBegin: true, + contains: [ { - className: 'bullet', - begin: '^\\s*([*+-]|(\\d+\\.))\\s+' + className: 'symbol', + begin: /\[/, end: /\]/, + excludeBegin: true, excludeEnd: true }, - // strong segments { - className: 'strong', - begin: '[*_]{2}.+?[*_]{2}' - }, - // emphasis segments + className: 'link', + begin: /:\s*/, end: /$/, + excludeBegin: true + } + ] + }; + LINK = { + begin: '\\[.+?\\][\\(\\[].*?[\\)\\]]', + returnBegin: true, + contains: [ { - className: 'emphasis', - variants: [ - { begin: '\\*.+?\\*' }, - { begin: '_.+?_' - , relevance: 0 - } - ] + className: 'string', + begin: '\\[', end: '\\]', + excludeBegin: true, + returnEnd: true, + relevance: 0 }, - // blockquotes { - className: 'quote', - begin: '^>\\s+', end: '$' + className: 'link', + begin: '\\]\\(', end: '\\)', + excludeBegin: true, excludeEnd: true }, - // code snippets { - className: 'code', - variants: [ - { - begin: '^```\\w*\\s*$', end: '^```[ ]*$' - }, - { - begin: '`.+?`' - }, - { - begin: '^( {4}|\\t)', end: '$', - relevance: 0 - } - ] - }, - // horizontal rules - { - begin: '^[-\\*]{3,}', end: '$' - }, - // using links - title and link + className: 'symbol', + begin: '\\]\\[', end: '\\]', + excludeBegin: true, excludeEnd: true + } + ], + relevance: 10 + }; + BOLD = { + className: 'strong', + contains: [], + variants: [ + {begin: /_{2}/, end: /_{2}/ }, + {begin: /\*{2}/, end: /\*{2}/ } + ] + }; + ITALIC = { + className: 'emphasis', + contains: [], + variants: [ + { begin: /\*(?!\*)/, end: /\*/ }, + { begin: /_(?!_)/, end: /_/, relevance: 0}, + ] + }; + BOLD.contains.push(ITALIC); + ITALIC.contains.push(BOLD); + + CONTAINABLE = [ + INLINE_HTML, + LINK + ]; + + BOLD.contains = BOLD.contains.concat(CONTAINABLE); + ITALIC.contains = ITALIC.contains.concat(CONTAINABLE); + + CONTAINABLE = CONTAINABLE.concat(BOLD,ITALIC); + + HEADER = { + className: 'section', + variants: [ { - begin: '\\[.+?\\][\\(\\[].*?[\\)\\]]', - returnBegin: true, - contains: [ - { - className: 'string', - begin: '\\[', end: '\\]', - excludeBegin: true, - returnEnd: true, - relevance: 0 - }, - { - className: 'link', - begin: '\\]\\(', end: '\\)', - excludeBegin: true, excludeEnd: true - }, - { - className: 'symbol', - begin: '\\]\\[', end: '\\]', - excludeBegin: true, excludeEnd: true - } - ], - relevance: 10 - }, + begin: '^#{1,6}', + end: '$', + contains: CONTAINABLE + }, { - begin: /^\[[^\n]+\]:/, - returnBegin: true, + begin: '(?=^.+?\\n[=-]{2,}$)', contains: [ - { - className: 'symbol', - begin: /\[/, end: /\]/, - excludeBegin: true, excludeEnd: true - }, - { - className: 'link', - begin: /:\s*/, end: /$/, - excludeBegin: true - } + { begin: '^[=-]*$' }, + { begin: '^', end: "\\n", contains: CONTAINABLE }, ] - } + } + ] + }; + + BLOCKQUOTE = { + className: 'quote', + begin: '^>\\s+', + contains: CONTAINABLE, + end: '$', + }; + + return { + aliases: ['md', 'mkdown', 'mkd'], + contains: [ + HEADER, + INLINE_HTML, + LIST, + BOLD, + ITALIC, + BLOCKQUOTE, + CODE, + HORIZONTAL_RULE, + LINK, + LINK_REFERENCE ] }; } diff --git a/test/markup/markdown/bold_italics.expect.txt b/test/markup/markdown/bold_italics.expect.txt new file mode 100644 index 0000000000..fee002a4a5 --- /dev/null +++ b/test/markup/markdown/bold_italics.expect.txt @@ -0,0 +1,18 @@ +_Italic_ +*Italic* +__Bold__ +**Bold** +*Is __Combined__* +__Bold *then italic*__ +**Bold _then italic_** +**Bold and <br/>** +**_[this](https://google.com)_** + +> quoted **Bold _then italic_** +> _[this](https://google.com)_ + + *this is a emphasized paragraph* + *this is too* + +* list with a *italic item* +* list with a **bold item** diff --git a/test/markup/markdown/bold_italics.txt b/test/markup/markdown/bold_italics.txt new file mode 100644 index 0000000000..2b72d45cdd --- /dev/null +++ b/test/markup/markdown/bold_italics.txt @@ -0,0 +1,18 @@ +_Italic_ +*Italic* +__Bold__ +**Bold** +*Is __Combined__* +__Bold *then italic*__ +**Bold _then italic_** +**Bold and
** +**_[this](https://google.com)_** + +> quoted **Bold _then italic_** +> _[this](https://google.com)_ + + *this is a emphasized paragraph* + *this is too* + +* list with a *italic item* +* list with a **bold item** diff --git a/test/markup/markdown/code.expect.txt b/test/markup/markdown/code.expect.txt index 881ec4420e..c50bd78a60 100644 --- a/test/markup/markdown/code.expect.txt +++ b/test/markup/markdown/code.expect.txt @@ -1,8 +1,38 @@ - var code = true; - + var code = true; + var code = false; + ```javascript var code = true; ``` +````md +``` +a = 'This is a code block in python' +``` +```` + +~~~ +tilde can be used also (github) +~~~ + +~~~~ ruby startline=3 $%@#$ +def foo(x) + return 3 +end +~~~~~~~ + +~~~~~~~something +code here +~~~~~~~ + +``` +aaa +~~~ +``` + + ```javascript + can be indented + ``` + Inline `code`, and `more code`. diff --git a/test/markup/markdown/code.txt b/test/markup/markdown/code.txt index d9bed99184..e095534bc0 100644 --- a/test/markup/markdown/code.txt +++ b/test/markup/markdown/code.txt @@ -1,8 +1,38 @@ var code = true; + var code = false; ```javascript var code = true; ``` +````md +``` +a = 'This is a code block in python' +``` +```` + +~~~ +tilde can be used also (github) +~~~ + +~~~~ ruby startline=3 $%@#$ +def foo(x) + return 3 +end +~~~~~~~ + +~~~~~~~something +code here +~~~~~~~ + +``` +aaa +~~~ +``` + + ```javascript + can be indented + ``` + Inline `code`, and `more code`. diff --git a/test/markup/markdown/list.expect.txt b/test/markup/markdown/list.expect.txt index 497d464750..64b2341b18 100644 --- a/test/markup/markdown/list.expect.txt +++ b/test/markup/markdown/list.expect.txt @@ -1,5 +1,5 @@ -- this is a list -- this is another - - nested list - - another nested - * nested alternative +- this is a list +- this is another + - nested list + - another nested + * nested alternative diff --git a/test/markup/markdown/sections.expect.txt b/test/markup/markdown/sections.expect.txt new file mode 100644 index 0000000000..36093ec8a7 --- /dev/null +++ b/test/markup/markdown/sections.expect.txt @@ -0,0 +1,11 @@ +# hello world + +## hello world + +hello world +=========== + +*hello world* or [google](link) +=========== + +# *hello world* or [google](link) diff --git a/test/markup/markdown/sections.txt b/test/markup/markdown/sections.txt new file mode 100644 index 0000000000..2dfe138e9f --- /dev/null +++ b/test/markup/markdown/sections.txt @@ -0,0 +1,12 @@ +# hello world + +## hello world + +hello world +=========== + +*hello world* or [google](link) +=========== + +# *hello world* or [google](link) +