Skip to content

Commit 96fe662

Browse files
author
Jesse Haigh
committed
update JSON structure for extensibility
1 parent f18f93c commit 96fe662

File tree

4 files changed

+228
-47
lines changed

4 files changed

+228
-47
lines changed

Sources/SwiftDocC/Checker/Checkers/InvalidCodeBlockOption.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ internal struct InvalidCodeBlockOption: Checker {
6363
// code property ends in a newline. this gives us a bogus extra line.
6464
let lineCount: Int = codeBlock.code.split(omittingEmptySubsequences: false, whereSeparator: { $0.isNewline }).count - 1
6565

66-
guard let indices = RenderBlockContent.CodeBlockOptions.parseCodeBlockOptionsArray(value) else {
66+
let indices = RenderBlockContent.CodeBlockOptions.parseCodeBlockOptionsArray(value)
67+
68+
if !value.isEmpty, indices.isEmpty {
6769
let diagnostic = Diagnostic(source: sourceFile, severity: .warning, range: codeBlock.range, identifier: "org.swift.docc.InvalidCodeBlockOption", summary: "Could not parse \(token.rawValue.singleQuoted) indices from \(value.singleQuoted). Expected an integer (e.g. 3) or an array (e.g. [1, 3, 5])")
6870
problems.append(Problem(diagnostic: diagnostic, possibleSolutions: []))
6971
return

Sources/SwiftDocC/Model/Rendering/Content/RenderBlockContent.swift

Lines changed: 76 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,36 @@ public enum RenderBlockContent: Equatable {
139139
public struct CodeBlockOptions: Equatable {
140140
public var language: String?
141141
public var copyToClipboard: Bool
142-
public var wrap: Int
143-
public var highlight: [Int]
144142
public var showLineNumbers: Bool
145-
public var strikeout: [Int]
143+
public var wrap: Int
144+
public var lineAnnotations: [LineAnnotation]
145+
146+
public struct Position: Equatable, Comparable, Codable {
147+
public static func < (lhs: RenderBlockContent.CodeBlockOptions.Position, rhs: RenderBlockContent.CodeBlockOptions.Position) -> Bool {
148+
if lhs.line == rhs.line, let lhsCharacter = lhs.character, let rhsCharacter = rhs.character {
149+
return lhsCharacter < rhsCharacter
150+
}
151+
return lhs.line < rhs.line
152+
}
153+
154+
public init(line: Int, character: Int? = nil) {
155+
self.line = line
156+
self.character = character
157+
}
158+
159+
var line: Int
160+
var character: Int?
161+
}
162+
163+
//public struct Range: Equatable, Codable {
164+
// var start: Position
165+
// var end: Position
166+
//}
167+
168+
public struct LineAnnotation: Equatable, Codable {
169+
var style: String
170+
var range: Range<Position>
171+
}
146172

147173
public enum OptionName: String, CaseIterable {
148174
case _nonFrozenEnum_useDefaultCase
@@ -166,10 +192,9 @@ public enum RenderBlockContent: Equatable {
166192
public init() {
167193
self.language = ""
168194
self.copyToClipboard = true
169-
self.wrap = 0
170-
self.highlight = []
171195
self.showLineNumbers = false
172-
self.strikeout = []
196+
self.wrap = 0
197+
self.lineAnnotations = []
173198
}
174199

175200
public init(parsingLanguageString language: String?) {
@@ -186,27 +211,53 @@ public enum RenderBlockContent: Equatable {
186211
self.wrap = 0
187212
}
188213

189-
if let highlightString = tokens.first(where: { $0.name == .highlight })?.value,
190-
let highlightValue = Self.parseCodeBlockOptionsArray(highlightString) {
191-
self.highlight = highlightValue
192-
} else {
193-
self.highlight = []
214+
var annotations: [LineAnnotation] = []
215+
216+
if let highlightString = tokens.first(where: { $0.name == .highlight })?.value {
217+
let highlightValue = Self.parseCodeBlockOptionsArray(highlightString)
218+
for line in highlightValue {
219+
let pos = Position(line: line, character: nil)
220+
let range = pos..<pos
221+
annotations.append(LineAnnotation(style: "highlight", range: range))
222+
}
194223
}
195224

196-
if let strikeoutString = tokens.first(where: { $0.name == .strikeout })?.value,
197-
let strikeoutValue = Self.parseCodeBlockOptionsArray(strikeoutString) {
198-
self.strikeout = strikeoutValue
199-
} else {
200-
self.strikeout = []
225+
if let strikeoutString = tokens.first(where: { $0.name == .strikeout })?.value {
226+
let strikeoutValue = Self.parseCodeBlockOptionsArray(strikeoutString)
227+
for line in strikeoutValue {
228+
let pos = Position(line: line, character: nil)
229+
let range = pos..<pos
230+
annotations.append(LineAnnotation(style: "strikeout", range: range))
231+
}
201232
}
233+
234+
self.lineAnnotations = annotations
202235
}
203236

204-
public init(copyToClipboard: Bool, wrap: Int, highlight: [Int], strikeout: [Int], showLineNumbers: Bool) {
237+
public init(copyToClipboard: Bool, showLineNumbers: Bool, wrap: Int, highlight: [Int], strikeout: [Int]) {
205238
self.copyToClipboard = copyToClipboard
239+
self.showLineNumbers = showLineNumbers
206240
self.wrap = wrap
207-
self.highlight = highlight
241+
242+
var annotations: [LineAnnotation] = []
243+
for line in highlight {
244+
let pos = Position(line: line, character: nil)
245+
let range = pos..<pos
246+
annotations.append(LineAnnotation(style: "highlight", range: range))
247+
}
248+
for line in strikeout {
249+
let pos = Position(line: line, character: nil)
250+
let range = pos..<pos
251+
annotations.append(LineAnnotation(style: "strikeout", range: range))
252+
}
253+
self.lineAnnotations = annotations
254+
}
255+
256+
public init(copyToClipboard: Bool, showLineNumbers: Bool, wrap: Int, lineAnnotations: [LineAnnotation]) {
257+
self.copyToClipboard = copyToClipboard
208258
self.showLineNumbers = showLineNumbers
209-
self.strikeout = strikeout
259+
self.wrap = wrap
260+
self.lineAnnotations = lineAnnotations
210261
}
211262

212263
/// A function that parses array values on code block options from the language line string
@@ -863,7 +914,7 @@ extension RenderBlockContent.Table: Codable {
863914
extension RenderBlockContent: Codable {
864915
private enum CodingKeys: CodingKey {
865916
case type
866-
case inlineContent, content, caption, style, name, syntax, code, level, text, items, media, runtimePreview, anchor, summary, example, metadata, start, copyToClipboard, wrap, highlight, strikeout, showLineNumbers
917+
case inlineContent, content, caption, style, name, syntax, code, level, text, items, media, runtimePreview, anchor, summary, example, metadata, start, copyToClipboard, showLineNumbers, wrap, lineAnnotations
867918
case request, response
868919
case header, rows
869920
case numberOfColumns, columns
@@ -887,13 +938,12 @@ extension RenderBlockContent: Codable {
887938
case .codeListing:
888939
let copy = FeatureFlags.current.isExperimentalCodeBlockAnnotationsEnabled
889940
let options: CodeBlockOptions?
890-
if !Set(container.allKeys).isDisjoint(with: [.copyToClipboard, .wrap, .highlight, .strikeout, .showLineNumbers]) {
941+
if !Set(container.allKeys).isDisjoint(with: [.copyToClipboard, .showLineNumbers, .wrap, .lineAnnotations]) {
891942
options = try CodeBlockOptions(
892943
copyToClipboard: container.decodeIfPresent(Bool.self, forKey: .copyToClipboard) ?? copy,
944+
showLineNumbers: container.decodeIfPresent(Bool.self, forKey: .showLineNumbers) ?? false,
893945
wrap: container.decodeIfPresent(Int.self, forKey: .wrap) ?? 0,
894-
highlight: container.decodeIfPresent([Int].self, forKey: .highlight) ?? [],
895-
strikeout: container.decodeIfPresent([Int].self, forKey: .strikeout) ?? [],
896-
showLineNumbers: container.decodeIfPresent(Bool.self, forKey: .showLineNumbers) ?? false
946+
lineAnnotations: container.decodeIfPresent([CodeBlockOptions.LineAnnotation].self, forKey: .lineAnnotations) ?? []
897947
)
898948
} else {
899949
options = nil
@@ -1007,10 +1057,9 @@ extension RenderBlockContent: Codable {
10071057
try container.encode(l.code, forKey: .code)
10081058
try container.encodeIfPresent(l.metadata, forKey: .metadata)
10091059
try container.encodeIfPresent(l.options?.copyToClipboard, forKey: .copyToClipboard)
1010-
try container.encodeIfPresent(l.options?.wrap, forKey: .wrap)
1011-
try container.encodeIfPresent(l.options?.highlight, forKey: .highlight)
1012-
try container.encodeIfPresent(l.options?.strikeout, forKey: .strikeout)
10131060
try container.encodeIfPresent(l.options?.showLineNumbers, forKey: .showLineNumbers)
1061+
try container.encodeIfPresent(l.options?.wrap, forKey: .wrap)
1062+
try container.encodeIfPresent(l.options?.lineAnnotations, forKey: .lineAnnotations)
10141063
case .heading(let h):
10151064
try container.encode(h.level, forKey: .level)
10161065
try container.encode(h.text, forKey: .text)

Sources/SwiftDocC/SwiftDocC.docc/Resources/RenderNode.spec.json

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,43 @@
781781
}
782782
}
783783
},
784+
"LineAnnotation": {
785+
"type": "object",
786+
"properties": {
787+
"style": {
788+
"type": "string",
789+
"enum": ["highlight", "strikeout"]
790+
},
791+
"range": {
792+
"$ref": "#/components/schemas/CharacterRange"
793+
}
794+
}
795+
},
796+
"CharacterRange": {
797+
"type": "object",
798+
"properties": {
799+
"start": {
800+
"$ref": "#/components/schemas/Position"
801+
},
802+
"end": {
803+
"$ref": "#/components/schemas/Position"
804+
}
805+
}
806+
},
807+
"Position": {
808+
"type": "object",
809+
"properties": {
810+
"line": {
811+
"type": "integer"
812+
},
813+
"character": {
814+
"type": "integer"
815+
}
816+
},
817+
"required": [
818+
"line"
819+
]
820+
},
784821
"CodeListing": {
785822
"type": "object",
786823
"required": [
@@ -815,16 +852,10 @@
815852
"wrap": {
816853
"type": "integer"
817854
},
818-
"highlight": {
819-
"type": "array",
820-
"items": {
821-
"type": "integer"
822-
}
823-
},
824-
"strikeout": {
855+
"lineAnnotations": {
825856
"type": "array",
826857
"items": {
827-
"type": "integer"
858+
"$ref": "#/components/schemas/LineAnnotation"
828859
}
829860
}
830861
}

0 commit comments

Comments
 (0)