// DEPENDENCE: z_test.cj
// EXEC: cjc %import-path %L %l %f z_test.cj -Woff unused
// EXEC: ./main
import commonmark4cj.commonmark.*
import std.unittest.*
import std.unittest.testmacro.*
import std.collection.*
import std.unicode.*
import std.fs.*
import std.reflect.{TypeInfo}
main() {
let tester = SpecialInputTest()
tester.empty()
tester.nullCharacterShouldBeReplaced()
tester.nullCharacterEntityShouldBeReplaced()
tester.crLfAsLineSeparatorShouldBeParsed()
tester.crLfAtEndShouldBeParsed()
tester.mixedLineSeparators()
tester.surrogatePair()
tester.surrogatePairInLinkDestination()
tester.indentedCodeBlockWithMixedTabsAndSpaces()
tester.tightListInBlockQuote()
tester.looseListInBlockQuote()
tester.lineWithOnlySpacesAfterListBullet()
tester.listWithTwoSpacesForFirstBullet()
tester.orderedListMarkerOnly()
tester.columnIsInTabOnPreviousLine()
tester.linkLabelWithBracket()
tester.linkLabelLength()
tester.linkDestinationEscaping()
tester.linkReferenceBackslash()
tester.emphasisMultipleOf3Rule()
tester.deeplyIndentedList()
return 0
}
@Test
public class SpecialInputTest {
private static let PARSER: Parser = Parser.builder().build()
private static let RENDERER: HtmlRenderer = HtmlRenderer.builder().build()
@TestCase
public func empty(): Unit {
assertRendering("", "")
}
@TestCase
public func nullCharacterShouldBeReplaced(): Unit {
assertRendering("foo\0bar", "<p>foo\u{FFFD}bar</p>\n")
}
@TestCase
public func nullCharacterEntityShouldBeReplaced() {
assertRendering("foo�bar", "<p>foo\u{FFFD}bar</p>\n")
}
@TestCase
public func crLfAsLineSeparatorShouldBeParsed() {
assertRendering("foo\r\nbar", "<p>foo\nbar</p>\n")
}
@TestCase
public func crLfAtEndShouldBeParsed() {
assertRendering("foo\r\n", "<p>foo</p>\n")
}
@TestCase
public func mixedLineSeparators() {
assertRendering("- a\n- b\r- c\r\n- d", "<ul>\n<li>a</li>\n<li>b</li>\n<li>c</li>\n<li>d</li>\n</ul>\n")
assertRendering("a\n\nb\r\rc\r\n\r\nd\n\re", "<p>a</p>\n<p>b</p>\n<p>c</p>\n<p>d</p>\n<p>e</p>\n")
}
@TestCase
public func surrogatePair() {
assertRendering("surrogate pair: \u{1D11E}", "<p>surrogate pair: \u{1D11E}</p>\n")
}
@TestCase
public func surrogatePairInLinkDestination() {
assertRendering("[title](\u{1D11E})", "<p><a href=\"\u{1D11E}\">title</a></p>\n")
}
@TestCase
public func indentedCodeBlockWithMixedTabsAndSpaces() {
assertRendering(" foo\n\tbar", "<pre><code>foo\nbar\n</code></pre>\n")
}
@TestCase
public func tightListInBlockQuote() {
assertRendering("> *\n> * a", "<blockquote>\n<ul>\n<li></li>\n<li>a</li>\n</ul>\n</blockquote>\n")
}
@TestCase
public func looseListInBlockQuote() {
assertRendering("> *\n>\n> * a", "<blockquote>\n<ul>\n<li></li>\n<li>\n<p>a</p>\n</li>\n</ul>\n</blockquote>\n")
}
@TestCase
public func lineWithOnlySpacesAfterListBullet() {
assertRendering("- \n \n foo\n", "<ul>\n<li></li>\n</ul>\n<p>foo</p>\n")
}
@TestCase
public func listWithTwoSpacesForFirstBullet() {
assertRendering("* \n foo\n", "<ul>\n<li>foo</li>\n</ul>\n")
}
@TestCase
public func orderedListMarkerOnly() {
assertRendering("2.", "<ol start=\"2\">\n<li></li>\n</ol>\n")
}
@TestCase
public func columnIsInTabOnPreviousLine() {
assertRendering(
"- foo\n\n\tbar\n\n# baz\n",
"<ul>\n<li>\n<p>foo</p>\n<p>bar</p>\n</li>\n</ul>\n<h1>baz</h1>\n"
)
assertRendering(
"- foo\n\n\tbar\n# baz\n",
"<ul>\n<li>\n<p>foo</p>\n<p>bar</p>\n</li>\n</ul>\n<h1>baz</h1>\n"
)
}
@TestCase
public func linkLabelWithBracket() {
assertRendering("[a[b]\n\n[a[b]: /", "<p>[a[b]</p>\n<p>[a[b]: /</p>\n")
assertRendering("[a]b]\n\n[a]b]: /", "<p>[a]b]</p>\n<p>[a]b]: /</p>\n")
assertRendering("[a[b]]\n\n[a[b]]: /", "<p>[a[b]]</p>\n<p>[a[b]]: /</p>\n")
}
@TestCase
public func linkLabelLength() {
let label1: String = Strings.repeat("a", 999)
assertRendering("[foo][" + label1 + "]\n\n[" + label1 + "]: /", "<p><a href=\"/\">foo</a></p>\n")
assertRendering(
"[foo][x" + label1 + "]\n\n[x" + label1 + "]: /",
"<p>[foo][x" + label1 + "]</p>\n<p>[x" + label1 + "]: /</p>\n"
)
assertRendering(
"[foo][\n" + label1 + "]\n\n[\n" + label1 + "]: /",
"<p>[foo][\n" + label1 + "]</p>\n<p>[\n" + label1 + "]: /</p>\n"
)
let label2: String = Strings.repeat("a\n", 499)
assertRendering("[foo][" + label2 + "]\n\n[" + label2 + "]: /", "<p><a href=\"/\">foo</a></p>\n")
assertRendering(
"[foo][12" + label2 + "]\n\n[12" + label2 + "]: /",
"<p>[foo][12" + label2 + "]</p>\n<p>[12" + label2 + "]: /</p>\n"
)
}
@TestCase
public func linkDestinationEscaping() {
assertRendering("[foo](\\))", "<p><a href=\")\">foo</a></p>\n")
assertRendering("[foo](\\ )", "<p><a href=\"\\\">foo</a></p>\n")
assertRendering("[foo](<a\\b>)", "<p><a href=\"a\\b\">foo</a></p>\n")
assertRendering("[foo](<a\\>>)", "<p><a href=\"a>\">foo</a></p>\n")
assertRendering("[foo](<\\>)", "<p>[foo](<>)</p>\n")
}
@TestCase
public func linkReferenceBackslash() {
assertRendering("[\\]: test", "<p>[]: test</p>\n")
assertRendering("[a\\b]\n\n[a\\b]: test", "<p><a href=\"test\">a\\b</a></p>\n")
assertRendering("[a\\]]\n\n[a\\]]: test", "<p><a href=\"test\">a]</a></p>\n")
}
@TestCase
public func emphasisMultipleOf3Rule() {
assertRendering("a***b* c*", "<p>a*<em><em>b</em> c</em></p>\n")
}
@TestCase
public func deeplyIndentedList() {
assertRendering(
"* one\n" + " * two\n" + " * three\n" + " * four",
"<ul>\n" + "<li>one\n" + "<ul>\n" + "<li>two\n" + "<ul>\n" + "<li>three\n" + "<ul>\n" + "<li>four</li>\n" +
"</ul>\n" + "</li>\n" + "</ul>\n" + "</li>\n" + "</ul>\n" + "</li>\n" + "</ul>\n"
)
}
func render(source: String): String {
let node = PARSER.parse(source)
return RENDERER.render(node)
}
func assertRendering(source: String, expectedResult: String): Unit {
let renderedContent: String = render(source)
let expected: String = showTabs(expectedResult + "\n\n" + source)
let actual: String = showTabs(renderedContent + "\n\n" + source)
assertEquals(expected, actual)
}
func showTabs(s: String): String {
return s.replace("\t", "\u{2192}")
}
}