"))
}
@Test
func markdownBlockquote() {
let html = markdownToHTML("> This is a quote")
#expect(html.contains("
"))
}
@Test
func markdownTable() {
let input = "| A | B |\n|---|---|\n| 1 | 2 |"
let html = markdownToHTML(input)
#expect(html.contains("
"))
#expect(html.contains("
"))
}
@Test
func markdownTableAlignment() {
let input = "| Left | Center | Right |\n|:-----|:------:|------:|\n| a | b | c |"
let html = markdownToHTML(input)
#expect(html.contains("text-align: left;"))
#expect(html.contains("text-align: center;"))
#expect(html.contains("text-align: right;"))
}
@Test
func markdownStrikethrough() {
let html = markdownToHTML("~~deleted~~")
#expect(html.contains(""))
}
@Test
func markdownDeepHeadings() {
let html = markdownToHTML("#### Level 4")
#expect(html.contains("
"))
}
@Test
func markdownHardWrapNormalization() {
let html = markdownToHTML("line one\nline two")
#expect(!html.contains("line one\nline two"))
#expect(html.contains("line one"))
#expect(html.contains("line two"))
}
@Test
func markdownSoftBreakIsSpace() {
let html = markdownToHTML("word one\nword two")
#expect(html.contains("word one word two") || (html.contains("word one") && html.contains("word two")))
#expect(!html.contains(" "))
}
@Test
func markdownUnsafeLinkDropped() {
let html = markdownToHTML("[click](javascript:alert(1))")
#expect(!html.contains("href="))
#expect(!html.contains("javascript:"))
}
@Test
func markdownRelativeLinkWithoutResolverDropped() {
let html = markdownToHTML("[LICENSE](LICENSE)")
#expect(!html.contains("href="))
#expect(html.contains("LICENSE"))
}
@Test
func markdownRelativeLinkWithResolverRendersAnchor() {
let html = markdownToHTML(
"[LICENSE](LICENSE)",
linkURLResolver: { source in
source == "LICENSE" ? "https://git.sr.ht/~ccleberg/Hutch/blob/HEAD/LICENSE" : nil
}
)
#expect(html.contains(#"href="https://git.sr.ht/~ccleberg/Hutch/blob/HEAD/LICENSE""#))
#expect(html.contains(">LICENSE"))
}
@Test
func markdownFragmentLinkWithResolverPreservesFragment() {
let html = markdownToHTML(
"[section](#install)",
linkURLResolver: { source in
resolveRepositoryLinkURL(
source,
owner: "~ccleberg",
repositoryName: "Hutch",
readmePath: "README.md"
)
}
)
#expect(html.contains("href=\"#install\""))
}
@Test
func markdownImageRenders() {
let html = markdownToHTML("")
#expect(html.contains(""))
#expect(!html.contains(#"\"#))
}
@Test
func markdownLinkedImageRendersAnchor() {
let html = markdownToHTML("[](https://example.com/build)")
#expect(html.contains(""))
#expect(html.contains(""))
#expect(!html.contains(#"\"#))
}
@Test
func markdownInlineCodeEscaping() {
let html = processInline("``")
#expect(html.contains(""))
#expect(html.contains("<b>"))
#expect(!html.contains(""))
}
@Test
func markdownPlainEmailAutolinks() {
let html = processInline("Contact hello@cleberg.net")
#expect(html.contains(#"href="mailto:hello@cleberg.net""#))
#expect(html.contains(">hello@cleberg.net"))
}
@Test
func markdownImageQueryStringPreservesAmpersands() {
let html = processInline("")
// `&` is the correct encoding for `&` in an attribute value, so the
// failure mode to guard against is double-escaping, which would make the
// browser request a literal "&" in the query string.
#expect(html.contains("metric=security_rating"))
#expect(!html.contains("&"))
#expect(html.contains("Bold Link"#)
#expect(html.contains("Bold"))
#expect(html.contains(#"Link"#))
}
@Test
func markdownProtectedTokensDoNotLeak() {
let html = processInline(#"Back to top `yoshi [ARG] `"#)
#expect(!html.contains("ZZPROTECTED"))
#expect(html.contains(#"Back to top"#))
#expect(html.contains("yoshi [ARG] <FILE>"))
}
}
struct OrgRenderingTests {
@Test
func orgDeepHeading() {
let html = orgToHTML("**** Level 4 Heading")
#expect(html.contains("
"))
}
@Test
func orgCommentLinesIgnored() {
let html = orgToHTML("# This is a comment\nNormal text")
#expect(!html.contains("This is a comment"))
#expect(html.contains("Normal text"))
}
@Test
func orgStrikethrough() {
let html = orgToHTML("+deleted text+")
#expect(html.contains(""))
}
@Test
func orgExampleBlock() {
let html = orgToHTML("#+begin_example\nhello world\n#+end_example")
#expect(html.contains("
"))
#expect(html.contains("hello world"))
}
@Test
func orgTitleKeyword() {
let html = orgToHTML("#+TITLE: My Document\nBody text")
#expect(html.contains("org-title"))
#expect(html.contains("My Document"))
}
@Test
func orgItalicDoesNotMatchURLPaths() {
let html = orgToHTML("[[https://example.com/path/to/file]]")
#expect(!html.contains(""))
}
@Test
func orgWrappedBulletNormalizesLines() {
let html = orgToHTML("- First line\n continues here")
#expect(html.contains("
First line continues here
"))
}
@Test
func orgHeaderKeywordsIgnored() {
let html = orgToHTML("""
#+OPTIONS: toc:nil
#+PROPERTY: header-args :results output
Body text
""")
#expect(!html.contains("#+OPTIONS"))
#expect(!html.contains("#+PROPERTY"))
#expect(html.contains("
Body text
"))
}
@Test
func orgVerseBlock() {
let html = orgToHTML("""
#+begin_verse
There is a line.
And an indented line.
#+end_verse
""")
#expect(html.contains(#"