diff --git a/Context.sublime-menu b/Context.sublime-menu index c9417f12..b2c9c0c5 100644 --- a/Context.sublime-menu +++ b/Context.sublime-menu @@ -10,5 +10,9 @@ { "caption": "MDE: Jump Reference", "command": "reference_jump_context" +}, +{ + "caption": "MDE: Convert inline link to reference", + "command": "convert_inline_link_to_reference" } ] \ No newline at end of file diff --git a/Default.sublime-commands b/Default.sublime-commands index f9f2e5c6..115c9679 100644 --- a/Default.sublime-commands +++ b/Default.sublime-commands @@ -144,5 +144,13 @@ { "caption": "MarkdownEditing: Change color scheme...", "command": "mde_color_activate" + }, + { + "caption": "MarkdownEditing: Convert all inline links to references", + "command": "convert_inline_links_to_references" + }, + { + "caption": "MarkdownEditing: Convert inline link to reference", + "command": "convert_inline_link_to_reference" } ] diff --git a/Markdown.sublime-syntax b/Markdown.sublime-syntax new file mode 100644 index 00000000..4cf45f9e --- /dev/null +++ b/Markdown.sublime-syntax @@ -0,0 +1,997 @@ +%YAML 1.2 +--- +# http://www.sublimetext.com/docs/3/syntax.html +name: Markdown GFM +file_extensions: + - md + - mdown + - markdown + - markdn +scope: text.html.markdown.gfm +contexts: + main: + - match: (?=(? + | ([ ]{4}|\t)(?!$) + | [#]{1,6}\s*+ + | [ ]{,3}(?[-*_])([ ]{,2}\k){2,}[ \t]*+$ + ) + comment: | + We could also use an empty end match and set + applyEndPatternLast, but then we must be sure that the begin + pattern will only match stuff matched by the sub-patterns. + push: + - meta_scope: meta.block-level.markdown + - match: |- + (?x)^ + (?! [ ]{,3}> + | ([ ]{4}|\t) + | [#]{1,6}\s*+ + | [ ]{,3}(?[-*_])([ ]{,2}\k){2,}[ \t]*+$ + ) + pop: true + - include: block_quote + - include: block_raw + - include: heading + - include: separator + - match: '^[ ]{0,3}([*+-])(?=\s)' + captures: + 1: punctuation.definition.list_item.markdown + push: + - meta_scope: markup.list.unnumbered.markdown + - match: ^(?=\S) + captures: + 1: punctuation.definition.list_item.markdown + pop: true + - include: fenced-code-blocks + - include: list-paragraph + - match: '^[ ]{0,3}([0-9]+\.)(?=\s)' + captures: + 1: punctuation.definition.list_item.markdown + push: + - meta_scope: markup.list.numbered.markdown + - match: ^(?=\S) + captures: + 1: punctuation.definition.list_item.markdown + pop: true + - include: fenced-code-blocks + - include: list-paragraph + - include: fenced-code-blocks + - match: '^(?=<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|noscript|form|fieldset|iframe|math|ins|del)\b[^>]*>)(?!.*?)' + comment: Markdown formatting is disabled inside block-level tags. + push: + - meta_scope: meta.disable-markdown + - match: (?<=^$\n) + pop: true + - include: tag-kbd + - include: scope:text.html.basic + - match: '^(?=<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|noscript|form|fieldset|iframe|math|ins|del)\b[^>]*>)' + comment: Same rule but for one line disables. + push: + - meta_scope: meta.disable-markdown + - match: $\n? + pop: true + - include: tag-kbd + - include: scope:text.html.basic + - match: |- + (?x: + \s* # Leading whitespace + (\[)(\^\d+?)(\])(:) # Reference name + [ \t]* # Optional whitespace + (.+?) # The footnote + [ \t]* # Optional whitespace + $ + ) + scope: meta.link.reference.footnote.markdown + captures: + 1: punctuation.definition.constant.begin.markdown + 2: constant.other.reference.link.markdown + 3: punctuation.definition.constant.end.markdown + 4: punctuation.separator.key-value.markdown + 5: meta.paragraph.markdown + - match: |- + (?x: + \s* # Leading whitespace + (\[)(.+?)(\])(:) # Reference name + [ \t]* # Optional whitespace + (?) # The url + [ \t]* # Optional whitespace + (?: + ((\().+?(\))) # Match title in quotes… + | ((").+?(")) # or in parens. + )? # Title is optional + [ \t]* # Optional whitespace + $ + ) + scope: meta.link.reference.def.markdown + captures: + 1: punctuation.definition.constant.begin.markdown + 2: constant.other.reference.link.markdown + 3: punctuation.definition.constant.end.markdown + 4: punctuation.separator.key-value.markdown + 5: punctuation.definition.link.markdown + 6: markup.underline.link.markdown + 7: punctuation.definition.link.markdown + 8: string.other.link.description.title.markdown + 9: punctuation.definition.string.begin.markdown + 10: punctuation.definition.string.end.markdown + 11: string.other.link.description.title.markdown + 12: punctuation.definition.string.begin.markdown + 13: punctuation.definition.string.end.markdown + - match: '^(?=\S)(?![=-]{3,}(?=$))' + push: + - meta_scope: meta.paragraph.markdown + - match: '^(?:\s*$|(?=[ ]{,3}>)|(?=```|~~~))|(?=[ \t]*\n)(?<=^===|^====|=====|^---|^----|-----)[ \t]*\n|(?=^#)' + pop: true + - include: inline + - include: scope:text.html.basic + - match: '^(={3,})(?=[ \t]*$)' + scope: markup.heading.1.markdown + captures: + 1: punctuation.definition.heading.markdown + - match: '^(-{3,})(?=[ \t]*$)' + scope: markup.heading.2.markdown + captures: + 1: punctuation.definition.heading.markdown + ampersand: + - match: "&(?!([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+);)" + comment: | + Markdown will convert this for us. We match it so that the + HTML grammar will not mark it up as invalid. + scope: meta.other.valid-ampersand.markdown + block_quote: + - match: '\G[ ]{,3}(>)[ ]?' + comment: | + We terminate the block quote when seeing an empty line, a + separator or a line with leading > characters. The latter is + to “reset” the quote level for quoted lines. + captures: + 1: punctuation.definition.blockquote.markdown + push: + - meta_scope: markup.quote.markdown + - match: |- + (?x)^ + (?= \s*$ + | [ ]{,3}(?[-*_])([ ]{,2}\k){2,}[ \t]*+$ + | [ ]{,3}> + ) + pop: true + - match: |- + (?x)\G + (?= [ ]{,3}> + ) + push: + - match: ^ + pop: true + - include: block_quote + - match: |- + (?x)\G + (?= ([ ]{4}|\t) + | [#]{1,6}\s*+ + | [ ]{,3}(?[-*_])([ ]{,2}\k){2,}[ \t]*+$ + ) + push: + - include: block_raw + - include: heading + - include: separator + - match: ^ + pop: true + - match: |- + (?x)\G + (?! $ + | [ ]{,3}> + | ([ ]{4}|\t) + | [#]{1,6}\s*+ + | [ ]{,3}(?[-*_])([ ]{,2}\k){2,}[ \t]*+$ + ) + push: + - match: $|(?<=\n) + pop: true + - include: inline + - include: scope:text.html.basic + block_raw: + - match: '\G([ ]{4}|\t).*$\n?' + scope: markup.raw.block.markdown + bold: + - match: |- + (?x) + (?]*+> # HTML tags + | (?`+)([^`]|(?!(?(?!`))`)*+\k + # Raw + | \\[\\`*_{}\[\]()#.!+\->]?+ # Escapes + | \[ + ( + (? # Named group + [^\[\]\\] # Match most chars + | \\. # Escaped chars + | \[ \g*+ \] # Nested brackets + )*+ + \] + ( + ( # Reference Link + [ ]? # Optional space + \[[^\]]*+\] # Ref name + ) + | ( # Inline Link + \( # Opening paren + [ \t]*+ # Optional whtiespace + ? # URL + [ \t]*+ # Optional whtiespace + ( # Optional Title + (?['"]) + (.*?) + \k<title> + )? + \) + ) + ) + ) + | (?!(?<=\S)\1). # Everything besides + # style closer + )++ + (?<=\S)\1 # Close + ) + captures: + 1: punctuation.definition.bold.markdown + push: + - meta_scope: markup.bold.markdown + - match: (?<=\S)(\1) + captures: + 1: punctuation.definition.bold.markdown + pop: true + - match: "(?=<[^>]*?>)" + push: + - include: tag-kbd + - include: scope:text.html.basic + - match: (?<=>) + pop: true + - include: escape + - include: ampersand + - include: bracket + - include: raw + - include: bold_italic + - include: italic + - include: strikethrough + - include: image-inline + - include: link-inline + - include: link-inet + - include: link-email + - include: image-ref + - include: link-ref + - include: link-ref-literal + - include: link-footnote + bold_italic: + - match: |- + (?x) + (?<!\w)(\*|_)(?=\1\1)(\1\1)(?=\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> + )? + \) + ) + ) + ) + | (?!(?<=\S)\1{3}(?!\1)). # Everything besides + # style closer + )++ + (?<=\S)\1{3}(?!\1) # Close + ) + captures: + 1: punctuation.definition.bold.markdown + 2: punctuation.definition.bold.markdown + push: + - meta_scope: markup.bold_italic.markdown + - match: '(?<=\S)(\1{3})(?!\1)' + captures: + 1: punctuation.definition.bold.markdown + 2: punctuation.definition.bold.markdown + pop: true + - match: "(?=<[^>]*?>)" + push: + - include: tag-kbd + - include: scope:text.html.basic + - match: (?<=>) + pop: true + - include: escape + - include: ampersand + - include: bracket + - include: raw + - include: italic + - include: strikethrough + - include: image-inline + - include: link-inline + - include: link-inet + - include: link-email + - include: image-ref + - include: link-ref + - include: link-ref-literal + - include: link-footnote + bracket: + - match: '<(?![a-z/?\$!])' + comment: | + Markdown will convert this for us. We match it so that the + HTML grammar will not mark it up as invalid. + scope: meta.other.valid-bracket.markdown + escape: + - match: '\\[-`*_#+.!(){}\[\]\\>]' + scope: constant.character.escape.markdown + fenced-c: + - match: '^(\s*[`~]{3,})\s*(c)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.c + fenced-csharp: + - match: '^(\s*[`~]{3,})\s*(c(?:s|sharp|#))\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.cs + fenced-c++: + - match: '^(\s*[`~]{3,})\s*(c\+\+|cpp)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.c++ + fenced-clojure: + - match: '^(\s*[`~]{3,})\s*(clojure)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.clojure + fenced-go: + - match: '^(\s*[`~]{3,})\s*(go|golang)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.go + fenced-kotlin: + - match: '^(\s*[`~]{3,})\s*(kt|kotlin)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.Kotlin + fenced-code-blocks: + - include: fenced-html + - include: fenced-xml + - include: fenced-diff + - include: fenced-perl + - include: fenced-php + - include: fenced-css + - include: fenced-less + - include: fenced-java + - include: fenced-c + - include: fenced-c++ + - include: fenced-csharp + - include: fenced-yaml + - include: fenced-sql + - include: fenced-shell + - include: fenced-sass + - include: fenced-scss + - include: fenced-scala + - include: fenced-obj-c + - include: fenced-coffee + - include: fenced-js + - include: fenced-ts + - include: fenced-tsx + - include: fenced-ruby + - include: fenced-python + - include: fenced-lisp + - include: fenced-lua + - include: fenced-scheme + - include: fenced-swift + - include: fenced-clojure + - include: fenced-go + - include: fenced-kotlin + - include: fenced-undefined + fenced-coffee: + - match: '^(\s*[`~]{3,})\s*(coffee|cjsx)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.coffee + fenced-css: + - match: '^(\s*[`~]{3,})\s*(css)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.css + fenced-diff: + - match: '^(\s*[`~]{3,})\s*(diff|patch)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.diff + fenced-html: + - match: '^(\s*[`~]{3,})\s*(html|html5)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:text.html.basic + fenced-java: + - match: '^(\s*[`~]{3,})\s*(java)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.java + fenced-js: + - match: '^(\s*[`~]{3,})\s*(js|jsx|json|javascript)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.js + fenced-less: + - match: '^(\s*[`~]{3,})\s*(less)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.less + fenced-lisp: + - match: '^(\s*[`~]{3,})\s*(lisp)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.lisp + fenced-lua: + - match: '^(\s*[`~]{3,})\s*(lua)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.lua + fenced-obj-c: + - match: '^(\s*[`~]{3,})\s*(obj(ective-)?c)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.objc + fenced-perl: + - match: '^(\s*[`~]{3,})\s*(perl)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.perl + fenced-php: + - match: '^(\s*[`~]{3,})\s*(php)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.php + fenced-python: + - match: '^(\s*[`~]{3,})\s*(py|python)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.python + fenced-ruby: + - match: '^(\s*[`~]{3,})\s*(ruby)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.ruby + fenced-sass: + - match: '^(\s*[`~]{3,})\s*(sass)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.sass + fenced-scala: + - match: '^(\s*[`~]{3,})\s*(scala)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.scala + fenced-scheme: + - match: '^(\s*[`~]{3,})\s*(scheme)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.scheme + fenced-scss: + - match: '^(\s*[`~]{3,})\s*(scss)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.scss + fenced-shell: + - match: '^(\s*[`~]{3,})\s*(sh|shell|bash)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.shell + fenced-sql: + - match: '^(\s*[`~]{3,})\s*(sql)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.sql + fenced-swift: + - match: '^(\s*[`~]{3,})\s*(swift)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.swift + fenced-ts: + - match: '^(\s*[`~]{3,})\s*(ts|typescript)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.ts + fenced-tsx: + - match: '^(\s*[`~]{3,})\s*(tsx)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.tsx + fenced-undefined: + - match: '^(\s*[`~]{3,}).*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + fenced-xml: + - match: '^(\s*[`~]{3,})\s*(xml)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:text.xml + fenced-yaml: + - match: '^(\s*[`~]{3,})\s*(yaml)\s*$' + push: + - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown + - match: ^(\1)\n + pop: true + - include: scope:source.yaml + heading: + - match: '\G(#{1,6})(?!#)\s*(?=\S)' + captures: + 1: punctuation.definition.heading.markdown + push: + - meta_scope: markup.heading.markdown + - meta_content_scope: entity.name.section.markdown + - match: '[ \t]*(#*)$' + captures: + 1: punctuation.definition.heading.markdown + pop: true + - include: inline + image-inline: + - match: |- + (?x: + \! # Images start with ! + (\[)((?<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 + (\)) + ) + scope: meta.image.inline.markdown + captures: + 1: punctuation.definition.string.begin.markdown + 2: string.other.link.description.markdown + 4: punctuation.definition.string.end.markdown + 5: invalid.illegal.whitespace.markdown + 6: punctuation.definition.metadata.markdown + 7: punctuation.definition.link.markdown + 8: markup.underline.link.image.markdown + 9: punctuation.definition.link.markdown + 10: string.other.link.description.title.markdown + 11: punctuation.definition.string.markdown + 12: punctuation.definition.string.markdown + 13: string.other.link.description.title.markdown + 14: punctuation.definition.string.markdown + 15: punctuation.definition.string.markdown + 16: punctuation.definition.metadata.markdown + image-ref: + - match: '\!(\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(\[)(.*?)(\])' + scope: meta.image.reference.markdown + captures: + 1: punctuation.definition.string.begin.markdown + 2: string.other.link.description.markdown + 4: punctuation.definition.string.end.markdown + 5: punctuation.definition.constant.begin.markdown + 6: constant.other.reference.link.markdown + 7: punctuation.definition.constant.end.markdown + inline: + - include: escape + - include: ampersand + - include: bracket + - include: raw + - include: bold_italic + - include: bold + - include: italic + - include: strikethrough + - include: line-break + - include: image-inline + - include: link-inline + - include: link-inet + - include: link-email + - include: image-ref + - include: link-ref + - include: link-ref-literal + - include: link-footnote + - include: tag-kbd + - include: latex-inline + - include: scope:text.html.basic + italic: + - match: |- + (?x) + (?<!\w)(\*|_)(?=\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: punctuation.definition.italic.markdown + push: + - meta_scope: markup.italic.markdown + - match: (?<=\S)(\1)((?!\1)|(?=\1\1)) + captures: + 1: punctuation.definition.italic.markdown + pop: true + - match: "(?=<[^>]*?>)" + push: + - include: tag-kbd + - include: scope:text.html.basic + - match: (?<=>) + pop: true + - include: escape + - include: ampersand + - include: bracket + - include: raw + - include: bold_italic + - include: bold + - include: strikethrough + - include: image-inline + - include: link-inline + - include: link-inet + - include: link-email + - include: image-ref + - include: link-ref + - include: link-ref-literal + - include: link-footnote + line-break: + - match: " {2,}$" + scope: meta.dummy.line-break + link-email: + - match: '(<)?((?:mailto:)?[-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(>)?' + scope: meta.link.email.lt-gt.markdown + captures: + 1: punctuation.definition.link.markdown + 2: markup.underline.link.markdown + 4: punctuation.definition.link.markdown + link-footnote: + - match: '(\[)(\^[^\]]*+)(\])' + scope: meta.link.reference.markdown + captures: + 1: punctuation.definition.constant.begin.markdown + 2: constant.other.reference.link.markdown + 3: punctuation.definition.constant.end.markdown + link-inet: + - match: '(<)?(\b(?:https?|ftp|file|git):///?[^\s()<>\[\]]+)(>)?' + scope: meta.link.inet.markdown + captures: + 1: punctuation.definition.link.markdown + 2: markup.underline.link.markdown + 3: punctuation.definition.link.markdown + link-inline: + - 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 + (\)) + ) + scope: meta.link.inline.markdown + captures: + 1: punctuation.definition.string.begin.markdown + 2: string.other.link.title.markdown + 4: punctuation.definition.string.end.markdown + 5: invalid.illegal.whitespace.markdown + 6: punctuation.definition.metadata.markdown + 7: punctuation.definition.link.markdown + 8: markup.underline.link.markdown + 9: punctuation.definition.link.markdown + 10: string.other.link.description.title.markdown + 11: punctuation.definition.string.begin.markdown + 12: punctuation.definition.string.end.markdown + 13: string.other.link.description.title.markdown + 14: punctuation.definition.string.begin.markdown + 15: punctuation.definition.string.end.markdown + 16: punctuation.definition.metadata.markdown + link-ref: + - match: '(\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(\[)([^\]]*+)(\])' + scope: meta.link.reference.markdown + captures: + 1: punctuation.definition.string.begin.markdown + 2: string.other.link.title.markdown + 4: punctuation.definition.string.end.markdown + 5: punctuation.definition.constant.begin.markdown + 6: constant.other.reference.link.markdown + 7: punctuation.definition.constant.end.markdown + link-ref-literal: + - match: '(\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(?:(\[)(\]))?' + scope: meta.link.reference.literal.markdown + captures: + 1: punctuation.definition.string.begin.markdown + 2: string.other.link.title.markdown + 4: punctuation.definition.string.end.markdown + 5: punctuation.definition.constant.begin.markdown + 6: punctuation.definition.constant.end.markdown + list-paragraph: + - match: \G\s+(?=\S) + push: + - meta_scope: meta.paragraph.list.markdown + - match: ^\s*$ + pop: true + - include: inline + - match: '\G\s*([*\-+]|[0-9]+\.)\s+' + captures: + 1: punctuation.definition.list_item.markdown + - include: scope:text.html.basic + - include: fenced-code-blocks + raw: + - include: latex-display + - match: '(`+)((?:[^`]|(?!(?<!`)\1(?!`))`)*+)(\1)' + scope: markup.raw.inline.markdown + captures: + 1: punctuation.definition.raw.markdown + 2: markup.raw.inline.content.markdown + 3: punctuation.definition.raw.markdown + separator: + - match: '\G[ ]{,3}([-*_])([ ]{,2}\1){2,}[ \t]*$\n?' + scope: meta.separator.markdown + strikethrough: + - match: |- + (?x) + (?<!\w)(~~)(?=[^\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> + )? + \) + ) + ) + ) + | (?!(?<=\S)\1). # Everything besides + # style closer + )++ + ) + captures: + 1: punctuation.definition.strikethrough.markdown + push: + - meta_scope: markup.strikethrough.markdown + - match: (?<=\S)(\1)(?!\w) + captures: + 1: punctuation.definition.strikethrough.markdown + pop: true + - match: "(?=<[^>]*?>)" + push: + - include: tag-kbd + - include: scope:text.html.basic + - match: (?<=>) + pop: true + - include: escape + - include: ampersand + - include: bracket + - include: raw + - include: bold_italic + - include: bold + - include: italic + - include: image-inline + - include: link-inline + - include: link-inet + - include: link-email + - include: image-ref + - include: link-ref + - include: link-ref-literal + - include: link-footnote + tag-kbd: + - match: "((<)(kbd)(>))([^<]+)((</)(kbd)(>))" + scope: markup.kbd.markdown + captures: + 1: meta.tag.other.html + 2: punctuation.definition.tag.begin.html + 3: entity.name.tag.other.html + 4: punctuation.definition.tag.end.html + 5: markup.kbd.content.markdown + 6: meta.tag.other.html + 7: punctuation.definition.tag.begin.html + 8: entity.name.tag.other.html + 9: punctuation.definition.tag.end.html + + latex-inline: + - match: \\\$ + - match: |- + (?x) + (\$)(?=\S) + (?= + (?: + \\\\ + |\\\$ + |[^\$] + )*? + \S\$(?:[^a-zA-Z0-9]|$) + ) + scope: string.other.math.latex punctuation.definition.string.begin.latex + push: + - meta_scope: text.tex.latex meta.environment.math.latex + - include: scope:text.tex.latex#macros + - include: scope:text.tex.latex#math-content + - match: \$ + scope: string.other.math.latex punctuation.definition.string.end.latex + pop: true + + latex-display: + - match: \$\$ + scope: string.other.math.latex punctuation.definition.string.begin.latex + push: + - meta_scope: text.tex.latex meta.environment.math.latex + - include: scope:text.tex.latex#macros + - include: scope:text.tex.latex#math-content + - match: \$\$ + scope: string.other.math.latex punctuation.definition.string.end.latex + pop: true diff --git a/Markdown.tmLanguage b/Markdown.tmLanguage deleted file mode 100644 index d8ea3786..00000000 --- a/Markdown.tmLanguage +++ /dev/null @@ -1,2277 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>fileTypes</key> - <array> - <string>md</string> - <string>mdown</string> - <string>markdown</string> - <string>markdn</string> - </array> - <key>foldingStartMarker</key> - <string>(?x) - (<(?i:head|body|table|thead|tbody|tfoot|tr|div|select|fieldset|style|script|ul|ol|form|dl)\b.*?> - |<!--(?!.*-->) - |\{\s*($|\?>\s*$|//|/\*(.*\*/\s*$|(?!.*?\*/))) - )</string> - <key>foldingStopMarker</key> - <string>(?x) - (</(?i:head|body|table|thead|tbody|tfoot|tr|div|select|fieldset|style|script|ul|ol|form|dl)> - |^\s*--> - |(^|\s)\} - )</string> - <key>keyEquivalent</key> - <string>^~M</string> - <key>name</key> - <string>Markdown GFM</string> - <key>patterns</key> - <array> - <dict> - <key>begin</key> - <string>(?x)^ - (?= [ ]{,3}> - | ([ ]{4}|\t)(?!$) - | [#]{1,6}\s*+ - | [ ]{,3}(?<marker>[-*_])([ ]{,2}\k<marker>){2,}[ \t]*+$ - )</string> - <key>comment</key> - <string> - We could also use an empty end match and set - applyEndPatternLast, but then we must be sure that the begin - pattern will only match stuff matched by the sub-patterns. - </string> - <key>end</key> - <string>(?x)^ - (?! [ ]{,3}> - | ([ ]{4}|\t) - | [#]{1,6}\s*+ - | [ ]{,3}(?<marker>[-*_])([ ]{,2}\k<marker>){2,}[ \t]*+$ - )</string> - <key>name</key> - <string>meta.block-level.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>#block_quote</string> - </dict> - <dict> - <key>include</key> - <string>#block_raw</string> - </dict> - <dict> - <key>include</key> - <string>#heading</string> - </dict> - <dict> - <key>include</key> - <string>#separator</string> - </dict> - </array> - </dict> - <dict> - <key>begin</key> - <string>^[ ]{0,3}([*+-])(?=\s)</string> - <key>captures</key> - <dict> - <key>1</key> - <dict> - <key>name</key> - <string>punctuation.definition.list_item.markdown</string> - </dict> - </dict> - <key>end</key> - <string>^(?=\S)</string> - <key>name</key> - <string>markup.list.unnumbered.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>#fenced-code-blocks</string> - </dict> - <dict> - <key>include</key> - <string>#list-paragraph</string> - </dict> - </array> - </dict> - <dict> - <key>begin</key> - <string>^[ ]{0,3}([0-9]+\.)(?=\s)</string> - <key>captures</key> - <dict> - <key>1</key> - <dict> - <key>name</key> - <string>punctuation.definition.list_item.markdown</string> - </dict> - </dict> - <key>end</key> - <string>^(?=\S)</string> - <key>name</key> - <string>markup.list.numbered.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>#fenced-code-blocks</string> - </dict> - <dict> - <key>include</key> - <string>#list-paragraph</string> - </dict> - </array> - </dict> - <dict> - <key>include</key> - <string>#fenced-code-blocks</string> - </dict> - <dict> - <key>begin</key> - <string>^(?=<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|noscript|form|fieldset|iframe|math|ins|del)\b[^>]*>)(?!.*?</\1>)</string> - <key>comment</key> - <string> - Markdown formatting is disabled inside block-level tags. - </string> - <key>end</key> - <string>(?<=^</\1>$\n)</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>#tag-kbd</string> - </dict> - <dict> - <key>include</key> - <string>text.html.basic</string> - </dict> - </array> - <key>name</key> - <string>meta.disable-markdown</string> - </dict> - <dict> - <key>begin</key> - <string>^(?=<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|noscript|form|fieldset|iframe|math|ins|del)\b[^>]*>)</string> - <key>comment</key> - <string>Same rule but for one line disables.</string> - <key>end</key> - <string>$\n?</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>#tag-kbd</string> - </dict> - <dict> - <key>include</key> - <string>text.html.basic</string> - </dict> - </array> - <key>name</key> - <string>meta.disable-markdown</string> - </dict> - <dict> - <key>captures</key> - <dict> - <key>1</key> - <dict> - <key>name</key> - <string>punctuation.definition.constant.begin.markdown</string> - </dict> - <key>2</key> - <dict> - <key>name</key> - <string>constant.other.reference.link.markdown</string> - </dict> - <key>3</key> - <dict> - <key>name</key> - <string>punctuation.definition.constant.end.markdown</string> - </dict> - <key>4</key> - <dict> - <key>name</key> - <string>punctuation.separator.key-value.markdown</string> - </dict> - <key>5</key> - <dict> - <key>name</key> - <string>meta.paragraph.markdown</string> - </dict> - </dict> - <key>match</key> - <string>(?x: - \s* # Leading whitespace - (\[)(\^\d+?)(\])(:) # Reference name - [ \t]* # Optional whitespace - (.+?) # The footnote - [ \t]* # Optional whitespace - $ - )</string> - <key>name</key> - <string>meta.link.reference.footnote.markdown</string> - </dict> - <dict> - <key>captures</key> - <dict> - <key>1</key> - <dict> - <key>name</key> - <string>punctuation.definition.constant.begin.markdown</string> - </dict> - <key>10</key> - <dict> - <key>name</key> - <string>punctuation.definition.string.end.markdown</string> - </dict> - <key>11</key> - <dict> - <key>name</key> - <string>string.other.link.description.title.markdown</string> - </dict> - <key>12</key> - <dict> - <key>name</key> - <string>punctuation.definition.string.begin.markdown</string> - </dict> - <key>13</key> - <dict> - <key>name</key> - <string>punctuation.definition.string.end.markdown</string> - </dict> - <key>2</key> - <dict> - <key>name</key> - <string>constant.other.reference.link.markdown</string> - </dict> - <key>3</key> - <dict> - <key>name</key> - <string>punctuation.definition.constant.end.markdown</string> - </dict> - <key>4</key> - <dict> - <key>name</key> - <string>punctuation.separator.key-value.markdown</string> - </dict> - <key>5</key> - <dict> - <key>name</key> - <string>punctuation.definition.link.markdown</string> - </dict> - <key>6</key> - <dict> - <key>name</key> - <string>markup.underline.link.markdown</string> - </dict> - <key>7</key> - <dict> - <key>name</key> - <string>punctuation.definition.link.markdown</string> - </dict> - <key>8</key> - <dict> - <key>name</key> - <string>string.other.link.description.title.markdown</string> - </dict> - <key>9</key> - <dict> - <key>name</key> - <string>punctuation.definition.string.begin.markdown</string> - </dict> - </dict> - <key>match</key> - <string>(?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 - [ \t]* # Optional whitespace - $ - )</string> - <key>name</key> - <string>meta.link.reference.def.markdown</string> - </dict> - <dict> - <key>begin</key> - <string>^(?=\S)(?![=-]{3,}(?=$))</string> - <key>end</key> - <string>^(?:\s*$|(?=[ ]{,3}>)|(?=```|~~~))|(?=[ \t]*\n)(?<=^===|^====|=====|^---|^----|-----)[ \t]*\n|(?=^#)</string> - <key>name</key> - <string>meta.paragraph.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>#inline</string> - </dict> - <dict> - <key>include</key> - <string>text.html.basic</string> - </dict> - <dict> - <key>captures</key> - <dict> - <key>1</key> - <dict> - <key>name</key> - <string>punctuation.definition.heading.markdown</string> - </dict> - </dict> - <key>match</key> - <string>^(={3,})(?=[ \t]*$)</string> - <key>name</key> - <string>markup.heading.1.markdown</string> - </dict> - <dict> - <key>captures</key> - <dict> - <key>1</key> - <dict> - <key>name</key> - <string>punctuation.definition.heading.markdown</string> - </dict> - </dict> - <key>match</key> - <string>^(-{3,})(?=[ \t]*$)</string> - <key>name</key> - <string>markup.heading.2.markdown</string> - </dict> - </array> - </dict> - </array> - <key>repository</key> - <dict> - <key>ampersand</key> - <dict> - <key>comment</key> - <string> - Markdown will convert this for us. We match it so that the - HTML grammar will not mark it up as invalid. - </string> - <key>match</key> - <string>&(?!([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+);)</string> - <key>name</key> - <string>meta.other.valid-ampersand.markdown</string> - </dict> - <key>block_quote</key> - <dict> - <key>begin</key> - <string>\G[ ]{,3}(>)[ ]?</string> - <key>beginCaptures</key> - <dict> - <key>1</key> - <dict> - <key>name</key> - <string>punctuation.definition.blockquote.markdown</string> - </dict> - </dict> - <key>comment</key> - <string> - We terminate the block quote when seeing an empty line, a - separator or a line with leading > characters. The latter is - to “reset” the quote level for quoted lines. - </string> - <key>end</key> - <string>(?x)^ - (?= \s*$ - | [ ]{,3}(?<marker>[-*_])([ ]{,2}\k<marker>){2,}[ \t]*+$ - | [ ]{,3}> - )</string> - <key>name</key> - <string>markup.quote.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>begin</key> - <string>(?x)\G - (?= [ ]{,3}> - )</string> - <key>end</key> - <string>^</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>#block_quote</string> - </dict> - </array> - </dict> - <dict> - <key>applyEndPatternLast</key> - <integer>1</integer> - <key>begin</key> - <string>(?x)\G - (?= ([ ]{4}|\t) - | [#]{1,6}\s*+ - | [ ]{,3}(?<marker>[-*_])([ ]{,2}\k<marker>){2,}[ \t]*+$ - )</string> - <key>end</key> - <string>^</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>#block_raw</string> - </dict> - <dict> - <key>include</key> - <string>#heading</string> - </dict> - <dict> - <key>include</key> - <string>#separator</string> - </dict> - </array> - </dict> - <dict> - <key>begin</key> - <string>(?x)\G - (?! $ - | [ ]{,3}> - | ([ ]{4}|\t) - | [#]{1,6}\s*+ - | [ ]{,3}(?<marker>[-*_])([ ]{,2}\k<marker>){2,}[ \t]*+$ - )</string> - <key>end</key> - <string>$|(?<=\n)</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>#inline</string> - </dict> - <dict> - <key>include</key> - <string>text.html.basic</string> - </dict> - </array> - </dict> - </array> - </dict> - <key>block_raw</key> - <dict> - <key>match</key> - <string>\G([ ]{4}|\t).*$\n?</string> - <key>name</key> - <string>markup.raw.block.markdown</string> - </dict> - <key>bold_italic</key> - <dict> - <key>begin</key> - <string>(?x) - (?<!\w)(\*|_)(?=\1\1)(\1\1)(?=\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> - )? - \) - ) - ) - ) - | (?!(?<=\S)\1{3}(?!\1)). # Everything besides - # style closer - )++ - (?<=\S)\1{3}(?!\1) # Close - ) - </string> - <key>captures</key> - <dict> - <key>1</key> - <dict> - <key>name</key> - <string>punctuation.definition.bold.markdown</string> - </dict> - <key>2</key> - <dict> - <key>name</key> - <string>punctuation.definition.bold.markdown</string> - </dict> - </dict> - <key>end</key> - <string>(?<=\S)(\1{3})(?!\1)</string> - <key>name</key> - <string>markup.bold_italic.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>applyEndPatternLast</key> - <integer>1</integer> - <key>begin</key> - <string>(?=<[^>]*?>)</string> - <key>end</key> - <string>(?<=>)</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>#tag-kbd</string> - </dict> - <dict> - <key>include</key> - <string>text.html.basic</string> - </dict> - </array> - </dict> - <dict> - <key>include</key> - <string>#escape</string> - </dict> - <dict> - <key>include</key> - <string>#ampersand</string> - </dict> - <dict> - <key>include</key> - <string>#bracket</string> - </dict> - <dict> - <key>include</key> - <string>#raw</string> - </dict> - <dict> - <key>include</key> - <string>#italic</string> - </dict> - <dict> - <key>include</key> - <string>#strikethrough</string> - </dict> - <dict> - <key>include</key> - <string>#image-inline</string> - </dict> - <dict> - <key>include</key> - <string>#link-inline</string> - </dict> - <dict> - <key>include</key> - <string>#link-inet</string> - </dict> - <dict> - <key>include</key> - <string>#link-email</string> - </dict> - <dict> - <key>include</key> - <string>#image-ref</string> - </dict> - <dict> - <key>include</key> - <string>#link-ref</string> - </dict> - <dict> - <key>include</key> - <string>#link-ref-literal</string> - </dict> - <dict> - <key>include</key> - <string>#link-footnote</string> - </dict> - </array> - </dict> - <key>bold</key> - <dict> - <key>begin</key> - <string>(?x) - (?<!\w)(\*\*|__)(?=\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> - )? - \) - ) - ) - ) - | (?!(?<=\S)\1). # Everything besides - # style closer - )++ - (?<=\S)\1 # Close - ) - </string> - <key>captures</key> - <dict> - <key>1</key> - <dict> - <key>name</key> - <string>punctuation.definition.bold.markdown</string> - </dict> - </dict> - <key>end</key> - <string>(?<=\S)(\1)</string> - <key>name</key> - <string>markup.bold.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>applyEndPatternLast</key> - <integer>1</integer> - <key>begin</key> - <string>(?=<[^>]*?>)</string> - <key>end</key> - <string>(?<=>)</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>#tag-kbd</string> - </dict> - <dict> - <key>include</key> - <string>text.html.basic</string> - </dict> - </array> - </dict> - <dict> - <key>include</key> - <string>#escape</string> - </dict> - <dict> - <key>include</key> - <string>#ampersand</string> - </dict> - <dict> - <key>include</key> - <string>#bracket</string> - </dict> - <dict> - <key>include</key> - <string>#raw</string> - </dict> - <dict> - <key>include</key> - <string>#bold_italic</string> - </dict> - <dict> - <key>include</key> - <string>#italic</string> - </dict> - <dict> - <key>include</key> - <string>#strikethrough</string> - </dict> - <dict> - <key>include</key> - <string>#image-inline</string> - </dict> - <dict> - <key>include</key> - <string>#link-inline</string> - </dict> - <dict> - <key>include</key> - <string>#link-inet</string> - </dict> - <dict> - <key>include</key> - <string>#link-email</string> - </dict> - <dict> - <key>include</key> - <string>#image-ref</string> - </dict> - <dict> - <key>include</key> - <string>#link-ref</string> - </dict> - <dict> - <key>include</key> - <string>#link-ref-literal</string> - </dict> - <dict> - <key>include</key> - <string>#link-footnote</string> - </dict> - </array> - </dict> - <key>strikethrough</key> - <dict> - <key>begin</key> - <string>(?x) - (?<!\w)(~~)(?=[^\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> - )? - \) - ) - ) - ) - | (?!(?<=\S)\1). # Everything besides - # style closer - )++ - ) - </string> - <key>captures</key> - <dict> - <key>1</key> - <dict> - <key>name</key> - <string>punctuation.definition.strikethrough.markdown</string> - </dict> - </dict> - <key>end</key> - <string>(?<=\S)(\1)(?!\w)</string> - <key>name</key> - <string>markup.strikethrough.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>applyEndPatternLast</key> - <integer>1</integer> - <key>begin</key> - <string>(?=<[^>]*?>)</string> - <key>end</key> - <string>(?<=>)</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>#tag-kbd</string> - </dict> - <dict> - <key>include</key> - <string>text.html.basic</string> - </dict> - </array> - </dict> - <dict> - <key>include</key> - <string>#escape</string> - </dict> - <dict> - <key>include</key> - <string>#ampersand</string> - </dict> - <dict> - <key>include</key> - <string>#bracket</string> - </dict> - <dict> - <key>include</key> - <string>#raw</string> - </dict> - <dict> - <key>include</key> - <string>#bold_italic</string> - </dict> - <dict> - <key>include</key> - <string>#bold</string> - </dict> - <dict> - <key>include</key> - <string>#italic</string> - </dict> - <dict> - <key>include</key> - <string>#image-inline</string> - </dict> - <dict> - <key>include</key> - <string>#link-inline</string> - </dict> - <dict> - <key>include</key> - <string>#link-inet</string> - </dict> - <dict> - <key>include</key> - <string>#link-email</string> - </dict> - <dict> - <key>include</key> - <string>#image-ref</string> - </dict> - <dict> - <key>include</key> - <string>#link-ref</string> - </dict> - <dict> - <key>include</key> - <string>#link-ref-literal</string> - </dict> - <dict> - <key>include</key> - <string>#link-footnote</string> - </dict> - </array> - </dict> - <key>bracket</key> - <dict> - <key>comment</key> - <string> - Markdown will convert this for us. We match it so that the - HTML grammar will not mark it up as invalid. - </string> - <key>match</key> - <string><(?![a-z/?\$!])</string> - <key>name</key> - <string>meta.other.valid-bracket.markdown</string> - </dict> - <key>escape</key> - <dict> - <key>match</key> - <string>\\[-`*_#+.!(){}\[\]\\>]</string> - <key>name</key> - <string>constant.character.escape.markdown</string> - </dict> - <key>heading</key> - <dict> - <key>begin</key> - <string>\G(#{1,6})(?!#)\s*(?=\S)</string> - <key>captures</key> - <dict> - <key>1</key> - <dict> - <key>name</key> - <string>punctuation.definition.heading.markdown</string> - </dict> - </dict> - <key>contentName</key> - <string>entity.name.section.markdown</string> - <key>end</key> - <string>[ \t]*(#*)$</string> - <key>name</key> - <string>markup.heading.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>#inline</string> - </dict> - </array> - </dict> - <key>image-inline</key> - <dict> - <key>captures</key> - <dict> - <key>1</key> - <dict> - <key>name</key> - <string>punctuation.definition.string.begin.markdown</string> - </dict> - <key>10</key> - <dict> - <key>name</key> - <string>string.other.link.description.title.markdown</string> - </dict> - <key>11</key> - <dict> - <key>name</key> - <string>punctuation.definition.string.markdown</string> - </dict> - <key>12</key> - <dict> - <key>name</key> - <string>punctuation.definition.string.markdown</string> - </dict> - <key>13</key> - <dict> - <key>name</key> - <string>string.other.link.description.title.markdown</string> - </dict> - <key>14</key> - <dict> - <key>name</key> - <string>punctuation.definition.string.markdown</string> - </dict> - <key>15</key> - <dict> - <key>name</key> - <string>punctuation.definition.string.markdown</string> - </dict> - <key>16</key> - <dict> - <key>name</key> - <string>punctuation.definition.metadata.markdown</string> - </dict> - <key>2</key> - <dict> - <key>name</key> - <string>string.other.link.description.markdown</string> - </dict> - <key>4</key> - <dict> - <key>name</key> - <string>punctuation.definition.string.end.markdown</string> - </dict> - <key>5</key> - <dict> - <key>name</key> - <string>invalid.illegal.whitespace.markdown</string> - </dict> - <key>6</key> - <dict> - <key>name</key> - <string>punctuation.definition.metadata.markdown</string> - </dict> - <key>7</key> - <dict> - <key>name</key> - <string>punctuation.definition.link.markdown</string> - </dict> - <key>8</key> - <dict> - <key>name</key> - <string>markup.underline.link.image.markdown</string> - </dict> - <key>9</key> - <dict> - <key>name</key> - <string>punctuation.definition.link.markdown</string> - </dict> - </dict> - <key>match</key> - <string>(?x: - \! # Images start with ! - (\[)((?<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 - (\)) - )</string> - <key>name</key> - <string>meta.image.inline.markdown</string> - </dict> - <key>image-ref</key> - <dict> - <key>captures</key> - <dict> - <key>1</key> - <dict> - <key>name</key> - <string>punctuation.definition.string.begin.markdown</string> - </dict> - <key>2</key> - <dict> - <key>name</key> - <string>string.other.link.description.markdown</string> - </dict> - <key>4</key> - <dict> - <key>name</key> - <string>punctuation.definition.string.end.markdown</string> - </dict> - <key>5</key> - <dict> - <key>name</key> - <string>punctuation.definition.constant.begin.markdown</string> - </dict> - <key>6</key> - <dict> - <key>name</key> - <string>constant.other.reference.link.markdown</string> - </dict> - <key>7</key> - <dict> - <key>name</key> - <string>punctuation.definition.constant.end.markdown</string> - </dict> - </dict> - <key>match</key> - <string>\!(\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(\[)(.*?)(\])</string> - <key>name</key> - <string>meta.image.reference.markdown</string> - </dict> - <key>inline</key> - <dict> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>#escape</string> - </dict> - <dict> - <key>include</key> - <string>#ampersand</string> - </dict> - <dict> - <key>include</key> - <string>#bracket</string> - </dict> - <dict> - <key>include</key> - <string>#raw</string> - </dict> - <dict> - <key>include</key> - <string>#bold_italic</string> - </dict> - <dict> - <key>include</key> - <string>#bold</string> - </dict> - <dict> - <key>include</key> - <string>#italic</string> - </dict> - <dict> - <key>include</key> - <string>#strikethrough</string> - </dict> - <dict> - <key>include</key> - <string>#line-break</string> - </dict> - <dict> - <key>include</key> - <string>#image-inline</string> - </dict> - <dict> - <key>include</key> - <string>#link-inline</string> - </dict> - <dict> - <key>include</key> - <string>#link-inet</string> - </dict> - <dict> - <key>include</key> - <string>#link-email</string> - </dict> - <dict> - <key>include</key> - <string>#image-ref</string> - </dict> - <dict> - <key>include</key> - <string>#link-ref</string> - </dict> - <dict> - <key>include</key> - <string>#link-ref-literal</string> - </dict> - <dict> - <key>include</key> - <string>#link-footnote</string> - </dict> - <dict> - <key>include</key> - <string>#tag-kbd</string> - </dict> - <dict> - <key>include</key> - <string>text.html.basic</string> - </dict> - </array> - </dict> - <key>italic</key> - <dict> - <key>begin</key> - <string>(?x) - (?<!\w)(\*|_)(?=\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 - ) - </string> - <key>captures</key> - <dict> - <key>1</key> - <dict> - <key>name</key> - <string>punctuation.definition.italic.markdown</string> - </dict> - </dict> - <key>end</key> - <string>(?<=\S)(\1)((?!\1)|(?=\1\1))</string> - <key>name</key> - <string>markup.italic.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>applyEndPatternLast</key> - <integer>1</integer> - <key>begin</key> - <string>(?=<[^>]*?>)</string> - <key>end</key> - <string>(?<=>)</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>#tag-kbd</string> - </dict> - <dict> - <key>include</key> - <string>text.html.basic</string> - </dict> - </array> - </dict> - <dict> - <key>include</key> - <string>#escape</string> - </dict> - <dict> - <key>include</key> - <string>#ampersand</string> - </dict> - <dict> - <key>include</key> - <string>#bracket</string> - </dict> - <dict> - <key>include</key> - <string>#raw</string> - </dict> - <dict> - <key>include</key> - <string>#bold_italic</string> - </dict> - <dict> - <key>include</key> - <string>#bold</string> - </dict> - <dict> - <key>include</key> - <string>#strikethrough</string> - </dict> - <dict> - <key>include</key> - <string>#image-inline</string> - </dict> - <dict> - <key>include</key> - <string>#link-inline</string> - </dict> - <dict> - <key>include</key> - <string>#link-inet</string> - </dict> - <dict> - <key>include</key> - <string>#link-email</string> - </dict> - <dict> - <key>include</key> - <string>#image-ref</string> - </dict> - <dict> - <key>include</key> - <string>#link-ref</string> - </dict> - <dict> - <key>include</key> - <string>#link-ref-literal</string> - </dict> - <dict> - <key>include</key> - <string>#link-footnote</string> - </dict> - </array> - </dict> - <key>line-break</key> - <dict> - <key>match</key> - <string> {2,}$</string> - <key>name</key> - <string>meta.dummy.line-break</string> - </dict> - <key>link-email</key> - <dict> - <key>captures</key> - <dict> - <key>1</key> - <dict> - <key>name</key> - <string>punctuation.definition.link.markdown</string> - </dict> - <key>2</key> - <dict> - <key>name</key> - <string>markup.underline.link.markdown</string> - </dict> - <key>4</key> - <dict> - <key>name</key> - <string>punctuation.definition.link.markdown</string> - </dict> - </dict> - <key>match</key> - <string>(<)?((?:mailto:)?[-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(>)?</string> - <key>name</key> - <string>meta.link.email.lt-gt.markdown</string> - </dict> - <key>link-inet</key> - <dict> - <key>captures</key> - <dict> - <key>1</key> - <dict> - <key>name</key> - <string>punctuation.definition.link.markdown</string> - </dict> - <key>2</key> - <dict> - <key>name</key> - <string>markup.underline.link.markdown</string> - </dict> - <key>3</key> - <dict> - <key>name</key> - <string>punctuation.definition.link.markdown</string> - </dict> - </dict> - <key>match</key> - <string>(<)?(\b(?:https?|ftp|file|git):///?[^\s()<>\[\]]+)(>)?</string> - <key>name</key> - <string>meta.link.inet.markdown</string> - </dict> - <key>link-inline</key> - <dict> - <key>captures</key> - <dict> - <key>1</key> - <dict> - <key>name</key> - <string>punctuation.definition.string.begin.markdown</string> - </dict> - <key>10</key> - <dict> - <key>name</key> - <string>string.other.link.description.title.markdown</string> - </dict> - <key>11</key> - <dict> - <key>name</key> - <string>punctuation.definition.string.begin.markdown</string> - </dict> - <key>12</key> - <dict> - <key>name</key> - <string>punctuation.definition.string.end.markdown</string> - </dict> - <key>13</key> - <dict> - <key>name</key> - <string>string.other.link.description.title.markdown</string> - </dict> - <key>14</key> - <dict> - <key>name</key> - <string>punctuation.definition.string.begin.markdown</string> - </dict> - <key>15</key> - <dict> - <key>name</key> - <string>punctuation.definition.string.end.markdown</string> - </dict> - <key>16</key> - <dict> - <key>name</key> - <string>punctuation.definition.metadata.markdown</string> - </dict> - <key>2</key> - <dict> - <key>name</key> - <string>string.other.link.title.markdown</string> - </dict> - <key>4</key> - <dict> - <key>name</key> - <string>punctuation.definition.string.end.markdown</string> - </dict> - <key>5</key> - <dict> - <key>name</key> - <string>invalid.illegal.whitespace.markdown</string> - </dict> - <key>6</key> - <dict> - <key>name</key> - <string>punctuation.definition.metadata.markdown</string> - </dict> - <key>7</key> - <dict> - <key>name</key> - <string>punctuation.definition.link.markdown</string> - </dict> - <key>8</key> - <dict> - <key>name</key> - <string>markup.underline.link.markdown</string> - </dict> - <key>9</key> - <dict> - <key>name</key> - <string>punctuation.definition.link.markdown</string> - </dict> - </dict> - <key>match</key> - <string>(?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 - (\)) - )</string> - <key>name</key> - <string>meta.link.inline.markdown</string> - </dict> - <key>link-footnote</key> - <dict> - <key>captures</key> - <dict> - <key>1</key> - <dict> - <key>name</key> - <string>punctuation.definition.constant.begin.markdown</string> - </dict> - <key>2</key> - <dict> - <key>name</key> - <string>constant.other.reference.link.markdown</string> - </dict> - <key>3</key> - <dict> - <key>name</key> - <string>punctuation.definition.constant.end.markdown</string> - </dict> - </dict> - <key>match</key> - <string>(\[)(\^[^\]]*+)(\])</string> - <key>name</key> - <string>meta.link.reference.markdown</string> - </dict> - <key>link-ref</key> - <dict> - <key>captures</key> - <dict> - <key>1</key> - <dict> - <key>name</key> - <string>punctuation.definition.string.begin.markdown</string> - </dict> - <key>2</key> - <dict> - <key>name</key> - <string>string.other.link.title.markdown</string> - </dict> - <key>4</key> - <dict> - <key>name</key> - <string>punctuation.definition.string.end.markdown</string> - </dict> - <key>5</key> - <dict> - <key>name</key> - <string>punctuation.definition.constant.begin.markdown</string> - </dict> - <key>6</key> - <dict> - <key>name</key> - <string>constant.other.reference.link.markdown</string> - </dict> - <key>7</key> - <dict> - <key>name</key> - <string>punctuation.definition.constant.end.markdown</string> - </dict> - </dict> - <key>match</key> - <string>(\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(\[)([^\]]*+)(\])</string> - <key>name</key> - <string>meta.link.reference.markdown</string> - </dict> - <key>link-ref-literal</key> - <dict> - <key>captures</key> - <dict> - <key>1</key> - <dict> - <key>name</key> - <string>punctuation.definition.string.begin.markdown</string> - </dict> - <key>2</key> - <dict> - <key>name</key> - <string>string.other.link.title.markdown</string> - </dict> - <key>4</key> - <dict> - <key>name</key> - <string>punctuation.definition.string.end.markdown</string> - </dict> - <key>5</key> - <dict> - <key>name</key> - <string>punctuation.definition.constant.begin.markdown</string> - </dict> - <key>6</key> - <dict> - <key>name</key> - <string>punctuation.definition.constant.end.markdown</string> - </dict> - </dict> - <key>match</key> - <string>(\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(?:(\[)(\]))?</string> - <key>name</key> - <string>meta.link.reference.literal.markdown</string> - </dict> - <key>list-paragraph</key> - <dict> - <key>patterns</key> - <array> - <dict> - <key>begin</key> - <string>\G\s+(?=\S)</string> - <key>end</key> - <string>^\s*$</string> - <key>name</key> - <string>meta.paragraph.list.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>#inline</string> - </dict> - <dict> - <key>match</key> - <string>\G\s*([*\-+]|[0-9]+\.)\s+</string> - <key>captures</key> - <dict> - <key>1</key> - <dict> - <key>name</key> - <string>punctuation.definition.list_item.markdown</string> - </dict> - </dict> - </dict> - <dict> - <key>include</key> - <string>text.html.basic</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-code-blocks</string> - </dict> - </array> - </dict> - </array> - </dict> - <key>raw</key> - <dict> - <key>captures</key> - <dict> - <key>1</key> - <dict> - <key>name</key> - <string>punctuation.definition.raw.markdown</string> - </dict> - <key>2</key> - <dict> - <key>name</key> - <string>markup.raw.inline.content.markdown</string> - </dict> - <key>3</key> - <dict> - <key>name</key> - <string>punctuation.definition.raw.markdown</string> - </dict> - </dict> - <key>match</key> - <string>(`+)((?:[^`]|(?!(?<!`)\1(?!`))`)*+)(\1)</string> - <key>name</key> - <string>markup.raw.inline.markdown</string> - </dict> - <key>separator</key> - <dict> - <key>match</key> - <string>\G[ ]{,3}([-*_])([ ]{,2}\1){2,}[ \t]*$\n?</string> - <key>name</key> - <string>meta.separator.markdown</string> - </dict> - <key>fenced-html</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(html|html5)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>text.html.basic</string> - </dict> - </array> - </dict> - <key>fenced-xml</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(xml)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>text.xml</string> - </dict> - </array> - </dict> - <key>fenced-diff</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(diff|patch)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.diff</string> - </dict> - </array> - </dict> - <key>fenced-perl</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(perl)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.perl</string> - </dict> - </array> - </dict> - <key>fenced-php</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(php)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.php</string> - </dict> - </array> - </dict> - <key>fenced-css</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(css)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.css</string> - </dict> - </array> - </dict> - <key>fenced-less</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(less)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.less</string> - </dict> - </array> - </dict> - <key>fenced-java</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(java)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.java</string> - </dict> - </array> - </dict> - <key>fenced-c</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(c)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.c</string> - </dict> - </array> - </dict> - <key>fenced-c++</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(c\+\+|cpp)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.c++</string> - </dict> - </array> - </dict> - <key>fenced-c#</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(c(?:s|sharp|#))\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.cs</string> - </dict> - </array> - </dict> - <key>fenced-yaml</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(yaml)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.yaml</string> - </dict> - </array> - </dict> - <key>fenced-sql</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(sql)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.sql</string> - </dict> - </array> - </dict> - <key>fenced-shell</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(sh|shell|bash)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.shell</string> - </dict> - </array> - </dict> - <key>fenced-sass</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(sass)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.sass</string> - </dict> - </array> - </dict> - <key>fenced-scss</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(scss)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.scss</string> - </dict> - </array> - </dict> - <key>fenced-scala</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(scala)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.scala</string> - </dict> - </array> - </dict> - <key>fenced-obj-c</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(obj(ective-)?c)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.objc</string> - </dict> - </array> - </dict> - <key>fenced-coffee</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(coffee|cjsx)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.coffee</string> - </dict> - </array> - </dict> - <key>fenced-js</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(js|jsx|json|javascript)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.js</string> - </dict> - </array> - </dict> - <key>fenced-ts</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(ts|typescript)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.ts</string> - </dict> - </array> - </dict> - <key>fenced-tsx</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(tsx)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.tsx</string> - </dict> - </array> - </dict> - <key>fenced-ruby</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(ruby)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.ruby</string> - </dict> - </array> - </dict> - <key>fenced-python</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(py|python)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.python</string> - </dict> - </array> - </dict> - <key>fenced-lisp</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(lisp)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.lisp</string> - </dict> - </array> - </dict> - <key>fenced-lua</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(lua)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.lua</string> - </dict> - </array> - </dict> - <key>fenced-scheme</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(scheme)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.scheme</string> - </dict> - </array> - </dict> - <key>fenced-swift</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(swift)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.swift</string> - </dict> - </array> - </dict> - <key>fenced-clojure</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,})\s*(clojure)\s*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>source.clojure</string> - </dict> - </array> - </dict> - <key>fenced-undefined</key> - <dict> - <key>begin</key> - <string>^(\s*[`~]{3,}).*$</string> - <key>end</key> - <string>^(\1)\n</string> - <key>name</key> - <string>markup.raw.block.markdown markup.raw.block.fenced.markdown</string> - </dict> - <key>fenced-code-blocks</key> - <dict> - <key>patterns</key> - <array> - <dict> - <key>include</key> - <string>#fenced-html</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-xml</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-diff</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-perl</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-php</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-css</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-less</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-java</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-c</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-c++</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-c#</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-yaml</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-sql</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-shell</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-sass</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-scss</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-scala</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-obj-c</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-coffee</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-js</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-ts</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-tsx</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-ruby</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-python</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-lisp</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-lua</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-scheme</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-swift</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-clojure</string> - </dict> - <dict> - <key>include</key> - <string>#fenced-undefined</string> - </dict> - </array> - </dict> - <key>tag-kbd</key> - <dict> - <key>name</key> - <string>markup.kbd.markdown</string> - <key>match</key> - <string>((<)(kbd)(>))([^<]+)((</)(kbd)(>))</string> - <key>captures</key> - <dict> - <key>1</key> - <dict> - <key>name</key> - <string>meta.tag.other.html</string> - </dict> - <key>2</key> - <dict> - <key>name</key> - <string>punctuation.definition.tag.begin.html</string> - </dict> - <key>3</key> - <dict> - <key>name</key> - <string>entity.name.tag.other.html</string> - </dict> - <key>4</key> - <dict> - <key>name</key> - <string>punctuation.definition.tag.end.html</string> - </dict> - <key>5</key> - <dict> - <key>name</key> - <string>markup.kbd.content.markdown</string> - </dict> - <key>6</key> - <dict> - <key>name</key> - <string>meta.tag.other.html</string> - </dict> - <key>7</key> - <dict> - <key>name</key> - <string>punctuation.definition.tag.begin.html</string> - </dict> - <key>8</key> - <dict> - <key>name</key> - <string>entity.name.tag.other.html</string> - </dict> - <key>9</key> - <dict> - <key>name</key> - <string>punctuation.definition.tag.end.html</string> - </dict> - </dict> - </dict> - </dict> - <key>scopeName</key> - <string>text.html.markdown.gfm</string> - <key>uuid</key> - <string>423378C0-3E42-11E3-AA6E-0800200C9A66</string> -</dict> -</plist> diff --git a/MarkdownEditor.tmTheme b/MarkdownEditor.tmTheme index d65842f4..3f007da0 100644 --- a/MarkdownEditor.tmTheme +++ b/MarkdownEditor.tmTheme @@ -897,6 +897,72 @@ <string>#565656</string> </dict> </dict> + <!--====================================== + = Persistent Regex Highlights = + =======================================--> + <!-- Warm Blue color --> + <dict> + <key>name</key> + <string>Highlight Color Warm Blue</string> + <key>scope</key> + <string>highlight.color.ADD8E6</string> + <key>settings</key> + <dict> + <key>foreground</key> + <string>#ADD8E6</string> + </dict> + </dict> + <!-- Misty Rose color --> + <dict> + <key>name</key> + <string>Highlight Color MistyRose</string> + <key>scope</key> + <string>highlight.color.FFE4E1</string> + <key>settings</key> + <dict> + <key>foreground</key> + <string>#FFE4E1</string> + </dict> + </dict> + <!-- Green Tea color --> + <dict> + <key>name</key> + <string>Highlight Color Green Tea</string> + <key>scope</key> + <string>highlight.color.D0F0C0</string> + <key>settings</key> + <dict> + <key>foreground</key> + <string>#D0F0C0</string> + </dict> + </dict> + <!--=================================== + = SublimeLinter = + ====================================--> + <!-- SublimeLinter: warning --> + <dict> + <key>name</key> + <string>SublimeLinter: Warning</string> + <key>scope</key> + <string>sublimelinter.mark.warning</string> + <key>settings</key> + <dict> + <key>foreground</key> + <string>#DDB700</string> + </dict> + </dict> + <!-- SublimeLinter: error --> + <dict> + <key>name</key> + <string>SublimeLinter: Error</string> + <key>scope</key> + <string>sublimelinter.mark.error</string> + <key>settings</key> + <dict> + <key>foreground</key> + <string>#D02000</string> + </dict> + </dict> </array> <key>uuid</key> <string>BF4E1964-0DB9-4E88-8142-E8F52D7EDEEC</string> diff --git a/README.md b/README.md index 3f8b1b1d..201afa69 100644 --- a/README.md +++ b/README.md @@ -2,43 +2,54 @@ Markdown plugin for Sublime Text. Provides a decent Markdown color scheme (light and dark) with more __robust__ syntax highlighting and useful Markdown editing features for Sublime Text. 3 flavors are supported: Standard Markdown, __GitHub flavored Markdown__, MultiMarkdown. -![MarkdownEditing][github] +![MarkdownEditing][LightTheme] -[Dark][github 2] and [yellow][github 3] theme available, plus [thirdparty themes](#additional-color-themes). See [configuration](#configuration) section to learn **how to change the theme**. +[Dark][DarkTheme] and [Yellow][YellowTheme] and [ArcDark][ArcDarkTheme] theme available, plus [thirdparty themes](#additional-color-themes). See [configuration](#configuration) section to learn **how to change the theme**. ## Overview -* [Installation](#installation) -* [Features](#features) -* [Key Bindings](#key-bindings) -* [GFM Specific Features](#gfm-specific-features) -* [Commands for Command Palette](#commands-for-command-palette) -* [Configuration](#configuration) -* [Tips](#tips) -* [Similar Plugins](#similar-plugins) -* [Known Bugs](#known-bugs) -* [Contributing](#contributing) -* [Credits](#credits) -* [Donation](#donation) -* [License](#license) +<!-- MarkdownTOC autolink="true" bracket="round" markdown_preview="markdown" --> + +- [Installation](#installation) + - [Package Control](#package-control) + - [Manual Installation](#manual-installation) +- [Features](#features) +- [Key Bindings](#key-bindings) +- [GFM Specific Features](#gfm-specific-features) +- [Commands for Command Palette](#commands-for-command-palette) + - [General Commands](#general-commands) + - [Links, References and Footnotes](#links-references-and-footnotes) + - [Folding and Navigation](#folding-and-navigation) +- [Configuration](#configuration) + - [Additional color themes:](#additional-color-themes) +- [Tips](#tips) +- [Enable WYSIWYG](#enable-wysiwyg) +- [Troubleshooting](#troubleshooting) + - [Error loading syntax file...](#error-loading-syntax-file) +- [Related Plugins](#related-plugins) +- [Known Bugs](#known-bugs) +- [Contributing](#contributing) +- [Credits](#credits) +- [Donation](#donation) +- [License](#license) + +<!-- /MarkdownTOC --> ## Installation -> __Important Note About Installation__ -> -> Are you getting this error after installation: _**Error loading syntax file** "Packages/Markdown/Markdown.tmLanguage": Unable to open Packages/Markdown/Markdown.tmLanguage_? This is caused by open markdown files at the install time. You have to __manually change their syntax to your newly installed Markdown syntax__. Read the below paragraph for more details on this. - -_Note_: Sublime text has a native tiny package for Markdown. However, when MarkdownEditing is enabled, native package causes some conflicts. For this reason, MarkdownEditing will automatically disable it. Since it doesn't bring anything new over MarkdownEditing, this is not a loss. But remember, when you disable MarkdownEditing, you have to reenable the native one manually (if you want). +You can install MarkdownEditing either from Package Control (recommended) or manually. Package Control automatically download the package and keeps it up-to-date. Manual installation is required if you need to tweak the code. If you are using Sublime Text 2, you have to disable the native package _manually_. To do that, add `Markdown` to your `ignored_packages` list in ST user settings: "ignored_packages": [..., "Markdown"], +> Getting "Error loading syntax file..."? See [this](#error-loading-syntax-file). + ### Package Control -The preferred method of installation is via [Sublime Package Control][wbond]. +The preferred method of installation is via [Sublime Package Control][PackageControl]. -1. [Install Sublime Package Control][wbond 2] +1. [Install Sublime Package Control][InstallPackageControl] 2. From inside Sublime Text, open Package Control's Command Pallet: <kbd>CTRL</kbd> <kbd>SHIFT</kbd> <kbd>P</kbd> (Windows, Linux) or <kbd>CMD</kbd> <kbd>SHIFT</kbd> <kbd>P</kbd> on Mac. 3. Type `install package` and hit Return. A list of available packages will be displayed. 4. Type `MarkdownEditing` and hit Return. The package will be downloaded to the appropriate directory. @@ -46,33 +57,45 @@ The preferred method of installation is via [Sublime Package Control][wbond]. ### Manual Installation -1. Download or clone this repository to a directory `MarkdownEditing` in the Sublime Text Packages directory for your platform: - * Mac: `git clone https://github.com/SublimeText-Markdown/MarkdownEditing.git ~/Library/Application\ Support/Sublime\ Text\ 2/Packages/MarkdownEditing` - * Windows: `git clone https://github.com/SublimeText-Markdown/MarkdownEditing.git %APPDATA%\Sublime/ Text/ 2/\MarkdownEditing` - * Linux: `git clone https://github.com/SublimeText-Markdown/MarkdownEditing.git ~/.Sublime\ Text\ 2/Packages/MarkdownEditing` -2. Restart Sublime Text to complete installation. Open a Markdown file and this custom theme. The features listed above should now be available. +1. In Sublime Text, open the menu "Preferences" -> "Browse Packages...". This is the Sublime Text Packages directory. +2. [Download and unzip](https://github.com/SublimeText-Markdown/MarkdownEditing/archive/master.zip) or [clone](https://help.github.com/articles/cloning-a-repository/) this repository to a directory `MarkdownEditing` in the Sublime Text Packages directory. +3. The folder structure should look like `.../Sublime Text 3/Packages/MarkdownEditing/[files]`. +4. Restart Sublime Text to complete installation. Open a Markdown file. The features listed below should now be available. ## Features -* Asterisks and underscores are autopaired and will wrap selected text - - If you start an empty pair and hit backspace, both elements are deleted - - If you start an empty pair and hit space, the right element is deleted -* Backticks are paired -* At the end of a list item, pressing <kbd>Enter</kbd> will automatically insert the new list item bullet. +You can access most features through Command Palette. You can launch it from `Tools -> Command Palette...`. MarkdownEditing commands start with `MarkdownEditing:`. And they are only visible when a markdown file is open and active. + +* __Pairing__ + - Asterisks and underscores are autopaired and will wrap selected text. + - If you start an empty pair and hit backspace, both elements are deleted. + - If you start an empty pair and hit space, the right element is deleted. + - Backticks are paired. So entering `` ` `` will expand to `` `(cursor here)` ``. +* __List__ + - At the end of a list item, pressing <kbd>Enter</kbd> will automatically insert the new list item bullet. - Pressing <kbd>Tab</kbd> on the blank list item will indent it and switch the list bullet to another one (Order is `*`, `-`, `+` in a cycle). - Pressing <kbd>Shift</kbd> <kbd>Tab</kbd> on the blank list item will unindent it in the same way as above. - Sequential <kbd>Tab</kbd> s or <kbd>Shift</kbd> <kbd>Tab</kbd> s are supported. - - You can disable automatic bullet switching or choose which bullets to be used, in your settings file. - - If a list item contains a [GFM task][GFM], pressing <kbd>Enter</kbd> at the end of the line will continue with a new blank task. -* At the end of a blockquote line, pressing <kbd>Enter</kbd> will automatically extend blockquote. -* Selecting some text and pressing <kbd>></kbd> will convert it to blockquote. The first and the last line don't have to be fully selected; partial select works, too. -* Left bracket pairing is modified to eliminate the selection and leave the cursor at a point where you can insert a `[]` or `()` pair for a link -* Displays Markdown headers in the Project Symbol List (<kbd>Ctrl</kbd> <kbd>Shift</kbd> <kbd>R</kbd>). They will start with `#`, so you will know they belong to markdown files at a glance. Also they will be on top of the list because of the precedence of `#`. -* <kbd>~</kbd> wraps selected text with `~~` (strikethrough). -* Typing `#` when there's a selection will surround it with `#` to make it a headline. Multiple presses add additional hashes, increasing the level of the header. Once you hit 6 hashes, it will reset to 0 on the next press. The `mde.match_header_hashes` will determine if the `#` are mirrored on both sides or just at the beginning of the line. -* Typing return at the end of a line that begins with hashmarks will insert closing hashmarks on the headline. They're not required for Markdown, it's just aesthetics, and you can change the `mde.match_header_hashes` option in your settings to enable (disabled by default). -* Setext-style headers can be completed with `Tab`. That is, typing `Tab` on a line containing only `=` or `-` characters will add or remove enough characters to it to match the length of the line above. -* New documents will be named automatically based on the first header. + - You can disable automatic bullet switching or choose which bullets to be used, in your settings file (`mde.list_indent_bullets`). + - If a list item contains a [GFM task][], pressing <kbd>Enter</kbd> at the end of the line will continue with a new blank task. +* __Blockquote__ + - At the end of a blockquote line, pressing <kbd>Enter</kbd> will automatically extend blockquote. + - Selecting some text and pressing <kbd>></kbd> will convert it to blockquote. The first and the last line don't have to be fully selected; partial select works, too. +* __Link__ + - Left bracket pairing is modified to eliminate the selection and leave the cursor at a point where you can insert a `[]` or `()` pair for a link. + - If you leave the cursor on a link, you can right click and jump between reference and url. +* __Navigation__ + - Displays Markdown headers in the Project Symbol List (`Goto -> Goto Symbol in Project...`). They will start with `#`, so you will know they belong to markdown files at a glance. Also they will be on top of the list because of the precedence of `#`. + - Headers also appear in Document Symbol List (`Goto -> Goto Symbol...`) + - You can fold current section with <kbd>Ctrl</kbd> <kbd>Tab</kbd> + - You can navigate between adjacent headers with `Find Next(Previous) Heading` command. +* __Strikethrough__ + - <kbd>~</kbd> wraps selected text with `~~` (strikethrough). When you for instance select the word "foo" and hit `~`, the result will be `~~foo~~`. +* __Header__ + - Typing `#` when there's a selection will surround it with `#` to make it a headline. Multiple presses add additional hashes, increasing the level of the header. Once you hit 6 hashes, it will reset to 0 on the next press. The `mde.match_header_hashes` will determine if the `#` are mirrored on both sides or just at the beginning of the line. + - Typing return at the end of a line that begins with hashmarks will insert closing hashmarks on the headline. They're not required for Markdown, it's just aesthetics, and you can change the `mde.match_header_hashes` option in your settings to enable (disabled by default). + - Setext-style headers can be completed with `Tab`. That is, typing `Tab` on a line containing only `=` or `-` characters will add or remove enough characters to it to match the length of the line above. + - New documents will be named automatically based on the first header. ## Key Bindings @@ -91,83 +114,78 @@ The preferred method of installation is via [Sublime Package Control][wbond]. ## GFM Specific Features +[GFM][] means GitHub Flavored Markdown is the dialect of Markdown that is currently supported for user content on GitHub.com and GitHub Enterprise. It has [some unique features][GFMFeatures]: + Underscores in words doesn't mess with bold or italic style: -![underscore-in-words][github 5] +![underscore-in-words][GFM-UnderscoreInWords] Fenced code blocks gets syntax highlighting inside: -![fenced-code-block][github 6] +![fenced-code-block][GFM-FencedCodeBlock] Keyboard shortcuts gets highlighted like in GitHub: -![keyboard-shortcut][github 7] +![keyboard-shortcut][GFM-KeyboardShortcut] Strikethrough is supported: -![strikethrough][github 8] +![strikethrough][GFM-Strikethrough] ## Commands for Command Palette -### Fix Underlined Headers - -Adjusts every setext-style header to add or remove `=` or `-` characters as needed to match the lengths of their header text. - -### Convert Underlined Headers to ATX - -Converts every setext-style header into an ATX style header. If something is selected only the headers in the selections will be converted, otherwise the conversion will be applied to the whole view. - -### Add Missing Link Labels - -Scans document for referenced link usages (`[some link][some_ref]` and `[some link][]`) and checks if they are all defined. If there are undefined link references, command will automatically create their definition snippet at the bottom of the file. - -### Markdown Lint - -Performs lint on current Markdown file. See [lint rules](lint_docs/RULES.md). Some of the linting rules are customizable via user settings file. - -### Switch List Bullet Type - -Switches the highlighted list between numbered and bulleted style. - -### Magic Footnotes Command - -Adds a footnote after the word under cursor. If cursor is already on a footnote, jumps to its definition or reference. - -### Gather Missing Footnotes - -Add definition stubs (if there is none) for all footnotes references. - -### Jump Reference - -Jumps cursor between definitions and references. - -### New Reference - -Adds a new link under cursor. - -### New Inline Link - -Adds a new inline link under cursor. - -### New Inline Image - -Adds a new inline image under cursor. - -### New Image - -Adds a new image under cursor. - -### New Footnote - -Adds a footnote under cursor. - -### Delete Reference - -Deletes the definition and references of a link. - -### Organize References - -Sorts and gives a report on current link references usage. +You can launch Command Palette from `Tools -> Command Palette...`. MarkdownEditing commands start with `MarkdownEditing:`. And they are only visible when a markdown file is open and active. + +### General Commands + +* __Fix Underlined Headers__ + Adjusts every setext-style header to add or remove `=` or `-` characters as needed to match the lengths of their header text. +* __Convert Underlined Headers to ATX__ + Converts every setext-style header into an ATX style header. If something is selected only the headers in the selections will be converted, otherwise the conversion will be applied to the whole view. +* __Markdown Lint__ + Performs lint on current Markdown file. See [lint rules](lint_docs/RULES.md). Some of the linting rules are customizable via user settings file. +* __Change color scheme...__ + Lists built-in Markdown color schemes for you to preview and use. +* __Switch List Bullet Type__ + Switches the highlighted list between numbered and bulleted style. + +### Links, References and Footnotes + +* __Add Missing Link Labels__ + Scans document for referenced link usages (`[some link][some_ref]` and `[some link][]`) and checks if they are all defined. If there are undefined link references, command will automatically create their definition snippet at the bottom of the file. +* __Magic Footnotes Command__ + Adds a footnote after the word under cursor. If cursor is already on a footnote, jumps to its definition or reference. +* __Gather Missing Footnotes__ + Add definition stubs (if there is none) for all footnotes references. +* __Jump Reference__ + Jumps cursor between definitions and references. +* __New Reference__ + Adds a new link under cursor. +* __New Inline Link__ + Adds a new inline link under cursor. +* __New Inline Image__ + Adds a new inline image under cursor. +* __New Image__ + Adds a new image under cursor. +* __New Footnote__ + Adds a footnote under cursor. +* __Delete Reference__ + Deletes the definition and references of a link. +* __Organize References__ + Sorts and gives a report on current link references usage. + +### Folding and Navigation + +Remeber you can <kbd>Ctrl</kbd> <kbd>R</kbd> (in document) and <kbd>Ctrl</kbd> <kbd>Shift</kbd> <kbd>R</kbd> (project-wise) for quick navigation for all headers. + +* __Toggle Folding Current Section__ + Folds/unfolds current section. +* __Fold Level 1-4 Sections__ + Fold all sections under headers of specific level. +* __Fold/Unfold All Sections__ + Self explanatory. +* __Find Next/Previous Heading__ + You have option to find just same or higher level or any level ## Configuration @@ -220,7 +238,17 @@ Install them if you haven't. Then 1. LiveReload: Enable/Disable Plugins 1. Enable Simple Reload. -Now open palette and choose "Preview in Broswer" and you will get a WYSIWYG editor. +Now open palette and choose "Preview in Browser" and you will get a WYSIWYG editor. + +## Troubleshooting + +### Error loading syntax file... + +__Are you getting this error after installation: _**Error loading syntax file** "Packages/Markdown/Markdown.tmLanguage": Unable to open Packages/Markdown/Markdown.tmLanguage_?__ + +> This is caused by open markdown files at the install time. You have to __manually change their syntax to your newly installed Markdown syntax__. Read the below paragraph for more details on this. + +_Note_: Sublime text has a native tiny package for Markdown. However, when MarkdownEditing is enabled, native package causes some conflicts. For this reason, MarkdownEditing will automatically disable it. Since it doesn't bring anything new over MarkdownEditing, this is not a loss. But remember, when you disable MarkdownEditing, you have to reenable the native one manually (if you want). ## Related Plugins @@ -229,6 +257,8 @@ Now open palette and choose "Preview in Broswer" and you will get a WYSIWYG edit Knockdown offers useful Markdown features and a custom Markdown theme. All of its unique features except its theme are ported to MarkdownEditing and some of them are actually improved further in MarkdownEditing. * [Sublime Markdown Extended][] * [SmartMarkdown][] +* [MarkdownTOC][] + - Sublime Text 3 plugin for generating a Table of Contents (TOC) in a Markdown document. * See https://packagecontrol.io/search/markdown for more. ## Known Bugs @@ -243,7 +273,7 @@ See `CONTRIBUTING.md` file. ## Credits -MarkdownEditing was originally created by [Brett Terpstra][brettterpstra] and has become a community project with the goal of consolidating the best features from the varied collection of Markdown packages for Sublime Text. Current development is headed up by [Ali Ayas][github 9] and [Felix Hao][github 10]. +MarkdownEditing was originally created by [Brett Terpstra][brettterpstra] and has become a community project with the goal of consolidating the best features from the varied collection of Markdown packages for Sublime Text. Current development is headed up by [Ali Ayas][maliayas] and [Felix Hao][felixhao28]. Related blog posts from Brett: * http://brettterpstra.com/2012/05/17/markdown-editing-for-sublime-text-2-humble-beginnings/ @@ -251,41 +281,45 @@ Related blog posts from Brett: This plugin contains portions of code from [Knockdown][]. -Footnote commands were submitted by [J. Nicholas Geist][github 4] and originated at [geekabouttown][geekabouttown]. +Footnote commands were submitted by [J. Nicholas Geist][] and originated at [geekabouttown][geekabouttown]. ## Donation You can support [contributors](https://github.com/SublimeText-Markdown/MarkdownEditing/graphs/contributors) of this project individually. Every contributor is welcomed to add his/her line below with any content. Ordering shall be alphabetically by GitHub username. -* [@felixhao28][github 10]: <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9QV2RFV2J8UZS"><img src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif" alt="[paypal]" /></a> -* [@maliayas][github 9]: <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=W2NXRPD43YSCU&lc=TR&item_name=open-source&item_number=markdown-editing&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted"><img src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif" alt="[paypal]" /></a> ![donation received](http://maliayas.com/business/donation/badge.php?project=markdown_editing) +* [@felixhao28][felixhao28]: <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9QV2RFV2J8UZS"><img src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif" alt="[paypal]" /></a> +* [@maliayas][maliayas]: <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=W2NXRPD43YSCU&lc=TR&item_name=open-source&item_number=markdown-editing&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted"><img src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif" alt="[paypal]" /></a> ![donation received](http://maliayas.com/business/donation/badge.php?project=markdown_editing) ## License MarkdownEditing is released under the [MIT License][opensource]. -[github]: https://raw.github.com/SublimeText-Markdown/MarkdownEditing/master/screenshots/light.png -[github 2]: https://raw.github.com/SublimeText-Markdown/MarkdownEditing/master/screenshots/dark.png -[github 3]: https://raw.github.com/SublimeText-Markdown/MarkdownEditing/master/screenshots/yellow.png -[wbond]: http://wbond.net/sublime_packages/package_control -[wbond 2]: http://wbond.net/sublime_packages/package_control/installation -[GFM]: https://help.github.com/articles/github-flavored-markdown -[github 5]: https://raw.github.com/SublimeText-Markdown/MarkdownEditing/master/screenshots/underscore-in-words.png -[github 6]: https://raw.github.com/SublimeText-Markdown/MarkdownEditing/master/screenshots/fenced-code-block.png -[github 7]: https://raw.github.com/SublimeText-Markdown/MarkdownEditing/master/screenshots/keyboard-shortcut.png -[github 8]: https://raw.github.com/SublimeText-Markdown/MarkdownEditing/master/screenshots/strikethrough.png +[LightTheme]: https://raw.github.com/SublimeText-Markdown/MarkdownEditing/master/screenshots/light.png +[DarkTheme]: https://raw.github.com/SublimeText-Markdown/MarkdownEditing/master/screenshots/dark.png +[YellowTheme]: https://raw.github.com/SublimeText-Markdown/MarkdownEditing/master/screenshots/yellow.png +[ArcDarkTheme]: https://raw.github.com/SublimeText-Markdown/MarkdownEditing/master/screenshots/arcdark.png +[PackageControl]: http://wbond.net/sublime_packages/package_control +[InstallPackageControl]: http://wbond.net/sublime_packages/package_control/installation +[GFM task]: https://github.github.com/gfm/#task-list-items-extension- +[GFM]: https://github.github.com/gfm/ +[GFMFeatures]: https://guides.github.com/features/mastering-markdown/ +[GFM-UnderscoreInWords]: https://raw.github.com/SublimeText-Markdown/MarkdownEditing/master/screenshots/underscore-in-words.png +[GFM-FencedCodeBlock]: https://raw.github.com/SublimeText-Markdown/MarkdownEditing/master/screenshots/fenced-code-block.png +[GFM-KeyboardShortcut]: https://raw.github.com/SublimeText-Markdown/MarkdownEditing/master/screenshots/keyboard-shortcut.png +[GFM-Strikethrough]: https://raw.github.com/SublimeText-Markdown/MarkdownEditing/master/screenshots/strikethrough.png [linkBlackboardTheme]: https://github.com/mdesantis/MarkdownEditing/blob/blackboard-theme/MarkdownEditor-Blackboard.tmTheme [mdesantis]: https://github.com/mdesantis [avivace]: https://github.com/avivace [tips]: https://github.com/SublimeText-Markdown/MarkdownEditing/wiki/Tips [Wiki]: https://github.com/SublimeText-Markdown/MarkdownEditing/wiki -[Knockdown]: https://github.com/aziz/knockdown/ -[Sublime Markdown Extended]: https://github.com/jonschlinkert/sublime-markdown-extended -[SmartMarkdown]: https://github.com/demon386/SmartMarkdown +[Knockdown]: https://github.com/aziz/knockdown/ +[Sublime Markdown Extended]: https://github.com/jonschlinkert/sublime-markdown-extended +[SmartMarkdown]: https://github.com/demon386/SmartMarkdown +[MarkdownTOC]: https://github.com/naokazuterada/MarkdownTOC [#158]: https://github.com/SublimeText-Markdown/MarkdownEditing/issues/158 [brettterpstra]: http://brettterpstra.com -[github 9]: https://github.com/maliayas -[github 10]: https://github.com/felixhao28 -[github 4]: https://github.com/jngeist +[maliayas]: https://github.com/maliayas +[felixhao28]: https://github.com/felixhao28 +[J. Nicholas Geist]: https://github.com/jngeist [geekabouttown]: http://geekabouttown.com/posts/sublime-text-2-markdown-footnote-goodness [opensource]: http://www.opensource.org/licenses/MIT diff --git a/decide_title.py b/decide_title.py index c0fe1a8c..664691f5 100644 --- a/decide_title.py +++ b/decide_title.py @@ -11,21 +11,21 @@ def on_modified_async(self, view): text = view.substr(sublime.Region(0, view.size())) it = re.finditer(r'^(#{1,6}(?!#))|^(-{3,}|={3,})', text, re.M) title = '' + title_begin = None for m in it: + if '.front-matter' in view.scope_name(m.start()): + continue if re.match(r'^(-{3,}|={3,})$', m.group()): title_end = m.start() - 1 title_begin = text.rfind('\n', 0, title_end) + 1 - title = text[title_begin: title_end] else: title_begin = m.end() title_end = re.search('(' + m.group() + ')?(\n|$)', text[title_begin:]).start() + title_begin - title = text[title_begin: title_end] - break - if len(title) == 0: - firstLineEnd = text.find('\n') - if firstLineEnd == -1: - firstLineEnd = len(text) - title = text[0: firstLineEnd] + title_begin = m.start() + 1 + if 'markup.raw.block.markdown' not in view.scope_name(title_begin).split(' '): + break + if len(title) == 0 and title_begin is not None: + title = text[title_begin: title_end] title = title.strip() if view.file_name() is None and len(title) > 0: diff --git a/folding.py b/folding.py index 8c6270c1..109cf4e0 100644 --- a/folding.py +++ b/folding.py @@ -18,6 +18,8 @@ def all_headings(view): text = view.substr(sublime.Region(0, view.size())) it = re.finditer(r'^(#{1,6}(?!#))|^(-{3,}|={3,})', text, re.M) for m in it: + if '.front-matter' in view.scope_name(m.start()): + continue if re.match(r'^(-{3,}|={3,})$', m.group()): title_end = m.start() - 1 title_begin = text.rfind('\n', 0, title_end) + 1 @@ -79,6 +81,7 @@ def run(self, edit): view.fold(reg) sublime.status_message('%d region%s %sfolded' % (len(sections), 's' if len(sections) > 1 else '', 'un' if shouldUnfold else '')) + class FoldSectionContextCommand(FoldSectionCommand): def is_visible(self): @@ -106,6 +109,7 @@ def is_visible(self): hasSection = True return hasSection + class UnfoldSectionContextCommand(FoldSectionCommand): def is_visible(self): @@ -133,6 +137,7 @@ def is_visible(self): return False return hasSection + class ShowFoldAllSectionsCommand(MDETextCommand): def run(self, edit): diff --git a/messages.json b/messages.json index f45e2820..4fdab49f 100644 --- a/messages.json +++ b/messages.json @@ -23,5 +23,6 @@ "2.2.0": "messages/2.2.0.md", "2.2.1": "messages/2.2.1.md", "2.2.2": "messages/2.2.2.md", - "2.2.3": "messages/2.2.3.md" + "2.2.3": "messages/2.2.3.md", + "2.2.4": "messages/2.2.4.md" } diff --git a/messages/2.2.4.md b/messages/2.2.4.md new file mode 100644 index 00000000..a8dd1b92 --- /dev/null +++ b/messages/2.2.4.md @@ -0,0 +1,26 @@ +# MarkdownEditing 2.2.4 Changelog + +Your _MarkdownEditing_ plugin is updated. Enjoy new version. For any type of +feedback you can use [GitHub issues][issues]. + +## Bug Fixes + +* Fix an issue that occationally prevents creating link references with command. +* Fix an issue that breaks navigating through headers while front matter is present. + +## New Features + +* Latex math expressions are highlighted now: + - $\frac{d}{dx}\left( \int_{0}^{x} f(u)\,du\right)=f(x).$ +* Front matter (yaml, coffee, json) highlight. +* Go Programming Language highlight in code blocks. +* Kotlin Programming Language highlight in code blocks (requires Kotlin package). +* Convert between inline links and references. + - Command: MarkdownEditing: Convert all inline links to references + - Command: MarkdownEditing: Convert inline link to references + + Only appear if cursor is on an inline link + + Also appear in context menu + +## Changes + +[issues]: https://github.com/SublimeText-Markdown/MarkdownEditing/issues diff --git a/references.py b/references.py index 11e2ec85..7dbb7544 100644 --- a/references.py +++ b/references.py @@ -1,11 +1,27 @@ +""" +Commands related to links, references and footnotes. + +Exported commands: + ReferenceJumpCommand + ReferenceJumpContextCommand + ReferenceNewReferenceCommand + ReferenceNewInlineLinkCommand + ReferenceNewInlineImage + ReferenceNewImage + ReferenceNewFootnote + ReferenceDeleteReference + ReferenceOrganize + GatherMissingLinkMarkersCommand + ConvertInlineLinkToReferenceCommand + ConvertInlineLinksToReferencesCommand +""" import sublime -import sublime_plugin import re import operator try: - from MarkdownEditing.mdeutils import * + from MarkdownEditing.mdeutils import MDETextCommand except ImportError: - from mdeutils import * + from mdeutils import MDETextCommand refname_scope_name = "constant.other.reference.link.markdown" definition_scope_name = "meta.link.reference.def.markdown" @@ -22,16 +38,20 @@ def hasScope(scope_name, to_find): + """Test to_find's existence in scope_name.""" return to_find in scope_name.split(" ") class Obj(object): + """A utility obj for anoymous object.""" def __init__(self, **kwargs): + """Take keyword arguments.""" self.__dict__.update(kwargs) def getMarkers(view, name=''): + """Find all markers.""" # returns {name -> Region} markers = [] name = re.escape(name) @@ -66,6 +86,7 @@ def getMarkers(view, name=''): def getReferences(view, name=''): + """Find all reference definitions.""" # returns {name -> Region} refs = [] name = re.escape(name) @@ -86,15 +107,15 @@ def getReferences(view, name=''): def isMarkerDefined(view, name): - # returns bool + """Return True if a marker is defined by that name.""" return len(getReferences(view, name)) > 0 def getCurrentScopeRegion(view, pt): - # returns Region + """Extend the region under current scope.""" scope = view.scope_name(pt) l = pt - while l > 0 and view.scope_name(l-1) == scope: + while l > 0 and view.scope_name(l - 1) == scope: l -= 1 r = pt while r < view.size() and view.scope_name(r) == scope: @@ -102,18 +123,21 @@ def getCurrentScopeRegion(view, pt): return sublime.Region(l, r) -def findScopeFrom(view, pt, scope, backwards=False): - # returns number +def findScopeFrom(view, pt, scope, backwards=False, char=None): + """Find the nearest position of a scope from given position.""" if backwards: - while pt >= 0 and not hasScope(view.scope_name(pt), scope): + while pt >= 0 and (not hasScope(view.scope_name(pt), scope) or + (char is not None and view.substr(pt) != char)): pt -= 1 else: - while pt < view.size() and not hasScope(view.scope_name(pt), scope): + while pt < view.size() and (not hasScope(view.scope_name(pt), scope) or + (char is not None and view.substr(pt) != char)): pt += 1 return pt def get_reference(view, pos): + """Try to match a marker or reference on given position. Return a tuple (matched, is_definition, name).""" scope = view.scope_name(pos).split(" ") if definition_scope_name in scope or footnote_scope_name in scope: if refname_scope_name in scope: @@ -121,7 +145,7 @@ def get_reference(view, pos): defname = view.substr(getCurrentScopeRegion(view, pos)) elif refname_start_scope_name in scope: # Starting "[" - defname = view.substr(getCurrentScopeRegion(view, pos+1)) + defname = view.substr(getCurrentScopeRegion(view, pos + 1)) else: # URL or footnote marker_pt = findScopeFrom(view, pos, refname_scope_name, True) @@ -154,18 +178,20 @@ def get_reference(view, pos): class ReferenceJumpCommand(MDETextCommand): - # reference_jump command + """Jump between definition and reference.""" def description(self): + """Description for package control.""" return 'Jump between definition and reference' def run(self, edit): + """Run command callback.""" view = self.view edit_regions = [] markers = getMarkers(view) refs = getReferences(view) - missingMarkers = [] - missingRefs = [] + missing_markers = [] + missing_refs = [] for sel in view.sel(): matched, is_definition, defname = get_reference(view, sel.begin()) if matched: @@ -174,41 +200,44 @@ def run(self, edit): if defname_key in markers: edit_regions.extend(markers[defname_key].regions) else: - missingMarkers.append(defname) + missing_markers.append(defname) else: if defname_key in refs: edit_regions.extend(refs[defname_key].regions) else: - missingRefs.append(defname) + missing_refs.append(defname) if len(edit_regions) > 0: sels = view.sel() sels.clear() sels.add_all(edit_regions) view.show(edit_regions[0]) - if len(missingRefs) + len(missingMarkers) > 0: + if len(missing_refs) + len(missing_markers) > 0: # has something missing - if len(missingMarkers) == 0: - sublime.status_message("The definition%s of %s cannot be found." % ("" if len(missingRefs) == 1 else "s", ", ".join(missingRefs))) - elif len(missingRefs) == 0: - sublime.status_message("The marker%s of %s cannot be found." % ("" if len(missingMarkers) == 1 else "s", ", ".join(missingMarkers))) + if len(missing_markers) == 0: + sublime.status_message("The definition%s of %s cannot be found." % ("" if len(missing_refs) == 1 else "s", ", ".join(missing_refs))) + elif len(missing_refs) == 0: + sublime.status_message("The marker%s of %s cannot be found." % ("" if len(missing_markers) == 1 else "s", ", ".join(missing_markers))) else: - sublime.status_message("The definition%s of %s and the marker%s of %s cannot be found." % ("" if len(missingRefs) == 1 else "s", ", ".join(missingRefs), "" if len(missingMarkers) == 1 else "s", ", ".join(missingMarkers))) + sublime.status_message("The definition%s of %s and the marker%s of %s cannot be found." % ("" if len(missing_refs) == 1 else "s", ", ".join(missing_refs), "" if len(missing_markers) == 1 else "s", ", ".join(missing_markers))) class ReferenceJumpContextCommand(ReferenceJumpCommand): + """Jump between definition and reference. Used in context menu.""" def is_visible(self): + """Return True if cursor is on a marker or reference.""" return ReferenceJumpCommand.is_visible(self) and any(get_reference(self.view, sel.begin())[0] for sel in self.view.sel()) def is_url(contents): - # Returns if contents contains an URL + """Return if contents contains an URL.""" re_match_urls = re.compile(r"""((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.‌​][a-z]{2,4}/)(?:[^\s()<>]+|(([^\s()<>]+|(([^\s()<>]+)))*))+(?:(([^\s()<>]+|(‌​([^\s()<>]+)))*)|[^\s`!()[]{};:'".,<>?«»“”‘’]))""", re.DOTALL) m = re_match_urls.search(contents) return True if m else False def mangle_url(url): + """Mangle URL for links.""" url = url.strip() if re.match(r'^([a-z0-9-]+\.)+\w{2,4}', url, re.IGNORECASE): url = 'http://' + url @@ -216,7 +245,7 @@ def mangle_url(url): def append_reference_link(edit, view, name, url): - # Detect if file ends with \n + r"""Detect if file ends with \n.""" if view.substr(view.size() - 1) == '\n': nl = '' else: @@ -228,7 +257,7 @@ def append_reference_link(edit, view, name, url): def suggest_default_link_name(name, image): - # Camel case impl. + """Suggest default link name in camel case.""" ret = '' name_segs = name.split() if len(name_segs) > 1: @@ -236,16 +265,17 @@ def suggest_default_link_name(name, image): ret += word.capitalize() if len(ret) > 30: break - return ('image' if image else 'link') + ret + return ('image' if image else '') + ret else: return name def check_for_link(view, link): + """Check if the link already defined. Return the name if so.""" refs = getReferences(view) link = link.strip() for name in refs: - link_begin = findScopeFrom(view, refs[name][0].begin(), ref_link_scope_name) + link_begin = findScopeFrom(view, refs[name].regions[0].begin(), ref_link_scope_name) reg = getCurrentScopeRegion(view, link_begin) found_link = view.substr(reg).strip() if found_link == link: @@ -254,16 +284,17 @@ def check_for_link(view, link): class ReferenceNewReferenceCommand(MDETextCommand): - # reference_new_reference command + """Create a new reference.""" def run(self, edit, image=False): + """Run command callback.""" view = self.view edit_regions = [] contents = sublime.get_clipboard().strip() link = mangle_url(contents) if is_url(contents) else "" suggested_name = "" if len(link) > 0: - # If link already exists, reuse existing reference + # If link already exists, reuse existing reference suggested_link_name = suggested_name = check_for_link(view, link) for sel in view.sel(): text = view.substr(sel) @@ -286,12 +317,11 @@ def run(self, edit, image=False): class ReferenceNewInlineLinkCommand(MDETextCommand): - # reference_new_inline_link command + """Create a new inline link.""" def run(self, edit, image=False): + """Run command callback.""" view = self.view - edit_regions = [] - suggested_name = False contents = sublime.get_clipboard().strip() link = mangle_url(contents) if is_url(contents) else "" link = link.replace("$", "\\$") @@ -302,22 +332,25 @@ def run(self, edit, image=False): class ReferenceNewInlineImage(MDETextCommand): - # reference_new_inline_image command + """Create a new inline image.""" def run(self, edit): + """Run command callback.""" self.view.run_command("reference_new_inline_link", {"image": True}) class ReferenceNewImage(MDETextCommand): - # reference_new_image command + """Create a new image.""" def run(self, edit): + """Run command callback.""" self.view.run_command("reference_new_reference", {"image": True}) def get_next_footnote_marker(view): + """Get the number of the next footnote.""" refs = getReferences(view) - footnotes = [int(ref[1:]) for ref in refs if view.substr(refs[ref][0])[0] == "^"] + footnotes = [int(ref[1:]) for ref in refs if view.substr(refs[ref].regions[0])[0] == "^"] def target_loc(num): return (num - 1) % len(footnotes) @@ -336,15 +369,16 @@ def target_loc(num): else: break for i in range(len(footnotes)): - if footnotes[i] != i+1: - return i+1 + if footnotes[i] != i + 1: + return i + 1 return len(footnotes) + 1 class ReferenceNewFootnote(MDETextCommand): - # reference_new_footnote command + """Create a new footnote.""" def run(self, edit): + """Run command callback.""" view = self.view markernum = get_next_footnote_marker(view) markernum_str = '[^%s]' % markernum @@ -363,9 +397,10 @@ def run(self, edit): class ReferenceDeleteReference(MDETextCommand): - # reference_delete_reference command + """Delete a reference.""" def run(self, edit): + """Run command callback.""" view = self.view edit_regions = [] markers = getMarkers(view) @@ -377,25 +412,25 @@ def run(self, edit): if defname_key in markers: for marker in markers[defname_key].regions: if defname[0] == "^": - edit_regions.append(sublime.Region(marker.begin()-1, marker.end()+1)) + edit_regions.append(sublime.Region(marker.begin() - 1, marker.end() + 1)) else: l = findScopeFrom(view, marker.begin(), marker_begin_scope_name, True) - if l > 0 and view.substr(sublime.Region(l-1, l)) == "!": - edit_regions.append(sublime.Region(l-1, l+1)) + if l > 0 and view.substr(sublime.Region(l - 1, l)) == "!": + edit_regions.append(sublime.Region(l - 1, l + 1)) else: - edit_regions.append(sublime.Region(l, l+1)) + edit_regions.append(sublime.Region(l, l + 1)) if hasScope(view.scope_name(marker.end()), marker_text_end_scope_name): - if view.substr(sublime.Region(marker.end()+1, marker.end()+2)) == '[': + if view.substr(sublime.Region(marker.end() + 1, marker.end() + 2)) == '[': # [Text][] r = findScopeFrom(view, marker.end(), marker_end_scope_name, False) - edit_regions.append(sublime.Region(marker.end(), r+1)) + edit_regions.append(sublime.Region(marker.end(), r + 1)) else: # [Text] - edit_regions.append(sublime.Region(marker.end(), marker.end()+1)) + edit_regions.append(sublime.Region(marker.end(), marker.end() + 1)) else: # [Text][name] r = findScopeFrom(view, marker.begin(), marker_text_end_scope_name, True) - edit_regions.append(sublime.Region(r, marker.end()+1)) + edit_regions.append(sublime.Region(r, marker.end() + 1)) if defname_key in refs: for ref in refs[defname_key].regions: edit_regions.append(view.full_line(ref.begin())) @@ -412,9 +447,10 @@ def delete_all(index): class ReferenceOrganize(MDETextCommand): - # reference_organize command + """Sort and report all references.""" def run(self, edit): + """Run command callback.""" view = self.view # reorder @@ -440,8 +476,8 @@ def run(self, edit): flatrefs.sort(key=lambda x: marker_order[x[0].lower()] if x[0].lower() in marker_order else 9999) view.run_command("left_delete") - if view.size() >= 2 and view.substr(sublime.Region(view.size()-2, view.size())) == "\n\n": - view.erase(edit, sublime.Region(view.size()-1, view.size())) + if view.size() >= 2 and view.substr(sublime.Region(view.size() - 2, view.size())) == "\n\n": + view.erase(edit, sublime.Region(view.size() - 1, view.size())) for fn_tuple in flatfns: view.insert(edit, view.size(), fn_tuple[1]) view.insert(edit, view.size(), "\n") @@ -523,8 +559,10 @@ def get_times_string(n): class GatherMissingLinkMarkersCommand(MDETextCommand): + """Gather all missing references and creates them.""" def run(self, edit): + """Run command callback.""" view = self.view refs = getReferences(view) markers = getMarkers(view) @@ -537,9 +575,105 @@ def run(self, edit): whitespace_at_end = view.find(r'\s*\z', 0) view.replace(edit, whitespace_at_end, "\n") - # If there is not already a reference list at the and, insert a new line at the end + # If there is not already a reference list at the end, insert a new line at the end if not view.find(r'\n\s*\[[^\]]*\]:.*\s*\z', 0): view.insert(edit, view.size(), "\n") for link in missings: view.insert(edit, view.size(), '[%s]: \n' % link) + + +def convert2ref(view, edit, link_span, name, omit_name=False): + """Convert single link to reference.""" + view.sel().clear() + link = view.substr(sublime.Region(link_span.a + 1, link_span.b - 1)) + if omit_name: + view.replace(edit, link_span, '[]') + link_span = sublime.Region(link_span.a + 1, link_span.a + 1) + offset = len(link) + else: + view.replace(edit, link_span, '[%s]' % name) + link_span = sublime.Region(link_span.a + 1, link_span.a + 1 + len(name)) + offset = len(link) - len(name) + view.sel().add(link_span) + view.show_at_center(link_span) + + _viewsize = view.size() + view.insert(edit, _viewsize, '[%s]: %s\n' % (name, link)) + reference_span = sublime.Region(_viewsize + 1, _viewsize + 1 + len(name)) + view.sel().add(reference_span) + return offset + + +class ConvertInlineLinkToReferenceCommand(MDETextCommand): + """Convert an inline link to reference.""" + + def is_visible(self): + """Return True if cursor is on a marker or reference.""" + for sel in self.view.sel(): + scope_name = self.view.scope_name(sel.b) + if hasScope(scope_name, 'meta.link.inline.markdown'): + return True + return False + + def run(self, edit, name=None): + """Run command callback.""" + view = self.view + pattern = r"\[([^\]]+)\]\((?!#)([^\)]+)\)" + + # Remove all whitespace at the end of the file + whitespace_at_end = view.find(r'\s*\z', 0) + view.replace(edit, whitespace_at_end, "\n") + + # If there is not already a reference list at the end, insert a new line at the end + if not view.find(r'\n\s*\[[^\]]*\]:.*\s*\z', 0): + view.insert(edit, view.size(), "\n") + + link_spans = [] + + for sel in view.sel(): + scope_name = view.scope_name(sel.b) + if not hasScope(scope_name, 'meta.link.inline.markdown'): + continue + start = findScopeFrom(view, sel.b, marker_begin_scope_name, backwards=True) + end = findScopeFrom(view, sel.b, 'punctuation.definition.metadata.markdown', char=')') + 1 + text = view.substr(sublime.Region(start, end)) + m = re.match(pattern, text) + if m is None: + continue + text = m.group(1) + link = m.group(2) + link_span = sublime.Region(start + m.span(2)[0] - 1, start + m.span(2)[1] + 1) + if is_url(link): + link = mangle_url(link) + if len(link) > 0: + if name is None: + # If link already exists, reuse existing reference + suggested_name = check_for_link(view, link) + if suggested_name is None: + is_image = view.substr(start - 1) == '!' if start > 0 else False + suggested_name = suggest_default_link_name(text, is_image) + + _name = name if name is not None else suggested_name + link_spans.append((link_span, _name, _name == text)) + + offset = 0 + for link_span in link_spans: + _link_span = sublime.Region(link_span[0].a + offset, link_span[0].b + offset) + offset -= convert2ref(view, edit, _link_span, link_span[1], link_span[2]) + + +class ConvertInlineLinksToReferencesCommand(MDETextCommand): + """Convert inline links to references.""" + + def run(self, edit): + """Run command callback.""" + view = self.view + pattern = r"(?<=\]\()(?!#)([^\)]+)(?=\))" + + _sel = [] + for sel in view.sel(): + _sel.append(sel) + view.sel().clear() + view.sel().add_all(view.find_all(pattern)) + view.run_command('convert_inline_link_to_reference') diff --git a/screenshots/arcdark.png b/screenshots/arcdark.png new file mode 100644 index 00000000..6a242e3a Binary files /dev/null and b/screenshots/arcdark.png differ diff --git a/tests/syntax_test_GFM.md b/tests/syntax_test_GFM.md index 79ca8c84..5676530c 100644 --- a/tests/syntax_test_GFM.md +++ b/tests/syntax_test_GFM.md @@ -1,4 +1,4 @@ -<!-- SYNTAX TEST "Packages/MarkdownEditing/Markdown.tmLanguage" --> +<!-- SYNTAX TEST "Packages/MarkdownEditing/Markdown.sublime-syntax" --> Inline styles =============