Initial commit
This commit is contained in:
parent
5d7c9d6e07
commit
c2dcb27f8c
|
@ -0,0 +1,39 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 0,
|
||||||
|
"narHash": "sha256-463SNPWmz46iLzJKRzO3Q2b0Aurff3U1n0nYItxq7jU=",
|
||||||
|
"path": "/nix/store/yw6kg4rb9v8s3ypjbpspig5r81m4lr5s-source",
|
||||||
|
"type": "path"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"id": "nixpkgs",
|
||||||
|
"type": "indirect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"systems": "systems"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
inputs = {
|
||||||
|
# nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||||
|
systems.url = "github:nix-systems/default";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs =
|
||||||
|
{ systems, nixpkgs, ... }@inputs:
|
||||||
|
let
|
||||||
|
eachSystem = f: nixpkgs.lib.genAttrs (import systems) (system: f nixpkgs.legacyPackages.${system});
|
||||||
|
in
|
||||||
|
{
|
||||||
|
devShells = eachSystem (pkgs: {
|
||||||
|
default = pkgs.mkShell {
|
||||||
|
buildInputs = [
|
||||||
|
pkgs.nodejs_22
|
||||||
|
];
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 512 512"
|
||||||
|
width="32"
|
||||||
|
height="32"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
sodipodi:docname="library.svg"
|
||||||
|
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs1">
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient11"
|
||||||
|
inkscape:collect="always">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#2a90cb;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop12" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#2a90cb;stop-opacity:1;"
|
||||||
|
offset="0.45122612"
|
||||||
|
id="stop13" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#22719a;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop11" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient1"
|
||||||
|
inkscape:swatch="gradient">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#27983a;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop1" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#27983a;stop-opacity:0;"
|
||||||
|
offset="1"
|
||||||
|
id="stop2" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient11"
|
||||||
|
id="linearGradient12"
|
||||||
|
x1="256"
|
||||||
|
y1="4.7133198"
|
||||||
|
x2="256"
|
||||||
|
y2="516.71332"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview1"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.25"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:zoom="14.230524"
|
||||||
|
inkscape:cx="15.143504"
|
||||||
|
inkscape:cy="10.435315"
|
||||||
|
inkscape:window-width="1277"
|
||||||
|
inkscape:window-height="864"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="0"
|
||||||
|
inkscape:current-layer="svg1" />
|
||||||
|
<path
|
||||||
|
id="path11"
|
||||||
|
style="fill:#2a90cb;fill-opacity:1;stroke:url(#linearGradient12);stroke-width:15.5153;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
|
||||||
|
d="m 215.22028,38.871995 c -4.34372,0.303826 -8.65502,1.096343 -12.79663,2.448948 -5.93985,1.922995 -11.53239,4.920956 -16.41582,8.811486 -1.76365,1.417918 -3.46026,2.919246 -5.01704,4.56358 -14.636,-3.798687 -29.75685,-5.860967 -44.88746,-5.742441 -14.68272,0.379878 -29.51967,2.710272 -43.033824,8.664817 -10.977835,4.822375 -20.961579,12.233426 -28.009521,22.005037 -7.050461,9.664813 -10.992922,21.550288 -11.066377,33.516658 -0.169287,14.92345 5.535781,29.70673 15.271568,40.96315 4.373745,5.08863 9.549047,9.48723 15.279627,12.97831 0.542441,5.29028 1.667985,10.52221 3.376926,15.55886 -23.221327,10.97251 -43.33471,28.4246 -57.436944,49.89292 -12.70417,19.22237 -20.483342,41.67752 -22.2863846,64.65411 -1.5554936,19.84165 0.9781838,40.10268 8.1825416,58.70009 6.210988,16.16091 15.894545,30.87732 27.739004,43.46312 16.487951,17.57083 36.752681,31.11853 57.877414,42.47694 0.75168,0.43906 1.59701,0.77511 2.29306,1.27388 2.86679,4.6313 5.37096,9.48946 8.52384,13.94228 5.45956,7.92277 12.65714,14.75439 21.2551,19.16193 9.6394,5.0174 20.71523,6.96599 31.51599,6.28795 10.90179,-0.83701 21.2892,-4.91931 30.77723,-10.18133 12.4166,-6.93812 23.56256,-15.98376 33.58249,-26.03914 9.96279,-10.0289 18.79496,-21.17022 26.39113,-33.0889 10.87699,16.91934 24.18793,32.34401 39.74938,45.12077 10.00713,8.14757 20.97471,15.31593 33.06537,19.95959 7.93816,3.03334 16.45952,4.79051 24.9827,4.29735 10.21404,-0.42126 20.38768,-3.4272 28.9131,-9.13093 7.64187,-5.02101 13.76108,-12.06794 18.51752,-19.82113 2.18351,-3.46929 4.05021,-7.12613 6.22223,-10.6015 19.47332,-10.29917 38.22477,-22.35497 54.16907,-37.65945 12.90338,-12.36533 23.80556,-26.96729 31.10415,-43.32695 7.42472,-16.45569 11.06132,-34.51755 11.17414,-52.54357 0.26042,-23.29706 -5.49528,-46.63235 -16.59853,-67.11795 -11.57326,-21.48158 -28.90977,-39.80528 -49.69952,-52.57602 -4.32446,-2.66803 -8.80214,-5.08501 -13.38779,-7.27285 1.71297,-5.08008 2.82802,-10.35954 3.34284,-15.69522 13.91733,-8.58279 24.37005,-22.65677 28.36297,-38.53166 3.18363,-12.38154 2.28224,-25.81377 -2.79783,-37.567954 C 448.76107,79.66973 440.5163,70.303487 430.53327,63.714302 419.01053,56.051725 405.46698,51.925294 391.83504,50.11818 c -7.83832,-1.029924 -15.76743,-1.426209 -23.66581,-1.013174 -12.38775,0.548433 -24.70857,2.456562 -36.70542,5.583427 -1.54528,-1.866107 -3.52301,-3.287056 -5.31823,-4.89588 -2.23763,-1.449855 -4.41243,-3.00815 -6.6898,-4.389415 -2.08719,-1.000821 -4.08801,-2.204635 -6.31907,-2.867257 -2.34646,-0.768464 -4.61216,-1.818471 -7.05535,-2.249609 -1.7561,-0.398382 -3.50633,-0.834055 -5.3136,-0.907448 -2.46607,-0.17371 -4.92244,-0.640087 -7.40012,-0.463166 -1.80034,0.04161 -3.60407,0.04563 -5.3749,0.414583 -2.43413,0.432272 -4.93022,0.578062 -7.29011,1.353554 -1.73521,0.47884 -3.48277,0.922329 -5.10986,1.710803 -2.25278,1.010618 -4.63539,1.758472 -6.73261,3.083917 -1.56702,0.887219 -3.15474,1.742947 -4.54121,2.904546 -1.94148,1.531076 -4.07302,2.83879 -5.78679,4.637466 -0.8085,0.794753 -1.6512,1.558226 -2.43839,2.372458 -6.54832,-7.042367 -15.07389,-12.223504 -24.35195,-14.760401 -4.45885,-1.22347 -9.08035,-1.881211 -13.70735,-1.838619 -0.93882,-0.03679 -1.87608,0.05046 -2.81419,0.07803 z"
|
||||||
|
inkscape:label="behind" />
|
||||||
|
<path
|
||||||
|
d="m 217.5,62.992572 a 21.875,21.875 0 0 0 -21.875,24.5 c -20.125,-9.625 -42.875,-14 -62.125,-14 -77,1.75 -59.5,66.499998 -21,67.374998 -4.375,20.125 -1.75,37.625 23.625,56.875 -57.75,4.375 -104.125,52.5 -104.125,111.125 0,55.125 37.625,87.5 84.875,112 15.75,8.75 14,35.875 42,35.875 27.125,0 98,-59.5 97.125,-148.75 0,89.25 70.875,148.75 98,148.75 27.125,0 25.375,-27.125 41.125,-35.875 47.25,-24.5 84.875,-56.875 84.875,-112 0,-58.625 -45.5,-106.75 -103.25,-111.125 24.5,-19.25 28,-36.75 22.75,-56.875 38.5,-0.875 56,-65.624998 -20.125,-67.374998 -20.125,0 -42,4.375 -63,14 l 0.875,-2.625 a 21.875,21.875 0 1 0 -28,20.999998 c -17.5,14.875 -30.625,36.75 -33.25,64.75 -1.75,-28 -14.875,-49.875 -33.25,-64.75 A 21.875,21.875 0 0 0 217.5,62.992572 Z m -77,174.999998 a 70,70 0 1 1 0,140 70,70 0 0 1 0,-140 z m 231,0 a 70,70 0 1 1 0,140 70,70 0 0 1 0,-140 z m -236.25,44.625 a 27.125,27.125 0 1 0 0,54.25 27.125,27.125 0 0 0 0,-54.25 z m 241.5,0 a 27.125,27.125 0 1 0 0,54.25 27.125,27.125 0 0 0 0,-54.25 z"
|
||||||
|
style="display:inline;fill:#fcfaf8;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers;fill-opacity:1"
|
||||||
|
id="path1" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 6.6 KiB |
|
@ -0,0 +1,630 @@
|
||||||
|
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);
|
||||||
|
const articleHelper = require("indefinite");
|
||||||
|
|
||||||
|
/* Replaces MetamorPOV markers with English according to the options */
|
||||||
|
exports.translate = function(input, options) {
|
||||||
|
let request = {
|
||||||
|
input: input,
|
||||||
|
options: options,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof(input) == "object" && input instanceof Node) {
|
||||||
|
request.loop = loopNode;
|
||||||
|
}
|
||||||
|
else if (typeof(input) == "string") {
|
||||||
|
request.loop = loopString;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.error("Invalid input type");
|
||||||
|
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) {
|
||||||
|
vrb(request);
|
||||||
|
pov(request);
|
||||||
|
plv(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNameSet) {
|
||||||
|
yn(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPronounsSet) {
|
||||||
|
prn(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
const isAlsoSet = !(options.also === undefined);
|
||||||
|
if (isAlsoSet) {
|
||||||
|
also(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
const isAllSet = isNameSet && isPronounsSet && isPovLegal;
|
||||||
|
if (isAllSet) {
|
||||||
|
alt(request);
|
||||||
|
ife(request);
|
||||||
|
cut(request);
|
||||||
|
cap(request);
|
||||||
|
mrr(request);
|
||||||
|
aan(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
return request.input;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Iterator for HTML Node elements */
|
||||||
|
function loopNode(request, params, method) {
|
||||||
|
const node = request.input;
|
||||||
|
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;
|
||||||
|
loopNode(node, params, method);
|
||||||
|
child = next;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3: /* TEXT_NODE */
|
||||||
|
loopString(node.nodeValue, params, method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Iterator for string elements */
|
||||||
|
function loopString(request, params, method) {
|
||||||
|
if (request.input.match(params.regexp) == null) { return; }
|
||||||
|
request.input = method(request.input, params);
|
||||||
|
loopString(request, params, method);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vrb/be/ becomes "were" in second-person and "was" in third-person POV */
|
||||||
|
function vrb(request) {
|
||||||
|
const regexp = new RegExp([
|
||||||
|
/(?<firstLetter>v)r/,
|
||||||
|
/(?<category>[nb])\//,
|
||||||
|
/(?<verb>[\w\s]+)\//,
|
||||||
|
/(?:(?<tense>(?:(?:simple|progressive|perfect|perfect[ _]progressive|participle(?![ _]future))[ _])*(?:past|present|future))\/)*/
|
||||||
|
].map(r => r.source).join(''),'i');
|
||||||
|
|
||||||
|
request.loop(request, {
|
||||||
|
regexp: regexp,
|
||||||
|
options: request.options
|
||||||
|
}, (input, params) => {
|
||||||
|
const options = params.options;
|
||||||
|
const vars = input.match(params.regexp).groups;
|
||||||
|
let tense = vars.tense;
|
||||||
|
if (tense == null) {
|
||||||
|
tense = "PAST";
|
||||||
|
} else {
|
||||||
|
tense = tense.toUpperCase().replaceAll(" ", "_");
|
||||||
|
}
|
||||||
|
|
||||||
|
let povIndex;
|
||||||
|
switch (vars.category) {
|
||||||
|
case "B": /* B and b vary by POV, capitalized to indicate a named subject */
|
||||||
|
if (options.pov == "third") {
|
||||||
|
povIndex = getPovIndex("third-singular", null);
|
||||||
|
} else {
|
||||||
|
povIndex = getPovIndex(options.pov, options);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "b":
|
||||||
|
povIndex = getPovIndex(options.pov, options);
|
||||||
|
break;
|
||||||
|
case "N": /* N and n are always third-person */
|
||||||
|
povIndex = getPovIndex("third-singular", null);
|
||||||
|
break;
|
||||||
|
case "n":
|
||||||
|
povIndex = getPovIndex("third", options);
|
||||||
|
}
|
||||||
|
|
||||||
|
let replacement = verbsHelper.getConjugation(verbsData, vars.verb, tense, povIndex);
|
||||||
|
const isCapital = /V/.test(vars.firstLetter);
|
||||||
|
if (isCapital) {
|
||||||
|
replacement = capitalize(replacement);
|
||||||
|
}
|
||||||
|
return input.replace(params.regexp, replacement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pov/s becomes "I" or "you" or "she" by POV */
|
||||||
|
function pov(request) {
|
||||||
|
const options = request.options;
|
||||||
|
let pronouns, params;
|
||||||
|
if (request.options.pov == "third") {
|
||||||
|
pronouns = getPronouns(options.preset, options.other);
|
||||||
|
params = [
|
||||||
|
{
|
||||||
|
regexp: /([Pp])ov\/S/,
|
||||||
|
pronoun: options.name
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])ov\/O/,
|
||||||
|
pronoun: options.name
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])ov\/P/,
|
||||||
|
pronoun: options.name + "’s"
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])ov\/A/,
|
||||||
|
pronoun: options.name + "’s"
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])ov\/R/,
|
||||||
|
pronoun: options.name + "’s self"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
pronouns = getPronouns(options.pov, null);
|
||||||
|
params = [
|
||||||
|
{
|
||||||
|
regexp: /([Pp])ov\/S/,
|
||||||
|
pronoun: pronouns["subjective"]
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])ov\/O/,
|
||||||
|
pronoun: pronouns["objective"]
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])ov\/P/,
|
||||||
|
pronoun: pronouns["possessive"]
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])ov\/A/,
|
||||||
|
pronoun: pronouns["adjective"]
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])ov\/R/,
|
||||||
|
pronoun: pronouns["reflexive"]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
params.push(
|
||||||
|
{
|
||||||
|
regexp: /([Pp])ov\/s/,
|
||||||
|
pronoun: pronouns["subjective"]
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])ov\/o/,
|
||||||
|
pronoun: pronouns["objective"]
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])ov\/p/,
|
||||||
|
pronoun: pronouns["possessive"]
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])ov\/a/,
|
||||||
|
pronoun: pronouns["adjective"]
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])ov\/r/,
|
||||||
|
pronoun: pronouns["reflexive"]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
params.forEach((pronoun) => request.loop(request, pronoun, prnHelper));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* prn/s becomes "we" or "they" by POV */
|
||||||
|
function plv(request) {
|
||||||
|
const pronouns = getPronouns(request.options.pov + "-plural", null);
|
||||||
|
const params = [
|
||||||
|
{
|
||||||
|
regexp: /([Pp])lv\/s/,
|
||||||
|
pronoun: pronouns["subjective"]
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])lv\/o/,
|
||||||
|
pronoun: pronouns["objective"]
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])lv\/p/,
|
||||||
|
pronoun: pronouns["possessive"]
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])lv\/a/,
|
||||||
|
pronoun: pronouns["adjective"]
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])lv\/r/,
|
||||||
|
pronoun: pronouns["reflexive"]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
params.forEach((pronoun) => request.loop(request, pronoun, prnHelper));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Y/n becomes the name indicated in the options */
|
||||||
|
function yn(request) {
|
||||||
|
request.loop(request, {
|
||||||
|
regexp: /\by\/n\b|\(y\/n\)|\[y\/n\]/ig,
|
||||||
|
replacement: request.options["name"]
|
||||||
|
}, (input, params) => {
|
||||||
|
return input.replaceAll(params.regexp, params.replacement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* prn/s becomes "he" or "she" and are always third-person */
|
||||||
|
function prn(request) {
|
||||||
|
const pronouns = getPronouns(request.options.preset, request.options.other);
|
||||||
|
const params = [
|
||||||
|
{
|
||||||
|
regexp: /([Pp])rn\/s/,
|
||||||
|
pronoun: pronouns["subjective"]
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])rn\/o/,
|
||||||
|
pronoun: pronouns["objective"]
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])rn\/p/,
|
||||||
|
pronoun: pronouns["possessive"]
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])rn\/a/,
|
||||||
|
pronoun: pronouns["adjective"]
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])rn\/r/,
|
||||||
|
pronoun: pronouns["reflexive"]
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])rn\/H/,
|
||||||
|
pronoun: pronouns["honorific-abbr"]
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])rn\/h/,
|
||||||
|
pronoun: pronouns["honorific"]
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])rn\/N/,
|
||||||
|
pronoun: pronouns["adult"]
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])rn\/n/,
|
||||||
|
pronoun: pronouns["youth"]
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])rn\/F/,
|
||||||
|
pronoun: pronouns["parent"]
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])rn\/f/,
|
||||||
|
pronoun: pronouns["child"]
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])rn\/k/,
|
||||||
|
pronoun: pronouns["sibling"]
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])rn\/m/,
|
||||||
|
pronoun: pronouns["married"]
|
||||||
|
}, {
|
||||||
|
regexp: /([Pp])rn\/d/,
|
||||||
|
pronoun: pronouns["dating"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
params.forEach((pronoun) => request.loop(request, pronoun, prnHelper));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Replaces specific words indicated in the options */
|
||||||
|
function also(request) {
|
||||||
|
Object.entries(options.also).forEach(([searchTerm, replacement]) => {
|
||||||
|
let searchTermEscaped = searchTerm.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
|
||||||
|
|
||||||
|
// Remove whitespace from the front and back
|
||||||
|
if (searchTermEscaped[0].match(/[a-z]/i)) {
|
||||||
|
searchTermEscaped = `\\b${searchTermEscaped}`;
|
||||||
|
}
|
||||||
|
if (searchTermEscaped[searchTermEscaped.length - 1].match((/[a-z]/i))) {
|
||||||
|
searchTermEscaped = `${searchTermEscaped}\\b`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchTermRegexp = new RegExp(searchTermEscaped);
|
||||||
|
request.loop(request, {
|
||||||
|
regexp: searchTermRegexp,
|
||||||
|
replacement: replacement
|
||||||
|
}, (input, params) => {
|
||||||
|
return input.replaceAll(params.regexp, params.replacement);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* alt/first and second or third/word1/word2/ becomes "word1" in first and second-person POV but "word2" in third-person */
|
||||||
|
function alt(request) {
|
||||||
|
const regexp1 = new RegExp([
|
||||||
|
/alt\/(?<targetPov>first|second|third)/,
|
||||||
|
/\/(?<replacement>[^\/]*)\//
|
||||||
|
].map(r => r.source).join(''),'i');
|
||||||
|
request.loop(request, {
|
||||||
|
regexp: regexp1,
|
||||||
|
pov: request.options.pov
|
||||||
|
}, (input, params) => {
|
||||||
|
const vars = input.match(params.regexp).groups;
|
||||||
|
if (vars.targetPov == params.pov) {
|
||||||
|
return input.replace(params.regexp, vars.replacement);
|
||||||
|
} else {
|
||||||
|
return input.replace(params.regexp, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const regexp2 = new RegExp([
|
||||||
|
/alt\/(?<targetPov1>first|second|third) /,
|
||||||
|
/(?<conjunction1>and|or) /,
|
||||||
|
/(?!\1)(?<targetPov2>first|second|third)/,
|
||||||
|
/(?: (?!\2)(?<conjunction2>and|or) (?!\1|\3)(?:first|second|third))?/,
|
||||||
|
/\/(?<replacement1>[^\/]*)\//,
|
||||||
|
/(?<replacement2>[^\/]*)\//
|
||||||
|
].map(r => r.source).join(''),'i');
|
||||||
|
request.loop(request, {
|
||||||
|
regexp: regexp2,
|
||||||
|
pov: request.options.pov
|
||||||
|
}, (input, params) => {
|
||||||
|
const vars = input.match(params.regexp).groups;
|
||||||
|
if (vars.targetPov1 == params.pov || vars.conjunction1.toLowerCase() == "and" && vars.targetPov2 == params.pov) {
|
||||||
|
return input.replace(params.regexp, vars.replacement1);
|
||||||
|
} else if (vars.conjunction1.toLowerCase() == "or" && vars.targetPov2 == params.pov) {
|
||||||
|
return input.replace(params.regexp, vars.replacement2);
|
||||||
|
} else if (vars.conjunction2 == null) {
|
||||||
|
return input.replace(params.regexp, null);
|
||||||
|
} else {
|
||||||
|
return input.replace(params.regexp, vars.replacement2);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const regexp3 = new RegExp([
|
||||||
|
/alt\/(?<replacement1>[^\/]*)\//,
|
||||||
|
/(?<replacement2>[^\/]*)\//,
|
||||||
|
/(?<replacement3>[^\/]*)\//
|
||||||
|
].map(r => r.source).join(''),'i');
|
||||||
|
request.loop(request, {
|
||||||
|
regexp: regexp3,
|
||||||
|
pov: request.options.pov
|
||||||
|
}, (input, params) => {
|
||||||
|
const vars = input.match(params.regexp).groups;
|
||||||
|
switch (params.pov) {
|
||||||
|
case "first":
|
||||||
|
return input.replace(params.regexp, vars.replacement1);
|
||||||
|
case "second":
|
||||||
|
return input.replace(params.regexp, vars.replacement2);
|
||||||
|
case "third":
|
||||||
|
return input.replace(params.regexp, vars.replacement3);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if/a is a/word/ becomes "word" because the condition is met */
|
||||||
|
function ife(request) {
|
||||||
|
const regexp1 = new RegExp([
|
||||||
|
/if\/(?<lhs>[^\/]*) is /,
|
||||||
|
/(?<rhs>[^\/]*)\//,
|
||||||
|
/(?<replacement>[^\/]*)\//
|
||||||
|
].map(r => r.source).join(''),'i');
|
||||||
|
request.loop(request, {
|
||||||
|
regexp: regexp1
|
||||||
|
}, (input, params) => {
|
||||||
|
const vars = input.match(params.regexp).groups;
|
||||||
|
if (vars.lhs === vars.rhs) {
|
||||||
|
return input.replace(params.regexp, vars.replacement);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const regexp2 = new RegExp([
|
||||||
|
/ife\/(?<lhs>[^\/]*) is /,
|
||||||
|
/(?<rhs>[^\/]*)\//,
|
||||||
|
/(?<replacement>[^\/]*)\//,
|
||||||
|
/(?<else>[^\/]*)\//
|
||||||
|
].map(r => r.source).join(''),'i');
|
||||||
|
request.loop(request, {
|
||||||
|
regexp: regexp1
|
||||||
|
}, (input, params) => {
|
||||||
|
const vars = input.match(params.regexp).groups;
|
||||||
|
if (vars.lhs === vars.rhs) {
|
||||||
|
return input.replace(params.regexp, vars.replacement);
|
||||||
|
} else {
|
||||||
|
return input.replace(params.regexp, vars.else);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cut/off first 1/word/ shortens into "ord" */
|
||||||
|
function cut(request) {
|
||||||
|
const regexp = new RegExp([
|
||||||
|
/cut\/(?<target>[^\/]+)\//,
|
||||||
|
/(?<offonly>off|only) /,
|
||||||
|
/(?<firstlast>first|last) /,
|
||||||
|
/(?<index>[1-9][0-9]*)\//
|
||||||
|
].map(r => r.source).join(''),'i');
|
||||||
|
request.loop(request, {
|
||||||
|
regexp: regexp
|
||||||
|
}, (input, params) => {
|
||||||
|
const vars = input.match(params.regexp).groups;
|
||||||
|
const length = vars.target.length;
|
||||||
|
let start, end;
|
||||||
|
if (vars.offonly == "only") {
|
||||||
|
if (isFirst) { // only first n
|
||||||
|
start = 0;
|
||||||
|
end = Math.min(vars.index, length - 1);
|
||||||
|
} else { // only last n
|
||||||
|
start = Math.max(length - vars.index, 1);
|
||||||
|
end = length;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (vars.firstlast == "first") { // off first n
|
||||||
|
start = Math.min(vars.index, length - 1);;
|
||||||
|
end = length;
|
||||||
|
} else { // off last n
|
||||||
|
start = 0;
|
||||||
|
end = Math.max(length - vars.index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vars.target.slice(start, end);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cap/WORD/ changes the case to "word" (Cap/word/ for "Word" and CAP/word/ for "WORD") */
|
||||||
|
function cap(request) {
|
||||||
|
const regexp = new RegExp([
|
||||||
|
/(?<style>cap|Cap|CAP)\//,
|
||||||
|
/(?<target>[^\/]+)\//
|
||||||
|
].map(r => r.source).join(''),'i');
|
||||||
|
request.loop(request, {
|
||||||
|
regexp: regexp
|
||||||
|
}, (input, params) => {
|
||||||
|
const vars = input.match(params.regexp).groups;
|
||||||
|
const isLowerCase = /c/.test(vars.style.slice(0,1)); // cap
|
||||||
|
if (isLowerCase) {
|
||||||
|
return vars.target.toLowerCase();
|
||||||
|
} else {
|
||||||
|
const isStartCase = /a/.test(vars.style.slice(1,2)); // Cap
|
||||||
|
if (isStartCase) {
|
||||||
|
return capitalize(vars.target);
|
||||||
|
} else { // CAP
|
||||||
|
return vars.target.toUpperCase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mrr/word/ flips into "dorw" */
|
||||||
|
function mrr(request) {
|
||||||
|
request.loop(request, {
|
||||||
|
regexp: /mrr\/(?<target>[^\/]+)\//i
|
||||||
|
}, (input, params) => {
|
||||||
|
const target = input.match(params.regexp).groups.target;
|
||||||
|
return target.split('').reverse().join('');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* a/an determines "a" or "an" by the pronunciation of the following word */
|
||||||
|
function aan(request) {
|
||||||
|
request.loop(request, {
|
||||||
|
regexp: /a\/an (?<target>\w+)/i
|
||||||
|
}, (input, params) => {
|
||||||
|
const target = input.match(params.regexp).groups.target;
|
||||||
|
return articleHelper(target, { numbers: 'colloquial' });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retrieves an index used by the verbs library for conjugation */
|
||||||
|
function getPovIndex(pov, options) {
|
||||||
|
switch (pov) {
|
||||||
|
case "first":
|
||||||
|
return 0;
|
||||||
|
case "second":
|
||||||
|
return 1;
|
||||||
|
case "third-singular":
|
||||||
|
return 2;
|
||||||
|
case "third":
|
||||||
|
if (getPronouns(options.preset, options.other).plurality == "singular") {
|
||||||
|
return 2;
|
||||||
|
} else { /* Plurality is plural, "they go" */
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
return getThirdIndex(options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns the input word, capitalized */
|
||||||
|
function capitalize(word) {
|
||||||
|
return word.charAt(0).toUpperCase() + word.slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns pronouns by preset */
|
||||||
|
function getPronouns(key, other) {
|
||||||
|
switch (key) {
|
||||||
|
case "she":
|
||||||
|
return {
|
||||||
|
"subjective": "she",
|
||||||
|
"objective": "her",
|
||||||
|
"possessive": "her",
|
||||||
|
"adjective": "hers",
|
||||||
|
"reflexive": "herself",
|
||||||
|
"honorific-abbr": "Ms.",
|
||||||
|
"honorific": "miss",
|
||||||
|
"adult": "woman",
|
||||||
|
"youth": "girl",
|
||||||
|
"parent": "mother",
|
||||||
|
"child": "daughter",
|
||||||
|
"sibling": "sister",
|
||||||
|
"married": "wife",
|
||||||
|
"dating": "girlfriend",
|
||||||
|
"plurality": "singular"
|
||||||
|
};
|
||||||
|
case "he":
|
||||||
|
return {
|
||||||
|
"subjective": "he",
|
||||||
|
"objective": "him",
|
||||||
|
"possessive": "his",
|
||||||
|
"adjective": "his",
|
||||||
|
"reflexive": "himself",
|
||||||
|
"honorific-abbr": "Mr.",
|
||||||
|
"honorific": "mister",
|
||||||
|
"adult": "man",
|
||||||
|
"youth": "boy",
|
||||||
|
"parent": "father",
|
||||||
|
"child": "son",
|
||||||
|
"sibling": "brother",
|
||||||
|
"married": "husband",
|
||||||
|
"dating": "boyfriend",
|
||||||
|
"plurality": "singular"
|
||||||
|
};
|
||||||
|
case "they":
|
||||||
|
return {
|
||||||
|
"subjective": "they",
|
||||||
|
"objective": "them",
|
||||||
|
"possessive": "their",
|
||||||
|
"adjective": "theirs",
|
||||||
|
"reflexive": "themself",
|
||||||
|
"honorific-abbr": "Mx.",
|
||||||
|
"honorific": "mix",
|
||||||
|
"adult": "person",
|
||||||
|
"youth": "kid",
|
||||||
|
"parent": "parent",
|
||||||
|
"child": "child",
|
||||||
|
"sibling": "sibling",
|
||||||
|
"married": "spouse",
|
||||||
|
"dating": "partner",
|
||||||
|
"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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handles capitalization and replacement for pronouns */
|
||||||
|
function prnHelper(input, params) {
|
||||||
|
let replacement = params.pronoun;
|
||||||
|
const isCapital = /P/.test(input.match(params.regexp)[1]);
|
||||||
|
if (isCapital) {
|
||||||
|
replacement = capitalize(replacement);
|
||||||
|
}
|
||||||
|
return input.replace(params.regexp, replacement);
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
{
|
||||||
|
"name": "metamorpov",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "metamorpov",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"english-verbs-gerunds": "^3.4.0",
|
||||||
|
"english-verbs-helper": "^3.4.0",
|
||||||
|
"english-verbs-irregular": "^3.4.0",
|
||||||
|
"indefinite": "^2.5.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/english-verbs-gerunds": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/english-verbs-gerunds/-/english-verbs-gerunds-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-sc6Zgm7Du+KKIloln0GzcT/fZxIqJBXlfU9B8DLi1bPmKK/hVK3HsRWywNaAGwHU4+SpZ7ADvLvoXlMI2PkwUw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "Apache-2.0"
|
||||||
|
},
|
||||||
|
"node_modules/english-verbs-helper": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/english-verbs-helper/-/english-verbs-helper-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-yP1msoIysGuUolx1s3K7dHj5ASqitjHN3PAe3rrF7/mbcHqg1VaLyGVII7Onkv3AHnrPqMT6ITiPtd2rccE7eg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"funding": {
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/ludan"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/english-verbs-irregular": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/english-verbs-irregular/-/english-verbs-irregular-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-Rk0fgdzJ0oqpERPHr6QV2Dp8nnNKO3Si92RWYCe7fgxks8+yEOtUDu0ZBm3AJ6Ccqaa5ZtVh/pndUYdbKkr7xg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "Apache-2.0"
|
||||||
|
},
|
||||||
|
"node_modules/indefinite": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/indefinite/-/indefinite-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-Ul0hCdnSjuFDEloYWeozTaEfljbz+0q+u4HsHns2dOk2DlhGlbRMGFtNcIL+Ve7sZYeIOTOAKA0usAXBGHpNDg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"name": "metamorpov",
|
||||||
|
"title": "MetamorPOV",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Enables customization of reader-insert stories by replacing author-provided hooks such as Y/n, pov/s, and vrb/do/present/.",
|
||||||
|
"main": "metamorpov.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "Jean Viscogliosi-Pate",
|
||||||
|
"license": "GPL-3.0-or-later",
|
||||||
|
"devDependencies": {
|
||||||
|
"english-verbs-gerunds": "^3.4.0",
|
||||||
|
"english-verbs-helper": "^3.4.0",
|
||||||
|
"english-verbs-irregular": "^3.4.0",
|
||||||
|
"indefinite": "^2.5.1"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue