| 194 | } |
| 195 | |
| 196 | function parseRelationLine(text: string) { |
| 197 | const relations: RelationEdgeDatum[] = []; |
| 198 | const nodes: ParsedNode[] = []; |
| 199 | const nodeMap = new Map<string, ParsedNode>(); |
| 200 | let index = 0; |
| 201 | const first = readNode(text, index); |
| 202 | if (!first) return { relations, nodes }; |
| 203 | let current = first.node; |
| 204 | if (!nodeMap.has(current.id)) { |
| 205 | nodeMap.set(current.id, current); |
| 206 | nodes.push(current); |
| 207 | } |
| 208 | index = first.nextIndex; |
| 209 | |
| 210 | while (index < text.length) { |
| 211 | const edge = readEdge(text, index); |
| 212 | if (!edge) break; |
| 213 | index = edge.nextIndex; |
| 214 | const nextNode = readNode(text, index); |
| 215 | if (!nextNode) break; |
| 216 | index = nextNode.nextIndex; |
| 217 | |
| 218 | let from = current.id; |
| 219 | let to = nextNode.node.id; |
| 220 | const direction = edge.direction; |
| 221 | if (edge.reverse) { |
| 222 | from = nextNode.node.id; |
| 223 | to = current.id; |
| 224 | } |
| 225 | |
| 226 | const relation: RelationEdgeDatum = { |
| 227 | from, |
| 228 | to, |
| 229 | }; |
| 230 | if (edge.label) relation.label = edge.label; |
| 231 | if (direction === 'both') relation.direction = 'both'; |
| 232 | if (direction === 'none') relation.direction = 'none'; |
| 233 | relations.push(relation); |
| 234 | |
| 235 | if (!nodeMap.has(current.id)) { |
| 236 | nodeMap.set(current.id, current); |
| 237 | nodes.push(current); |
| 238 | } |
| 239 | if (!nodeMap.has(nextNode.node.id)) { |
| 240 | nodeMap.set(nextNode.node.id, nextNode.node); |
| 241 | nodes.push(nextNode.node); |
| 242 | } |
| 243 | current = nextNode.node; |
| 244 | } |
| 245 | |
| 246 | return { relations, nodes }; |
| 247 | } |
| 248 | |
| 249 | function ensureItemLabel( |
| 250 | items: Map<string, ItemDatum>, |