Skip to content

Commit f130a75

Browse files
authored
Extract language from fenced code blocks (#47)
1 parent 42f4767 commit f130a75

File tree

2 files changed

+19
-2
lines changed

2 files changed

+19
-2
lines changed

Sources/SwiftParser/Markdown/Builders/MarkdownFencedCodeBuilder.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ public class MarkdownFencedCodeBuilder: CodeNodeBuilder {
1010
isStartOfLine(context) else { return false }
1111
context.consuming += 1
1212
let code = trimFence(token.text)
13-
let node = CodeBlockNode(source: code, language: nil)
13+
let language = extractLanguage(token.text)
14+
let node = CodeBlockNode(source: code, language: language)
1415
context.current.append(node)
1516
if context.consuming < context.tokens.count,
1617
let nl = context.tokens[context.consuming] as? MarkdownToken,
@@ -30,6 +31,18 @@ public class MarkdownFencedCodeBuilder: CodeNodeBuilder {
3031
return lines.joined(separator: "\n")
3132
}
3233

34+
private func extractLanguage(_ text: String) -> String? {
35+
guard let firstLine = text.split(separator: "\n", maxSplits: 1).first else {
36+
return nil
37+
}
38+
var cleaned = firstLine.trimmingCharacters(in: .whitespaces)
39+
while cleaned.starts(with: "`") {
40+
cleaned.removeFirst()
41+
}
42+
let lang = cleaned.trimmingCharacters(in: .whitespaces)
43+
return lang.isEmpty ? nil : lang
44+
}
45+
3346
private func isStartOfLine(_ context: CodeContext<MarkdownNodeElement, MarkdownTokenElement>) -> Bool {
3447
if context.consuming == 0 { return true }
3548
if let prev = context.tokens[context.consuming - 1] as? MarkdownToken {

Tests/SwiftParserTests/Markdown/Consumer/MarkdownBlockElementTests.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ final class MarkdownBlockElementTests: XCTestCase {
1717
let (node, context) = parser.parse(input, root: root)
1818
XCTAssertTrue(context.errors.isEmpty)
1919
XCTAssertEqual(node.children.count, 1)
20-
XCTAssertTrue(node.children.first is CodeBlockNode)
20+
if let code = node.children.first as? CodeBlockNode {
21+
XCTAssertEqual(code.language, "swift")
22+
} else {
23+
XCTFail("Expected CodeBlockNode")
24+
}
2125
}
2226

2327
func testHorizontalRule() {

0 commit comments

Comments
 (0)