Skip to content

Commit a775753

Browse files
committed
Find closest node during link if linkPath.length = 1
if terse linking syntax is used (.e.g avatar: +avatar.jpg, transcript: +transcript.md) and there are multiple nodes with the same slug in the contentModel, find the node that is closest to the source node
1 parent 46d40a9 commit a775753

1 file changed

Lines changed: 30 additions & 5 deletions

File tree

src/ssg/lib/linking.js

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
const _ = require('lodash')
22

3-
function findLinkedNode(nodes, linkPath) {
3+
function findLinkedNode(sourceNode, allNodes, linkPath) {
44
const leafSlug = linkPath.pop()
55
const leafRe = new RegExp(`^${leafSlug}$`, 'i')
6-
const leafMatches = nodes.filter(p => p.slug.match(leafRe))
6+
const leafMatches = allNodes.filter(p => p.slug.match(leafRe))
77

88
if (!leafMatches.length) {
99
return undefined
@@ -14,7 +14,7 @@ function findLinkedNode(nodes, linkPath) {
1414
}
1515

1616
if (!linkPath.length) {
17-
return undefined
17+
return findClosestNode(sourceNode, leafMatches)
1818
}
1919

2020
const paths = linkPath.reverse()
@@ -29,6 +29,31 @@ function findLinkedNode(nodes, linkPath) {
2929
})
3030
}
3131

32+
function findClosestNode(sourceNode, candidates) {
33+
const sourceContext = [...sourceNode.context.items, sourceNode]
34+
let bestMatch = candidates[0]
35+
let bestScore = -1
36+
for (const candidate of candidates) {
37+
const candidateContext = candidate.context.items
38+
const maxDepth = Math.min(
39+
sourceContext.length, candidateContext.length
40+
)
41+
let score = 0
42+
for (let i = 0; i < maxDepth; i++) {
43+
if (sourceContext[i].slug === candidateContext[i].slug) {
44+
score++
45+
} else {
46+
break
47+
}
48+
}
49+
if (score > bestScore) {
50+
bestScore = score
51+
bestMatch = candidate
52+
}
53+
}
54+
return bestMatch
55+
}
56+
3257
function addLinkBack(sourceNode, targetNode, key) {
3358
if (sourceNode.schema) {
3459
Object.keys(sourceNode.schema.attributes || []).forEach(schemaKey => {
@@ -82,7 +107,7 @@ function resolveLinks(node, nodes) {
82107
if (!valueItem.linkPath) {
83108
continue
84109
}
85-
const linkedNode = findLinkedNode(nodes, [...valueItem.linkPath])
110+
const linkedNode = findLinkedNode(node, nodes, [...valueItem.linkPath])
86111
if (linkedNode) {
87112
node.addLink([key, i], Object.assign({}, linkedNode))
88113
linkedNode.addLinkBack(node, key)
@@ -92,7 +117,7 @@ function resolveLinks(node, nodes) {
92117
if (!value?.linkPath) {
93118
return
94119
}
95-
const linkedNode = findLinkedNode(nodes, [...value.linkPath])
120+
const linkedNode = findLinkedNode(node, nodes, [...value.linkPath])
96121
if (linkedNode) {
97122
node.addLink([key], Object.assign({}, linkedNode))
98123
linkedNode.addLinkBack(node, key)

0 commit comments

Comments
 (0)