displaying plural results
This commit is contained in:
parent
4bafd0fcf5
commit
271df7f2fd
|
@ -200,9 +200,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@lingdocs/pashto-inflector": {
|
"@lingdocs/pashto-inflector": {
|
||||||
"version": "0.9.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-0.9.2.tgz",
|
"resolved": "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-1.0.2.tgz",
|
||||||
"integrity": "sha512-9tmPPezEvPFR/tPkBuF/bj79dCAviFTGOmCVDbRCymXmv4gWWhH4lCueYOYhyWZ4vXcihMflVpRSmLtUDXmdjQ==",
|
"integrity": "sha512-voPdIePrMzLc9RNFjyo0RczOPDoOkIhQ/34CxwfnkOrt7k3EwahPikEWvRIN4+JoxKJI8oA+iFKAN9OoGmY3Yg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"pbf": "^3.2.1",
|
"pbf": "^3.2.1",
|
||||||
|
@ -1697,9 +1697,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"protocol-buffers-schema": {
|
"protocol-buffers-schema": {
|
||||||
"version": "3.5.2",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz",
|
||||||
"integrity": "sha512-LPzSaBYp/TcbuSlpGwqT5jR9kvJ3Zp5ic2N5c2ybx6XB/lSfEHq2D7ja8AgoxHoMD91wXFALJoXsvshKPuXyew=="
|
"integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw=="
|
||||||
},
|
},
|
||||||
"proxy-addr": {
|
"proxy-addr": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
"main": "lib/functions/src/index.js",
|
"main": "lib/functions/src/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@google-cloud/storage": "^5.8.1",
|
"@google-cloud/storage": "^5.8.1",
|
||||||
"@lingdocs/pashto-inflector": "^0.9.2",
|
"@lingdocs/pashto-inflector": "^1.0.2",
|
||||||
"@types/cors": "^2.8.10",
|
"@types/cors": "^2.8.10",
|
||||||
"@types/google-spreadsheet": "^3.0.2",
|
"@types/google-spreadsheet": "^3.0.2",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-free": "^5.15.2",
|
"@fortawesome/fontawesome-free": "^5.15.2",
|
||||||
"@lingdocs/pashto-inflector": "^0.9.2",
|
"@lingdocs/pashto-inflector": "^1.0.3",
|
||||||
"@testing-library/jest-dom": "^5.11.4",
|
"@testing-library/jest-dom": "^5.11.4",
|
||||||
"@testing-library/react": "^11.1.0",
|
"@testing-library/react": "^11.1.0",
|
||||||
"@testing-library/user-event": "^12.1.10",
|
"@testing-library/user-event": "^12.1.10",
|
||||||
|
|
|
@ -13,7 +13,7 @@ const InflectionsInfo = ({ entry, textOptions }: {
|
||||||
entry: Types.DictionaryEntry,
|
entry: Types.DictionaryEntry,
|
||||||
textOptions: Types.TextOptions,
|
textOptions: Types.TextOptions,
|
||||||
}) => {
|
}) => {
|
||||||
const inf = ((): Types.Inflections | false => {
|
const inf = ((): Types.InflectorOutput | false => {
|
||||||
try {
|
try {
|
||||||
return inflectWord(entry);
|
return inflectWord(entry);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -25,20 +25,20 @@ const InflectionsInfo = ({ entry, textOptions }: {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// unisex noun / adjective
|
// unisex noun / adjective
|
||||||
if ("masc" in inf && "fem" in inf) {
|
if (inf.inflections && "masc" in inf.inflections && "fem" in inf.inflections) {
|
||||||
return (
|
return (
|
||||||
<div className="entry-extra-info" data-testid="inflections-info">
|
<div className="entry-extra-info" data-testid="inflections-info">
|
||||||
<InlinePs opts={textOptions}>{inf.masc[1][0]}</InlinePs>
|
<InlinePs opts={textOptions}>{inf.inflections.masc[1][0]}</InlinePs>
|
||||||
{` `}
|
{` `}
|
||||||
<InlinePs opts={textOptions}>{inf.fem[0][0]}</InlinePs>
|
<InlinePs opts={textOptions}>{inf.inflections.fem[0][0]}</InlinePs>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// masculine noun
|
// masculine noun
|
||||||
if ("masc" in inf) {
|
if (inf.inflections && "masc" in inf.inflections) {
|
||||||
return (
|
return (
|
||||||
<div className="entry-extra-info" data-testid="inflections-info">
|
<div className="entry-extra-info" data-testid="inflections-info">
|
||||||
<InlinePs opts={textOptions}>{inf.masc[1][0]}</InlinePs>
|
<InlinePs opts={textOptions}>{inf.inflections.masc[1][0]}</InlinePs>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,23 +51,16 @@ function conflateUnisexPeople(arr: (string | T.Person)[]): (string | T.Person)[]
|
||||||
return newArr;
|
return newArr;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function displayPositionResult(res: (T.Person | "plain" | "1st" | "2nd")[] | null): string {
|
export function displayPositionResult(res: (T.Person | "plain" | "1st" | "2nd" | "plural")[] | null): string {
|
||||||
const conflated = res
|
const conflated = res
|
||||||
? conflateUnisexPeople(res)
|
? conflateUnisexPeople(res)
|
||||||
: ["Doesn't change"];
|
: ["Doesn't change"];
|
||||||
return conflated.map((x) => {
|
return conflated.map((x) => {
|
||||||
if (x === "plain") {
|
if (x === "plural") return "";
|
||||||
return "Plain";
|
if (x === "plain") return "Plain";
|
||||||
}
|
if (x === "1st") return "1st Inflection";
|
||||||
if (x === "1st") {
|
if (x === "2nd") return "2nd Inflection";
|
||||||
return "1st Inflection";
|
if (typeof x === "string") return x;
|
||||||
}
|
|
||||||
if (x === "2nd") {
|
|
||||||
return "2nd Inflection";
|
|
||||||
}
|
|
||||||
if (typeof x === "string") {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
return x === null ? "Same for all" : getEnglishPersonInfo(x);
|
return x === null ? "Same for all" : getEnglishPersonInfo(x);
|
||||||
}).join(" / ");
|
}).join(" / ");
|
||||||
}
|
}
|
||||||
|
@ -109,6 +102,7 @@ export function displayFormResult(res: string[]): string {
|
||||||
.replace("MascPlur", "(with a masc. plur. object)")
|
.replace("MascPlur", "(with a masc. plur. object)")
|
||||||
.replace("FemSing", "(with a fem. sing. object)")
|
.replace("FemSing", "(with a fem. sing. object)")
|
||||||
.replace("FemPlur", "(with a fem. plur. object)")
|
.replace("FemPlur", "(with a fem. plur. object)")
|
||||||
|
.replace("ArabicPlural", "Arabic Plural")
|
||||||
.replace("Fem", "Fem.")
|
.replace("Fem", "Fem.")
|
||||||
.replace("Masc", "Masc.")
|
.replace("Masc", "Masc.")
|
||||||
}
|
}
|
|
@ -11,17 +11,21 @@ import {
|
||||||
isVerbBlock,
|
isVerbBlock,
|
||||||
isImperativeBlock,
|
isImperativeBlock,
|
||||||
isInflectionSet,
|
isInflectionSet,
|
||||||
|
isPluralInflectionSet,
|
||||||
} from "@lingdocs/pashto-inflector";
|
} from "@lingdocs/pashto-inflector";
|
||||||
import { personFromVerbBlockPos } from "@lingdocs/pashto-inflector";
|
import { personFromVerbBlockPos } from "@lingdocs/pashto-inflector";
|
||||||
|
|
||||||
const inflectionNames: InflectionName[] = ["plain", "1st", "2nd"];
|
const inflectionNames: { inflections: InflectionName[], plural: PluralInflectionName[] } = {
|
||||||
|
inflections: ["plain", "1st", "2nd"],
|
||||||
|
plural: ["plural", "2nd"],
|
||||||
|
};
|
||||||
|
|
||||||
type ObPile = { [key: string]: ObRec; }
|
type ObPile = { [key: string]: ObRec; }
|
||||||
type ObRec = T.VerbBlock | T.ImperativeBlock | T.InflectionSet | T.PsString | boolean | null | string | ObPile;
|
type ObRec = T.VerbBlock | T.ImperativeBlock | T.InflectionSet | T.PsString | boolean | null | string | ObPile;
|
||||||
|
|
||||||
type SinglePsResult = T.PsString | null;
|
type SinglePsResult = T.PsString | null;
|
||||||
type BlockResult = { ps: T.PsString, pos: T.Person[] | InflectionName[] }[];
|
type BlockResult = { ps: T.PsString, pos: T.Person[] | InflectionName[] }[];
|
||||||
type InflectionSetResult = { ps: T.PsString, pos: InflectionName[] }[];
|
type InflectionSetResult = { ps: T.PsString, pos: (InflectionName | PluralInflectionName)[] }[];
|
||||||
type BlockResultRaw = { ps: T.PsString, pos: [number, number][] }[];
|
type BlockResultRaw = { ps: T.PsString, pos: [number, number][] }[];
|
||||||
type RowResult = { ps: T.PsString, pos: (0 | 1)[] }[];
|
type RowResult = { ps: T.PsString, pos: (0 | 1)[] }[];
|
||||||
|
|
||||||
|
@ -46,6 +50,7 @@ export function searchPile(pile: ObPile, searchFun: (s: T.PsString) => boolean,
|
||||||
function searchObRecord(record: ObRec): null | BlockResult | SinglePsResult | InflectionSearchResult[] {
|
function searchObRecord(record: ObRec): null | BlockResult | SinglePsResult | InflectionSearchResult[] {
|
||||||
// hit a bottom part a tree, see if what we're looking for is there
|
// hit a bottom part a tree, see if what we're looking for is there
|
||||||
if (Array.isArray(record)) {
|
if (Array.isArray(record)) {
|
||||||
|
// @ts-ignore
|
||||||
return searchBlock(record, searchFun);
|
return searchBlock(record, searchFun);
|
||||||
}
|
}
|
||||||
if (typeof record !== "object") return null;
|
if (typeof record !== "object") return null;
|
||||||
|
@ -65,7 +70,7 @@ export function searchPile(pile: ObPile, searchFun: (s: T.PsString) => boolean,
|
||||||
}
|
}
|
||||||
const result = searchObRecord(value);
|
const result = searchObRecord(value);
|
||||||
// Result: Hit the bottom and nothing found
|
// Result: Hit the bottom and nothing found
|
||||||
if (result === null) {
|
if (result === null || result === undefined) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
// Result: Hit a PsString with what we want at the bottom
|
// Result: Hit a PsString with what we want at the bottom
|
||||||
|
@ -115,6 +120,20 @@ function searchBlock(block: T.VerbBlock | T.ImperativeBlock | T.InflectionSet, s
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (isInflectionSet(block)) {
|
||||||
|
const results = searchInflectionSet(block, searchFun, "inflections");
|
||||||
|
if (results.length) {
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (isPluralInflectionSet(block)) {
|
||||||
|
const results = searchInflectionSet(block, searchFun, "plural");
|
||||||
|
if (results.length) {
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (isImperativeBlock(block)) {
|
if (isImperativeBlock(block)) {
|
||||||
const results = searchVerbBlock(block, searchFun);
|
const results = searchVerbBlock(block, searchFun);
|
||||||
if (results.length) {
|
if (results.length) {
|
||||||
|
@ -125,13 +144,6 @@ function searchBlock(block: T.VerbBlock | T.ImperativeBlock | T.InflectionSet, s
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (isInflectionSet(block)) {
|
|
||||||
const results = searchInflectionSet(block, searchFun);
|
|
||||||
if (results.length) {
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,18 +185,18 @@ export function searchVerbBlock(vb: T.VerbBlock | T.ImperativeBlock, searchFun:
|
||||||
}, []);
|
}, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
function searchInflectionSet(inf: T.InflectionSet, searchFun: (ps: T.PsString) => boolean): InflectionSetResult {
|
function searchInflectionSet(inf: T.InflectionSet | T.PluralInflectionSet, searchFun: (ps: T.PsString) => boolean, type: "inflections" | "plural"): InflectionSetResult {
|
||||||
return inf.reduce((all: InflectionSetResult, item, i): InflectionSetResult => {
|
return inf.reduce((all: InflectionSetResult, item, i): InflectionSetResult => {
|
||||||
const matching = item.filter(searchFun);
|
const matching = item.filter(searchFun);
|
||||||
if (i === 0) {
|
if (i === 0) {
|
||||||
return matching.map(ps => ({ ps, pos: [inflectionNames[i]] }))
|
return matching.map(ps => ({ ps, pos: [inflectionNames[type][i]] }))
|
||||||
}
|
}
|
||||||
matching.forEach(it => {
|
matching.forEach(it => {
|
||||||
const index = all.findIndex(x => x.ps.f === it.f);
|
const index = all.findIndex(x => x.ps.f === it.f);
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
all[index].pos.push(inflectionNames[i])
|
all[index].pos.push(inflectionNames[type][i])
|
||||||
} else {
|
} else {
|
||||||
all.push({ ps: it, pos: [inflectionNames[i]] });
|
all.push({ ps: it, pos: [inflectionNames[type][i]] });
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return all;
|
return all;
|
||||||
|
|
|
@ -175,7 +175,7 @@ function EntryEditor({ isolatedEntry, dictionary, searchParams, textOptions, use
|
||||||
}
|
}
|
||||||
|
|
||||||
const complement = entry.l ? dictionary.findOneByTs(entry.l) : undefined;
|
const complement = entry.l ? dictionary.findOneByTs(entry.l) : undefined;
|
||||||
const inflections = ((): T.Inflections | false => {
|
const inf = ((): T.InflectorOutput | false => {
|
||||||
try {
|
try {
|
||||||
return inflectWord(entry);
|
return inflectWord(entry);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -334,7 +334,9 @@ function EntryEditor({ isolatedEntry, dictionary, searchParams, textOptions, use
|
||||||
</ul>
|
</ul>
|
||||||
</div>}
|
</div>}
|
||||||
</form>
|
</form>
|
||||||
{inflections && <InflectionsTable inf={inflections} textOptions={textOptions} />}
|
{inf && inf.inflections && <InflectionsTable inf={inf.inflections} textOptions={textOptions} />}
|
||||||
|
{inf && "plural" in inf && <InflectionsTable inf={inf.plural as T.PluralInflections} textOptions={textOptions} />}
|
||||||
|
{inf && "arabicPlural" in inf && <InflectionsTable inf={inf.arabicPlural as T.PluralInflections} textOptions={textOptions} />}
|
||||||
{/* TODO: aay tail from state options */}
|
{/* TODO: aay tail from state options */}
|
||||||
<ConjugationViewer
|
<ConjugationViewer
|
||||||
entry={entry}
|
entry={entry}
|
||||||
|
|
|
@ -87,7 +87,7 @@ function IsolatedEntry({ state, dictionary, isolateEntry }: {
|
||||||
? dictionary.findOneByTs(entry.l)
|
? dictionary.findOneByTs(entry.l)
|
||||||
: undefined;
|
: undefined;
|
||||||
const relatedEntries = dictionary.findRelatedEntries(entry);
|
const relatedEntries = dictionary.findRelatedEntries(entry);
|
||||||
const inflections = ((): T.Inflections | false => {
|
const inf = ((): T.InflectorOutput | false => {
|
||||||
try {
|
try {
|
||||||
return inflectWord(entry);
|
return inflectWord(entry);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -95,6 +95,7 @@ function IsolatedEntry({ state, dictionary, isolateEntry }: {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
console.log(inf);
|
||||||
return <div className="width-limiter">
|
return <div className="width-limiter">
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>{entry.p} - LingDocs Pashto Dictionary</title>
|
<title>{entry.p} - LingDocs Pashto Dictionary</title>
|
||||||
|
@ -187,7 +188,17 @@ function IsolatedEntry({ state, dictionary, isolateEntry }: {
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
{editSubmitted && <p>Thank you for your help!</p>}
|
{editSubmitted && <p>Thank you for your help!</p>}
|
||||||
{inflections && <InflectionsTable inf={inflections} textOptions={textOptions} />}
|
{inf && <>
|
||||||
|
{inf.inflections && <InflectionsTable inf={inf.inflections} textOptions={textOptions} />}
|
||||||
|
{"plural" in inf && <div>
|
||||||
|
<h5>Plural</h5>
|
||||||
|
<InflectionsTable inf={inf.plural as T.PluralInflections} textOptions={textOptions} />
|
||||||
|
</div>}
|
||||||
|
{"arabicPlural" in inf && <div>
|
||||||
|
<h5>Arabic Plural</h5>
|
||||||
|
<InflectionsTable inf={inf.arabicPlural as T.PluralInflections} textOptions={textOptions} />
|
||||||
|
</div>}
|
||||||
|
</>}
|
||||||
{/* TODO: State options for tail type here */}
|
{/* TODO: State options for tail type here */}
|
||||||
<ConjugationViewer
|
<ConjugationViewer
|
||||||
entry={entry}
|
entry={entry}
|
||||||
|
|
|
@ -21,7 +21,7 @@ import {
|
||||||
import {
|
import {
|
||||||
ButtonSelect,
|
ButtonSelect,
|
||||||
InlinePs,
|
InlinePs,
|
||||||
removeFVariants,
|
removeFVarients,
|
||||||
} from "@lingdocs/pashto-inflector";
|
} from "@lingdocs/pashto-inflector";
|
||||||
import {
|
import {
|
||||||
Modal,
|
Modal,
|
||||||
|
@ -315,7 +315,7 @@ function Wordlist({ options, wordlist, isolateEntry, optionsDispatch }: {
|
||||||
return <div>
|
return <div>
|
||||||
<div className="lead my-3">None to review</div>
|
<div className="lead my-3">None to review</div>
|
||||||
<p>Next word up for review <strong>{dayjs().to(nextUp.dueDate)}</strong>: <InlinePs opts={textOptions}>
|
<p>Next word up for review <strong>{dayjs().to(nextUp.dueDate)}</strong>: <InlinePs opts={textOptions}>
|
||||||
{removeFVariants(ps)}
|
{removeFVarients(ps)}
|
||||||
</InlinePs></p>
|
</InlinePs></p>
|
||||||
</div>;
|
</div>;
|
||||||
})()
|
})()
|
||||||
|
|
|
@ -158,6 +158,8 @@ type WordlistWordDoc = WordlistWord & { _rev: string, _id: string };
|
||||||
|
|
||||||
type InflectionName = "plain" | "1st" | "2nd";
|
type InflectionName = "plain" | "1st" | "2nd";
|
||||||
|
|
||||||
|
type PluralInflectionName = "plural" | "2nd";
|
||||||
|
|
||||||
type InflectionSearchResult = {
|
type InflectionSearchResult = {
|
||||||
form: string[],
|
form: string[],
|
||||||
matches: {
|
matches: {
|
||||||
|
|
|
@ -1483,10 +1483,10 @@
|
||||||
"@types/yargs" "^16.0.0"
|
"@types/yargs" "^16.0.0"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
|
|
||||||
"@lingdocs/pashto-inflector@^0.9.2":
|
"@lingdocs/pashto-inflector@^1.0.3":
|
||||||
version "0.9.2"
|
version "1.0.3"
|
||||||
resolved "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-0.9.2.tgz#7ef3b3344c3eb3e3d1db77142ef83f0ac7e8e230"
|
resolved "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-1.0.3.tgz#4ba205869f41a540d85d045eee23c484814f1fd8"
|
||||||
integrity sha512-9tmPPezEvPFR/tPkBuF/bj79dCAviFTGOmCVDbRCymXmv4gWWhH4lCueYOYhyWZ4vXcihMflVpRSmLtUDXmdjQ==
|
integrity sha512-bxz94hmCfVfJg2CthViFZ/14cQmhPHtS+uA/d11vViI6qad5Kl4U33jm1ZfS7AaXHasqmnsKyYW7Qn+y/E0yUA==
|
||||||
dependencies:
|
dependencies:
|
||||||
classnames "^2.2.6"
|
classnames "^2.2.6"
|
||||||
pbf "^3.2.1"
|
pbf "^3.2.1"
|
||||||
|
|
Loading…
Reference in New Issue