Align rendering with Matrix' CommonMark guidelines
This commit is contained in:
parent
86da6a7d56
commit
26fa98c359
2 changed files with 90 additions and 16 deletions
|
|
@ -273,8 +273,9 @@ func (c *MatrixChannel) Stop(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func markdownToHTML(md string) string {
|
func markdownToHTML(md string) string {
|
||||||
p := parser.NewWithExtensions(parser.CommonExtensions | parser.AutoHeadingIDs)
|
extensions := (parser.CommonExtensions | parser.NoEmptyLineBeforeBlock) &^ parser.DefinitionLists
|
||||||
renderer := mdhtml.NewRenderer(mdhtml.RendererOptions{Flags: mdhtml.CommonFlags})
|
p := parser.NewWithExtensions(extensions)
|
||||||
|
renderer := mdhtml.NewRenderer(mdhtml.RendererOptions{Flags: mdhtml.UseXHTML})
|
||||||
return strings.TrimSpace(string(markdown.ToHTML([]byte(md), p, renderer)))
|
return strings.TrimSpace(string(markdown.ToHTML([]byte(md), p, renderer)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -340,23 +340,96 @@ func TestMatrixOutboundContent(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMarkdownToHTML(t *testing.T) {
|
func TestMarkdownToHTML(t *testing.T) {
|
||||||
tests := []struct {
|
cases := []struct {
|
||||||
name string
|
name string
|
||||||
input string
|
md string
|
||||||
contains string
|
rendered string
|
||||||
}{
|
}{
|
||||||
{"bold", "**hello**", "<strong>hello</strong>"},
|
{
|
||||||
{"italic", "_world_", "<em>world</em>"},
|
name: "paragraph",
|
||||||
{"header", "### Title", "<h3"},
|
md: "just **some** text with _custom_ formatting and `inline` code",
|
||||||
{"code block", "```\nfoo()\n```", "<code>"},
|
rendered: "<p>just <strong>some</strong> text with <em>custom</em> formatting and <code>inline</code> code</p>",
|
||||||
{"inline code", "`x`", "<code>x</code>"},
|
},
|
||||||
{"plain text", "just text", "just text"},
|
{
|
||||||
|
name: "heading",
|
||||||
|
md: "### Title",
|
||||||
|
rendered: `<h3>Title</h3>`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fenced code block",
|
||||||
|
md: "```\nfoo()\n```",
|
||||||
|
rendered: "<pre><code>foo()\n</code></pre>",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "loose list",
|
||||||
|
md: "- Item one\n\n- Item two\n",
|
||||||
|
rendered: `<ul>
|
||||||
|
<li><p>Item one</p></li>
|
||||||
|
|
||||||
|
<li><p>Item two</p></li>
|
||||||
|
</ul>`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "tight list",
|
||||||
|
md: "- Alpha\n- Beta\n",
|
||||||
|
rendered: `<ul>
|
||||||
|
<li>Alpha</li>
|
||||||
|
<li>Beta</li>
|
||||||
|
</ul>`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "list item with nested sublist",
|
||||||
|
md: "1. Steps overview:\n\n - Step A\n - Step B\n",
|
||||||
|
rendered: `<ol>
|
||||||
|
<li><p>Steps overview:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Step A</li>
|
||||||
|
<li>Step B</li>
|
||||||
|
</ul></li>
|
||||||
|
</ol>`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Definition list syntax is not enabled; the term and definition are
|
||||||
|
// rendered as a plain paragraph rather than <dl>/<dt>/<dd> elements.
|
||||||
|
name: "definition list syntax renders as plain paragraph",
|
||||||
|
md: "Term\n: Definition of the term.\n",
|
||||||
|
rendered: "<p>Term\n: Definition of the term.</p>",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "comprehensive document with headings, paragraphs, list, and code block",
|
||||||
|
md: "# Overview\n\nThis is a sample document designed to demonstrate various Markdown elements in a single block of text.\n\nThe first paragraph introduces the concept of structured data.\n\n## Details\n\nThe following is a list:\n\n* First\n* Second\n* Third\n\nThe second paragraph focuses on details. Below is a generic code snippet:\n\n```python\ndef calculate_area(radius):\n import math\n return math.pi * (radius ** 2)\n```\n\nThis concludes the generic sample text.\n",
|
||||||
|
rendered: `<h1>Overview</h1>
|
||||||
|
|
||||||
|
<p>This is a sample document designed to demonstrate various Markdown elements in a single block of text.</p>
|
||||||
|
|
||||||
|
<p>The first paragraph introduces the concept of structured data.</p>
|
||||||
|
|
||||||
|
<h2>Details</h2>
|
||||||
|
|
||||||
|
<p>The following is a list:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>First</li>
|
||||||
|
<li>Second</li>
|
||||||
|
<li>Third</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>The second paragraph focuses on details. Below is a generic code snippet:</p>
|
||||||
|
|
||||||
|
<pre><code class="language-python">def calculate_area(radius):
|
||||||
|
import math
|
||||||
|
return math.pi * (radius ** 2)
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<p>This concludes the generic sample text.</p>`,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
for _, tc := range cases {
|
||||||
got := markdownToHTML(tt.input)
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
if !strings.Contains(got, tt.contains) {
|
if got := markdownToHTML(tc.md); got != tc.rendered {
|
||||||
t.Fatalf("markdownToHTML(%q) = %q, want it to contain %q", tt.input, got, tt.contains)
|
t.Fatalf("markdownToHTML(%q)\n got: %q\nwant: %q", tc.md, got, tc.rendered)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue