Skip to content

Commit d3d20a6

Browse files
committed
LinkWizard: add method to create a relative link
This is not used, yet. Usage will be added in a future commit. Since we don't have a proper testing framework in place, yet. Tests have been added as a standalone script that can be run manually.
1 parent d2fda51 commit d3d20a6

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed

lib/scripts/linkwiz.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,69 @@ class LinkWizard {
336336
this.hide();
337337
}
338338
}
339+
340+
/**
341+
* Create a relative ID from a given reference ID and a full ID to link to
342+
*
343+
* Both IDs are expected to be clean, (eg. the result of cleanID()). No relative paths,
344+
* leading colons or similar things are alowed. As long as pages have a common prefix,
345+
* a relative link is constructed.
346+
*
347+
* This method is static and meant to be reused by other scripts if needed.
348+
*
349+
* @todo does currently not create page relative links using ~
350+
* @param {string} ref The ID of a page the link is used on
351+
* @param {string} id The ID to link to
352+
*/
353+
static createRelativeID(ref, id) {
354+
const sourceNs = ref.split(':');
355+
[/*sourcePage*/] = sourceNs.pop();
356+
const targetNs = id.split(':');
357+
const targetPage = targetNs.pop()
358+
const relativeID = [];
359+
360+
// Find the common prefix length
361+
let commonPrefixLength = 0;
362+
while (
363+
commonPrefixLength < sourceNs.length &&
364+
commonPrefixLength < targetNs.length &&
365+
sourceNs[commonPrefixLength] === targetNs[commonPrefixLength]
366+
) {
367+
commonPrefixLength++;
368+
}
369+
370+
371+
if (sourceNs.length) {
372+
// special treatment is only needed when the reference is a namespaced page
373+
if (commonPrefixLength) {
374+
if (commonPrefixLength === sourceNs.length && commonPrefixLength === targetNs.length) {
375+
// both pages are in the same namespace
376+
// link consists of simple page only
377+
// namespaces are irrelevant
378+
} else if (commonPrefixLength < sourceNs.length) {
379+
// add .. for each missing namespace from common to the target
380+
relativeID.push('..'.repeat(sourceNs.length - commonPrefixLength));
381+
} else {
382+
// target is below common prefix, add .
383+
relativeID.push('.');
384+
}
385+
} else if (targetNs.length === 0) {
386+
// target is in the root namespace, but source is not, make it absolute
387+
relativeID.push('');
388+
}
389+
// add any remaining parts of targetNS
390+
relativeID.push(...targetNs.slice(commonPrefixLength));
391+
} else {
392+
// source is in the root namespace, just use target as is
393+
relativeID.push(...targetNs);
394+
}
395+
396+
// add targetPage
397+
relativeID.push(targetPage);
398+
399+
return relativeID.join(':');
400+
}
401+
339402
}
340403

341404
const dw_linkwiz = new LinkWizard();

lib/scripts/linkwiz.test.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* Tests for the LinkWizard class
3+
*
4+
* This is a simple self-contained test suite until we introduce a proper way to run JavaScript tests
5+
* in DokuWiki.
6+
*
7+
* Needs to be run manually as:
8+
*
9+
* cat linkwiz.js linkwiz.test.js | node
10+
*/
11+
12+
function runLinkWizardTests() {
13+
const testCases = [
14+
{ ref: 'a:b:c', id: 'a:b:d', expected: 'd' },
15+
{ ref: 'a:b:c', id: 'a:b:c:d:e', expected: '.:c:d:e' },
16+
{ ref: 'a:b:c', id: 'a:b:c:d:e', expected: '.:c:d:e' },
17+
{ ref: 'a', id: 'a:b:c', expected: 'a:b:c' },
18+
{ ref: 'a:b', id: 'c:d', expected: 'c:d' },
19+
{ ref: 'a:b:c', id: 'a:d:e', expected: '..:d:e' },
20+
{ ref: 'a:b', id: 'c', expected: ':c' },
21+
];
22+
23+
testCases.forEach(({ ref, id, expected }, index) => {
24+
const result = LinkWizard.createRelativeID(ref, id);
25+
if (result === expected) {
26+
console.log(`Test ${index + 1} passed`);
27+
} else {
28+
console.log(`Test ${index + 1} failed: expected ${expected}, got ${result}`);
29+
}
30+
});
31+
}
32+
33+
// Run the tests
34+
runLinkWizardTests();

0 commit comments

Comments
 (0)