diff --git a/Erlang.plist b/Erlang.plist
index de33086..00e40d6 100644
--- a/Erlang.plist
+++ b/Erlang.plist
@@ -621,13 +621,22 @@
name
meta.directive.doc.erlang
- contentName
- meta.embedded.block.markdown
patterns
- include
- text.html.markdown
+ begin
+ (\s*|$)
+ while
+ ^(?!\s*["]{3,})
+ contentName
+ meta.embedded.block.markdown
+ patterns
+
+
+ include
+ text.html.markdown
+
+
diff --git a/package.json b/package.json
index 518374f..99aa93e 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"scripts": {
- "test": "vscode-tmgrammar-test ./tests/*.erl && vscode-tmgrammar-snap ./tests/snap/*.erl"
+ "test": "vscode-tmgrammar-test -g ./tests/grammars/markdown.tmLanguage.json ./tests/*.erl && vscode-tmgrammar-snap -g ./tests/grammars/markdown.tmLanguage.json ./tests/snap/*.erl"
},
"contributes": {
"languages": [
@@ -27,4 +27,4 @@
"devDependencies": {
"vscode-tmgrammar-test": "^0.1.3"
}
-}
\ No newline at end of file
+}
diff --git a/tests/doc_markdown.erl b/tests/doc_markdown.erl
new file mode 100644
index 0000000..f948720
--- /dev/null
+++ b/tests/doc_markdown.erl
@@ -0,0 +1,21 @@
+% SYNTAX TEST "source.erlang" "doc attributes with malformed Markdown"
+-module(doc_markdown).
+
+%% An unclosed code fence in a doc attribute must not leak past the closing
+%% triple quotes and turn the rest of the module into Markdown.
+-doc """
+Unclosed code fence:
+```erlang
+%<--- source.erlang meta.directive.doc.erlang meta.embedded.block.markdown markup.fenced_code.block.markdown
+foo() -> ok.
+""".
+%<--- source.erlang meta.directive.doc.erlang comment.block.documentation.erlang punctuation.definition.string.end.erlang
+f() -> ok.
+%<- source.erlang meta.function.erlang entity.name.function.definition.erlang
+
+-moduledoc """
+~~~
+""".
+%<--- source.erlang meta.directive.doc.erlang comment.block.documentation.erlang punctuation.definition.string.end.erlang
+g() -> ok.
+%<- source.erlang meta.function.erlang entity.name.function.definition.erlang
diff --git a/tests/grammars/markdown.tmLanguage.json b/tests/grammars/markdown.tmLanguage.json
new file mode 100644
index 0000000..641e120
--- /dev/null
+++ b/tests/grammars/markdown.tmLanguage.json
@@ -0,0 +1,11 @@
+{
+ "comment": "Minimal stand-in for text.html.markdown, used only by the tests. Like the real Markdown grammar, it has a fenced code block rule that keeps consuming lines until the closing fence, which is enough to reproduce Markdown leaking out of doc attributes.",
+ "scopeName": "text.html.markdown",
+ "patterns": [
+ {
+ "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})",
+ "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
+ "name": "markup.fenced_code.block.markdown"
+ }
+ ]
+}
diff --git a/tests/snap/docstring.erl.snap b/tests/snap/docstring.erl.snap
index 8cff1d2..2d2a84e 100644
--- a/tests/snap/docstring.erl.snap
+++ b/tests/snap/docstring.erl.snap
@@ -6,15 +6,15 @@
# ^ source.erlang meta.directive.module.erlang punctuation.definition.parameters.end.erlang
# ^ source.erlang meta.directive.module.erlang punctuation.section.directive.end.erlang
>-moduledoc """
-#^ source.erlang meta.directive.erlang punctuation.section.directive.begin.erlang
-# ^^^^^^^^^ source.erlang meta.directive.erlang keyword.control.directive.erlang
-# ^ source.erlang meta.directive.erlang
-# ^^^ source.erlang meta.directive.erlang string.quoted.triple.erlang meta.string.quoted.triple.begin.erlang punctuation.definition.string.begin.erlang
+#^ source.erlang meta.directive.doc.erlang punctuation.section.directive.begin.erlang
+# ^^^^^^^^^ source.erlang meta.directive.doc.erlang keyword.control.directive.doc.erlang
+# ^ source.erlang meta.directive.doc.erlang
+# ^^^ source.erlang meta.directive.doc.erlang comment.block.documentation.erlang punctuation.definition.string.begin.erlang
>Triple quoted strings examples
-#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.erlang meta.directive.erlang string.quoted.triple.erlang
+#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.erlang meta.directive.doc.erlang meta.embedded.block.markdown
>""".
-#^^^ source.erlang meta.directive.erlang string.quoted.triple.erlang meta.string.quoted.triple.end.erlang punctuation.definition.string.end.erlang
-# ^ source.erlang meta.directive.erlang punctuation.section.directive.end.erlang
+#^^^ source.erlang meta.directive.doc.erlang comment.block.documentation.erlang punctuation.definition.string.end.erlang
+# ^ source.erlang meta.directive.doc.erlang
>
>-export([f1/0, f2/0, f3/0, f4/0, f5/0,
#^ source.erlang meta.directive.export.erlang punctuation.section.directive.begin.erlang
@@ -79,16 +79,16 @@
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.erlang comment.line.percentage.erlang
>
>-doc """
-#^ source.erlang meta.directive.erlang punctuation.section.directive.begin.erlang
-# ^^^ source.erlang meta.directive.erlang keyword.control.directive.erlang
-# ^ source.erlang meta.directive.erlang
-# ^^^ source.erlang meta.directive.erlang string.quoted.triple.erlang meta.string.quoted.triple.begin.erlang punctuation.definition.string.begin.erlang
+#^ source.erlang meta.directive.doc.erlang punctuation.section.directive.begin.erlang
+# ^^^ source.erlang meta.directive.doc.erlang keyword.control.directive.doc.erlang
+# ^ source.erlang meta.directive.doc.erlang
+# ^^^ source.erlang meta.directive.doc.erlang comment.block.documentation.erlang punctuation.definition.string.begin.erlang
> Docstring examples
-#^^^^^^^^^^^^^^^^^^^^^^^^ source.erlang meta.directive.erlang string.quoted.triple.erlang
+#^^^^^^^^^^^^^^^^^^^^^^^^ source.erlang meta.directive.doc.erlang meta.embedded.block.markdown
> """.
-#^^^^^ source.erlang meta.directive.erlang string.quoted.triple.erlang meta.string.quoted.triple.end.erlang
-# ^^^ source.erlang meta.directive.erlang string.quoted.triple.erlang meta.string.quoted.triple.end.erlang punctuation.definition.string.end.erlang
-# ^ source.erlang meta.directive.erlang punctuation.section.directive.end.erlang
+#^^^^^ source.erlang meta.directive.doc.erlang comment.block.documentation.erlang
+# ^^^ source.erlang meta.directive.doc.erlang comment.block.documentation.erlang punctuation.definition.string.end.erlang
+# ^ source.erlang meta.directive.doc.erlang
>f1() ->
#^^ source.erlang meta.function.erlang entity.name.function.definition.erlang
# ^ source.erlang meta.function.erlang meta.expression.parenthesized punctuation.section.expression.begin.erlang
@@ -252,19 +252,17 @@
# ^ source.erlang meta.function.erlang punctuation.terminator.function.erlang
>
>-doc ~s"""""
-#^ source.erlang meta.directive.erlang punctuation.section.directive.begin.erlang
-# ^^^ source.erlang meta.directive.erlang keyword.control.directive.erlang
-# ^ source.erlang meta.directive.erlang
-# ^^ source.erlang meta.directive.erlang string.quoted.tripple.sigil.erlang storage.type.string.erlang
-# ^^^^^ source.erlang meta.directive.erlang string.quoted.tripple.sigil.erlang meta.string.quoted.triple.begin.erlang punctuation.definition.string.begin.erlang
+#^ source.erlang meta.directive.doc.erlang punctuation.section.directive.begin.erlang
+# ^^^ source.erlang meta.directive.doc.erlang keyword.control.directive.doc.erlang
+# ^ source.erlang meta.directive.doc.erlang
+# ^^ source.erlang meta.directive.doc.erlang storage.type.string.erlang
+# ^^^^^ source.erlang meta.directive.doc.erlang comment.block.documentation.erlang punctuation.definition.string.begin.erlang
> Hello\n
-#^^^^^^^^^^^ source.erlang meta.directive.erlang string.quoted.tripple.sigil.erlang
-# ^ source.erlang meta.directive.erlang string.quoted.tripple.sigil.erlang constant.character.escape.erlang punctuation.definition.escape.erlang
-# ^ source.erlang meta.directive.erlang string.quoted.tripple.sigil.erlang constant.character.escape.erlang
+#^^^^^^^^^^^^^^ source.erlang meta.directive.doc.erlang meta.embedded.block.markdown
> """"".
-#^^^^^^ source.erlang meta.directive.erlang string.quoted.tripple.sigil.erlang meta.string.quoted.triple.end.erlang
-# ^^^^^ source.erlang meta.directive.erlang string.quoted.tripple.sigil.erlang meta.string.quoted.triple.end.erlang punctuation.definition.string.end.erlang
-# ^ source.erlang meta.directive.erlang punctuation.section.directive.end.erlang
+#^^^^^^ source.erlang meta.directive.doc.erlang comment.block.documentation.erlang
+# ^^^^^ source.erlang meta.directive.doc.erlang comment.block.documentation.erlang punctuation.definition.string.end.erlang
+# ^ source.erlang meta.directive.doc.erlang
>f2() -> ok.
#^^ source.erlang meta.function.erlang entity.name.function.definition.erlang
# ^ source.erlang meta.function.erlang meta.expression.parenthesized punctuation.section.expression.begin.erlang
@@ -349,17 +347,17 @@
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.erlang comment.line.percentage.erlang
>
>-doc("""
-#^ source.erlang meta.directive.erlang punctuation.section.directive.begin.erlang
-# ^^^ source.erlang meta.directive.erlang keyword.control.directive.erlang
-# ^ source.erlang meta.directive.erlang punctuation.definition.parameters.begin.erlang
-# ^^^ source.erlang meta.directive.erlang string.quoted.triple.erlang meta.string.quoted.triple.begin.erlang punctuation.definition.string.begin.erlang
+#^ source.erlang meta.directive.doc.erlang punctuation.section.directive.begin.erlang
+# ^^^ source.erlang meta.directive.doc.erlang keyword.control.directive.doc.erlang
+# ^ source.erlang meta.directive.doc.erlang punctuation.definition.parameters.begin.erlang
+# ^^^ source.erlang meta.directive.doc.erlang comment.block.documentation.erlang punctuation.definition.string.begin.erlang
> Hello\n
-#^^^^^^^^^^^^^ source.erlang meta.directive.erlang string.quoted.triple.erlang
+#^^^^^^^^^^^^^ source.erlang meta.directive.doc.erlang meta.embedded.block.markdown
> """).
-#^^^^^ source.erlang meta.directive.erlang string.quoted.triple.erlang meta.string.quoted.triple.end.erlang
-# ^^^ source.erlang meta.directive.erlang string.quoted.triple.erlang meta.string.quoted.triple.end.erlang punctuation.definition.string.end.erlang
-# ^ source.erlang meta.directive.erlang punctuation.definition.parameters.end.erlang
-# ^ source.erlang meta.directive.erlang punctuation.section.directive.end.erlang
+#^^^^^ source.erlang meta.directive.doc.erlang comment.block.documentation.erlang
+# ^^^ source.erlang meta.directive.doc.erlang comment.block.documentation.erlang punctuation.definition.string.end.erlang
+# ^ source.erlang meta.directive.doc.erlang punctuation.section.directive.end.Erlang
+# ^ source.erlang meta.directive.doc.erlang
>g1() -> ok.
#^^ source.erlang meta.function.erlang entity.name.function.definition.erlang
# ^ source.erlang meta.function.erlang meta.expression.parenthesized punctuation.section.expression.begin.erlang
@@ -372,18 +370,18 @@
# ^ source.erlang meta.function.erlang punctuation.terminator.function.erlang
>
>-doc(~B"""""
-#^ source.erlang meta.directive.erlang punctuation.section.directive.begin.erlang
-# ^^^ source.erlang meta.directive.erlang keyword.control.directive.erlang
-# ^ source.erlang meta.directive.erlang punctuation.definition.parameters.begin.erlang
-# ^^ source.erlang meta.directive.erlang string.quoted.tripple.sigil.erlang storage.type.string.erlang
-# ^^^^^ source.erlang meta.directive.erlang string.quoted.tripple.sigil.erlang meta.string.quoted.triple.begin.erlang punctuation.definition.string.begin.erlang
+#^ source.erlang meta.directive.doc.erlang punctuation.section.directive.begin.erlang
+# ^^^ source.erlang meta.directive.doc.erlang keyword.control.directive.doc.erlang
+# ^ source.erlang meta.directive.doc.erlang punctuation.definition.parameters.begin.erlang
+# ^^ source.erlang meta.directive.doc.erlang storage.type.string.erlang
+# ^^^^^ source.erlang meta.directive.doc.erlang comment.block.documentation.erlang punctuation.definition.string.begin.erlang
> Hello\n
-#^^^^^^^^^^^^^^ source.erlang meta.directive.erlang string.quoted.tripple.sigil.erlang
+#^^^^^^^^^^^^^^ source.erlang meta.directive.doc.erlang meta.embedded.block.markdown
> """"").
-#^^^^^^ source.erlang meta.directive.erlang string.quoted.tripple.sigil.erlang meta.string.quoted.triple.end.erlang
-# ^^^^^ source.erlang meta.directive.erlang string.quoted.tripple.sigil.erlang meta.string.quoted.triple.end.erlang punctuation.definition.string.end.erlang
-# ^ source.erlang meta.directive.erlang punctuation.definition.parameters.end.erlang
-# ^ source.erlang meta.directive.erlang punctuation.section.directive.end.erlang
+#^^^^^^ source.erlang meta.directive.doc.erlang comment.block.documentation.erlang
+# ^^^^^ source.erlang meta.directive.doc.erlang comment.block.documentation.erlang punctuation.definition.string.end.erlang
+# ^ source.erlang meta.directive.doc.erlang punctuation.section.directive.end.Erlang
+# ^ source.erlang meta.directive.doc.erlang
>g2() -> ok.
#^^ source.erlang meta.function.erlang entity.name.function.definition.erlang
# ^ source.erlang meta.function.erlang meta.expression.parenthesized punctuation.section.expression.begin.erlang
diff --git a/tests/snap/sigil.erl.snap b/tests/snap/sigil.erl.snap
index 5155f86..266a4bf 100644
--- a/tests/snap/sigil.erl.snap
+++ b/tests/snap/sigil.erl.snap
@@ -24,16 +24,16 @@
# ^ source.erlang meta.directive.export.erlang punctuation.section.directive.end.erlang
>
>-doc """
-#^ source.erlang meta.directive.erlang punctuation.section.directive.begin.erlang
-# ^^^ source.erlang meta.directive.erlang keyword.control.directive.erlang
-# ^ source.erlang meta.directive.erlang
-# ^^^ source.erlang meta.directive.erlang string.quoted.triple.erlang meta.string.quoted.triple.begin.erlang punctuation.definition.string.begin.erlang
+#^ source.erlang meta.directive.doc.erlang punctuation.section.directive.begin.erlang
+# ^^^ source.erlang meta.directive.doc.erlang keyword.control.directive.doc.erlang
+# ^ source.erlang meta.directive.doc.erlang
+# ^^^ source.erlang meta.directive.doc.erlang comment.block.documentation.erlang punctuation.definition.string.begin.erlang
> Sigil examples
-#^^^^^^^^^^^^^^^^^^^^ source.erlang meta.directive.erlang string.quoted.triple.erlang
+#^^^^^^^^^^^^^^^^^^^^ source.erlang meta.directive.doc.erlang meta.embedded.block.markdown
> """.
-#^^^^^ source.erlang meta.directive.erlang string.quoted.triple.erlang meta.string.quoted.triple.end.erlang
-# ^^^ source.erlang meta.directive.erlang string.quoted.triple.erlang meta.string.quoted.triple.end.erlang punctuation.definition.string.end.erlang
-# ^ source.erlang meta.directive.erlang punctuation.section.directive.end.erlang
+#^^^^^ source.erlang meta.directive.doc.erlang comment.block.documentation.erlang
+# ^^^ source.erlang meta.directive.doc.erlang comment.block.documentation.erlang punctuation.definition.string.end.erlang
+# ^ source.erlang meta.directive.doc.erlang
>-spec f() -> ok.
#^ source.erlang meta.directive.erlang meta.type.erlang punctuation.section.directive.begin.erlang
# ^^^^ source.erlang meta.directive.erlang meta.type.erlang keyword.control.directive.erlang