From 1dd884a88a03293d406e92a43cf03bf83cb692f7 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 6 Mar 2017 18:21:16 -0800 Subject: [PATCH] Use Gulp To Generate Markdown Langauge Includes (#22117) **Bug** The markdown grammar for fenced code blocks is rather unmaintainable since it involves lots of copy and pasted code **Fix** Use a gulp task and a template to generate the fenced code block grammars include directly. This allows adding new language support much more easily. --- extensions/markdown/package.json | 7 +- extensions/markdown/syntaxes/gulpfile.js | 147 ++ .../markdown/syntaxes/markdown.tmLanguage | 59 +- .../syntaxes/markdown.tmLanguage.base | 1202 +++++++++++++++++ 4 files changed, 1356 insertions(+), 59 deletions(-) create mode 100644 extensions/markdown/syntaxes/gulpfile.js create mode 100644 extensions/markdown/syntaxes/markdown.tmLanguage.base diff --git a/extensions/markdown/package.json b/extensions/markdown/package.json index 713e53b873d..3960d740e56 100644 --- a/extensions/markdown/package.json +++ b/extensions/markdown/package.json @@ -186,7 +186,8 @@ } }, "scripts": { - "vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:markdown ./tsconfig.json" + "vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:markdown ./tsconfig.json", + "update-grammar": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ./syntaxes/gulpfile.js" }, "dependencies": { "highlight.js": "^9.3.0", @@ -196,6 +197,8 @@ "vscode-nls": "^2.0.2" }, "devDependencies": { - "@types/node": "^7.0.4" + "@types/node": "^7.0.4", + "gulp-rename": "^1.2.2", + "gulp-replace": "^0.5.4" } } \ No newline at end of file diff --git a/extensions/markdown/syntaxes/gulpfile.js b/extensions/markdown/syntaxes/gulpfile.js new file mode 100644 index 00000000000..f57cb80fb9d --- /dev/null +++ b/extensions/markdown/syntaxes/gulpfile.js @@ -0,0 +1,147 @@ +var gulp = require('gulp'); +var replace = require('gulp-replace'); +var rename = require('gulp-rename'); + +const languages = [ + { name: 'css', identifiers: ['css', 'css.erb'], source: 'source.css' }, + { name: 'basic', identifiers: ['html', 'htm', 'shtml', 'xhtml', 'inc', 'tmpl', 'tpl'], source: 'text.html.basic' }, + { name: 'ini', identifiers: ['ini', 'conf'], source: 'source.ini' }, + { name: 'java', identifiers: ['java', 'bsh'], source: 'source.java' }, + { name: 'lua', identifiers: ['lua'], source: 'source.lua' }, + { name: 'makefile', identifiers: ['Makefile', 'makefile', 'GNUmakefile', 'OCamlMakefile'], source: 'source.makefile' }, + { name: 'perl', identifiers: ['perl', 'pl', 'pm', 'pod', 't', 'PL', 'psgi', 'vcl'], source: 'source.perl' }, + { name: 'r', identifiers: ['R', 'r', 's', 'S', 'Rprofile'], source: 'source.r' }, + { name: 'ruby', identifiers: ['ruby', 'rb', 'rbx', 'rjs', 'Rakefile', 'rake', 'cgi', 'fcgi', 'gemspec', 'irbrc', 'Capfile', 'ru', 'prawn', 'Cheffile', 'Gemfile', 'Guardfile', 'Hobofile', 'Vagrantfile', 'Appraisals', 'Rantfile', 'Berksfile', 'Berksfile.lock', 'Thorfile', 'Puppetfile'], source: 'source.ruby' }, + // Left to its own devices, the PHP grammar will match HTML as a combination of operators + // and constants. Therefore, HTML must take precedence over PHP in order to get proper + // syntax highlighting. + { name: 'php', identifiers: ['php', 'php3', 'php4', 'php5', 'phpt', 'phtml', 'aw', 'ctp'], source: ['text.html.basic', 'text.html.php#language'] }, + { name: 'sql', identifiers: ['sql', 'ddl', 'dml'], source: 'source.sql' }, + { name: 'vs_net', identifiers: ['vb'], source: 'source.asp.vb.net' }, + { name: 'xml', identifiers: ['xml', 'xsd', 'tld', 'jsp', 'pt', 'cpt', 'dtml', 'rss', 'opml'], source: 'text.xml' }, + { name: 'xsl', identifiers: ['xsl', 'xslt'], source: 'text.xml.xsl' }, + { name: 'yaml', identifiers: ['yaml', 'yml'], source: 'source.yaml' }, + { name: 'dosbatch', identifiers: ['bat', 'batch'], source: 'source.dosbatch' }, + { name: 'clojure', identifiers: ['clj', 'cljs', 'clojure'], source: 'source.clojure' }, + { name: 'coffee', identifiers: ['coffee', 'Cakefile', 'coffee.erb'], source: 'source.coffee' }, + { name: 'c', identifiers: ['c', 'h'], source: 'source.c' }, + { name: 'cpp', identifiers: ['cpp', 'c\\+\\+', 'cxx'], source: 'source.cpp' }, + { name: 'diff', identifiers: ['patch', 'diff', 'rej'], source: 'source.diff' }, + { name: 'dockerfile', identifiers: ['dockerfile', 'Dockerfile'], source: 'source.dockerfile' }, + { name: 'git_commit', identifiers: ['COMMIT_EDITMSG', 'MERGE_MSG'], source: 'text.git-commit' }, + { name: 'git_rebase', identifiers: ['git-rebase-todo'], source: 'text.git-rebase' }, + { name: 'go', identifiers: ['go', 'golang'], source: 'source.go' }, + { name: 'groovy', identifiers: ['groovy', 'gvy'], source: 'source.groovy' }, + { name: 'jade', identifiers: ['jade'], source: 'text.jade' }, + + { name: 'js', identifiers: ['js', 'jsx', 'javascript'], source: 'source.js' }, + { name: 'js_regexp', identifiers: ['regexp'], source: 'source.js.regexp' }, + { name: 'json', identifiers: ['json', 'sublime-settings', 'sublime-menu', 'sublime-keymap', 'sublime-mousemap', 'sublime-theme', 'sublime-build', 'sublime-project', 'sublime-completions'], source: 'source.json' }, + { name: 'less', identifiers: ['less'], source: 'source.css.less' }, + { name: 'objc', identifiers: ['objectivec', 'objective-c', 'mm', 'objc', 'obj-c', 'm', 'h'], source: 'source.objc' }, + { name: 'perl6', identifiers: ['perl6', 'p6', 'pl6', 'pm6', 'nqp'], source: 'source.perl.6' }, + { name: 'powershell', identifiers: ['powershell', 'ps1', 'psm1', 'psd1'], source: 'source.powershell' }, + { name: 'python', identifiers: ['python', 'py', 'py3', 'rpy', 'pyw', 'cpy', 'SConstruct', 'Sconstruct', 'sconstruct', 'SConscript', 'gyp', 'gypi'], source: 'source.python' }, + { name: 'regexp_python', identifiers: ['re'], source: 'source.regexp.python' }, + { name: 'rust', identifiers: ['rust', 'rs'], source: 'source.rust' }, + { name: 'scala', identifiers: ['scala', 'sbt'], source: 'source.scala' }, + { name: 'shell', identifiers: ['shell', 'sh', 'bash', 'zsh', 'bashrc', 'bash_profile', 'bash_login', 'profile', 'bash_logout', '.textmate_init'], source: 'source.shell' }, + { name: 'ts', identifiers: ['typescript', 'ts'], source: 'source.ts' }, + { name: 'tsx', identifiers: ['tsx'], source: 'source.tsx' }, + { name: 'csharp', identifiers: ['cs', 'csharp', 'c#'], source: 'source.cs' }, + { name: 'fsharp', identifiers: ['fs', 'fsharp', 'f#'], source: 'source.fsharp' }, +]; + +const fencedCodeBlockDefinition = (name, identifiers, sourceScope) => { + if (!Array.isArray(sourceScope)) { + sourceScope = [sourceScope]; + } + + const scopes = sourceScope.map(scope => + ` + include + ${scope} +`).join('\n'); + + return `fenced_code_block_${name} + + begin + (^|\\G)(\\s*)([\`~]{3,})\\s*((${identifiers.join('|')})(\\s+[^\`~]*)?$) + name + markup.fenced_code.block.markdown + end + (^|\\G)(\\2|\\s{0,3})(\\3)\\s*$ + beginCaptures + + 3 + + name + punctuation.definition.markdown + + 5 + + name + fenced_code.block.language + + 6 + + name + fenced_code.block.language.attributes + + + endCaptures + + 3 + + name + punctuation.definition.markdown + + + patterns + + + begin + (^|\\G)(\\s*)(.*) + while + (^|\\G)(?!\\s*([\`~]{3,})\\s*$) + patterns + +${indent(4, scopes)} + + + +`; +}; + +const indent = (count, text) => { + const indent = new Array(count + 1).join('\t'); + return text.replace(/^/gm, indent); +}; + +const fencedCodeBlockInclude = (name) => + ` + include + #fenced_code_block_${name} +`; + + +const fencedCodeBlockDefinitions = () => + languages + .map(language => fencedCodeBlockDefinition(language.name, language.identifiers, language.source)) + .join('\n'); + + + +const fencedCodeBlockIncludes = () => + languages + .map(language => fencedCodeBlockInclude(language.name)) + .join('\n'); + + +gulp.task('default', function () { + gulp.src(['markdown.tmLanguage.base']) + .pipe(replace('{{languageIncludes}}', indent(4, fencedCodeBlockIncludes()))) + .pipe(replace('{{languageDefinitions}}', indent(4, fencedCodeBlockDefinitions()))) + .pipe(rename('markdown.tmLanguage')) + .pipe(gulp.dest('.')); +}); diff --git a/extensions/markdown/syntaxes/markdown.tmLanguage b/extensions/markdown/syntaxes/markdown.tmLanguage index 06fd9ec0335..855f438cb0c 100644 --- a/extensions/markdown/syntaxes/markdown.tmLanguage +++ b/extensions/markdown/syntaxes/markdown.tmLanguage @@ -717,7 +717,6 @@ punctuation.definition.markdown - patterns @@ -769,7 +768,6 @@ punctuation.definition.markdown - patterns @@ -821,7 +819,6 @@ punctuation.definition.markdown - patterns @@ -873,7 +870,6 @@ punctuation.definition.markdown - patterns @@ -925,7 +921,6 @@ punctuation.definition.markdown - patterns @@ -1028,7 +1023,6 @@ punctuation.definition.markdown - patterns @@ -1048,18 +1042,6 @@ fenced_code_block_php - comment - - In fenced PHP code blocks, we match a "fuzzy" version of the PHP language. - This is because code blocks may be an incomplete PHP script that lacks a script - section start tag, and we still want to provide syntax highlighting, rather - than adhering to the actual grammar, where everything not prepended by a - start tag would be ignored. Additionally, we want to provide highlighting - for potential non-PHP languages (in particular HTML). - - There are certainly plenty of edge cases here, but this seems to cover most popular - scenarios, and also appears to be consistent with the approach that GitHub takes. - begin (^|\G)(\s*)([`~]{3,})\s*((php|php3|php4|php5|phpt|phtml|aw|ctp)(\s+[^`~]*)?$) name @@ -1092,7 +1074,6 @@ punctuation.definition.markdown - patterns @@ -1103,14 +1084,6 @@ patterns - comment - - - - Left to its own devices, the PHP grammar will match HTML as a combination of operators - and constants. Therefore, HTML must take precedence over PHP in order to get proper - syntax highlighting. - include text.html.basic @@ -1156,7 +1129,6 @@ punctuation.definition.markdown - patterns @@ -1208,7 +1180,6 @@ punctuation.definition.markdown - patterns @@ -1260,7 +1231,6 @@ punctuation.definition.markdown - patterns @@ -1312,7 +1282,6 @@ punctuation.definition.markdown - patterns @@ -1364,7 +1333,6 @@ punctuation.definition.markdown - patterns @@ -1416,7 +1384,6 @@ punctuation.definition.markdown - patterns @@ -1468,7 +1435,6 @@ punctuation.definition.markdown - patterns @@ -1520,7 +1486,6 @@ punctuation.definition.markdown - patterns @@ -1674,7 +1639,6 @@ punctuation.definition.markdown - patterns @@ -1726,7 +1690,6 @@ punctuation.definition.markdown - patterns @@ -1778,7 +1741,6 @@ punctuation.definition.markdown - patterns @@ -1830,7 +1792,6 @@ punctuation.definition.markdown - patterns @@ -1882,7 +1843,6 @@ punctuation.definition.markdown - patterns @@ -1934,7 +1894,6 @@ punctuation.definition.markdown - patterns @@ -1986,7 +1945,6 @@ punctuation.definition.markdown - patterns @@ -2038,7 +1996,6 @@ punctuation.definition.markdown - patterns @@ -2090,7 +2047,6 @@ punctuation.definition.markdown - patterns @@ -2142,7 +2098,6 @@ punctuation.definition.markdown - patterns @@ -2194,7 +2149,6 @@ punctuation.definition.markdown - patterns @@ -2215,7 +2169,7 @@ fenced_code_block_objc begin - (^|\G)(\s*)([`~]{3,})\s*((objectivec|mm|objc|obj-c|m|h)(\s+[^`~]*)?$) + (^|\G)(\s*)([`~]{3,})\s*((objectivec|objective-c|mm|objc|obj-c|m|h)(\s+[^`~]*)?$) name markup.fenced_code.block.markdown end @@ -2246,7 +2200,6 @@ punctuation.definition.markdown - patterns @@ -2298,7 +2251,6 @@ punctuation.definition.markdown - patterns @@ -2350,7 +2302,6 @@ punctuation.definition.markdown - patterns @@ -2453,7 +2404,6 @@ punctuation.definition.markdown - patterns @@ -2505,7 +2455,6 @@ punctuation.definition.markdown - patterns @@ -2523,7 +2472,7 @@ - fenced_code_block_scala + fenced_code_block_scala begin (^|\G)(\s*)([`~]{3,})\s*((scala|sbt)(\s+[^`~]*)?$) @@ -2557,7 +2506,6 @@ punctuation.definition.markdown - patterns @@ -2609,7 +2557,6 @@ punctuation.definition.markdown - patterns @@ -2661,7 +2608,6 @@ punctuation.definition.markdown - patterns @@ -2713,7 +2659,6 @@ punctuation.definition.markdown - patterns diff --git a/extensions/markdown/syntaxes/markdown.tmLanguage.base b/extensions/markdown/syntaxes/markdown.tmLanguage.base new file mode 100644 index 00000000000..44e8cdf8a3f --- /dev/null +++ b/extensions/markdown/syntaxes/markdown.tmLanguage.base @@ -0,0 +1,1202 @@ + + + + + fileTypes + + md + mdown + markdown + markdn + + keyEquivalent + ^~M + name + Markdown + patterns + + + include + #frontMatter + + + include + #block + + + repository + + block + + patterns + + + include + #separator + + + include + #heading + + + include + #blockquote + + + include + #lists + +{{languageIncludes}} + + include + #fenced_code_block_unknown + + + include + #raw_block + + + include + #link-def + + + include + #html + + + include + #paragraph + + + repository + + blockquote + + begin + (^|\G)[ ]{0,3}(>) ? + captures + + 2 + + name + beginning.punctuation.definition.quote.markdown + + + name + markup.quote.markdown + patterns + + + include + #block + + + while + (^|\G)\s*(>) ? + + heading + + begin + (?:^|\G)[ ]{0,3}(#{1,6})\s*(?=[\S[^#]]) + captures + + 1 + + name + punctuation.definition.heading.markdown + + + contentName + entity.name.section.markdown + end + \s*(#{1,6})?$\n? + name + markup.heading.markdown + patterns + + + include + #inline + + + + heading-setext + + patterns + + + match + ^(={3,})(?=[ \t]*$\n?) + name + markup.heading.setext.1.markdown + + + match + ^(-{3,})(?=[ \t]*$\n?) + name + markup.heading.setext.2.markdown + + + + html + + patterns + + + begin + (^|\G)\s*(<!--) + end + (-->) + name + comment.block.html + captures + + 1 + + name + punctuation.definition.comment.html + + 2 + + name + punctuation.definition.comment.html + + + + + begin + (^|\G)\s*(?=<(script|style|pre)(\s|$|>)(?!.*?</(script|style|pre)>)) + patterns + + + begin + (\s*|$) + patterns + + + include + text.html.basic + + + while + ^\s*(?!</(script|style|pre)>) + + + end + (?=</(script|style|pre)>) + + + begin + (^|\G)\s*(?=</?(address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h1|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul)(\s|$|/?>)) + patterns + + + include + text.html.basic + + + while + ^(?!\s*$) + + + begin + (^|\G)\s*(?=(<[a-zA-Z0-9\-](/?>|\s.*?>)|</[a-zA-Z0-9\-]>)\s*$) + patterns + + + include + text.html.basic + + + while + ^(?!\s*$) + + + + link-def + + captures + + 1 + + name + punctuation.definition.constant.markdown + + 10 + + name + punctuation.definition.string.end.markdown + + 11 + + name + string.other.link.description.title.markdown + + 12 + + name + punctuation.definition.string.begin.markdown + + 13 + + name + punctuation.definition.string.end.markdown + + 2 + + name + constant.other.reference.link.markdown + + 3 + + name + punctuation.definition.constant.markdown + + 4 + + name + punctuation.separator.key-value.markdown + + 5 + + name + punctuation.definition.link.markdown + + 6 + + name + markup.underline.link.markdown + + 7 + + name + punctuation.definition.link.markdown + + 8 + + name + string.other.link.description.title.markdown + + 9 + + name + punctuation.definition.string.begin.markdown + + + match + ^(?x: + \s* # Leading whitespace + (\[)(.+?)(\])(:) # Reference name + [ \t]* # Optional whitespace + (<?)(\S+?)(>?) # The url + [ \t]* # Optional whitespace + (?: + ((\().+?(\))) # Match title in quotes… + | ((").+?(")) # or in parens. + )? # Title is optional + \s* # Optional whitespace + $ + ) + name + meta.link.reference.def.markdown + + list_paragraph + + begin + (^|\G)(?=\S)(?![*+-]\s|[0-9]+\.\s) + name + meta.paragraph.markdown + patterns + + + include + #inline + + + include + text.html.basic + + + include + #heading-setext + + + while + (^|\G)(?!\s*$|#|[ ]{0,3}([-*_][ ]{2,}){3,}[ \t]*$\n?|>|[ ]{0,3}[*+-]|[ ]{0,3}[0-9]+\.) + + lists + + patterns + + + begin + (^|\G)([ ]{0,3})([*+-])([ ]{1,3}|\t) + beginCaptures + + 3 + + name + beginning.punctuation.definition.list.markdown + + + comment + Currently does not support un-indented second lines. + name + markup.list.unnumbered.markdown + patterns + + + include + #list_paragraph + + + include + #block + + + while + ((^|\G)([ ]{4}|\t))|(^[ \t]*$) + + + begin + (^|\G)([ ]{0,3})([0-9]+\.)([ ]{1,3}|\t) + beginCaptures + + 3 + + name + beginning.punctuation.definition.list.markdown + + + name + markup.list.numbered.markdown + patterns + + + include + #list_paragraph + + + include + #block + + + while + ((^|\G)([ ]{4}|\t))|(^[ \t]*$) + + + + paragraph + + begin + (^|\G)[ ]{0,3}(?=\S) + name + meta.paragraph.markdown + patterns + + + include + #inline + + + include + text.html.basic + + + include + #heading-setext + + + while + (^|\G)((?=\s*[-=]{3,}\s*$)|[ ]{4,}(?=\S)) + +{{languageDefinitions}} + fenced_code_block_unknown + + name + markup.fenced_code.block.markdown + begin + (^|\G)(\s*)([`~]{3,})\s*([^`~]*)?$ + end + (^|\G)(\2|\s{0,3})(\3)\s*$ + beginCaptures + + 3 + + name + punctuation.definition.markdown + + 4 + + name + fenced_code.block.language + + + endCaptures + + 3 + + name + punctuation.definition.markdown + + + + raw_block + + begin + (^|\G)([ ]{4}|\t) + name + markup.raw.block.markdown + while + (^|\G)([ ]{4}|\t) + + separator + + match + (^|\G)[ ]{0,3}([*-_])([ ]{0,2}\2){2,}[ \t]*$\n? + name + meta.separator.markdown + + + + inline + + patterns + + + include + #ampersand + + + include + #bracket + + + include + #bold + + + include + #italic + + + include + #raw + + + include + #escape + + + include + #image-inline + + + include + #image-ref + + + include + #link-email + + + include + #link-inet + + + include + #link-inline + + + include + #link-ref + + + include + #link-ref-literal + + + repository + + ampersand + + comment + + Markdown will convert this for us. We match it so that the + HTML grammar will not mark it up as invalid. + + match + &(?!([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+);) + name + meta.other.valid-ampersand.markdown + + bold + + begin + (?x) + (\*\*|__)(?=\S) # Open + (?= + ( + <[^>]*+> # HTML tags + | (?<raw>`+)([^`]|(?!(?<!`)\k<raw>(?!`))`)*+\k<raw> + # Raw + | \\[\\`*_{}\[\]()#.!+\->]?+ # Escapes + | \[ + ( + (?<square> # Named group + [^\[\]\\] # Match most chars + | \\. # Escaped chars + | \[ \g<square>*+ \] # Nested brackets + )*+ + \] + ( + ( # Reference Link + [ ]? # Optional space + \[[^\]]*+\] # Ref name + ) + | ( # Inline Link + \( # Opening paren + [ \t]*+ # Optional whitespace + <?(.*?)>? # URL + [ \t]*+ # Optional whitespace + ( # Optional Title + (?<title>['"]) + (.*?) + \k<title> + )? + \) + ) + ) + ) + | (?!(?<=\S)\1). # Everything besides + # style closer + )++ + (?<=\S)\1 # Close + ) + + captures + + 1 + + name + punctuation.definition.bold.markdown + + + end + (?<=\S)(\1) + name + markup.bold.markdown + patterns + + + applyEndPatternLast + 1 + begin + (?=<[^>]*?>) + end + (?<=>) + patterns + + + include + text.html.basic + + + + + include + #escape + + + include + #ampersand + + + include + #bracket + + + include + #raw + + + include + #italic + + + include + #image-inline + + + include + #link-inline + + + include + #link-inet + + + include + #link-email + + + include + #image-ref + + + include + #link-ref-literal + + + include + #link-ref + + + + bracket + + comment + + Markdown will convert this for us. We match it so that the + HTML grammar will not mark it up as invalid. + + match + <(?![a-z/?\$!]) + name + meta.other.valid-bracket.markdown + + escape + + match + \\[-`*_#+.!(){}\[\]\\>] + name + constant.character.escape.markdown + + image-inline + + captures + + 1 + + name + punctuation.definition.string.begin.markdown + + 10 + + name + string.other.link.description.title.markdown + + 11 + + name + punctuation.definition.string.markdown + + 12 + + name + punctuation.definition.string.markdown + + 13 + + name + string.other.link.description.title.markdown + + 14 + + name + punctuation.definition.string.markdown + + 15 + + name + punctuation.definition.string.markdown + + 16 + + name + punctuation.definition.metadata.markdown + + 2 + + name + string.other.link.description.markdown + + 4 + + name + punctuation.definition.string.end.markdown + + 5 + + name + invalid.illegal.whitespace.markdown + + 6 + + name + punctuation.definition.metadata.markdown + + 7 + + name + punctuation.definition.link.markdown + + 8 + + name + markup.underline.link.image.markdown + + 9 + + name + punctuation.definition.link.markdown + + + match + (?x: + (\!\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\]) + # Match the link text. + ([ ])? # Space not allowed + (\() # Opening paren for url + (<?)(\S+?)(>?) # The url + [ \t]* # Optional whitespace + (?: + ((\().+?(\))) # Match title in parens… + | ((").+?(")) # or in quotes. + )? # Title is optional + \s* # Optional whitespace + (\)) + ) + name + meta.image.inline.markdown + + image-ref + + captures + + 1 + + name + punctuation.definition.string.begin.markdown + + 2 + + name + string.other.link.description.markdown + + 4 + + name + punctuation.definition.string.begin.markdown + + 5 + + name + punctuation.definition.constant.markdown + + 6 + + name + constant.other.reference.link.markdown + + 7 + + name + punctuation.definition.constant.markdown + + + match + (\!\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(\[)(.*?)(\]) + name + meta.image.reference.markdown + + italic + + begin + (?x) + (\*|_)(?=\S) # Open + (?= + ( + <[^>]*+> # HTML tags + | (?<raw>`+)([^`]|(?!(?<!`)\k<raw>(?!`))`)*+\k<raw> + # Raw + | \\[\\`*_{}\[\]()#.!+\->]?+ # Escapes + | \[ + ( + (?<square> # Named group + [^\[\]\\] # Match most chars + | \\. # Escaped chars + | \[ \g<square>*+ \] # Nested brackets + )*+ + \] + ( + ( # Reference Link + [ ]? # Optional space + \[[^\]]*+\] # Ref name + ) + | ( # Inline Link + \( # Opening paren + [ \t]*+ # Optional whtiespace + <?(.*?)>? # URL + [ \t]*+ # Optional whtiespace + ( # Optional Title + (?<title>['"]) + (.*?) + \k<title> + )? + \) + ) + ) + ) + | \1\1 # Must be bold closer + | (?!(?<=\S)\1). # Everything besides + # style closer + )++ + (?<=\S)\1 # Close + ) + + captures + + 1 + + name + punctuation.definition.italic.markdown + + + end + (?<=\S)(\1)((?!\1)|(?=\1\1)) + name + markup.italic.markdown + patterns + + + applyEndPatternLast + 1 + begin + (?=<[^>]*?>) + end + (?<=>) + patterns + + + include + text.html.basic + + + + + include + #escape + + + include + #ampersand + + + include + #bracket + + + include + #raw + + + include + #bold + + + include + #image-inline + + + include + #link-inline + + + include + #link-inet + + + include + #link-email + + + include + #image-ref + + + include + #link-ref-literal + + + include + #link-ref + + + + link-email + + captures + + 1 + + name + punctuation.definition.link.markdown + + 2 + + name + markup.underline.link.markdown + + 4 + + name + punctuation.definition.link.markdown + + + match + (<)((?:mailto:)?[-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(>) + name + meta.link.email.lt-gt.markdown + + link-inet + + captures + + 1 + + name + punctuation.definition.link.markdown + + 2 + + name + markup.underline.link.markdown + + 3 + + name + punctuation.definition.link.markdown + + + match + (<)((?:https?|ftp)://.*?)(>) + name + meta.link.inet.markdown + + link-inline + + captures + + 1 + + name + punctuation.definition.string.begin.markdown + + 10 + + name + string.other.link.description.title.markdown + + 11 + + name + punctuation.definition.string.begin.markdown + + 12 + + name + punctuation.definition.string.end.markdown + + 13 + + name + string.other.link.description.title.markdown + + 14 + + name + punctuation.definition.string.begin.markdown + + 15 + + name + punctuation.definition.string.end.markdown + + 16 + + name + punctuation.definition.metadata.markdown + + 2 + + name + string.other.link.title.markdown + + 4 + + name + punctuation.definition.string.end.markdown + + 5 + + name + invalid.illegal.whitespace.markdown + + 6 + + name + punctuation.definition.metadata.markdown + + 7 + + name + punctuation.definition.link.markdown + + 8 + + name + markup.underline.link.markdown + + 9 + + name + punctuation.definition.link.markdown + + + match + (?x: + (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\]) + # Match the link text. + ([ ])? # Space not allowed + (\() # Opening paren for url + (<?)(.*?)(>?) # The url + [ \t]* # Optional whitespace + (?: + ((\().+?(\))) # Match title in parens… + | ((").+?(")) # or in quotes. + )? # Title is optional + \s* # Optional whitespace + (\)) + ) + name + meta.link.inline.markdown + + link-ref + + captures + + 1 + + name + punctuation.definition.string.begin.markdown + + 2 + + name + string.other.link.title.markdown + + 4 + + name + punctuation.definition.string.end.markdown + + 5 + + name + punctuation.definition.constant.begin.markdown + + 6 + + name + constant.other.reference.link.markdown + + 7 + + name + punctuation.definition.constant.end.markdown + + + match + (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(\[)([^\]]*+)(\]) + name + meta.link.reference.markdown + + link-ref-literal + + captures + + 1 + + name + punctuation.definition.string.begin.markdown + + 2 + + name + string.other.link.title.markdown + + 4 + + name + punctuation.definition.string.end.markdown + + 5 + + name + punctuation.definition.constant.begin.markdown + + 6 + + name + punctuation.definition.constant.end.markdown + + + match + (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(\[)(\]) + name + meta.link.reference.literal.markdown + + raw + + captures + + 1 + + name + punctuation.definition.raw.markdown + + 3 + + name + punctuation.definition.raw.markdown + + + match + (`+)([^`]|(?!(?<!`)\1(?!`))`)*+(\1) + name + markup.inline.raw.markdown + + + + frontMatter + + begin + \A-{3}\s*$ + while + ^(?!-{3}\s*$) + patterns + + + include + source.yaml + + + + + scopeName + text.html.markdown + uuid + 0A1D9874-B448-11D9-BD50-000D93B6E43C + +