1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
import {isExternalLinkContext} from '#external-links';
import {empty, stitchArrays} from '#sugar';
export default {
relations: (relation, urlEntries) => ({
externalLinks:
urlEntries.map(entry => relation('linkExternal', entry)),
}),
data: (urlEntries) => ({
totalEntries:
urlEntries.length,
annotatedEntries:
urlEntries.filter(entry => entry.annotation).length,
}),
slots: {
string: {type: 'string'},
context: {
validate: () => isExternalLinkContext,
default: 'generic',
},
contexts: {
validate: v => v.strictArrayOf(isExternalLinkContext),
default: [],
},
maximumTotalEntriesInLine: {type: 'number', default: 4},
maximumAnnotatedEntriesInLine: {type: 'number', default: 1},
maximumParenthesizedEntriesInLine: {type: 'number', default: 3},
},
generate(data, relations, slots, {html, language}) {
const {externalLinks} = relations;
if (empty(externalLinks)) {
return html.blank();
}
if (!html.isBlank(slots.contexts)) {
stitchArrays({
link: externalLinks,
linkContext: slots.contexts,
}).forEach(({link, linkContext}) => {
link.setSlot('context', [slots.context, linkContext].flat(Infinity));
});
} else {
externalLinks.forEach(link => {
link.setSlot('context', slots.context);
});
}
let style = 'line';
if (data.totalEntries > slots.maximumTotalEntriesInLine) {
style = 'list';
}
if (data.annotatedEntries > slots.maximumAnnotatedEntriesInLine) {
style = 'list';
}
let parenthesizedEntries = 0;
for (const item of externalLinks) {
const plainText = html.resolve(item, {normalize: 'plain'});
if (plainText.endsWith(')')) {
parenthesizedEntries++;
}
}
if (parenthesizedEntries > slots.maximumParenthesizedEntriesInLine) {
style = 'list';
}
switch (style) {
case 'line': return (
html.tag('p',
language.$(slots.string, {
links:
language.formatDisjunctionList(externalLinks),
}))
);
case 'list': return (
html.tags([
html.tag('p', language.$(slots.string, 'title')),
html.tag('ul',
externalLinks.map(link => html.tag('li', link))),
])
);
default:
return html.blank();
}
},
};
|