aboutsummaryrefslogtreecommitdiff
path: root/Tests/NorgKitTests/Parsers/NorgInlineParserTests.swift
diff options
context:
space:
mode:
authorRuben Beltran del Rio <jj@r.bdr.sh>2026-06-16 12:08:21 +0200
committerRuben Beltran del Rio <jj@r.bdr.sh>2026-06-16 12:22:47 +0200
commit501fdce29e4d2c46c4708ad7f44056878e0db3fa (patch)
treedb923b77037db9f5b37600a6e34c3bb2e8a971be /Tests/NorgKitTests/Parsers/NorgInlineParserTests.swift
Initial extraction from Norganize1.0.0
Diffstat (limited to 'Tests/NorgKitTests/Parsers/NorgInlineParserTests.swift')
-rw-r--r--Tests/NorgKitTests/Parsers/NorgInlineParserTests.swift141
1 files changed, 141 insertions, 0 deletions
diff --git a/Tests/NorgKitTests/Parsers/NorgInlineParserTests.swift b/Tests/NorgKitTests/Parsers/NorgInlineParserTests.swift
new file mode 100644
index 0000000..d59fc35
--- /dev/null
+++ b/Tests/NorgKitTests/Parsers/NorgInlineParserTests.swift
@@ -0,0 +1,141 @@
+import Testing
+
+@testable import NorgKit
+
+struct NorgInlineParserTests {
+
+ private func span(_ spans: [InlineSpan], withText text: String) -> InlineSpan? {
+ spans.first { $0.text == text }
+ }
+
+ @Test func parsesBold() {
+ let spans = NorgInlineParser.parse("This is *bold*.")
+ #expect(spans.plainText == "This is bold.")
+ #expect(span(spans, withText: "bold")?.styles.contains(.bold) == true)
+ }
+
+ @Test func parsesMixedStyles() {
+ let spans = NorgInlineParser.parse("a /italic/ and _underline_ and -strike-")
+ #expect(span(spans, withText: "italic")?.styles.contains(.italic) == true)
+ #expect(span(spans, withText: "underline")?.styles.contains(.underline) == true)
+ #expect(span(spans, withText: "strike")?.styles.contains(.strikethrough) == true)
+ }
+
+ @Test func parsesNestedStyles() {
+ let spans = NorgInlineParser.parse("_under /italic/_")
+ let inner = span(spans, withText: "italic")
+ #expect(inner?.styles.contains(.italic) == true)
+ #expect(inner?.styles.contains(.underline) == true)
+ }
+
+ @Test func verbatimIsLiteral() {
+ let spans = NorgInlineParser.parse("a `b*c*d` e")
+ let verbatim = span(spans, withText: "b*c*d")
+ #expect(verbatim?.styles.contains(.verbatim) == true)
+ #expect(spans.plainText == "a b*c*d e")
+ }
+
+ @Test func dropsComments() {
+ let spans = NorgInlineParser.parse("visible %hidden% text")
+ #expect(!spans.plainText.contains("hidden"))
+ #expect(spans.plainText.contains("visible"))
+ #expect(spans.plainText.contains("text"))
+ }
+
+ @Test func escapesModifier() {
+ let spans = NorgInlineParser.parse("\\*not bold\\*")
+ #expect(spans.plainText == "*not bold*")
+ #expect(spans.allSatisfy { !$0.styles.contains(.bold) })
+ }
+
+ @Test func doesNotMatchMidWordHyphen() {
+ let spans = NorgInlineParser.parse("well-known value")
+ #expect(spans.plainText == "well-known value")
+ #expect(spans.allSatisfy { !$0.styles.contains(.strikethrough) })
+ }
+
+ @Test func parsesLinkWithDescription() {
+ let spans = NorgInlineParser.parse("see {https://example.com}[the site] now")
+ let link = span(spans, withText: "the site")
+ #expect(link?.link == InlineLink(kind: .link, target: "https://example.com"))
+ }
+
+ @Test func linkDescriptionIsLiteralNotPrefixStripped() {
+ // A `*`-prefixed description must not be mistaken for a location prefix.
+ let spans = NorgInlineParser.parse("{https://example.com}[* keep me]")
+ #expect(spans.first?.text == "* keep me")
+ #expect(spans.first?.link?.target == "https://example.com")
+ }
+
+ @Test func stripsLocationPrefixFromBareLink() {
+ let spans = NorgInlineParser.parse("{* Some Heading}")
+ #expect(spans.first?.text == "Some Heading")
+ #expect(spans.first?.link == InlineLink(kind: .link, target: "* Some Heading"))
+ }
+
+ @Test func parsesAnchorDefinition() {
+ let spans = NorgInlineParser.parse("[my label]{https://example.com}")
+ #expect(spans.first?.text == "my label")
+ #expect(spans.first?.link == InlineLink(kind: .anchor, target: "https://example.com"))
+ }
+
+ @Test func bareAnchorDeclarationHasNoInlineTarget() {
+ // `[Neorg]` references a target defined elsewhere; its target is unknown
+ // at the declaration site, so it must not echo the label as the target.
+ let spans = NorgInlineParser.parse("I like [Neorg] a lot")
+ let anchor = span(spans, withText: "Neorg")
+ #expect(anchor?.link == InlineLink(kind: .anchor, target: nil))
+ }
+
+ @Test func anchorDeclarationWithDescription() {
+ let spans = NorgInlineParser.parse("[anchor name][shown text]")
+ #expect(spans.first?.text == "shown text")
+ #expect(spans.first?.link == InlineLink(kind: .anchor, target: nil))
+ }
+
+ @Test func unterminatedModifierIsLiteral() {
+ let spans = NorgInlineParser.parse("a * b c")
+ #expect(spans.plainText == "a * b c")
+ }
+
+ @Test func unterminatedAttachedModifierWithOpenerIsLiteral() {
+ // A valid opener (`*` followed by non-space) with no closing modifier
+ // falls through to plain text rather than styling the rest of the line.
+ let spans = NorgInlineParser.parse("*bold but never closed")
+ #expect(spans.plainText == "*bold but never closed")
+ #expect(spans.allSatisfy { !$0.styles.contains(.bold) })
+ }
+
+ @Test func unterminatedVerbatimIsLiteral() {
+ let spans = NorgInlineParser.parse("a `b c d")
+ #expect(spans.plainText == "a `b c d")
+ #expect(spans.allSatisfy { !$0.styles.contains(.verbatim) })
+ }
+
+ @Test func unmatchedLinkBraceIsLiteral() {
+ let spans = NorgInlineParser.parse("see {never closed here")
+ #expect(spans.plainText == "see {never closed here")
+ #expect(spans.allSatisfy { $0.link == nil })
+ }
+
+ @Test func unmatchedAnchorBracketIsLiteral() {
+ let spans = NorgInlineParser.parse("see [never closed here")
+ #expect(spans.plainText == "see [never closed here")
+ #expect(spans.allSatisfy { $0.link == nil })
+ }
+
+ @Test func stripsFileSpecifierAndLocationPrefixFromBareLink() {
+ // `{:path:* Heading}` carries a `:file:` specifier before the location
+ // prefix; both are stripped to derive the display label.
+ let spans = NorgInlineParser.parse("{:notes.norg:* Some Heading}")
+ #expect(spans.first?.text == "Some Heading")
+ #expect(spans.first?.link == InlineLink(kind: .link, target: ":notes.norg:* Some Heading"))
+ }
+
+ @Test func plainTextHelperReturnsUnstyledText() {
+ // Exercises the static plainText(_:) entry used by the task scanner.
+ #expect(NorgInlineParser.plainText("just *bold* here") == "just bold here")
+ #expect(NorgInlineParser.plainText("") == "")
+ #expect(NorgInlineParser.plainText("no markup at all") == "no markup at all")
+ }
+}