From a55616030664891c20ffae449728fc58aa757916 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Tue, 7 Mar 2023 09:00:45 -0800 Subject: [PATCH] validate markdown --- ci/release/changelogs/next.md | 1 + d2compiler/compile.go | 24 +++++++++++++++++-- d2compiler/compile_test.go | 20 ++++++++++++++++ .../TestCompile/unsemantic_markdown.exp.json | 12 ++++++++++ .../unsemantic_markdown_2.exp.json | 12 ++++++++++ 5 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 testdata/d2compiler/TestCompile/unsemantic_markdown.exp.json create mode 100644 testdata/d2compiler/TestCompile/unsemantic_markdown_2.exp.json diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md index d3ac356a3..256afb7d9 100644 --- a/ci/release/changelogs/next.md +++ b/ci/release/changelogs/next.md @@ -4,6 +4,7 @@ - ELK nodes with > 1 connection grow to ensure padding around ports [#981](https://github.com/terrastruct/d2/pull/981) - Using a style keyword incorrectly in connections returns clear error message [#989](https://github.com/terrastruct/d2/pull/989) +- Unsemantic Markdown returns clear error message [#994](https://github.com/terrastruct/d2/pull/994) #### Bugfixes ⛑️ diff --git a/d2compiler/compile.go b/d2compiler/compile.go index 6fa9106f3..729f2e46f 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -1,6 +1,7 @@ package d2compiler import ( + "encoding/xml" "fmt" "io" "net/url" @@ -15,6 +16,7 @@ import ( "oss.terrastruct.com/d2/d2ir" "oss.terrastruct.com/d2/d2parser" "oss.terrastruct.com/d2/d2target" + "oss.terrastruct.com/d2/lib/textmeasure" ) type CompileOptions struct { @@ -224,9 +226,27 @@ func (c *compiler) compileLabel(attrs *d2graph.Attributes, f d2ir.Node) { if ok { attrs.Language = fullTag } - if attrs.Language == "markdown" || attrs.Language == "latex" { + switch attrs.Language { + case "latex": attrs.Shape.Value = d2target.ShapeText - } else { + case "markdown": + rendered, err := textmeasure.RenderMarkdown(scalar.ScalarString()) + if err != nil { + c.errorf(f.LastPrimaryKey(), "malformed Markdown") + } + rendered = "
" + rendered + "
" + var xmlParsed interface{} + err = xml.Unmarshal([]byte(rendered), &xmlParsed) + if err != nil { + switch xmlErr := err.(type) { + case *xml.SyntaxError: + c.errorf(f.LastPrimaryKey(), "malformed Markdown: %s", xmlErr.Msg) + default: + c.errorf(f.LastPrimaryKey(), "malformed Markdown: %s", err.Error()) + } + } + attrs.Shape.Value = d2target.ShapeText + default: attrs.Shape.Value = d2target.ShapeCode } attrs.Label.Value = scalar.ScalarString() diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index 0444f00ae..e40083b34 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -869,6 +869,26 @@ b.(x -> y)[0]: two } }, }, + { + name: "unsemantic_markdown", + + text: `test:| +foobar +

+| +`, + expErr: `d2/testdata/d2compiler/TestCompile/unsemantic_markdown.d2:1:1: malformed Markdown: element

closed by `, + }, + { + name: "unsemantic_markdown_2", + + text: `test:| +foo
+bar +| +`, + expErr: `d2/testdata/d2compiler/TestCompile/unsemantic_markdown_2.d2:1:1: malformed Markdown: element
closed by

`, + }, { name: "edge_map", diff --git a/testdata/d2compiler/TestCompile/unsemantic_markdown.exp.json b/testdata/d2compiler/TestCompile/unsemantic_markdown.exp.json new file mode 100644 index 000000000..b0dbf4465 --- /dev/null +++ b/testdata/d2compiler/TestCompile/unsemantic_markdown.exp.json @@ -0,0 +1,12 @@ +{ + "graph": null, + "err": { + "ioerr": null, + "errs": [ + { + "range": "d2/testdata/d2compiler/TestCompile/unsemantic_markdown.d2,0:0:0-3:1:19", + "errmsg": "d2/testdata/d2compiler/TestCompile/unsemantic_markdown.d2:1:1: malformed Markdown: element

closed by " + } + ] + } +} diff --git a/testdata/d2compiler/TestCompile/unsemantic_markdown_2.exp.json b/testdata/d2compiler/TestCompile/unsemantic_markdown_2.exp.json new file mode 100644 index 000000000..adfb7f026 --- /dev/null +++ b/testdata/d2compiler/TestCompile/unsemantic_markdown_2.exp.json @@ -0,0 +1,12 @@ +{ + "graph": null, + "err": { + "ioerr": null, + "errs": [ + { + "range": "d2/testdata/d2compiler/TestCompile/unsemantic_markdown_2.d2,0:0:0-3:1:20", + "errmsg": "d2/testdata/d2compiler/TestCompile/unsemantic_markdown_2.d2:1:1: malformed Markdown: element
closed by

" + } + ] + } +}