This commit is contained in:
lingdocs 2022-04-26 13:08:32 +05:00
parent 5c283f2cea
commit b4a84645ea
15 changed files with 65 additions and 690 deletions

View File

@ -5,7 +5,7 @@
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-free": "^5.15.4", "@fortawesome/fontawesome-free": "^5.15.4",
"@lingdocs/lingdocs-main": "^0.2.0", "@lingdocs/lingdocs-main": "^0.2.0",
"@lingdocs/pashto-inflector": "^2.0.5", "@lingdocs/pashto-inflector": "^2.3.2",
"@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",

View File

@ -1,7 +1,6 @@
const fs = require("fs"); const fs = require("fs");
const fetch = require("node-fetch"); const fetch = require("node-fetch");
const path = require("path"); const path = require("path");
const { readDictionary } = require("@lingdocs/pashto-inflector");
const verbsPath = path.join(".", "src", "words"); const verbsPath = path.join(".", "src", "words");
const pChars = [ const pChars = [
"آ", "آ",
@ -51,10 +50,11 @@ const pChars = [
'ږ', 'ږ',
]; ];
fetch(process.env.LINGDOCS_DICTIONARY_URL).then(res => res.arrayBuffer()).then(data => {
const { entries } = readDictionary(data); fetch(process.env.LINGDOCS_DICTIONARY_URL + ".json").then(res => res.json()).then(data => {
const { entries } = data;
const filtered = shuffle(entries.filter(e => ( const filtered = shuffle(entries.filter(e => (
e.c?.includes("n. f.") && e.p.endsWith(") e.c?.includes("loc. adv.")
))); )));
const content = `module.exports = [ const content = `module.exports = [
${filtered.reduce((text, entry) => ( ${filtered.reduce((text, entry) => (

View File

@ -4,11 +4,8 @@ import {
EntrySelect, EntrySelect,
Types as T, Types as T,
} from "@lingdocs/pashto-inflector"; } from "@lingdocs/pashto-inflector";
import {
nouns,
verbs,
} from "../words/words";
import { useStickyState } from "@lingdocs/pashto-inflector"; import { useStickyState } from "@lingdocs/pashto-inflector";
import entryFeeder from "../lib/entry-feeder";
function VPBuilder() { function VPBuilder() {
const [entry, setEntry] = useStickyState<T.VerbEntry | undefined>(undefined, "vEntrySelect"); const [entry, setEntry] = useStickyState<T.VerbEntry | undefined>(undefined, "vEntrySelect");
@ -18,7 +15,7 @@ function VPBuilder() {
<EntrySelect <EntrySelect
value={entry} value={entry}
onChange={setEntry} onChange={setEntry}
entries={verbs} entryFeeder={entryFeeder.verbs}
opts={defaultTextOptions} opts={defaultTextOptions}
isVerbSelect isVerbSelect
name="Verb" name="Verb"
@ -29,8 +26,8 @@ function VPBuilder() {
? <VPExplorer ? <VPExplorer
verb={entry} verb={entry}
opts={defaultTextOptions} opts={defaultTextOptions}
nouns={nouns} entryFeeder={entryFeeder}
verbs={verbs} handleLinkClick="none"
/> />
: <div className="lead"> : <div className="lead">
Choose a verb to start building Choose a verb to start building

View File

@ -1,155 +0,0 @@
import {
VerbTable,
defaultTextOptions as opts,
ButtonSelect,
Types as T,
personGender,
personIsPlural,
typePredicates,
} from "@lingdocs/pashto-inflector";
import {
ExplorerState,
ExplorerReducerAction,
} from "./explorer-types";
import {
equativeMachine,
assembleEquativeOutput,
} from "../../lib/equative-machine";
const {
isUnisexNounEntry,
isAdjectiveEntry,
isVerbEntry,
isLocativeAdverbEntry,
isNounEntry,
} = typePredicates;
function chooseLength<O>(o: T.SingleOrLengthOpts<O>, length: "short" | "long"): O {
return ("long" in o) ? o[length] : o;
}
function SingleItemDisplay({ state }: { state: ExplorerState }) {
if (state.subject.type === "pronouns") {
return <div>ERROR: Wrong display being used</div>;
}
try {
const se = state.subject[state.subject.type];
const pe = state.predicate[state.predicate.type];
const subject = makeNounPhrase(se, state, "subject");
const predicate = (isAdjectiveEntry(pe) || isLocativeAdverbEntry(pe))
? makeComplement(pe)
: makeNounPhrase(pe, state, "predicate");
const block = assembleEquativeOutput(
equativeMachine({
subject,
predicate,
tense: state.tense,
negative: state.negative,
})
);
return <div>
<VerbTable textOptions={opts} block={chooseLength(block, state.length)} />
</div>;
} catch (e) {
console.error(e);
return <div>Error making equative sentence</div>
}
}
function makeComplement(entry: T.AdjectiveEntry | T.LocativeAdverbEntry): Compliment {
return {
type: "compliment",
entry,
};
}
function makeNounPhrase(entry: T.NounEntry | T.UnisexNounEntry | T.VerbEntry, state: ExplorerState, entity: "subject" | "predicate"): NounPhrase {
if (isVerbEntry(entry)) {
return {
type: "participle",
entry,
};
}
return {
type: "noun",
number: state[entity].info.number,
gender: state[entity].info.gender,
entry,
};
}
export function makeBlockWPronouns(e: T.AdjectiveEntry | T.UnisexNounEntry | T.LocativeAdverbEntry, tense: EquativeTense, negative: boolean, length?: "short" | "long"): T.SingleOrLengthOpts<T.VerbBlock> {
// if the output's gonna have long / short forms (if it's past or wouldBe) then recursive call to make the long and short versions
if (!length && "long" in assembleEquativeOutput(equativeMachine({
subject: { type: "pronoun", pronounType: "near", person: 0 },
predicate: (isAdjectiveEntry(e) || isLocativeAdverbEntry(e))
? { type: "compliment", entry: e }
: { type: "noun", gender: "masc", number: "singular", entry: e },
tense,
negative,
}))) {
return {
short: makeBlockWPronouns(e, tense, negative, "short") as T.VerbBlock,
long: makeBlockWPronouns(e, tense, negative, "long") as T.VerbBlock,
};
}
const makeP = (p: T.Person): T.ArrayOneOrMore<T.PsString> => {
const b = assembleEquativeOutput(equativeMachine({
subject: { type: "pronoun", pronounType: "far", person: p },
predicate: (isAdjectiveEntry(e) || isLocativeAdverbEntry(e))
? { type: "compliment", entry: e }
: { type: "noun", gender: personGender(p), number: personIsPlural(p) ? "plural" : "singular", entry: e },
tense,
negative,
}));
if ("long" in b) {
if (!length) throw new Error("bad length processing");
return b[length];
}
return b;
};
return [
[makeP(0), makeP(6)],
[makeP(1), makeP(7)],
[makeP(2), makeP(8)],
[makeP(3), makeP(9)],
[makeP(4), makeP(10)],
[makeP(5), makeP(11)],
];
}
function PronounBlockDisplay({ state }: { state: ExplorerState }) {
const pred = state.predicate[state.predicate.type];
if (!isVerbEntry(pred) && (isAdjectiveEntry(pred) || isLocativeAdverbEntry(pred) || (isNounEntry(pred) && isUnisexNounEntry(pred)))) {
const block = makeBlockWPronouns(pred, state.tense, state.negative);
return <VerbTable
textOptions={opts}
block={chooseLength(block, state.length)}
/>;
}
return <div>Invalid combination</div>
}
function EquativeDisplay({ state, dispatch }: { state: ExplorerState, dispatch: (action: ExplorerReducerAction) => void }) {
return <>
{(state.tense === "past" || state.tense === "wouldBe") && <div className="text-center">
<ButtonSelect
small
options={[
{ label: "Long", value: "long" },
{ label: "Short", value: "short" },
]}
value={state.length}
handleChange={(p) => dispatch({ type: "setLength", payload: p as "long" | "short" })}
/>
</div>}
{state.subject.type === "pronouns"
? <PronounBlockDisplay state={state} />
: <SingleItemDisplay state={state} />
}
{state.predicate.type === "participle" && <div className="mt-2 small text-muted text-center">
Note: This means that the subject <em>is</em> the act of the participle/verb, not that the subject is currently doing the verb!
</div>}
</>;
}
export default EquativeDisplay;

View File

@ -1,70 +0,0 @@
import { useState } from "react";
import {
reducer,
} from "./explorer-reducer";
import {
InputSelector,
TenseSelector,
} from "./explorer-selectors";
import {
ExplorerState,
ExplorerReducerAction,
} from "./explorer-types";
import {
defaultUnisexNoun,
defaultAdjective,
defaultNoun,
defaultParticiple,
defaultAdverb,
} from "./explorer-inputs";
import EquativeDisplay from "./EquativeDisplay";
const defaultState: ExplorerState = {
tense: "present",
length: "short",
negative: false,
predicate: {
type: "adjective",
adjective: defaultAdjective,
adverb: defaultAdverb,
unisexNoun: defaultUnisexNoun,
participle: defaultParticiple,
noun: defaultNoun,
info: {
number: "singular",
gender: "masc",
},
},
subject: {
type: "pronouns",
noun: defaultNoun,
participle: defaultParticiple,
unisexNoun: defaultUnisexNoun,
info: {
number: "singular",
gender: "masc",
},
},
};
function EquativeExplorer() {
const [state, unsafeSetState] = useState<ExplorerState>(defaultState);
function dispatch(action: ExplorerReducerAction) {
const newState = reducer(state, action);
unsafeSetState(newState);
}
return <>
<TenseSelector state={state} dispatch={dispatch} />
<div className="row">
<div className="col">
<InputSelector entity="subject" state={state} dispatch={dispatch} />
</div>
<div className="col">
<InputSelector entity="predicate" state={state} dispatch={dispatch} />
</div>
</div>
<EquativeDisplay state={state} dispatch={dispatch} />
</>;
}
export default EquativeExplorer;

View File

@ -1,37 +0,0 @@
import { nouns, adjectives, verbs, adverbs } from "../../words/words";
import {
Types as T,
typePredicates as tp,
} from "@lingdocs/pashto-inflector";
function sort<T extends (T.AdjectiveEntry | T.NounEntry | T.VerbEntry | T.AdverbEntry)>(arr: Readonly<T[]>): T[] {
if ("entry" in arr[0]) {
return [...arr].sort((a, b) => (
// @ts-ignore
a.entry.p.localeCompare(b.entry.p)
));
}
return [...arr].sort((a, b) => (
// @ts-ignore
a.p.localeCompare(b.p)
));
}
const unisexNouns = sort(nouns.filter(x => tp.isUnisexNounEntry(x)) as T.UnisexNounEntry[]);
const nonUnisexNouns = sort(nouns.filter(x => !tp.isUnisexNounEntry(x)) as (T.MascNounEntry | T.FemNounEntry)[]);
const inputs = {
adjective: sort(adjectives),
unisexNoun: unisexNouns,
noun: nonUnisexNouns,
participle: sort(verbs),
adverb: sort(adverbs.filter(tp.isLocativeAdverbEntry)),
};
export const defaultAdjective = inputs.adjective.find(ps => ps.p === "زوړ") || inputs.adjective[0];
export const defaultAdverb = inputs.adverb.find(ps => ps.p === "دلته") || inputs.adverb[0];
export const defaultUnisexNoun = inputs.unisexNoun.find(ps => ps.p === "پښتون") || inputs.unisexNoun[0];
export const defaultNoun = inputs.noun.find(ps => ps.p === "کتاب") || inputs.noun[0];
export const defaultParticiple = inputs.participle.find(ps => ps.entry.p === "لیکل") || inputs.participle[0];
export default inputs;

View File

@ -1,110 +0,0 @@
import inputs from "./explorer-inputs";
import { ExplorerState, ExplorerReducerAction } from "./explorer-types";
import {
Types as T,
} from "@lingdocs/pashto-inflector";
export function reducer(state: ExplorerState, action: ExplorerReducerAction): ExplorerState {
if (action.type === "setPredicate") {
const pile = inputs[state.predicate.type] as (T.UnisexNounEntry | T.AdjectiveEntry)[];
const predicate = (pile.find(p => p.ts === action.payload) || pile[0]);
return {
...state,
predicate: {
...state.predicate,
[state.predicate.type]: predicate,
},
};
}
if (action.type === "setPredicateType") {
const predicateType = action.payload;
return {
...state,
predicate: {
...state.predicate,
type: predicateType,
},
};
}
if (action.type === "setSubjectType") {
const subjectType = action.payload;
return {
...state,
subject: {
...state.subject,
type: subjectType,
},
predicate: {
...state.predicate,
type: (
subjectType === "pronouns" &&
!["adjective", "adverb", "unisexNoun"].includes(state.predicate.type)
) ? "adjective" : state.predicate.type,
},
};
}
if (action.type === "setSubject") {
if (state.subject.type === "pronouns") return state;
const pile = inputs[state.subject.type];
// @ts-ignore
const subject = (pile.find(p => p.ts === action.payload) || pile[0]);
return {
...state,
subject: {
...state.subject,
[state.subject.type]: subject,
},
};
}
if (action.type === "setNumber") {
const entity = action.payload.entity;
return {
...state,
[entity]: {
...state[entity],
info: {
...state[entity].info,
number: action.payload.number,
},
},
};
}
if (action.type === "setGender") {
const entity = action.payload.entity;
return {
...state,
[entity]: {
...state[entity],
info: {
...state[entity].info,
gender: action.payload.gender,
},
},
};
}
if (action.type === "setTense") {
return {
...state,
tense: action.payload,
};
}
// if (action.type === "setPredicateEntity") {
// return {
// ...state,
// predicate: {
// ...state.predicate,
// entity: action.payload,
// },
// };
// }
if (action.type === "setNegative") {
return {
...state,
negative: action.payload,
};
}
return {
...state,
length: action.payload,
};
}

View File

@ -1,233 +0,0 @@
// import { makeOptionLabel } from "./explorer-helpers";
import inputs from "./explorer-inputs";
import {
ExplorerReducerAction,
ExplorerState,
SubjectType,
PredicateType,
} from "./explorer-types";
import {
getEnglishParticiple,
} from "../../lib/np-tools";
import {
ButtonSelect,
getEnglishWord,
Types as T,
removeFVarients,
typePredicates,
} from "@lingdocs/pashto-inflector";
import Select from "react-select";
const {
isAdjectiveEntry,
isAdverbEntry,
isFemNounEntry,
isMascNounEntry,
isNounEntry,
isPluralNounEntry,
} = typePredicates;
const zIndexProps = {
menuPortalTarget: document.body,
styles: { menuPortal: (base: any) => ({ ...base, zIndex: 9999 }) },
};
const npTypeOptions: { type: SubjectType, label: string }[] = [
{ type: "unisexNoun", label: "Unisex Noun"},
{ type: "noun", label: "Noun" },
{ type: "participle", label: "Participle" },
];
const subjectTypeOptions: { type: SubjectType, label: string }[] = [
{ type: "pronouns" as SubjectType, label: "Pronouns" }
];
const compTypeOptions: { type: PredicateType, label: string }[] = [
{ type: "adjective", label: "Adjective" },
{ type: "adverb", label: "Loc. Adverb" },
];
export function InputSelector({ state, dispatch, entity }: {
state: ExplorerState,
dispatch: (action: ExplorerReducerAction) => void,
entity: "subject" | "predicate",
}) {
const typeOptions = [
...entity === "subject"
? subjectTypeOptions
: compTypeOptions,
...npTypeOptions.filter(o => !(entity === "predicate" && (
(state.subject.type === "pronouns" && ["noun", "participle"].includes(o.type))
// || (state.subject.type === "unisexNoun" && o.type === "unisexNoun")
))),
];
function onTypeSelect(e: React.ChangeEvent<HTMLInputElement>) {
if (entity === "subject") {
const t = e.target.value as SubjectType;
dispatch({ type: "setSubjectType", payload: t });
} else {
const t = e.target.value as PredicateType;
dispatch({ type: "setPredicateType", payload: t });
}
}
function onEntrySelect({ value }: any) {
dispatch({ type: entity === "subject" ? "setSubject" : "setPredicate", payload: parseInt(value) });
}
function CheckboxItem({ type, label }: { type: string, label: string }) {
const id = `${entity}-${type}-radio`;
return <div className="form-check">
<input
className="form-check-input"
type="radio"
id={id}
value={type}
checked={state[entity].type === type}
onChange={onTypeSelect}
/>
<label className="form-check-label" htmlFor={id}>
{label}
</label>
</div>
}
const type = state[entity].type;
const entry: T.NounEntry | T.VerbEntry | T.AdjectiveEntry | T.LocativeAdverbEntry | undefined = type === "pronouns"
? undefined
// @ts-ignore
: state[entity][type];
const options = type === "pronouns"
? []
: inputs[type].map(makeOption);
return <div className="form-group">
<h5 className="mb-2">{entity === "subject" ? "Subject:" : "Predicate:"}</h5>
<div className="mb-2">
{typeOptions.map(({ type, label }) => (
<CheckboxItem type={type} label={label} key={`${entity}-${type}-radio`} />
))}
</div>
{type !== "pronouns" && <>
<Select
value={entry && ("entry" in entry ? entry.entry : entry).ts.toString()}
onChange={onEntrySelect}
className="mb-2"
// @ts-ignore
options={options}
isSearchable
// @ts-ignore
placeholder={options.find(o => o.value === ("entry" in entry ? entry.entry : entry).ts.toString())?.label}
{...zIndexProps}
/>
{!["adjective", "adverb"].includes(type) && !(state.subject.type === "pronouns" && state.predicate.type === "unisexNoun") &&
<GenderAndNumberSelect state={state} dispatch={dispatch} entity={entity} />
}
</>}
</div>;
}
function GenderAndNumberSelect({ state, dispatch, entity }: {
state: ExplorerState,
dispatch: (action: ExplorerReducerAction) => void,
entity: "subject" | "predicate",
}) {
const type = state[entity].type;
if (type === "pronouns") {
return <div>ERROR: Should not display with pronouns</div>;
}
// @ts-ignore
const entry: NounEntry | VerbEntry | AdverbEntry | AdjectiveEntry = state[entity][type];
const gender = type === "noun"
? (isNounEntry(entry) && isMascNounEntry(entry) ? "masc" : "fem")
: type === "participle"
? "masc"
: state[entity].info.gender;
const pluralNounSelected = (
type === "noun" && isPluralNounEntry(state[entity][type])
);
return <div className="d-flex flex-row justify-content-center mt-3">
<div className="mr-2">
<ButtonSelect
small
options={[
...(type === "unisexNoun" || (type === "participle") || (isNounEntry(entry) && isMascNounEntry(entry)))
? [{ label: "Masc.", value: "masc" }] : [],
...(type === "unisexNoun" || ((type !== "participle") && (isNounEntry(entry) && isFemNounEntry(entry))))
? [{ label: "Fem.", value: "fem" }] : [],
]}
value={gender}
handleChange={type === "noun" ? p => null : (p) => dispatch({ type: "setGender", payload: { gender: p as T.Gender, entity }})}
/>
</div>
<div className="ml-2">
<ButtonSelect
small
options={[
...(!pluralNounSelected && type !== "participle") ? [{ label: "Singular", value: "singular" }] : [],
{ label: "Plural", value: "plural" },
]}
value={(state[entity].info.number === "plural" || pluralNounSelected || type === "participle") ? "plural" : "singular"}
handleChange={(p) => dispatch({ type: "setNumber", payload: { number: p as NounNumber, entity }})}
/>
</div>
</div>;
}
function makeOption(e: T.VerbEntry | T.NounEntry | T.AdjectiveEntry | T.LocativeAdverbEntry): { value: string, label: string } {
const entry = "entry" in e ? e.entry : e;
// TODO: THIS IS SUUUPER SKETCH
const eng = (isNounEntry(e) || isAdjectiveEntry(e) || isAdverbEntry(e))
? getEnglishWord(e)
: getEnglishParticiple(entry);
const english = typeof eng === "string"
? eng
: !eng
? ""
: ("singular" in eng && eng.singular !== undefined)
? eng.singular
: eng.plural;
return {
label: `${entry.p} - ${removeFVarients(entry.f)} (${english})`,
value: entry.ts.toString(),
};
}
export function TenseSelector({ state, dispatch }: {
state: ExplorerState,
dispatch: (action: ExplorerReducerAction) => void,
}) {
const options: { value: EquativeTense, label: string }[] = [
{ value: "present", label: "Present" },
{ value: "habitual", label: "Habitual" },
{ value: "subjunctive", label: "Subjunctive" },
{ value: "past", label: "Past" },
{ value: "future", label: "Future" },
{ value: "wouldBe", label: '"Would Be"' },
{ value: "pastSubjunctive", label: "Past Subjunctive" },
];
function onTenseSelect({ value }: any) {
dispatch({ type: "setTense", payload: value });
}
return <div>
<h5>Equative:</h5>
<Select
value={state.tense}
onChange={onTenseSelect}
className="mb-2"
// @ts-ignore
options={options}
placeholder={options.find(o => o.value === state.tense)?.label}
{...zIndexProps}
/>
<div className="text-center mb-2">
<ButtonSelect
small
options={[
{ label: "Pos.", value: "pos" },
{ label: "Neg.", value: "neg" },
]}
value={state.negative ? "neg" : "pos"}
handleChange={(p) => dispatch({ type: "setNegative", payload: p === "neg" })}
/>
</div>
</div>
}

View File

@ -1,52 +0,0 @@
import { Types as T } from "@lingdocs/pashto-inflector";
export type PredicateNPType = "noun" | "unisexNoun" | "participle";
export type PredicateCompType = "adjective" | "adverb";
export type PredicateType = PredicateNPType | PredicateCompType;
export type SubjectType = "pronouns" | "noun" | "unisexNoun" | "participle";
export type ExplorerState = {
tense: EquativeTense,
length: "short" | "long",
subject: SubjectEntityInfo,
predicate: PredicateEntityInfo,
negative: boolean,
};
export type SubjectEntityInfo = EntitiyInfo & { type: SubjectType };
export type PredicateEntityInfo = EntitiyInfo & {
type: PredicateType,
adjective: import("@lingdocs/pashto-inflector").Types.AdjectiveEntry,
adverb: import("@lingdocs/pashto-inflector").Types.LocativeAdverbEntry,
}
type EntitiyInfo = {
noun: import("@lingdocs/pashto-inflector").Types.NounEntry,
participle: import("@lingdocs/pashto-inflector").Types.VerbEntry,
unisexNoun: import("@lingdocs/pashto-inflector").Types.UnisexNounEntry,
info: {
number: NounNumber,
gender: T.Gender,
},
};
export type ExplorerReducerAction = {
type: "setPredicateType", payload: PredicateType,
} | {
type: "setPredicate", payload: number,
} | {
type: "setSubjectType", payload: SubjectType,
} | {
type: "setSubject", payload: number,
} | {
type: "setNumber", payload: { entity: "subject" | "predicate", number: NounNumber },
} | {
type: "setGender", payload: { entity: "subject" | "predicate", gender: T.Gender },
} | {
type: "setTense", payload: EquativeTense,
} | {
type: "setLength", payload: "short" | "long",
} | {
type: "setNegative", payload: boolean,
};

View File

@ -2,17 +2,15 @@
title: Equative Explorer 🌎 title: Equative Explorer 🌎
--- ---
import EquativeExplorer from "../../components/equative-explorer/EquativeExplorer"; import {
import { useState } from "react"; EPExplorer,
defaultTextOptions,
You can use this tool to explore how to make different equative sentences. Everything that comes out of this will be **gramatically correct**, but the sentences might not always make sense! 🤪 } from "@lingdocs/pashto-inflector";
import entryFeeder from "../../lib/entry-feeder";
<div className="mb-4"> <div className="mb-4">
<EquativeExplorer /> <EPExplorer
entryFeeder={entryFeeder}
opts={defaultTextOptions}
/>
</div> </div>
### Equative Rules: 👨‍🏫
- The **subject** has to be a **noun phrase**
- The **predicate** can be a **noun phrase** or **compliment**
- In Pashto, if the predicate is a noun phrase, the equative agrees with the predicate. Otherwise, if the predicate is a compliment, the equative agrees with the subject. In English, the equative always agrees with the subject.

16
src/lib/entry-feeder.ts Normal file
View File

@ -0,0 +1,16 @@
import { Types as T } from "@lingdocs/pashto-inflector";
import {
nouns,
verbs,
adjectives,
locativeAdverbs,
} from "../words/words";
const entryFeeder: T.EntryFeeder = {
nouns,
verbs,
adjectives,
locativeAdverbs,
}
export default entryFeeder;

View File

@ -1,6 +1,15 @@
// TODO: I think this is just used for the old equative explorer // TODO: I think this is just used for the old equative explorer
// build a new better equative explorer using NP Pickers etc and deprecate all this // build a new better equative explorer using NP Pickers etc and deprecate all this
type EPSelection = {
subject: NPSelection,
predicate: NPSelection | EComplementSelection,
equative: {
tense: EquativeTense,
negative: boolean,
},
};
type EquativeTense = "present" | "subjunctive" | "habitual" | "past" | "future" | "wouldBe" | "pastSubjunctive"; type EquativeTense = "present" | "subjunctive" | "habitual" | "past" | "future" | "wouldBe" | "pastSubjunctive";
type NounNumber = "singular" | "plural"; type NounNumber = "singular" | "plural";

View File

@ -5,16 +5,23 @@ import {
} from "@lingdocs/pashto-inflector"; } from "@lingdocs/pashto-inflector";
import { categorize } from "../lib/categorize"; import { categorize } from "../lib/categorize";
const words = categorize<T.Entry, T.Words>(rawWords, { const words = categorize<T.Entry, {
"nouns": tp.isNounEntry, nouns: T.NounEntry[],
"adjectives": tp.isAdjectiveEntry, adjectives: T.AdjectiveEntry[],
"verbs": tp.isVerbEntry, verbs: T.VerbEntry[],
"adverbs": tp.isAdverbEntry, adverbs: T.AdverbEntry[],
locativeAdverbs: T.LocativeAdverbEntry[],
}>(rawWords, {
nouns: tp.isNounEntry,
adjectives: tp.isAdjectiveEntry,
verbs: tp.isVerbEntry,
adverbs: tp.isAdverbEntry,
locativeAdverbs: tp.isLocativeAdverbEntry,
}); });
export default words; export default words;
export const { nouns, adjectives, verbs, adverbs } = words; export const { nouns, adjectives, verbs, adverbs, locativeAdverbs } = words;
// console.log( // console.log(
// Object.entries( // Object.entries(

View File

@ -21,6 +21,11 @@
"jsx": "react-jsx", "jsx": "react-jsx",
"noFallthroughCasesInSwitch": true "noFallthroughCasesInSwitch": true
}, },
"ts-node": {
"compilerOptions": {
"module": "commonjs"
}
},
"include": [ "include": [
"src" "src"
] ]

View File

@ -1684,10 +1684,10 @@
pbf "^3.2.1" pbf "^3.2.1"
rambda "^6.7.0" rambda "^6.7.0"
"@lingdocs/pashto-inflector@^2.0.5": "@lingdocs/pashto-inflector@^2.3.2":
version "2.0.5" version "2.3.2"
resolved "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-2.0.5.tgz#b917428e81395206d78f8f72122dddc4432364b3" resolved "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-2.3.2.tgz#59c42d5bbe4e2befc467cd506b12a11632545eaf"
integrity sha512-WdkunOYqj3045Too4PioDIh9ljYXrbGiV+CVZtbF8s8Bnw/L+6Y7ShgYFb2DQalkwtis+5BJzzcKMMUE4ZtTYQ== integrity sha512-EGWHwe8RdRD7NcZtE4CVUQGSvfXCcVyTrNmmqv1kJeRLZIn2MN2UMCbGRMZcz3681mCQvvfkRpsAD8xJSSjyNw==
dependencies: dependencies:
classnames "^2.2.6" classnames "^2.2.6"
pbf "^3.2.1" pbf "^3.2.1"