diff options
author | (quasar) nebula <qznebula@protonmail.com> | 2023-10-04 19:56:44 -0300 |
---|---|---|
committer | (quasar) nebula <qznebula@protonmail.com> | 2024-01-03 21:07:35 -0400 |
commit | 4ebe7fc5665b2428ab85ac1da888a2661a6fe94d (patch) | |
tree | 0eb78da70ceaa82186e3b2c2aaca285941fe804b | |
parent | a98f2af3d08c5566c188a79bc75c7168d2b555be (diff) |
external-links, test: fandom page links, custom "transform"
-rw-r--r-- | src/strings-default.yaml | 7 | ||||
-rw-r--r-- | src/util/external-links.js | 98 | ||||
-rw-r--r-- | tap-snapshots/test/snapshot/linkExternal.js.test.cjs | 18 | ||||
-rw-r--r-- | test/snapshot/linkExternal.js | 7 |
4 files changed, 126 insertions, 4 deletions
diff --git a/src/strings-default.yaml b/src/strings-default.yaml index 58f8401b..d194adde 100644 --- a/src/strings-default.yaml +++ b/src/strings-default.yaml @@ -505,6 +505,13 @@ misc: deviantart: "DeviantArt" + fandom: + _: "Fandom" + + mspaintadventures: + _: "MSPA Wiki" + page: "MSPA Wiki ({PAGE})" + homestuck: _: "Homestuck" page: "Homestuck (page {PAGE})" diff --git a/src/util/external-links.js b/src/util/external-links.js index 0b8b4ab6..57b6c3f6 100644 --- a/src/util/external-links.js +++ b/src/util/external-links.js @@ -6,6 +6,7 @@ import { isObject, isStringNonEmpty, optional, + validateAllPropertyValues, validateArrayItems, validateInstanceOf, validateProperties, @@ -35,10 +36,24 @@ export const isExternalLinkContext = is(...externalLinkContexts); const isRegExp = validateInstanceOf(RegExp); +export const isExternalLinkTransformCommand = + is(...[ + 'decode-uri', + 'find-replace', + ]); + +export const isExternalLinkTransformSpec = + anyOf( + isExternalLinkTransformCommand, + validateProperties({ + [validateProperties.allowOtherKeys]: true, + command: isExternalLinkTransformCommand, + })); + export const isExternalLinkExtractSpec = validateProperties({ prefix: optional(isStringNonEmpty), - + transform: optional(validateArrayItems(isExternalLinkTransformSpec)), url: optional(isRegExp), domain: optional(isRegExp), pathname: optional(isRegExp), @@ -79,7 +94,7 @@ export const isExternalLinkSpec = handle: optional(isExternalLinkExtractSpec), // TODO: This should validate each value with isExternalLinkExtractSpec. - custom: optional(isObject), + custom: optional(validateAllPropertyValues(isExternalLinkExtractSpec)), })); export const fallbackDescriptor = { @@ -268,6 +283,44 @@ export const externalLinkSpec = [ }, { + match: { + domain: 'mspaintadventures.fandom.com', + pathname: /^wiki\/(.+)\/?$/, + }, + + platform: 'fandom', + substring: 'mspaintadventures.page', + + normal: 'custom', + icon: 'globe', + + custom: { + page: { + pathname: /^wiki\/(.+)\/?$/, + transform: [ + {command: 'decode-uri'}, + {command: 'find-replace', find: /_/g, replace: ' '}, + ], + }, + }, + }, + + { + match: {domain: 'mspaintadventures.fandom.com'}, + + platform: 'fandom', + substring: 'mspaintadventures', + + icon: 'globe', + }, + + { + match: {domain: 'fandom.com'}, + platform: 'fandom', + icon: 'globe', + }, + + { match: {domain: 'homestuck.com'}, platform: 'homestuck', icon: 'globe', @@ -422,6 +475,7 @@ export function extractPartFromExternalLink(url, extract) { let regexen = []; let tests = []; + let transform = []; let prefix = ''; if (extract instanceof RegExp) { @@ -434,6 +488,32 @@ export function extractPartFromExternalLink(url, extract) { prefix = value; continue; + case 'transform': + for (const entry of value) { + const command = + (typeof entry === 'string' + ? command + : entry.command); + + const options = + (typeof entry === 'string' + ? {} + : entry); + + switch (command) { + case 'decode-uri': + transform.push(value => + decodeURIComponent(value)); + break; + + case 'find-replace': + transform.push(value => + value.replace(options.find, options.replace)); + break; + } + } + continue; + case 'url': tests.push(url); break; @@ -459,17 +539,27 @@ export function extractPartFromExternalLink(url, extract) { } } + let value; for (const {regex, test} of stitchArrays({ regex: regexen, test: tests, })) { const match = test.match(regex); if (match) { - return prefix + (match[1] ?? match[0]); + value = prefix + (match[1] ?? match[0]); + break; } } - return null; + if (!value) { + return null; + } + + for (const fn of transform) { + value = fn(value); + } + + return value; } export function extractAllCustomPartsFromExternalLink(url, custom) { diff --git a/tap-snapshots/test/snapshot/linkExternal.js.test.cjs b/tap-snapshots/test/snapshot/linkExternal.js.test.cjs index a9116be4..1327ba02 100644 --- a/tap-snapshots/test/snapshot/linkExternal.js.test.cjs +++ b/tap-snapshots/test/snapshot/linkExternal.js.test.cjs @@ -64,6 +64,12 @@ exports[`test/snapshot/linkExternal.js > TAP > linkExternal (snapshot) > context <a href="https://buzinkai.newgrounds.com/" class="nowrap">buzinkai.newgrounds.com</a> <a href="https://music.solatrus.com/" class="nowrap">music.solatrus.com</a> <a href="https://types.pl/" class="nowrap">types.pl</a> +<a href="https://community.fandom.com/" class="nowrap">community.fandom.com</a> +<a href="https://community.fandom.com/wiki/" class="nowrap">community.fandom.com</a> +<a href="https://community.fandom.com/wiki/Community_Central" class="nowrap">community.fandom.com</a> +<a href="https://mspaintadventures.fandom.com/" class="nowrap">mspaintadventures.fandom.com</a> +<a href="https://mspaintadventures.fandom.com/wiki/" class="nowrap">mspaintadventures.fandom.com</a> +<a href="https://mspaintadventures.fandom.com/wiki/Draconian_Dignitary" class="nowrap">mspaintadventures.fandom.com</a> ` exports[`test/snapshot/linkExternal.js > TAP > linkExternal (snapshot) > context: generic, style: normal 1`] = ` @@ -80,6 +86,12 @@ exports[`test/snapshot/linkExternal.js > TAP > linkExternal (snapshot) > context <a href="https://buzinkai.newgrounds.com/" class="nowrap">Newgrounds</a> <a href="https://music.solatrus.com/" class="nowrap">Bandcamp (music.solatrus.com)</a> <a href="https://types.pl/" class="nowrap">Mastodon (types.pl)</a> +<a href="https://community.fandom.com/" class="nowrap">Fandom</a> +<a href="https://community.fandom.com/wiki/" class="nowrap">Fandom</a> +<a href="https://community.fandom.com/wiki/Community_Central" class="nowrap">Fandom</a> +<a href="https://mspaintadventures.fandom.com/" class="nowrap">MSPA Wiki</a> +<a href="https://mspaintadventures.fandom.com/wiki/" class="nowrap">MSPA Wiki</a> +<a href="https://mspaintadventures.fandom.com/wiki/Draconian_Dignitary" class="nowrap">MSPA Wiki (Draconian Dignitary)</a> ` exports[`test/snapshot/linkExternal.js > TAP > linkExternal (snapshot) > context: generic, style: platform 1`] = ` @@ -96,6 +108,12 @@ exports[`test/snapshot/linkExternal.js > TAP > linkExternal (snapshot) > context <a href="https://buzinkai.newgrounds.com/" class="nowrap">Newgrounds</a> <a href="https://music.solatrus.com/" class="nowrap">Bandcamp</a> <a href="https://types.pl/" class="nowrap">Mastodon</a> +<a href="https://community.fandom.com/" class="nowrap">Fandom</a> +<a href="https://community.fandom.com/wiki/" class="nowrap">Fandom</a> +<a href="https://community.fandom.com/wiki/Community_Central" class="nowrap">Fandom</a> +<a href="https://mspaintadventures.fandom.com/" class="nowrap">Fandom</a> +<a href="https://mspaintadventures.fandom.com/wiki/" class="nowrap">Fandom</a> +<a href="https://mspaintadventures.fandom.com/wiki/Draconian_Dignitary" class="nowrap">Fandom</a> ` exports[`test/snapshot/linkExternal.js > TAP > linkExternal (snapshot) > unknown domain (arbitrary world wide web path) 1`] = ` diff --git a/test/snapshot/linkExternal.js b/test/snapshot/linkExternal.js index 434372a9..92cb8947 100644 --- a/test/snapshot/linkExternal.js +++ b/test/snapshot/linkExternal.js @@ -42,6 +42,13 @@ testContentFunctions(t, 'linkExternal (snapshot)', async (t, evaluate) => { // Just one custom domain of each platform is OK here 'https://music.solatrus.com/', 'https://types.pl/', + + 'https://community.fandom.com/', + 'https://community.fandom.com/wiki/', + 'https://community.fandom.com/wiki/Community_Central', + 'https://mspaintadventures.fandom.com/', + 'https://mspaintadventures.fandom.com/wiki/', + 'https://mspaintadventures.fandom.com/wiki/Draconian_Dignitary', ]); quickSnapshotAllStyles('album', [ |