const verbsHelper = require('english-verbs-helper'); const verbsIrregular = require('english-verbs-irregular/dist/verbs.json'); const verbsGerunds = require('english-verbs-gerunds/dist/gerunds.json'); const verbsData = verbsHelper.mergeVerbsData(verbsIrregular, verbsGerunds); function replaceAll() { browser.storage.local.get(null, (options) => { const hostname = window.location.hostname; const isEnabled = !(options.domains === undefined) && options.domains.includes(hostname); if (!isEnabled) { return; } const isNameSet = !(options.name === undefined || options.name == ""); const isPronounsSet = !(options.preset === undefined || options.preset == ""); const isPovSet = !(options.pov === undefined || options.pov == ""); const isPovLegal = isPovSet && (options.pov != "third" || (isNameSet && isPronounsSet)); if (isPovLegal) { replaceVerbs(options); replacePov(options); replacePlv(options); } if (isNameSet) { replaceName(options); } if (isPronounsSet) { replacePronouns(options); } const isAlsoSet = !options.also === undefined; if (isAlsoSet) { replaceAlso(options); } }); } function replaceName(options) { const search_term = /\by\/n\b|\(y\/n\)|\[y\/n\]/ig; walk(document.body, search_term, options["name"], directMethod); } function replaceVerbs(options) { const isPluralThird = options.pov == "third" && getPronouns(options.preset, options.other).plurality == "plural"; if (isPluralThird) { const search_term = /([Pp])(?:rn|ov)\/S [Vv]rb\/([\w\s]+)\/([\w\s]+)\/|[Vv]rb\/([\w\s]+)\/([\w\s]+)\/ ([Pp])(?:rn|ov)\/S/; walk(document.body, search_term, options, pluralThirdVerbMethod); } const search_term = /vrb\/([\w\s]+)\/([\w\s]+)\//; walk(document.body, search_term, options, verbMethod); } /* This could be made faster if I give premade regexp expressions for each, but I don't want to do that! */ function replacePronouns(options) { let pronouns = getPronouns(options.preset, options.other); replacePronounSet("Prn/s", "prn/s", pronouns["subjective"]); replacePronounSet("Prn/o", "prn/o", pronouns["objective"]); replacePronounSet("Prn/p", "prn/p", pronouns["possessive"]); replacePronounSet("Prn/a", "prn/a", pronouns["adjective"]); replacePronounSet("Prn/r", "prn/r", pronouns["reflexive"]); replacePronounSet("Prn/H", "prn/H", pronouns["honorific-abbr"]); replacePronounSet("Prn/h", "prn/h", pronouns["honorific"]); replacePronounSet("Prn/N", "prn/N", pronouns["noun-adult"]); replacePronounSet("Prn/n", "prn/n", pronouns["noun-child"]); } function getPronouns(key, other) { switch (key) { case "she": return { "subjective": "she", "objective": "her", "possessive": "her", "adjective": "hers", "reflexive": "herself", "honorific-abbr": "Ms.", "honorific": "miss", "noun-adult": "woman", "noun-child": "girl", "plurality": "singular" }; case "he": return { "subjective": "he", "objective": "him", "possessive": "his", "adjective": "his", "reflexive": "himself", "honorific-abbr": "Mr.", "honorific": "mister", "noun-adult": "man", "noun-child": "boy", "plurality": "singular" }; case "they": return { "subjective": "they", "objective": "them", "possessive": "their", "adjective": "theirs", "reflexive": "themself", "honorific-abbr": "Mx.", "honorific": "mix", "noun-adult": "person", "noun-child": "kid", "plurality": "plural" }; case "first": return { "subjective": "I", "objective": "me", "possessive": "my", "adjective": "mine", "reflexive": "myself" }; case "second": return { "subjective": "you", "objective": "you", "possessive": "your", "adjective": "yours", "reflexive": "yourself" }; case "first-plural": return { "subjective": "we", "objective": "us", "possessive": "our", "adjective": "ours", "reflexive": "ourselves" }; case "second-plural": return { "subjective": "you", "objective": "you", "possessive": "your", "adjective": "yours", "reflexive": "yourselves" }; case "third-plural": return { "subjective": "they", "objective": "them", "possessive": "their", "adjective": "theirs", "reflexive": "themselves" }; case "other": return other; } } function replacePronounSet(keyCapital, key, pronoun) { escapeAndReplace(keyCapital, capitalize(pronoun), true); escapeAndReplace(key, pronoun, true); } function replacePov(options) { let pronouns; if (options.pov == "third") { pronouns = getPronouns(options.preset, options.other); replacePronounSet("Pov/S", "pov/S", options.name); replacePronounSet("Pov/O", "pov/O", options.name); replacePronounSet("Pov/P", "pov/P", options.name + "'s"); replacePronounSet("Pov/A", "pov/A", options.name + "'s"); replacePronounSet("Pov/R", "pov/R", options.name + "'s self"); } else { pronouns = getPronouns(options.pov, null); replacePronounSet("Pov/S", "pov/S", pronouns["subjective"]); replacePronounSet("Pov/O", "pov/O", pronouns["objective"]); replacePronounSet("Pov/P", "pov/P", pronouns["possessive"]); replacePronounSet("Pov/A", "pov/A", pronouns["adjective"]); replacePronounSet("Pov/R", "pov/R", pronouns["reflexive"]); } replacePronounSet("Pov/s", "pov/s", pronouns["subjective"]); replacePronounSet("Pov/o", "pov/o", pronouns["objective"]); replacePronounSet("Pov/p", "pov/p", pronouns["possessive"]); replacePronounSet("Pov/a", "pov/a", pronouns["adjective"]); replacePronounSet("Pov/r", "pov/r", pronouns["reflexive"]); } function replacePlv(options) { let pronouns = getPronouns(options.pov + "-plural", null); replacePronounSet("Plv/s", "plv/s", pronouns["subjective"]); replacePronounSet("Plv/o", "plv/o", pronouns["objective"]); replacePronounSet("Plv/p", "plv/p", pronouns["possessive"]); replacePronounSet("Plv/a", "plv/a", pronouns["adjective"]); replacePronounSet("Plv/r", "plv/r", pronouns["reflexive"]); } function replaceAlso(options) { Object.entries(options.also).forEach(([key, value]) => { escapeAndReplace(key, value, true); }); } function escapeAndReplace(search_term, replace_value, case_sensitive) { let search_term_escaped = search_term.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); const flags = case_sensitive ? "g" : "ig" if (search_term_escaped[0].match(/[a-z]/i)) { search_term_escaped = `\\b${search_term_escaped}` } if (search_term_escaped[search_term_escaped.length - 1].match((/[a-z]/i))) { search_term_escaped = `${search_term_escaped}\\b` } const search_term_regexp = new RegExp(search_term_escaped, flags) walk(document.body, search_term_regexp, replace_value, directMethod); } function walk(node, search_term, replace_value, replaceMethod) { if (node.contentEditable == "true" || node.type == "textarea" || node.type == "input") { return; } let child, next; switch (node.nodeType) { case 1: /* ELEMENT_NODE */ case 9: /* DOCUMENT_NODE */ case 11: /* DOCUMENT_FRAGMENT_NODE */ child = node.firstChild; while (child) { next = child.nextSibling; walk(child, search_term, replace_value, replaceMethod); child = next; } break; case 3: /* TEXT_NODE */ replaceMethod(node, search_term, replace_value); } } function directMethod(node, search_term, replace_value) { node.nodeValue = node.nodeValue.replaceAll(search_term, replace_value); } //TODO are "options" here named comprehensibly function verbMethod(node, search_term, options) { let match = node.nodeValue.match(search_term); if (match == null) { return; } const verb = match[1]; const tense = match[2].toUpperCase().replaceAll(" ", "_"); const replace_value = verbsHelper.getConjugation(verbsData, verb, tense, getPovIndex(options)); node.nodeValue = node.nodeValue.replace(search_term, replace_value); verbMethod(node, search_term, options); } function pluralThirdVerbMethod(node, search_term, options) { let match = node.nodeValue.match(search_term); if (match == null) { return; } const before = match[1]; const after = match[4]; const wasBefore = !(before === undefined); let verb, tense; if (wasBefore) { verb = match[2]; tense = match[3]; } else { verb = match[5]; tense = match[6]; } tense = tense.toUpperCase().replaceAll(" ", "_"); const replace_verb = verbsHelper.getConjugation(verbsData, verb, tense, 2); let replace_value; if (wasBefore) { replace_value = options["name"] + " " + replace_verb; } else { replace_value = replace_verb + " " + options["name"]; } node.nodeValue = node.nodeValue.replace(search_term, replace_value); pluralThirdVerbMethod(node, search_term, options); } function capitalize(word) { return word.charAt(0).toUpperCase() + word.slice(1); } // TODO figure out plv for this function getPovIndex(options) { switch (options.pov) { case "first": return 0; case "second": return 1; case "third": if (getPronouns(options.preset, options.other).plurality == "singular") { return 2; } else { /* Plurality is plural, "they go" */ return 5; } } } replaceAll();