@@ -15,6 +15,25 @@ public protocol Node: Decodable {
15
15
var nodeType : NodeType { get }
16
16
}
17
17
18
+ public protocol RecursiveNode : Node {
19
+ var content : [ Node ] { get }
20
+ func resolveLinks( against includedEntries: [ Entry ] ? , and includedAssets: [ Asset ] ? )
21
+ }
22
+
23
+ private extension RecursiveNode {
24
+
25
+ func resolveLinksInChildNodes( against includedEntries: [ Entry ] ? , and includedAssets: [ Asset ] ? ) {
26
+ self . content. forEach { node in
27
+ switch node {
28
+ case let recursiveNode as RecursiveNode :
29
+ recursiveNode. resolveLinks ( against: includedEntries, and: includedAssets)
30
+ default :
31
+ break
32
+ }
33
+ }
34
+ }
35
+ }
36
+
18
37
/// The data describing the linked entry or asset for an `EmbeddedResouceNode`
19
38
public class ResourceLinkData : Decodable {
20
39
@@ -124,7 +143,7 @@ public enum NodeType: String, Decodable {
124
143
}
125
144
126
145
/// BlockNode is the base class for all nodes which are rendered as a block (as opposed to an inline node).
127
- public class BlockNode : Node {
146
+ public class BlockNode : RecursiveNode {
128
147
public let nodeType : NodeType
129
148
public internal( set) var content : [ Node ]
130
149
@@ -137,10 +156,14 @@ public class BlockNode: Node {
137
156
self . nodeType = nodeType
138
157
self . content = content
139
158
}
159
+
160
+ public func resolveLinks( against includedEntries: [ Entry ] ? , and includedAssets: [ Asset ] ? ) {
161
+ resolveLinksInChildNodes ( against: includedEntries, and: includedAssets)
162
+ }
140
163
}
141
164
142
165
/// InlineNode is the base class for all nodes which are rendered as an inline string (as opposed to a block node).
143
- public class InlineNode : Node {
166
+ public class InlineNode : RecursiveNode {
144
167
public let nodeType : NodeType
145
168
public internal( set) var content : [ Node ]
146
169
@@ -153,10 +176,14 @@ public class InlineNode: Node {
153
176
self . nodeType = nodeType
154
177
self . content = content
155
178
}
179
+
180
+ public func resolveLinks( against includedEntries: [ Entry ] ? , and includedAssets: [ Asset ] ? ) {
181
+ resolveLinksInChildNodes ( against: includedEntries, and: includedAssets)
182
+ }
156
183
}
157
184
158
185
/// The top level node which contains all other nodes.
159
- public class RichTextDocument : Node {
186
+ public class RichTextDocument : RecursiveNode {
160
187
public let nodeType : NodeType
161
188
public internal( set) var content : [ Node ]
162
189
@@ -170,6 +197,10 @@ public class RichTextDocument: Node {
170
197
nodeType = try container. decode ( NodeType . self, forKey: . nodeType)
171
198
content = try container. decodeContent ( forKey: . content)
172
199
}
200
+
201
+ public func resolveLinks( against includedEntries: [ Entry ] ? , and includedAssets: [ Asset ] ? ) {
202
+ resolveLinksInChildNodes ( against: includedEntries, and: includedAssets)
203
+ }
173
204
}
174
205
175
206
/// A block of text, containing child `Text` nodes.
@@ -245,6 +276,28 @@ public class ResourceLinkBlock: BlockNode {
245
276
data = try container. decode ( ResourceLinkData . self, forKey: . data)
246
277
try super. init ( from: decoder)
247
278
}
279
+
280
+ public override func resolveLinks( against includedEntries: [ Entry ] ? , and includedAssets: [ Asset ] ? ) {
281
+ switch data. target {
282
+ case . asset, . entry, . entryDecodable:
283
+ return
284
+ case let . unresolved( sys) :
285
+ switch sys. linkType. lowercased ( ) {
286
+ case " entry " :
287
+ guard let linkedEntry = includedEntries? . first ( where: { $0. sys. id == sys. id } ) else {
288
+ return
289
+ }
290
+ data. target = Link . entry ( linkedEntry)
291
+ case " asset " :
292
+ guard let linkedAsset = includedAssets? . first ( where: { $0. sys. id == sys. id } ) else {
293
+ return
294
+ }
295
+ data. target = Link . asset ( linkedAsset)
296
+ default :
297
+ return
298
+ }
299
+ }
300
+ }
248
301
}
249
302
250
303
/// A inline containing data for a linked entry or asset.
@@ -263,6 +316,28 @@ public class ResourceLinkInline: InlineNode {
263
316
data = try container. decode ( ResourceLinkData . self, forKey: . data)
264
317
try super. init ( from: decoder)
265
318
}
319
+
320
+ public override func resolveLinks( against includedEntries: [ Entry ] ? , and includedAssets: [ Asset ] ? ) {
321
+ switch data. target {
322
+ case . asset, . entry, . entryDecodable:
323
+ return
324
+ case let . unresolved( sys) :
325
+ switch sys. linkType. lowercased ( ) {
326
+ case " entry " :
327
+ guard let linkedEntry = includedEntries? . first ( where: { $0. sys. id == sys. id } ) else {
328
+ return
329
+ }
330
+ data. target = Link . entry ( linkedEntry)
331
+ case " asset " :
332
+ guard let linkedAsset = includedAssets? . first ( where: { $0. sys. id == sys. id } ) else {
333
+ return
334
+ }
335
+ data. target = Link . asset ( linkedAsset)
336
+ default :
337
+ return
338
+ }
339
+ }
340
+ }
266
341
}
267
342
268
343
/// A node containing text with marks.
0 commit comments