Skip to content

Commit fa01e4c

Browse files
committed
add support for terms lists
1 parent 0ab0bbb commit fa01e4c

11 files changed

+184
-58
lines changed

Sources/MarkdownSemantics/AST/Asides/Markdown.BlockParameter.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,3 @@ extension Markdown
2727
}
2828
}
2929
}
30-
extension Markdown.BlockParameter
31-
{
32-
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import MarkdownABI
2+
import MarkdownAST
3+
4+
extension Markdown
5+
{
6+
public final
7+
class BlockTerm:BlockContainer<BlockElement>
8+
{
9+
public
10+
let name:String
11+
12+
@inlinable public
13+
init(elements:[BlockElement], name:String)
14+
{
15+
self.name = name
16+
super.init(elements)
17+
}
18+
19+
public override
20+
func emit(into binary:inout BinaryEncoder)
21+
{
22+
binary[.dt] { $0[.id] = "st:\(self.name)" } = self.name
23+
binary[.dd]
24+
{
25+
super.emit(into: &$0)
26+
}
27+
}
28+
}
29+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import MarkdownABI
2+
import MarkdownAST
3+
4+
extension Markdown
5+
{
6+
public final
7+
class BlockTerms:BlockContainer<BlockTerm>
8+
{
9+
public override
10+
func emit(into binary:inout BinaryEncoder)
11+
{
12+
binary[.dl]
13+
{
14+
super.emit(into: &$0)
15+
}
16+
}
17+
}
18+
}

Sources/MarkdownSemantics/AST/Markdown.SwiftFlavor.swift

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,16 @@ extension Markdown.SwiftFlavor
7676
switch block
7777
{
7878
case let list as Markdown.BlockListUnordered:
79+
var terms:[Markdown.BlockTerm] = []
7980
var items:[Markdown.BlockItem] = []
8081
for item:Markdown.BlockItem in list.elements
8182
{
82-
if let prefix:Markdown.BlockPrefix = .extract(from: &item.elements),
83-
case .keywords(let aside) = prefix
83+
if let term:Markdown.TermPrefix = .extract(from: &item.elements)
84+
{
85+
terms.append(.init(elements: item.elements, name: term.name))
86+
}
87+
else if
88+
let aside:Markdown.KeywordPrefix = .extract(from: &item.elements)
8489
{
8590
blocks.append(aside(item.elements))
8691
}
@@ -89,14 +94,18 @@ extension Markdown.SwiftFlavor
8994
items.append(item)
9095
}
9196
}
97+
if !terms.isEmpty
98+
{
99+
blocks.append(Markdown.BlockTerms.init(terms))
100+
}
92101
if !items.isEmpty
93102
{
94103
list.elements = items
95104
blocks.append(list)
96105
}
97106

98107
case let quote as Markdown.BlockQuote:
99-
if case .keywords(let aside) = Markdown.BlockPrefix.extract(
108+
if let aside:Markdown.KeywordPrefix = .extract(
100109
from: &quote.elements)
101110
{
102111
blocks.append(aside(quote.elements))

Sources/MarkdownSemantics/Prefixes/Markdown.BlockPrefix.swift

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ extension Markdown
44
{
55
enum BlockPrefix:Equatable, Hashable, Sendable
66
{
7-
case parameter(Markdown.ParameterPrefix)
8-
case keywords(Markdown.KeywordPrefix)
7+
case parameter (Markdown.ParameterPrefix)
8+
case term (Markdown.TermPrefix)
9+
case keywords (Markdown.KeywordPrefix)
910
}
1011
}
1112
extension Markdown.BlockPrefix:Markdown.SemanticPrefix
@@ -15,11 +16,17 @@ extension Markdown.BlockPrefix:Markdown.SemanticPrefix
1516

1617
init?(from elements:__shared [Markdown.InlineElement])
1718
{
18-
if let parameter:Markdown.ParameterPrefix = .init(from: elements)
19+
if let parameter:Markdown.ParameterPrefix = .init(from: elements)
1920
{
2021
self = .parameter(parameter)
2122
}
22-
else if let keywords:Markdown.KeywordPrefix = .init(from: elements)
23+
else if
24+
let term:Markdown.TermPrefix = .init(from: elements)
25+
{
26+
self = .term(term)
27+
}
28+
else if
29+
let keywords:Markdown.KeywordPrefix = .init(from: elements)
2330
{
2431
self = .keywords(keywords)
2532
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
extension Markdown
2+
{
3+
typealias DefinePrefix = _MarkdownDefinePrefix
4+
}
5+
6+
protocol _MarkdownDefinePrefix:Markdown.SemanticPrefix
7+
{
8+
/// A lowercased keyword that begins this prefix pattern.
9+
static
10+
var keyword:String { get }
11+
12+
init(name:String)
13+
}
14+
extension Markdown.DefinePrefix
15+
{
16+
/// This is `4` to accommodate formatted definitions. The first span would be the formatted
17+
/// ``keyword``, the second span would contain the unformatted whitespace between the
18+
/// keyword and the name, the third span would be formatted name, and the fourth span would
19+
/// would contain the `:` separator, including any leading whitespace.
20+
static
21+
var radius:Int { 4 }
22+
23+
/// Detects an instance of this pattern type from the given array of
24+
/// inline block content. The array contains inline content up to, but
25+
/// not including, an unformatted `:` character.
26+
init?(from elements:__shared [Markdown.InlineElement])
27+
{
28+
let words:[Substring] = elements.lazy.map(\.text).joined().split(maxSplits: 1,
29+
omittingEmptySubsequences: true,
30+
whereSeparator: \.isWhitespace)
31+
32+
if words.count == 2,
33+
words[0].lowercased() == Self.keyword
34+
{
35+
// Don’t attempt to validate the identifier for disallowed characters,
36+
// this is the wrong place for that.
37+
self.init(name: String.init(words[1]))
38+
}
39+
else
40+
{
41+
return nil
42+
}
43+
}
44+
}

Sources/MarkdownSemantics/Prefixes/Markdown.ParameterNamePrefix.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ import MarkdownAST
33

44
extension Markdown
55
{
6+
/// A `ParameterNamePrefix` appears in a list item that begins with `- name:`, where *name*
7+
/// is the name of a parameter.
8+
///
9+
/// This prefix should only appear inside a ``KeywordPrefix/parameters`` block. Its
10+
/// top-level analogue is ``ParameterPrefix``.
611
struct ParameterNamePrefix
712
{
813
let name:String
Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import Codelinks
2-
import MarkdownAST
3-
41
extension Markdown
52
{
3+
/// A `ParameterPrefix` appears in a list item that begins with `- parameter name:`, where
4+
/// *name* is the name of a parameter.
65
struct ParameterPrefix:Equatable, Hashable, Sendable
76
{
87
let name:String
@@ -13,30 +12,8 @@ extension Markdown
1312
}
1413
}
1514
}
16-
extension Markdown.ParameterPrefix:Markdown.SemanticPrefix
15+
extension Markdown.ParameterPrefix:Markdown.DefinePrefix
1716
{
1817
static
19-
var radius:Int { 4 }
20-
21-
/// Detects an instance of this pattern type from the given array of
22-
/// inline block content. The array contains inline content up to, but
23-
/// not including, an unformatted `:` character.
24-
init?(from elements:__shared [Markdown.InlineElement])
25-
{
26-
let words:[Substring] = elements.lazy.map(\.text).joined().split(maxSplits: 1,
27-
omittingEmptySubsequences: true,
28-
whereSeparator: \.isWhitespace)
29-
30-
if words.count == 2,
31-
words[0].lowercased() == "parameter"
32-
{
33-
// Don’t attempt to validate the identifier for disallowed characters,
34-
// this is the wrong place for that.
35-
self.init(name: String.init(words[1]))
36-
}
37-
else
38-
{
39-
return nil
40-
}
41-
}
18+
var keyword:String { "parameter" }
4219
}

Sources/MarkdownSemantics/Prefixes/Markdown.SemanticPrefix.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,9 @@ extension Markdown.SemanticPrefix
5252
private static
5353
func extract(from elements:inout [Markdown.InlineElement]) rethrows -> Self?
5454
{
55-
for (index, span):(Int, Markdown.InlineElement)
56-
in zip(elements.indices, elements.prefix(Self.radius))
55+
for (index, span):(Int, Markdown.InlineElement) in zip(
56+
elements.indices,
57+
elements.prefix(Self.radius))
5758
{
5859
if case .text(let text) = span,
5960
let colon:String.Index = text.firstIndex(of: ":")
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
extension Markdown
2+
{
3+
/// A `Term` appears in a list item that begins with `- term name:`, where
4+
/// *name* is the name of a defined term.
5+
struct TermPrefix:Equatable, Hashable, Sendable
6+
{
7+
let name:String
8+
9+
init(name:String)
10+
{
11+
self.name = name
12+
}
13+
}
14+
}
15+
extension Markdown.TermPrefix:Markdown.DefinePrefix
16+
{
17+
static
18+
var keyword:String { "term" }
19+
}

0 commit comments

Comments
 (0)