getting EP blocks working

This commit is contained in:
lingdocs 2022-06-04 20:42:35 -05:00
parent 41bd7bfab7
commit 370ba3e521
9 changed files with 110 additions and 76 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "@lingdocs/pashto-inflector", "name": "@lingdocs/pashto-inflector",
"version": "2.8.2", "version": "2.8.3",
"author": "lingdocs.com", "author": "lingdocs.com",
"description": "A Pashto inflection and verb conjugation engine, inculding React components for displaying Pashto text, inflections, and conjugations", "description": "A Pashto inflection and verb conjugation engine, inculding React components for displaying Pashto text, inflections, and conjugations",
"homepage": "https://verbs.lingdocs.com", "homepage": "https://verbs.lingdocs.com",

View File

@ -21,7 +21,7 @@ function Block({ opts, block }: {
if (block.type === "predicateSelection") { if (block.type === "predicateSelection") {
const english = getEnglishFromRendered(block.selection); const english = getEnglishFromRendered(block.selection);
return <div className="text-center"> return <div className="text-center">
<div>Pred</div> <div><strong>Predicate</strong></div>
{block.selection.type === "EQComp" {block.selection.type === "EQComp"
? <EqCompBlock opts={opts} comp={block.selection.selection} /> ? <EqCompBlock opts={opts} comp={block.selection.selection} />
: <NPBlock opts={opts} english={english}>{block.selection}</NPBlock>} : <NPBlock opts={opts} english={english}>{block.selection}</NPBlock>}
@ -49,12 +49,8 @@ function NUBlock({ opts }: {
> >
nu nu
</div> </div>
<div className="small text-muted text-center" style={{ <div>Neg.</div>
// TODO: find a better way to keep this limited to the width of the div above <EnglishBelow>not</EnglishBelow>
// don't let this make the div above expand
margin: "0 auto",
maxWidth: "300px",
}}>not</div>
</div>; </div>;
} }
@ -73,6 +69,8 @@ function EquativeBlock({ opts, eq }: {
> >
{"short" in eq.ps ? eq.ps.short[0].f : eq.ps[0].f} {"short" in eq.ps ? eq.ps.short[0].f : eq.ps[0].f}
</div> </div>
<div>Equative</div>
<EnglishBelow>{"="}</EnglishBelow>
</div>; </div>;
} }
@ -82,7 +80,7 @@ function SubjectBlock({ opts, np }: {
}) { }) {
const english = getEnglishFromRendered(np); const english = getEnglishFromRendered(np);
return <div className="text-center"> return <div className="text-center">
<div>Subject</div> <div><strong>Subject</strong></div>
<NPBlock opts={opts} english={english}>{np}</NPBlock> <NPBlock opts={opts} english={english}>{np}</NPBlock>
</div>; </div>;
} }
@ -107,12 +105,7 @@ function EqCompBlock({ opts, comp }: {
{adj.ps[0].f} {adj.ps[0].f}
</div> </div>
<div>Adj.</div> <div>Adj.</div>
{adj.e && <div className="small text-muted text-center" style={{ <EnglishBelow>{adj.e}</EnglishBelow>
// TODO: find a better way to keep this limited to the width of the div above
// don't let this make the div above expand
margin: "0 auto",
maxWidth: "300px",
}}>{adj.e}</div>}
</div>; </div>;
} }
@ -132,16 +125,11 @@ function EqCompBlock({ opts, comp }: {
{adv.ps[0].f} {adv.ps[0].f}
</div> </div>
<div>Loc. Adv.</div> <div>Loc. Adv.</div>
{adv.e && <div className="small text-muted text-center" style={{ <EnglishBelow>{adv.e}</EnglishBelow>
// TODO: find a better way to keep this limited to the width of the div above
// don't let this make the div above expand
margin: "0 auto",
maxWidth: "300px",
}}>{adv.e}</div>}
</div>; </div>;
} }
return <div className="text-center mb-2"> return <div className="text-center">
<div>Comp.</div> <div>Comp.</div>
{comp.type === "adjective" {comp.type === "adjective"
? <AdjectiveBlock opts={opts} adj={comp} /> ? <AdjectiveBlock opts={opts} adj={comp} />
@ -150,6 +138,7 @@ function EqCompBlock({ opts, comp }: {
: <div> : <div>
<Sandwich opts={opts} sandwich={comp} /> <Sandwich opts={opts} sandwich={comp} />
<div>Sandwich</div> <div>Sandwich</div>
<EnglishBelow>{comp.e}</EnglishBelow>
</div>} </div>}
</div>; </div>;
} }
@ -184,12 +173,7 @@ export function APBlock({ opts, children, english }: {
return <div> return <div>
<Sandwich opts={opts} sandwich={ap.selection} /> <Sandwich opts={opts} sandwich={ap.selection} />
<div>AP</div> <div>AP</div>
{english && <div className="small text-muted text-center" style={{ <EnglishBelow>{english}</EnglishBelow>
// TODO: find a better way to keep this limited to the width of the div above
// don't let this make the div above expand
margin: "0 auto",
maxWidth: "300px",
}}>{english}</div>}
</div>; </div>;
} }
@ -226,7 +210,7 @@ export function NPBlock({ opts, children, inside, english }: {
english?: string, english?: string,
}) { }) {
const np = children; const np = children;
const hasPossesor = !!(np.selection.type !== "pronoun" && np.selection.possesor); const hasPossesor = !!(np.selection.type !== "pronoun" && np.selection.possesor && !np.selection.possesor.shrunken);
return <div> return <div>
<div <div
className={classNames("d-flex flex-row justify-content-center align-items-center", { "pt-2": !inside && hasPossesor })} className={classNames("d-flex flex-row justify-content-center align-items-center", { "pt-2": !inside && hasPossesor })}
@ -241,12 +225,7 @@ export function NPBlock({ opts, children, inside, english }: {
<div> {np.selection.ps[0].f}</div> <div> {np.selection.ps[0].f}</div>
</div> </div>
<div className={inside ? "small" : ""}>NP</div> <div className={inside ? "small" : ""}>NP</div>
{english && <div className="small text-muted text-center" style={{ <EnglishBelow>{english}</EnglishBelow>
// TODO: find a better way to keep this limited to the width of the div above
// don't let this make the div above expand
margin: "0 auto",
maxWidth: "300px",
}}>{english}</div>}
</div> </div>
} }
@ -257,6 +236,9 @@ function Possesors({ opts, children }: {
if (!children) { if (!children) {
return null; return null;
} }
if (children.shrunken) {
return null;
}
const contraction = checkForContraction(children.np); const contraction = checkForContraction(children.np);
return <div className="d-flex flex-row mr-1 align-items-end" style={{ return <div className="d-flex flex-row mr-1 align-items-end" style={{
marginBottom: "0.5rem", marginBottom: "0.5rem",
@ -304,3 +286,11 @@ function Adjectives({ opts, children }: {
{children.map(a => a.ps[0].f).join(" ")}{` `} {children.map(a => a.ps[0].f).join(" ")}{` `}
</em> </em>
} }
function EnglishBelow({ children: e }: { children: string | undefined }) {
return <div className="small text-muted text-center" style={{
margin: "0 auto",
maxWidth: "300px",
height: "1rem",
}}>{e ? e : ""}</div>;
}

View File

@ -0,0 +1,16 @@
import { baParticle } from "../../lib/grammar-units";
import * as T from "../../types";
import Phonetics from "../Phonetics";
function KidDisplay({ opts, kid }: {
opts: T.TextOptions,
kid: T.Kid,
}) {
return <div className="mx-1">
{kid.type === "ba"
? <Phonetics opts={opts}>{baParticle}</Phonetics>
: <Phonetics opts={opts}>{kid.ps}</Phonetics>}
</div>
}
export default KidDisplay;

View File

@ -1,18 +1,41 @@
import * as T from "../../types"; import * as T from "../../types";
import Block from "../blocks/Block"; import Block from "../blocks/Block";
import KidDisplay from "../blocks/KidDisplay";
function EPBlocksDisplay({ opts, rendered }: { opts: T.TextOptions, rendered: T.EPRendered }) { function EPBlocksDisplay({ opts, rendered }: {
opts: T.TextOptions,
rendered: T.EPRendered,
}) {
const blocks = rendered.omitSubject const blocks = rendered.omitSubject
? rendered.blocks.filter(b => b.type !== "subjectSelection") ? rendered.blocks.filter(b => b.type !== "subjectSelection")
: rendered.blocks; : rendered.blocks;
return <div>
return <div className="d-flex flex-row justify-content-center align-items-end mt-3"> <div className="d-flex flex-row justify-content-center align-items-end mt-3">
{blocks.map((block, i) => ( <div key={Math.random()} className="mr-2">
<Block opts={opts} block={blocks[0]} />
</div>
<KidsSection opts={opts} kids={rendered.kids} />
{blocks.slice(1).map((block, i) => (
<div key={Math.random()} className="mr-2"> <div key={Math.random()} className="mr-2">
<Block opts={opts} block={block} /> <Block opts={opts} block={block} />
</div> </div>
))} ))}
</div>; </div>
</div>
}
function KidsSection({ opts, kids }: {
opts: T.TextOptions,
kids: T.Kid[],
}) {
return kids.length > 0 ? <div className="text-center mx-1 mr-3" style={{ paddingBottom: "1rem"}}>
<div className="d-flex flex-row mb-3 justify-content-center">
{kids.map(kid => (
<KidDisplay key={Math.random()} opts={opts} kid={kid} />
))}
</div>
<div><strong>kids</strong></div>
</div> : null;
} }
export default EPBlocksDisplay; export default EPBlocksDisplay;

View File

@ -8,12 +8,14 @@ import EPTextDisplay from "./EPTextDisplay";
import EPBlocksDisplay from "./EPBlocksDisplay"; import EPBlocksDisplay from "./EPBlocksDisplay";
type Mode = "text" | "blocks"; type Mode = "text" | "blocks";
// BIG TODO: FIGRUE OUT A WAY TO HANDLE OMITING SUBJECT
function EPDisplay({ eps, opts, setOmitSubject }: { function EPDisplay({ eps, opts, setOmitSubject }: {
eps: T.EPSelectionState, eps: T.EPSelectionState,
opts: T.TextOptions, opts: T.TextOptions,
setOmitSubject: (value: "true" | "false") => void, setOmitSubject: (value: "true" | "false") => void,
}) { }) {
const [mode] = useState<Mode>("text"); const [mode, setMode] = useState<Mode>("text");
const EP = completeEPSelection(eps); const EP = completeEPSelection(eps);
const subject = getSubjectSelection(eps.blocks); const subject = getSubjectSelection(eps.blocks);
@ -34,7 +36,7 @@ function EPDisplay({ eps, opts, setOmitSubject }: {
const renderedPredicate = getPredicateSelectionFromBlocks(rendered.blocks).selection; const renderedPredicate = getPredicateSelectionFromBlocks(rendered.blocks).selection;
return <div className="text-center pt-3"> return <div className="text-center pt-3">
<div className="mb-2 d-flex flex-row justify-content-between align-items-center"> <div className="mb-2 d-flex flex-row justify-content-between align-items-center">
{/* <ModeSelect value={mode} onChange={setMode} /> */} <ModeSelect value={mode} onChange={setMode} />
<ButtonSelect <ButtonSelect
small small
value={(eps.omitSubject ? "true" : "false") as "true" | "false"} value={(eps.omitSubject ? "true" : "false") as "true" | "false"}
@ -49,6 +51,9 @@ function EPDisplay({ eps, opts, setOmitSubject }: {
{mode === "text" {mode === "text"
? <EPTextDisplay opts={opts} compiled={result} /> ? <EPTextDisplay opts={opts} compiled={result} />
: <EPBlocksDisplay opts={opts} rendered={rendered} />} : <EPBlocksDisplay opts={opts} rendered={rendered} />}
{result.e && <div className="text-muted mt-3">
{result.e.map((e, i) => <div key={i}>{e}</div>)}
</div>}
{EP.predicate.selection.selection.type === "participle" && <div style={{ maxWidth: "6 00px", margin: "0 auto" }} className="alert alert-warning mt-3 pt-4"> {EP.predicate.selection.selection.type === "participle" && <div style={{ maxWidth: "6 00px", margin: "0 auto" }} className="alert alert-warning mt-3 pt-4">
<p> NOTE: This means that the subject {renderedSubject.selection.e ? `(${renderedSubject.selection.e})` : ""} is <strong>the action/idea</strong> of <p> NOTE: This means that the subject {renderedSubject.selection.e ? `(${renderedSubject.selection.e})` : ""} is <strong>the action/idea</strong> of
{` `} {` `}
@ -58,14 +63,14 @@ function EPDisplay({ eps, opts, setOmitSubject }: {
</div> </div>
} }
// function ModeSelect({ value, onChange }: { value: Mode, onChange: (m: Mode) => void }) { function ModeSelect({ value, onChange }: { value: Mode, onChange: (m: Mode) => void }) {
// return <div style={{ fontSize: "larger" }}> return <div style={{ fontSize: "larger" }}>
// {value === "text" ? <div className="clickable" onClick={() => onChange("blocks")}> {value === "text" ? <div className="clickable" onClick={() => onChange("blocks")}>
// <i className="fas fa-cubes" /> <i className="fas fa-cubes" />
// </div> : <div className="clickable" onClick={() => onChange("text")}> </div> : <div className="clickable" onClick={() => onChange("text")}>
// <i className="fas fa-align-left" /> <i className="fas fa-align-left" />
// </div>} </div>}
// </div>; </div>;
// } }
export default EPDisplay; export default EPDisplay;

View File

@ -38,7 +38,7 @@ function EPExplorer(props: {
entryFeeder: T.EntryFeeder, entryFeeder: T.EntryFeeder,
}) { }) {
const [mode, setMode] = useStickyState<"charts" | "phrases">("charts", "EPExplorerMode"); const [mode, setMode] = useStickyState<"charts" | "phrases">("charts", "EPExplorerMode");
const [eps, adjustEps] = useStickyReducer(epsReducer, blankEps, "EPState6", flashMessage); const [eps, adjustEps] = useStickyReducer(epsReducer, blankEps, "EPState7", flashMessage);
const [alert, setAlert] = useState<string | undefined>(undefined); const [alert, setAlert] = useState<string | undefined>(undefined);
const [showClipped, setShowClipped] = useState<string>(""); const [showClipped, setShowClipped] = useState<string>("");
const parent = useRef<HTMLDivElement>(null); const parent = useRef<HTMLDivElement>(null);

View File

@ -19,9 +19,6 @@ function EPTextDisplay({ compiled, opts }: { compiled: {
</div> </div>
: <VariationLayer vs={compiled.ps} /> : <VariationLayer vs={compiled.ps} />
} }
{compiled.e && <div className="text-muted mt-3">
{compiled.e.map((e, i) => <div key={i}>{e}</div>)}
</div>}
</div>; </div>;
} }

View File

@ -263,23 +263,26 @@ function arrangeVerbWNegative(head: T.PsString | undefined, restRaw: T.PsString[
export function compileEP(EP: T.EPRendered): { ps: T.SingleOrLengthOpts<T.PsString[]>, e?: string[] }; export function compileEP(EP: T.EPRendered): { ps: T.SingleOrLengthOpts<T.PsString[]>, e?: string[] };
export function compileEP(EP: T.EPRendered, combineLengths: true, blankOut?: BlankoutOptions): { ps: T.PsString[], e?: string[] }; export function compileEP(EP: T.EPRendered, combineLengths: true, blankOut?: BlankoutOptions): { ps: T.PsString[], e?: string[] };
export function compileEP(EP: T.EPRendered, combineLengths?: boolean, blankOut?: BlankoutOptions): { ps: T.SingleOrLengthOpts<T.PsString[]>, e?: string[] } { export function compileEP(EP: T.EPRendered, combineLengths?: boolean, blankOut?: BlankoutOptions): { ps: T.SingleOrLengthOpts<T.PsString[]>, e?: string[] } {
const psResult = compileEPPs(EP.blocks, EP.kids, blankOut); const psResult = compileEPPs(EP.blocks, EP.kids, EP.omitSubject, blankOut);
return { return {
ps: combineLengths ? flattenLengths(psResult) : psResult, ps: combineLengths ? flattenLengths(psResult) : psResult,
e: compileEnglishEP(EP), e: compileEnglishEP(EP),
}; };
} }
function compileEPPs(blocks: T.Block[], kids: T.Kid[], blankOut?: BlankoutOptions): T.SingleOrLengthOpts<T.PsString[]> { function compileEPPs(blocks: T.Block[], kids: T.Kid[], omitSubject: boolean, blankOut?: BlankoutOptions): T.SingleOrLengthOpts<T.PsString[]> {
if (hasEquativeWithLengths(blocks)) { if (hasEquativeWithLengths(blocks)) {
return { return {
long: compileEPPs(specifyEquativeLength(blocks, "long"), kids, blankOut) as T.PsString[], long: compileEPPs(specifyEquativeLength(blocks, "long"), kids, omitSubject, blankOut) as T.PsString[],
short: compileEPPs(specifyEquativeLength(blocks, "short"), kids, blankOut) as T.PsString[], short: compileEPPs(specifyEquativeLength(blocks, "short"), kids, omitSubject, blankOut) as T.PsString[],
}; };
} }
const subjectPerson = getSubjectSelectionFromBlocks(blocks) const subjectPerson = getSubjectSelectionFromBlocks(blocks)
.selection.selection.person; .selection.selection.person;
const blocksWKids = putKidsInKidsSection(blocks, kids); const blocksWKids = putKidsInKidsSection(
omitSubject ? blocks.filter(b => b.type !== "subjectSelection") : blocks,
kids,
);
return removeDuplicates(combineIntoText(blocksWKids, subjectPerson)); return removeDuplicates(combineIntoText(blocksWKids, subjectPerson));
} }

View File

@ -39,7 +39,7 @@ function getEPSBlocksAndKids(EP: T.EPSelectionComplete): { kids: T.Kid[], blocks
const commandingPerson = getPersonFromNP(commandingNP); const commandingPerson = getPersonFromNP(commandingNP);
const equative: T.EquativeBlock = { type: "equative", equative: renderEquative(EP.equative, commandingPerson) }; const equative: T.EquativeBlock = { type: "equative", equative: renderEquative(EP.equative, commandingPerson) };
const blocks: T.Block[] = [ const blocks: T.Block[] = [
...renderEPSBlocks(EP.omitSubject ? EP.blocks.filter(b => b.block.type !== "subjectSelection") : EP.blocks), ...renderEPSBlocks(EP.blocks),
{ {
type: "predicateSelection", type: "predicateSelection",
selection: EP.predicate.selection.type === "NP" selection: EP.predicate.selection.type === "NP"
@ -122,19 +122,19 @@ function findPossesivesToShrink(blocks: (T.EPSBlockComplete | T.SubjectSelection
function findShrunkenPossInNP(NP: T.NPSelection): T.MiniPronoun[] { function findShrunkenPossInNP(NP: T.NPSelection): T.MiniPronoun[] {
if (NP.selection.type === "pronoun") return []; if (NP.selection.type === "pronoun") return [];
if (!NP.selection.possesor) return []; if (!NP.selection.possesor) return [];
if (NP.selection.type === "noun") { // if (NP.selection.type === "noun") {
if (NP.selection.adjectives) { // if (NP.selection.adjectives) {
const { adjectives, ...rest } = NP.selection; // const { adjectives, ...rest } = NP.selection;
return [ // return [
// TODO: ability to find possesives shrinkage in sandwiches in adjectives // // TODO: ability to find possesives shrinkage in sandwiches in adjectives
// ...findShrunkenPossInAdjectives(adjectives), // // ...findShrunkenPossInAdjectives(adjectives),
...findShrunkenPossInNP({ type: "NP", selection: { // ...findShrunkenPossInNP({ type: "NP", selection: {
...rest, // ...rest,
adjectives: [], // adjectives: [],
}}), // }}),
]; // ];
} // }
} // }
if (NP.selection.possesor.shrunken) { if (NP.selection.possesor.shrunken) {
const person = getPersonFromNP(NP.selection.possesor.np); const person = getPersonFromNP(NP.selection.possesor.np);
const miniP: T.MiniPronoun = { const miniP: T.MiniPronoun = {