From c87f53858b9ee7586e005c321fa2c46a8957f59a Mon Sep 17 00:00:00 2001 From: Josh Goebel Date: Tue, 12 Nov 2019 02:27:34 -0500 Subject: [PATCH] enh(elixir) improve heredoc and sigil support (#2257) --- src/languages/elixir.js | 66 ++++++++++++++++++- test/markup/elixir/sigils.expect.txt | 23 +++++++ test/markup/elixir/sigils.txt | 23 +++++++ test/markup/elixir/strings.expect.txt | 4 ++ test/markup/elixir/strings.txt | 4 ++ .../elixir/uppercase-string-sigil.expect.txt | 17 +++++ test/markup/elixir/uppercase-string-sigil.txt | 17 +++++ 7 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 test/markup/elixir/sigils.expect.txt create mode 100644 test/markup/elixir/sigils.txt create mode 100644 test/markup/elixir/strings.expect.txt create mode 100644 test/markup/elixir/strings.txt create mode 100644 test/markup/elixir/uppercase-string-sigil.expect.txt create mode 100644 test/markup/elixir/uppercase-string-sigil.txt diff --git a/src/languages/elixir.js b/src/languages/elixir.js index 6cdb91cee6..d96f143ddb 100644 --- a/src/languages/elixir.js +++ b/src/languages/elixir.js @@ -19,16 +19,78 @@ function(hljs) { lexemes: ELIXIR_IDENT_RE, keywords: ELIXIR_KEYWORDS }; + + var SIGIL_DELIMITERS = '[/|([{<"\']' + var LOWERCASE_SIGIL = { + className: 'string', + begin: '~[a-z]' + '(?=' + SIGIL_DELIMITERS + ')', + contains: [ + { + endsParent:true, + contains: [{ + contains: [hljs.BACKSLASH_ESCAPE, SUBST], + variants: [ + { begin: /"/, end: /"/ }, + { begin: /'/, end: /'/ }, + { begin: /\//, end: /\// }, + { begin: /\|/, end: /\|/ }, + { begin: /\(/, end: /\)/ }, + { begin: /\[/, end: /\]/ }, + { begin: /\{/, end: /\}/ }, + { begin: // } + ] + }] + }, + ], + }; + + var UPCASE_SIGIL = { + className: 'string', + begin: '~[A-Z]' + '(?=' + SIGIL_DELIMITERS + ')', + contains: [ + { begin: /"/, end: /"/ }, + { begin: /'/, end: /'/ }, + { begin: /\//, end: /\// }, + { begin: /\|/, end: /\|/ }, + { begin: /\(/, end: /\)/ }, + { begin: /\[/, end: /\]/ }, + { begin: /\{/, end: /\}/ }, + { begin: /\/ } + ] + }; + var STRING = { className: 'string', contains: [hljs.BACKSLASH_ESCAPE, SUBST], variants: [ + { + begin: /"""/, end: /"""/, + }, + { + begin: /'''/, end: /'''/, + }, + { + begin: /~S"""/, end: /"""/, + contains: [] + }, + { + begin: /~S"/, end: /"/, + contains: [] + }, + { + begin: /~S'''/, end: /'''/, + contains: [] + }, + { + begin: /~S'/, end: /'/, + contains: [] + }, { begin: /'/, end: /'/ }, { begin: /"/, end: /"/ - } + }, ] }; var FUNCTION = { @@ -47,6 +109,8 @@ function(hljs) { }); var ELIXIR_DEFAULT_CONTAINS = [ STRING, + UPCASE_SIGIL, + LOWERCASE_SIGIL, hljs.HASH_COMMENT_MODE, CLASS, FUNCTION, diff --git a/test/markup/elixir/sigils.expect.txt b/test/markup/elixir/sigils.expect.txt new file mode 100644 index 0000000000..3dc0c47266 --- /dev/null +++ b/test/markup/elixir/sigils.expect.txt @@ -0,0 +1,23 @@ +~R'this + i\s "a" regex too' +~w(hello #{ ["has" <> "123", '\c\d', "\123 interpol" | []] } world)s +~W(hello #{no "123" \c\d \123 interpol} world)s +~s{Escapes terminators \{ and \}, but no {balancing} # outside of sigil here } +~S"No escapes \s\t\n and no #{interpolation}" + +~S/hello/ +~S|hello| +~S"hello" +~S'hello' +~S(hello) +~S[hello] +~S{hello} +~S<hello> + +~s/hello #{name}/ +~s|hello #{name}| +~s"hello #{name}" +~s'hello #{name}' +~s(hello #{name}) +~s[hello #{name}] +~s{hello #{name}} +~s<hello #{name}> diff --git a/test/markup/elixir/sigils.txt b/test/markup/elixir/sigils.txt new file mode 100644 index 0000000000..7547ecd377 --- /dev/null +++ b/test/markup/elixir/sigils.txt @@ -0,0 +1,23 @@ +~R'this + i\s "a" regex too' +~w(hello #{ ["has" <> "123", '\c\d', "\123 interpol" | []] } world)s +~W(hello #{no "123" \c\d \123 interpol} world)s +~s{Escapes terminators \{ and \}, but no {balancing} # outside of sigil here } +~S"No escapes \s\t\n and no #{interpolation}" + +~S/hello/ +~S|hello| +~S"hello" +~S'hello' +~S(hello) +~S[hello] +~S{hello} +~S + +~s/hello #{name}/ +~s|hello #{name}| +~s"hello #{name}" +~s'hello #{name}' +~s(hello #{name}) +~s[hello #{name}] +~s{hello #{name}} +~s diff --git a/test/markup/elixir/strings.expect.txt b/test/markup/elixir/strings.expect.txt new file mode 100644 index 0000000000..4a8d486358 --- /dev/null +++ b/test/markup/elixir/strings.expect.txt @@ -0,0 +1,4 @@ +a = """test""" +b = '''test''' +c = "test" +d = 'test' diff --git a/test/markup/elixir/strings.txt b/test/markup/elixir/strings.txt new file mode 100644 index 0000000000..4c7c8fb4dc --- /dev/null +++ b/test/markup/elixir/strings.txt @@ -0,0 +1,4 @@ +a = """test""" +b = '''test''' +c = "test" +d = 'test' diff --git a/test/markup/elixir/uppercase-string-sigil.expect.txt b/test/markup/elixir/uppercase-string-sigil.expect.txt new file mode 100644 index 0000000000..44d07293d2 --- /dev/null +++ b/test/markup/elixir/uppercase-string-sigil.expect.txt @@ -0,0 +1,17 @@ +defmodule Long.Module.Name do + @doc ~S''' + No #{interpolation} of any kind. + \000 \x{ff} + + \n #{\x{ff}} + ''' + def func(a, b \\ []), do: :ok + + @doc ~S""" + No #{interpolation} of any kind. + \000 \x{ff} + + \n #{\x{ff}} + """ + def func(a, b \\ []), do: :ok +end diff --git a/test/markup/elixir/uppercase-string-sigil.txt b/test/markup/elixir/uppercase-string-sigil.txt new file mode 100644 index 0000000000..99731d8194 --- /dev/null +++ b/test/markup/elixir/uppercase-string-sigil.txt @@ -0,0 +1,17 @@ +defmodule Long.Module.Name do + @doc ~S''' + No #{interpolation} of any kind. + \000 \x{ff} + + \n #{\x{ff}} + ''' + def func(a, b \\ []), do: :ok + + @doc ~S""" + No #{interpolation} of any kind. + \000 \x{ff} + + \n #{\x{ff}} + """ + def func(a, b \\ []), do: :ok +end