diff --git a/components/prism-elixir.js b/components/prism-elixir.js index cfad1c8841..868e1fc732 100644 --- a/components/prism-elixir.js +++ b/components/prism-elixir.js @@ -1,5 +1,15 @@ Prism.languages.elixir = { - 'comment': /#.*/m, + 'doc': { + pattern: /@(?:doc|moduledoc)\s+(?:("""|''')[\s\S]*?\1|("|')(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2)/, + inside: { + 'attribute': /^@\w+/, + 'string': /['"][\s\S]+/ + } + }, + 'comment': { + pattern: /#.*/m, + greedy: true + }, // ~r"""foo""" (multi-line), ~r'''foo''' (multi-line), ~r/foo/, ~r|foo|, ~r"foo", ~r'foo', ~r(foo), ~r[foo], ~r{foo}, ~r 'regex': { pattern: /~[rR](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|[^\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[uismxfr]*/, @@ -36,14 +46,12 @@ Prism.languages.elixir = { lookbehind: true, alias: 'symbol' }, + 'module': { + pattern: /\b[A-Z]\w*\b/, + alias: 'class-name' + }, // Look-ahead prevents bad highlighting of the :: operator 'attr-name': /\w+\??:(?!:)/, - 'capture': { - // Look-behind prevents bad highlighting of the && operator - pattern: /(^|[^&])&(?:[^&\s\d()][^\s()]*|(?=\())/, - lookbehind: true, - alias: 'function' - }, 'argument': { // Look-behind prevents bad highlighting of the && operator pattern: /(^|[^&])&\d+/, @@ -54,8 +62,9 @@ Prism.languages.elixir = { pattern: /@\w+/, alias: 'variable' }, + 'function': /\b[_a-zA-Z]\w*[?!]?(?:(?=\s*(?:\.\s*)?\()|(?=\/\d+))/, 'number': /\b(?:0[box][a-f\d_]+|\d[\d_]*)(?:\.[\d_]+)?(?:e[+-]?[\d_]+)?\b/i, - 'keyword': /\b(?:after|alias|and|case|catch|cond|def(?:callback|exception|impl|module|p|protocol|struct|delegate)?|do|else|end|fn|for|if|import|not|or|require|rescue|try|unless|use|when)\b/, + 'keyword': /\b(?:after|alias|and|case|catch|cond|def(?:callback|exception|impl|module|p|protocol|struct|delegate)?|do|else|end|fn|for|if|import|not|or|raise|require|rescue|try|unless|use|when)\b/, 'boolean': /\b(?:true|false|nil)\b/, 'operator': [ /\bin\b|&&?|\|[|>]?|\\\\|::|\.\.\.?|\+\+?|-[->]?|<[-=>]|>=|!==?|\B!|=(?:==?|[>~])?|[*\/^]/, @@ -73,18 +82,6 @@ Prism.languages.elixir = { 'punctuation': /<<|>>|[.,%\[\]{}()]/ }; -Prism.languages.insertBefore('elixir', 'keyword', { - 'module': { - pattern: /\b(defmodule\s)[A-Z][\w.\\]+/, - lookbehind: true, - alias: 'class-name' - }, - 'function': { - pattern: /\b(defp?\s)[\w.\\]+/, - lookbehind: true - } -}); - Prism.languages.elixir.string.forEach(function(o) { o.inside = { 'interpolation': { diff --git a/components/prism-elixir.min.js b/components/prism-elixir.min.js index ee6542e41f..83f6871ed9 100644 --- a/components/prism-elixir.min.js +++ b/components/prism-elixir.min.js @@ -1 +1 @@ -Prism.languages.elixir={comment:/#.*/m,regex:{pattern:/~[rR](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|[^\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[uismxfr]*/,greedy:!0},string:[{pattern:/~[cCsSwW](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|#\{[^}]+\}|#(?!\{)|[^#\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[csa]?/,greedy:!0,inside:{}},{pattern:/("""|''')[\s\S]*?\1/,greedy:!0,inside:{}},{pattern:/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0,inside:{}}],atom:{pattern:/(^|[^:]):\w+/,lookbehind:!0,alias:"symbol"},"attr-name":/\w+\??:(?!:)/,capture:{pattern:/(^|[^&])&(?:[^&\s\d()][^\s()]*|(?=\())/,lookbehind:!0,alias:"function"},argument:{pattern:/(^|[^&])&\d+/,lookbehind:!0,alias:"variable"},attribute:{pattern:/@\w+/,alias:"variable"},number:/\b(?:0[box][a-f\d_]+|\d[\d_]*)(?:\.[\d_]+)?(?:e[+-]?[\d_]+)?\b/i,keyword:/\b(?:after|alias|and|case|catch|cond|def(?:callback|exception|impl|module|p|protocol|struct|delegate)?|do|else|end|fn|for|if|import|not|or|require|rescue|try|unless|use|when)\b/,boolean:/\b(?:true|false|nil)\b/,operator:[/\bin\b|&&?|\|[|>]?|\\\\|::|\.\.\.?|\+\+?|-[->]?|<[-=>]|>=|!==?|\B!|=(?:==?|[>~])?|[*\/^]/,{pattern:/([^<])<(?!<)/,lookbehind:!0},{pattern:/([^>])>(?!>)/,lookbehind:!0}],punctuation:/<<|>>|[.,%\[\]{}()]/},Prism.languages.insertBefore("elixir","keyword",{module:{pattern:/\b(defmodule\s)[A-Z][\w.\\]+/,lookbehind:!0,alias:"class-name"},function:{pattern:/\b(defp?\s)[\w.\\]+/,lookbehind:!0}}),Prism.languages.elixir.string.forEach(function(e){e.inside={interpolation:{pattern:/#\{[^}]+\}/,inside:{delimiter:{pattern:/^#\{|\}$/,alias:"punctuation"},rest:Prism.languages.elixir}}}}); \ No newline at end of file +Prism.languages.elixir={doc:{pattern:/@(?:doc|moduledoc)\s+(?:("""|''')[\s\S]*?\1|("|')(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2)/,inside:{attribute:/^@\w+/,string:/['"][\s\S]+/}},comment:{pattern:/#.*/m,greedy:!0},regex:{pattern:/~[rR](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|[^\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[uismxfr]*/,greedy:!0},string:[{pattern:/~[cCsSwW](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|#\{[^}]+\}|#(?!\{)|[^#\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[csa]?/,greedy:!0,inside:{}},{pattern:/("""|''')[\s\S]*?\1/,greedy:!0,inside:{}},{pattern:/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0,inside:{}}],atom:{pattern:/(^|[^:]):\w+/,lookbehind:!0,alias:"symbol"},module:{pattern:/\b[A-Z]\w*\b/,alias:"class-name"},"attr-name":/\w+\??:(?!:)/,argument:{pattern:/(^|[^&])&\d+/,lookbehind:!0,alias:"variable"},attribute:{pattern:/@\w+/,alias:"variable"},function:/\b[_a-zA-Z]\w*[?!]?(?:(?=\s*(?:\.\s*)?\()|(?=\/\d+))/,number:/\b(?:0[box][a-f\d_]+|\d[\d_]*)(?:\.[\d_]+)?(?:e[+-]?[\d_]+)?\b/i,keyword:/\b(?:after|alias|and|case|catch|cond|def(?:callback|exception|impl|module|p|protocol|struct|delegate)?|do|else|end|fn|for|if|import|not|or|raise|require|rescue|try|unless|use|when)\b/,boolean:/\b(?:true|false|nil)\b/,operator:[/\bin\b|&&?|\|[|>]?|\\\\|::|\.\.\.?|\+\+?|-[->]?|<[-=>]|>=|!==?|\B!|=(?:==?|[>~])?|[*\/^]/,{pattern:/([^<])<(?!<)/,lookbehind:!0},{pattern:/([^>])>(?!>)/,lookbehind:!0}],punctuation:/<<|>>|[.,%\[\]{}()]/},Prism.languages.elixir.string.forEach(function(e){e.inside={interpolation:{pattern:/#\{[^}]+\}/,inside:{delimiter:{pattern:/^#\{|\}$/,alias:"punctuation"},rest:Prism.languages.elixir}}}}); \ No newline at end of file diff --git a/tests/languages/elixir/attribute_feature.test b/tests/languages/elixir/attribute_feature.test index 273c2a402f..52c0bc1c6d 100644 --- a/tests/languages/elixir/attribute_feature.test +++ b/tests/languages/elixir/attribute_feature.test @@ -8,12 +8,10 @@ foobar [ ["attribute", "@vsn"], ["number", "2"], - ["attribute", "@moduledoc"], ["string", [ - "\"\"\"\r\nfoobar\r\n\"\"\"" - ]], + ["doc", [ ["attribute", "@moduledoc" ], [ "string", "\"\"\"\r\nfoobar\r\n\"\"\"" ] ] ], ["attribute", "@tag"], ["atom", ":external"] ] ---------------------------------------------------- -Checks for module attributes. \ No newline at end of file +Checks for module attributes. diff --git a/tests/languages/elixir/capture_feature.test b/tests/languages/elixir/capture_feature.test index 8a64b66154..caa9473be9 100644 --- a/tests/languages/elixir/capture_feature.test +++ b/tests/languages/elixir/capture_feature.test @@ -1,28 +1,56 @@ +&Math.zero?(0) fun = &Math.zero?/1 (&is_function/1).(fun) fun = &(&1 + 1) &List.flatten(&1, &2) +fun = &Math.zero?/invalid + ---------------------------------------------------- [ - "fun ", ["operator", "="], - ["capture", "&Math.zero?/1"], + ["operator", "&"], + ["module", "Math"], + ["punctuation", "."], + ["function", "zero?" ], ["punctuation", "("], - ["capture", "&is_function/1"], + ["number", "0"], + ["punctuation", ")"], + "\r\nfun ", ["operator", "="], + ["operator", "&"], + ["module", "Math"], + ["punctuation", "."], + ["function", "zero?" ], + ["operator", "/"], + ["number", "1"], + ["punctuation", "("], + ["operator", "&"], + ["function", "is_function"], + ["operator", "/"], + ["number", "1"], ["punctuation", ")"], ["punctuation", "."], ["punctuation", "("], "fun", ["punctuation", ")"], "\r\nfun ", ["operator", "="], - ["capture", "&"], + ["operator", "&"], ["punctuation", "("], ["argument", "&1"], ["operator", "+"], ["number", "1"], ["punctuation", ")"], - ["capture", "&List.flatten"], + ["operator", "&"], + ["module", "List"], + ["punctuation", "."], ["function", "flatten"], ["punctuation", "("], ["argument", "&1"], ["punctuation", ","], ["argument", "&2"], - ["punctuation", ")"] + ["punctuation", ")"], + "\r\n\r\nfun ", + [ "operator", "=" ], + [ "operator", "&" ], + [ "module", "Math" ], + [ "punctuation", "." ], + "zero?", + [ "operator", "/" ], + "invalid" ] ---------------------------------------------------- -Checks for function capturing and arguments. \ No newline at end of file +Checks for function capturing and arguments. diff --git a/tests/languages/elixir/doc_feature.test b/tests/languages/elixir/doc_feature.test new file mode 100644 index 0000000000..27e8ceadbb --- /dev/null +++ b/tests/languages/elixir/doc_feature.test @@ -0,0 +1,56 @@ +@doc "single" +@doc 'single' +@doc """triple""" +@doc '''triple''' +@doc ''' +multiline +''' +@doc """ +multiline +""" +@doc since: "1.3.0" +@doc deprecated: "phased out" + +@moduledoc "single" +@moduledoc 'single' +@moduledoc """triple""" +@moduledoc '''triple''' +@moduledoc ''' +multiline +''' +@moduledoc """ +multiline +""" +@moduledoc since: "1.3.0" +@moduledoc deprecated: "phased out" + +---------------------------------------------------- + +[ + [ "doc", [ [ "attribute", "@doc" ], [ "string", "\"single\"" ] ] ], + [ "doc", [ [ "attribute", "@doc" ], [ "string", "'single'" ] ] ], + [ "doc", [ [ "attribute", "@doc" ], [ "string", "\"\"\"triple\"\"\"" ] ] ], + [ "doc", [ [ "attribute", "@doc" ], [ "string", "'''triple'''" ] ] ], + [ "doc", [ [ "attribute", "@doc" ], [ "string", "'''\nmultiline\n'''" ] ] ], + [ "doc", [ [ "attribute", "@doc" ], [ "string", "\"\"\"\nmultiline\n\"\"\"" ] ] ], + [ "attribute", "@doc" ], + [ "attr-name", "since:" ], + [ "string", [ "\"1.3.0\"" ] ], + [ "attribute", "@doc" ], + [ "attr-name", "deprecated:" ], + [ "string", [ "\"phased out\"" ] ], + [ "doc", [ [ "attribute", "@moduledoc" ], [ "string", "\"single\"" ] ] ], + [ "doc", [ [ "attribute", "@moduledoc" ], [ "string", "'single'" ] ] ], + [ "doc", [ [ "attribute", "@moduledoc" ], [ "string", "\"\"\"triple\"\"\"" ] ] ], + [ "doc", [ [ "attribute", "@moduledoc" ], [ "string", "'''triple'''" ] ] ], + [ "doc", [ [ "attribute", "@moduledoc" ], [ "string", "'''\nmultiline\n'''" ] ] ], + [ "doc", [ [ "attribute", "@moduledoc" ], [ "string", "\"\"\"\nmultiline\n\"\"\"" ] ] ], + [ "attribute", "@moduledoc" ], + [ "attr-name", "since:" ], + [ "string", [ "\"1.3.0\"" ] ], + [ "attribute", "@moduledoc" ], + [ "attr-name", "deprecated:" ], + [ "string", [ "\"phased out\"" ] ] +] + +---------------------------------------------------- diff --git a/tests/languages/elixir/issue1392.test b/tests/languages/elixir/issue1392.test index c7d20a8366..1c0c93b3aa 100644 --- a/tests/languages/elixir/issue1392.test +++ b/tests/languages/elixir/issue1392.test @@ -3,9 +3,9 @@ String.upcase(@fixed) ---------------------------------------------------- [ - "String", + ["module", "String"], ["punctuation", "."], - "upcase", + ["function", "upcase"], ["punctuation", "("], ["attribute", "@fixed"], ["punctuation", ")"] @@ -13,4 +13,4 @@ String.upcase(@fixed) ---------------------------------------------------- -Ensure module attributes don't consume punctuation. \ No newline at end of file +Ensure module attributes don't consume punctuation. diff --git a/tests/languages/elixir/issue775.test b/tests/languages/elixir/issue775.test index d3243f80a8..9804bba6d9 100644 --- a/tests/languages/elixir/issue775.test +++ b/tests/languages/elixir/issue775.test @@ -5,13 +5,16 @@ ---------------------------------------------------- [ - ["attribute", "@doc"], - ["string", [ - "\"\"\"\r\n## Parameters\r\n\"\"\"" - ]] + [ + "doc", + [ + [ "attribute", "@doc" ], + [ "string", "\"\"\"\r\n## Parameters\r\n\"\"\"" ] + ] + ] ] ---------------------------------------------------- Ensures that markdown headers are not highlighted as comments inside strings. -See #775 for details. \ No newline at end of file +See #775 for details. diff --git a/tests/languages/elixir/keyword_feature.test b/tests/languages/elixir/keyword_feature.test index 6a851f1b24..c4f56fed67 100644 --- a/tests/languages/elixir/keyword_feature.test +++ b/tests/languages/elixir/keyword_feature.test @@ -9,7 +9,7 @@ defdelegate defstruct do else end fn for if import not or -require rescue try +raise require rescue try unless use when ---------------------------------------------------- @@ -26,7 +26,7 @@ unless use when ["keyword", "defstruct"], ["keyword", "do"], ["keyword", "else"], ["keyword", "end"], ["keyword", "fn"], ["keyword", "for"], ["keyword", "if"], ["keyword", "import"], ["keyword", "not"], ["keyword", "or"], - ["keyword", "require"], ["keyword", "rescue"], ["keyword", "try"], + ["keyword", "raise"], ["keyword", "require"], ["keyword", "rescue"], ["keyword", "try"], ["keyword", "unless"], ["keyword", "use"], ["keyword", "when"] ]