Add pronoun.page pronoun normalization

Especially for single-value pronoun.page URLs we want to show the
possessive pronoun as well. This is implemented by querying the API once
again and asking for the correct pronouns.

Closes #44.
This commit is contained in:
nachtjasmin 2023-07-16 10:53:16 +02:00
parent 6858978b99
commit 83aa9b41b0
No known key found for this signature in database
3 changed files with 37 additions and 9 deletions

View file

@ -66,6 +66,13 @@ async function extractFromField(field) {
return await queryUserFromPronounsPage(username); return await queryUserFromPronounsPage(username);
} }
// In case that we have single-word pronoun.page values, like "https://en.pronouns.page/it",
// we want to normalize that to include the possessive pronoun as well.
if (pronounsRaw.includes("pronouns.page") && !pronouns.includes("/")) {
return await normalizePronounPagePronouns(pronouns)
}
text = pronouns;
} }
if (!text) return null; if (!text) return null;
@ -107,20 +114,40 @@ async function queryUserFromPronounsPage(username) {
if (!pronouns) pronouns = profiles[0].pronouns; if (!pronouns) pronouns = profiles[0].pronouns;
let val = pronouns.find((x) => x.opinion === "yes" || x.opinion === "meh").value; let val = pronouns.find((x) => x.opinion === "yes" || x.opinion === "meh").value;
val = sanitizePronounPageValue(val); val = await normalizePronounPagePronouns(val);
return val; return val;
} }
/** /**
* @param {string} val * @param {string} val
* @returns {Promise<string>}
*/ */
function sanitizePronounPageValue(val) { async function normalizePronounPagePronouns(val) {
if (!val.startsWith("https://")) return val; const match = val.match(/pronouns\.page\/(.+)/);
if (match) val = match[1];
val = val.replace(/https?:\/\/.+\.pronouns\.page\/:?/, ""); if (val.includes("/")) return val;
if (val === "no-pronouns") val = "no pronouns"; if (val === "no-pronouns") return "no pronouns";
return val;
const pronounNameResp = await fetch("https://en.pronouns.page/api/pronouns/" + val);
if (!pronounNameResp.ok) {
// In case the request fails, better show the likely pronouns than nothing at all.
return val;
}
// If we query the pronouns.page API with invalid values, an empty body is returned, still with status code 200.
// Therefore, we just try to parse the JSON and if it does not work, we return the "val" from earlier and don't
// do further processing.
try {
const {
morphemes: { pronoun_subject, possessive_pronoun },
} = await pronounNameResp.json();
return [pronoun_subject, possessive_pronoun].join("/");
} catch {
return val;
}
} }
/** /**
@ -153,7 +180,7 @@ function sanitizePronouns(str) {
.join(" "); .join(" ");
// Remove trailing characters that are used as separators. // Remove trailing characters that are used as separators.
str = str.replace(/[-| /]+$/, ""); str = str.replace(/[-| :/]+$/, "");
// Finally, remove leading and trailing whitespace. // Finally, remove leading and trailing whitespace.
str = str.trim(); str = str.trim();

View file

@ -10,7 +10,7 @@
"description": "puts pronouns next to usernames on mastodon", "description": "puts pronouns next to usernames on mastodon",
"homepage_url": "https://github.com/ItsVipra/ProToots", "homepage_url": "https://github.com/ItsVipra/ProToots",
"permissions": ["storage", "https://en.pronouns.page/api/profile/get/*"], "permissions": ["storage", "https://en.pronouns.page/api/*"],
"browser_action": { "browser_action": {
"default_icon": "icons/icon small_size/icon small_size.png", "default_icon": "icons/icon small_size/icon small_size.png",

View file

@ -57,13 +57,14 @@ const valueExtractionTests = [
null, null,
], // 404 errors ], // 404 errors
[`<a href="https://de.pronouns.page/:Katze"></a>`, "Katze"], // custom pronouns [`<a href="https://de.pronouns.page/:Katze"></a>`, "Katze"], // custom pronouns
[`<a href="https://de.pronouns.page/@benaryorg"></a>`, "Katze"], // custom pronouns in profile [`<a href="https://de.pronouns.page/@benaryorg"></a>`, "Katze/Katze's"], // custom pronouns in profile
[`:theythem:`, null], // emojis shortcodes used for pronouns [`:theythem:`, null], // emojis shortcodes used for pronouns
[ [
// This is an actual example from a Mastodon field, with example.com redirecting to pronouns.page. // This is an actual example from a Mastodon field, with example.com redirecting to pronouns.page.
`dey/denen, es/ihm - <a href="https://example.com" rel="nofollow noopener noreferrer" target="_blank"><span class="invisible">https://</span><span class="">example.com</span><span class="invisible"></span></a>`, `dey/denen, es/ihm - <a href="https://example.com" rel="nofollow noopener noreferrer" target="_blank"><span class="invisible">https://</span><span class="">example.com</span><span class="invisible"></span></a>`,
"dey/denen, es/ihm", "dey/denen, es/ihm",
], ],
["https://en.pronouns.page/it", "it/its"], // single-word pronoun pages
]; ];
for (const [input, expects] of valueExtractionTests) { for (const [input, expects] of valueExtractionTests) {
valueExtractionSuite(input, async () => { valueExtractionSuite(input, async () => {