diff options
Diffstat (limited to 'src/content/dependencies/generateExternalLinksLineOrList.js')
| -rw-r--r-- | src/content/dependencies/generateExternalLinksLineOrList.js | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/src/content/dependencies/generateExternalLinksLineOrList.js b/src/content/dependencies/generateExternalLinksLineOrList.js new file mode 100644 index 00000000..18922db6 --- /dev/null +++ b/src/content/dependencies/generateExternalLinksLineOrList.js @@ -0,0 +1,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(); + } + }, +}; |