AP and NP block diagrams working
This commit is contained in:
parent
f4dc09e941
commit
2ba678b1ff
|
@ -6,7 +6,7 @@
|
||||||
"@formkit/auto-animate": "^1.0.0-beta.1",
|
"@formkit/auto-animate": "^1.0.0-beta.1",
|
||||||
"@fortawesome/fontawesome-free": "^5.15.4",
|
"@fortawesome/fontawesome-free": "^5.15.4",
|
||||||
"@lingdocs/lingdocs-main": "^0.3.1",
|
"@lingdocs/lingdocs-main": "^0.3.1",
|
||||||
"@lingdocs/pashto-inflector": "^2.6.8",
|
"@lingdocs/pashto-inflector": "^2.8.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",
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
import {
|
||||||
|
Types as T,
|
||||||
|
Examples,
|
||||||
|
renderEP,
|
||||||
|
compileEP,
|
||||||
|
|
||||||
|
} from "@lingdocs/pashto-inflector";
|
||||||
|
import { completeEPSelection } from "@lingdocs/pashto-inflector/dist/lib/phrase-building/render-ep";
|
||||||
|
import { useState } from "react";
|
||||||
|
// import EPBlocks from "./EPBlocks";
|
||||||
|
|
||||||
|
function getShort<X>(i: T.SingleOrLengthOpts<X>): X {
|
||||||
|
if ("long" in i) {
|
||||||
|
return i.long;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
function EditableExample({ children: eps, opts }: { children: T.EPSelectionState, opts: T.TextOptions }) {
|
||||||
|
const [mode, setMode] = useState<"example" | "blocks">("example");
|
||||||
|
const EPS = completeEPSelection(eps);
|
||||||
|
if (!EPS) {
|
||||||
|
return <div>Error: Invalid/incomplete Phrase</div>;
|
||||||
|
}
|
||||||
|
const rendered = renderEP(EPS);
|
||||||
|
const compiled = compileEP(rendered);
|
||||||
|
const text: T.PsString = {
|
||||||
|
...getShort(compiled.ps)[0],
|
||||||
|
e: compiled.e ? compiled.e.join(" / ") : undefined,
|
||||||
|
};
|
||||||
|
return <div>
|
||||||
|
<div className="d-flex flex-row justify-content-beginning">
|
||||||
|
{mode === "example" ? <div className="clickable" onClick={() => setMode("blocks")}>
|
||||||
|
<i className="fas fa-cubes" />
|
||||||
|
</div> : <div className="clickable" onClick={() => setMode("example")}>
|
||||||
|
<i className="fas fa-align-left" />
|
||||||
|
</div>}
|
||||||
|
</div>
|
||||||
|
{/* {mode === "example"
|
||||||
|
? <Examples opts={opts}>{[text]}</Examples>
|
||||||
|
: <EPBlocks opts={opts}>{rendered}</EPBlocks>} */}
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EditableExample;
|
|
@ -16,10 +16,17 @@ export function EditIcon() {
|
||||||
return <i className="fas fa-edit" />;
|
return <i className="fas fa-edit" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function selectionToBlock(s: T.NPSelection | T.APSelection): { type: "NP", block: T.NPSelection | undefined } | { type: "AP", block: T.APSelection | undefined } {
|
||||||
|
return (s.type === "AP")
|
||||||
|
? { type: "AP", block: s }
|
||||||
|
: { type: "NP", block: s };
|
||||||
|
}
|
||||||
|
|
||||||
function EditablePhraseDiagram({ opts, children }: {
|
function EditablePhraseDiagram({ opts, children }: {
|
||||||
opts: T.TextOptions,
|
opts: T.TextOptions,
|
||||||
children: BlockInput[],
|
children: (T.NPSelection | T.APSelection)[],
|
||||||
}) {
|
}) {
|
||||||
|
console.log({ aa: children[0] })
|
||||||
const block = children[0];
|
const block = children[0];
|
||||||
const parent = useRef<HTMLDivElement>(null);
|
const parent = useRef<HTMLDivElement>(null);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -32,8 +39,7 @@ function EditablePhraseDiagram({ opts, children }: {
|
||||||
} | {
|
} | {
|
||||||
type: "AP",
|
type: "AP",
|
||||||
block: T.APSelection | undefined,
|
block: T.APSelection | undefined,
|
||||||
}>(block);
|
}>(selectionToBlock(block));
|
||||||
console.log({ block });
|
|
||||||
if (children.length === 0) return null;
|
if (children.length === 0) return null;
|
||||||
function handleNPChange(np: T.NPSelection | undefined) {
|
function handleNPChange(np: T.NPSelection | undefined) {
|
||||||
setEdited({ type: "NP", block: np });
|
setEdited({ type: "NP", block: np });
|
||||||
|
@ -42,7 +48,7 @@ function EditablePhraseDiagram({ opts, children }: {
|
||||||
setEdited({ type: "AP", block: ap });
|
setEdited({ type: "AP", block: ap });
|
||||||
}
|
}
|
||||||
function handleReset() {
|
function handleReset() {
|
||||||
setEdited(block);
|
setEdited(selectionToBlock(block));
|
||||||
setEditing(false);
|
setEditing(false);
|
||||||
}
|
}
|
||||||
return <div>
|
return <div>
|
||||||
|
@ -76,7 +82,7 @@ function EditablePhraseDiagram({ opts, children }: {
|
||||||
</div>}
|
</div>}
|
||||||
{edited.block
|
{edited.block
|
||||||
&& <PhraseDiagram opts={opts}>
|
&& <PhraseDiagram opts={opts}>
|
||||||
{[edited] as BlockInput[]}
|
{edited.block}
|
||||||
</PhraseDiagram>}
|
</PhraseDiagram>}
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
|
|
|
@ -1,182 +1,31 @@
|
||||||
import {
|
import {
|
||||||
renderNPSelection,
|
renderNPSelection,
|
||||||
Types as T,
|
Types as T,
|
||||||
getEnglishFromRendered,
|
|
||||||
renderAPSelection,
|
renderAPSelection,
|
||||||
|
NPBlock,
|
||||||
|
APBlock,
|
||||||
} from "@lingdocs/pashto-inflector";
|
} from "@lingdocs/pashto-inflector";
|
||||||
import classNames from "classnames";
|
|
||||||
|
|
||||||
function PhraseDiagram({ opts, children }: {
|
function PhraseDiagram({ opts, children }: {
|
||||||
opts: T.TextOptions,
|
opts: T.TextOptions,
|
||||||
children: BlockInput[]
|
children: T.NPSelection | T.APSelection,
|
||||||
}) {
|
}) {
|
||||||
|
try {
|
||||||
|
const rendered = children.type === "AP"
|
||||||
|
? renderAPSelection(children)
|
||||||
|
: renderNPSelection(children, false, false, "subject", "none");
|
||||||
return <div>
|
return <div>
|
||||||
<div className="d-flex flex-row justify-content-center" style={{ maxWidth: "100%" }}>
|
<div className="d-flex flex-row justify-content-center" style={{ maxWidth: "100%" }}>
|
||||||
{children.map((block) => (
|
{rendered.type === "NP"
|
||||||
<Block key={Math.random()} opts={opts}>{block}</Block>
|
? <NPBlock opts={opts}>{rendered}</NPBlock>
|
||||||
))}
|
: <APBlock opts={opts}>{rendered}</APBlock>}
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
|
} catch(e) {
|
||||||
|
console.log(e);
|
||||||
|
return <div>ERROR</div>;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Block({ opts, children }: {
|
|
||||||
opts: T.TextOptions,
|
|
||||||
children: BlockInput,
|
|
||||||
}) {
|
|
||||||
if (children.type === "NP") {
|
|
||||||
const rendered = renderNPSelection(children.block, false, false, "subject", "none");
|
|
||||||
const english = getEnglishFromRendered(rendered)
|
|
||||||
return <div className="text-center mb-2">
|
|
||||||
<NP opts={opts} english={english}>{rendered}</NP>
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
const rendered = renderAPSelection(children.block);
|
|
||||||
const english = getEnglishFromRendered(rendered)
|
|
||||||
return <div className="text-center mb-2">
|
|
||||||
<AP opts={opts} english={english}>{rendered}</AP>
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
function AP({ opts, children, english }: {
|
|
||||||
opts: T.TextOptions,
|
|
||||||
children: T.Rendered<T.APSelection>,
|
|
||||||
english?: string,
|
|
||||||
}) {
|
|
||||||
const ap = children;
|
|
||||||
if (ap.type === "adverb") {
|
|
||||||
return <div>
|
|
||||||
<div
|
|
||||||
className={classNames("d-flex flex-row justify-content-center align-items-center")}
|
|
||||||
style={{
|
|
||||||
border: "2px solid black",
|
|
||||||
padding: "1rem",
|
|
||||||
textAlign: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{ap.ps[0].f}
|
|
||||||
</div>
|
|
||||||
<div>AP</div>
|
|
||||||
{english && <div className="small text-muted text-center" style={{
|
|
||||||
// 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>;
|
|
||||||
}
|
|
||||||
return <div>
|
|
||||||
<div className="text-center">Sandwich 🥪</div>
|
|
||||||
<div
|
|
||||||
className={classNames("d-flex flex-row justify-content-center align-items-center")}
|
|
||||||
style={{
|
|
||||||
border: "2px solid black",
|
|
||||||
padding: "0.75rem 0.5rem 0.25rem 0.5rem",
|
|
||||||
textAlign: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className="d-flex flex-row justify-content-between align-items-end">
|
|
||||||
<Possesors opts={opts}>{ap.inside.type !== "pronoun" ? ap.inside.possesor : undefined}</Possesors>
|
|
||||||
<div className="mr-2 ml-1 mb-1"><strong>{ap.before ? ap.before.f : ""}</strong></div>
|
|
||||||
<div>
|
|
||||||
<NP opts={opts} inside>{ap.inside}</NP>
|
|
||||||
</div>
|
|
||||||
<div className="ml-2 mr-1 mb-1"><strong>{ap.after ? ap.after.f : ""}</strong></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>AP</div>
|
|
||||||
{english && <div className="small text-muted text-center" style={{
|
|
||||||
// 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>;
|
|
||||||
}
|
|
||||||
|
|
||||||
function NP({ opts, children, inside, english }: {
|
|
||||||
opts: T.TextOptions,
|
|
||||||
children: T.Rendered<T.NPSelection>,
|
|
||||||
inside?: boolean,
|
|
||||||
english?: string,
|
|
||||||
}) {
|
|
||||||
const np = children;
|
|
||||||
const hasPossesor = !!(np.type !== "pronoun" && np.possesor);
|
|
||||||
return <div>
|
|
||||||
<div
|
|
||||||
className={classNames("d-flex flex-row justify-content-center align-items-center", { "pt-2": !inside && hasPossesor })}
|
|
||||||
style={{
|
|
||||||
border: "2px solid black",
|
|
||||||
padding: inside ? "0.3rem" : hasPossesor ? "0.5rem 1rem 0.25rem 1rem" : "1rem",
|
|
||||||
textAlign: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{!inside && <Possesors opts={opts}>{np.type !== "pronoun" ? np.possesor : undefined}</Possesors>}
|
|
||||||
<Adjectives opts={opts}>{np.adjectives}</Adjectives>
|
|
||||||
<div> {np.ps[0].f}</div>
|
|
||||||
</div>
|
|
||||||
<div className={inside ? "small" : ""}>NP</div>
|
|
||||||
{english && <div className="small text-muted text-center" style={{
|
|
||||||
// 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>
|
|
||||||
}
|
|
||||||
|
|
||||||
function Possesors({ opts, children }: {
|
|
||||||
opts: T.TextOptions,
|
|
||||||
children: { shrunken: boolean, np: T.Rendered<T.NPSelection> } | undefined,
|
|
||||||
}) {
|
|
||||||
if (!children) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const contraction = checkForContraction(children.np);
|
|
||||||
return <div className="d-flex flex-row mr-1 align-items-end" style={{
|
|
||||||
marginBottom: "0.5rem",
|
|
||||||
borderBottom: "1px solid grey",
|
|
||||||
}}>
|
|
||||||
{children.np.type !== "pronoun" && <Possesors opts={opts}>{children.np.possesor}</Possesors>}
|
|
||||||
<div>
|
|
||||||
{contraction && <div className="mb-1">({contraction})</div>}
|
|
||||||
<div className={classNames("d-flex", "flex-row", "align-items-center", { "text-muted": contraction })}>
|
|
||||||
<div className="mr-1 pb-2">du</div>
|
|
||||||
<div>
|
|
||||||
<NP opts={opts} inside>{children.np}</NP>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkForContraction(np: T.Rendered<T.NPSelection>): string | undefined {
|
|
||||||
if (np.type !== "pronoun") return undefined;
|
|
||||||
if (np.person === T.Person.FirstSingMale || np.person === T.Person.FirstSingFemale) {
|
|
||||||
return "zmaa"
|
|
||||||
}
|
|
||||||
if (np.person === T.Person.SecondSingMale || np.person === T.Person.SecondSingFemale) {
|
|
||||||
return "staa"
|
|
||||||
}
|
|
||||||
if (np.person === T.Person.FirstPlurMale || np.person === T.Person.FirstPlurFemale) {
|
|
||||||
return "zmoonG"
|
|
||||||
}
|
|
||||||
if (np.person === T.Person.SecondPlurMale || np.person === T.Person.SecondPlurFemale) {
|
|
||||||
return "staaso"
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Adjectives({ opts, children }: {
|
|
||||||
opts: T.TextOptions,
|
|
||||||
children: T.Rendered<T.AdjectiveSelection>[] | undefined,
|
|
||||||
}) {
|
|
||||||
if (!children) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return <em className="mr-1">
|
|
||||||
{children.map(a => a.ps[0].f).join(" ")}{` `}
|
|
||||||
</em>
|
|
||||||
}
|
|
||||||
|
|
||||||
export default PhraseDiagram;
|
export default PhraseDiagram;
|
|
@ -28,7 +28,7 @@ An adverb is a word or expression that modifies the time, manner, place, etc. of
|
||||||
<EditablePhraseDiagram opts={opts}>{[
|
<EditablePhraseDiagram opts={opts}>{[
|
||||||
{
|
{
|
||||||
type: "AP",
|
type: "AP",
|
||||||
block: {
|
selection: {
|
||||||
type: "adverb",
|
type: "adverb",
|
||||||
entry: {"ts":1527815160,"i":2394,"p":"پرون","f":"paroon","g":"paroon","e":"yesterday","c":"adv."},
|
entry: {"ts":1527815160,"i":2394,"p":"پرون","f":"paroon","g":"paroon","e":"yesterday","c":"adv."},
|
||||||
},
|
},
|
||||||
|
@ -38,7 +38,7 @@ An adverb is a word or expression that modifies the time, manner, place, etc. of
|
||||||
<EditablePhraseDiagram opts={opts}>{[
|
<EditablePhraseDiagram opts={opts}>{[
|
||||||
{
|
{
|
||||||
type: "AP",
|
type: "AP",
|
||||||
block: {
|
selection: {
|
||||||
type: "adverb",
|
type: "adverb",
|
||||||
entry: {"ts":1527819967,"i":5428,"p":"خامخا","f":"khaamakhaa","g":"khaamakhaa","e":"definitely, for sure, whether someone wants or not, willy-nilly (this last use more in Urdu)","c":"adv."},
|
entry: {"ts":1527819967,"i":5428,"p":"خامخا","f":"khaamakhaa","g":"khaamakhaa","e":"definitely, for sure, whether someone wants or not, willy-nilly (this last use more in Urdu)","c":"adv."},
|
||||||
},
|
},
|
||||||
|
@ -54,12 +54,14 @@ These "sandwiches" are also used as an adverb to give more information for the p
|
||||||
<EditablePhraseDiagram opts={opts}>{[
|
<EditablePhraseDiagram opts={opts}>{[
|
||||||
{
|
{
|
||||||
type: "AP",
|
type: "AP",
|
||||||
block: {
|
selection: {
|
||||||
type: "sandwich",
|
type: "sandwich",
|
||||||
before: { p: "په", f: "pu" },
|
before: { p: "په", f: "pu" },
|
||||||
after: { p: "کې", f: "ke" },
|
after: { p: "کې", f: "ke" },
|
||||||
e: "in",
|
e: "in",
|
||||||
inside: {
|
inside: {
|
||||||
|
type: "NP",
|
||||||
|
selection: {
|
||||||
type: "noun",
|
type: "noun",
|
||||||
entry: {"ts":1527812828,"i":10539,"p":"کور","f":"kor","g":"kor","e":"house, home","c":"n. m."},
|
entry: {"ts":1527812828,"i":10539,"p":"کور","f":"kor","g":"kor","e":"house, home","c":"n. m."},
|
||||||
gender: "masc",
|
gender: "masc",
|
||||||
|
@ -71,6 +73,7 @@ These "sandwiches" are also used as an adverb to give more information for the p
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
]}</EditablePhraseDiagram>
|
]}</EditablePhraseDiagram>
|
||||||
|
|
||||||
Because the inside of a sandwich is an <Link to="/phrase-structure/np/">NP</Link> we can also spice it up by adding adjectives.
|
Because the inside of a sandwich is an <Link to="/phrase-structure/np/">NP</Link> we can also spice it up by adding adjectives.
|
||||||
|
@ -78,12 +81,14 @@ Because the inside of a sandwich is an <Link to="/phrase-structure/np/">NP</Link
|
||||||
<EditablePhraseDiagram opts={opts}>{[
|
<EditablePhraseDiagram opts={opts}>{[
|
||||||
{
|
{
|
||||||
type: "AP",
|
type: "AP",
|
||||||
block: {
|
selection: {
|
||||||
type: "sandwich",
|
type: "sandwich",
|
||||||
before: { p: "په", f: "pu" },
|
before: { p: "په", f: "pu" },
|
||||||
after: { p: "کې", f: "ke" },
|
after: { p: "کې", f: "ke" },
|
||||||
e: "in",
|
e: "in",
|
||||||
inside: {
|
inside: {
|
||||||
|
type: "NP",
|
||||||
|
selection: {
|
||||||
type: "noun",
|
type: "noun",
|
||||||
entry: {"ts":1527812828,"i":10539,"p":"کور","f":"kor","g":"kor","e":"house, home","c":"n. m."},
|
entry: {"ts":1527812828,"i":10539,"p":"کور","f":"kor","g":"kor","e":"house, home","c":"n. m."},
|
||||||
gender: "masc",
|
gender: "masc",
|
||||||
|
@ -98,6 +103,7 @@ Because the inside of a sandwich is an <Link to="/phrase-structure/np/">NP</Link
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
]}</EditablePhraseDiagram>
|
]}</EditablePhraseDiagram>
|
||||||
|
|
||||||
We can also add a possesor it hangs outside of the sandwich. All together it's still all considered one AP block though.
|
We can also add a possesor it hangs outside of the sandwich. All together it's still all considered one AP block though.
|
||||||
|
@ -105,12 +111,14 @@ We can also add a possesor it hangs outside of the sandwich. All together it's s
|
||||||
<EditablePhraseDiagram opts={opts}>{[
|
<EditablePhraseDiagram opts={opts}>{[
|
||||||
{
|
{
|
||||||
type: "AP",
|
type: "AP",
|
||||||
block: {
|
selection: {
|
||||||
type: "sandwich",
|
type: "sandwich",
|
||||||
before: { p: "په", f: "pu" },
|
before: { p: "په", f: "pu" },
|
||||||
after: { p: "کې", f: "ke" },
|
after: { p: "کې", f: "ke" },
|
||||||
e: "in",
|
e: "in",
|
||||||
inside: {
|
inside: {
|
||||||
|
type: "NP",
|
||||||
|
selection: {
|
||||||
type: "noun",
|
type: "noun",
|
||||||
entry: {"ts":1527812828,"i":10539,"p":"کور","f":"kor","g":"kor","e":"house, home","c":"n. m."},
|
entry: {"ts":1527812828,"i":10539,"p":"کور","f":"kor","g":"kor","e":"house, home","c":"n. m."},
|
||||||
gender: "masc",
|
gender: "masc",
|
||||||
|
@ -124,6 +132,8 @@ We can also add a possesor it hangs outside of the sandwich. All together it's s
|
||||||
possesor: {
|
possesor: {
|
||||||
shrunken: false,
|
shrunken: false,
|
||||||
np: {
|
np: {
|
||||||
|
type: "NP",
|
||||||
|
selection: {
|
||||||
type: "noun",
|
type: "noun",
|
||||||
entry: {"ts":1527815251,"i":7802,"p":"سړی","f":"saRéy","g":"saRey","e":"man","c":"n. m.","ec":"man","ep":"men"},
|
entry: {"ts":1527815251,"i":7802,"p":"سړی","f":"saRéy","g":"saRey","e":"man","c":"n. m.","ec":"man","ep":"men"},
|
||||||
gender: "masc",
|
gender: "masc",
|
||||||
|
@ -137,6 +147,8 @@ We can also add a possesor it hangs outside of the sandwich. All together it's s
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
]}</EditablePhraseDiagram>
|
]}</EditablePhraseDiagram>
|
||||||
|
|
||||||
Here's another example using the sandwich <InlinePs opts={opts} ps={{ p: "سره", f: "sara", e: "with" }} />:
|
Here's another example using the sandwich <InlinePs opts={opts} ps={{ p: "سره", f: "sara", e: "with" }} />:
|
||||||
|
@ -144,12 +156,14 @@ Here's another example using the sandwich <InlinePs opts={opts} ps={{ p: "سره
|
||||||
<EditablePhraseDiagram opts={opts}>{[
|
<EditablePhraseDiagram opts={opts}>{[
|
||||||
{
|
{
|
||||||
type: "AP",
|
type: "AP",
|
||||||
block: {
|
selection: {
|
||||||
type: "sandwich",
|
type: "sandwich",
|
||||||
before: { p: "له", f: "la" },
|
before: { p: "له", f: "la" },
|
||||||
after: { p: "سره", f: "sara" },
|
after: { p: "سره", f: "sara" },
|
||||||
e: "with",
|
e: "with",
|
||||||
inside: {
|
inside: {
|
||||||
|
type: "NP",
|
||||||
|
selection: {
|
||||||
type: "noun",
|
type: "noun",
|
||||||
entry: {"ts":1527814159,"i":12723,"p":"ملګری","f":"malgúrey","g":"malgurey","e":"friend, companion","c":"n. m. anim. unisex"},
|
entry: {"ts":1527814159,"i":12723,"p":"ملګری","f":"malgúrey","g":"malgurey","e":"friend, companion","c":"n. m. anim. unisex"},
|
||||||
gender: "masc",
|
gender: "masc",
|
||||||
|
@ -160,6 +174,8 @@ Here's another example using the sandwich <InlinePs opts={opts} ps={{ p: "سره
|
||||||
possesor: {
|
possesor: {
|
||||||
shrunken: false,
|
shrunken: false,
|
||||||
np: {
|
np: {
|
||||||
|
type: "NP",
|
||||||
|
selection: {
|
||||||
type: "pronoun",
|
type: "pronoun",
|
||||||
distance: "far",
|
distance: "far",
|
||||||
person: 0,
|
person: 0,
|
||||||
|
@ -168,6 +184,8 @@ Here's another example using the sandwich <InlinePs opts={opts} ps={{ p: "سره
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
]}</EditablePhraseDiagram>
|
]}</EditablePhraseDiagram>
|
||||||
|
|
||||||
Notice how when we put the word <InlinePs opts={opts} ps={{ p: "ملګری", f: "malgúrey", e: "friend" }} /> inside the sandwich it <Link to="/inflection/inflection-intro/">inflects</Link>. You <strong>always inflect the inside of the sandwich</strong> except for <Link to="/inflection/inflection-patterns/#exceptions">two exceptions</Link>.
|
Notice how when we put the word <InlinePs opts={opts} ps={{ p: "ملګری", f: "malgúrey", e: "friend" }} /> inside the sandwich it <Link to="/inflection/inflection-intro/">inflects</Link>. You <strong>always inflect the inside of the sandwich</strong> except for <Link to="/inflection/inflection-patterns/#exceptions">two exceptions</Link>.
|
|
@ -10,9 +10,6 @@ import {
|
||||||
} from "@lingdocs/pashto-inflector";
|
} from "@lingdocs/pashto-inflector";
|
||||||
import psmd from "../../lib/psmd";
|
import psmd from "../../lib/psmd";
|
||||||
import Link from "../../components/Link";
|
import Link from "../../components/Link";
|
||||||
import EditablePhraseDiagram, {
|
|
||||||
EditIcon,
|
|
||||||
} from "../../components/phrase-diagram/EditablePhraseDiagram";
|
|
||||||
import EquativeIllustration from "../../components/EquativeIllustration";
|
import EquativeIllustration from "../../components/EquativeIllustration";
|
||||||
import BasicBlocks from "../../components/BasicBlocks"
|
import BasicBlocks from "../../components/BasicBlocks"
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ A **noun** is a word that we use to identify people, places, things, or ideas. O
|
||||||
<EditablePhraseDiagram opts={opts}>{[
|
<EditablePhraseDiagram opts={opts}>{[
|
||||||
{
|
{
|
||||||
type: "NP",
|
type: "NP",
|
||||||
block: {
|
selection: {
|
||||||
type: "noun",
|
type: "noun",
|
||||||
entry: {"ts":1527812817,"i":9999,"p":"کتاب","f":"kitáab","g":"kitaab","e":"book","c":"n. m."},
|
entry: {"ts":1527812817,"i":9999,"p":"کتاب","f":"kitáab","g":"kitaab","e":"book","c":"n. m."},
|
||||||
gender: "masc",
|
gender: "masc",
|
||||||
|
@ -58,7 +58,7 @@ We can also **extend our noun by adding *adjectives***. Let's add the *adjective
|
||||||
<EditablePhraseDiagram opts={opts}>{[
|
<EditablePhraseDiagram opts={opts}>{[
|
||||||
{
|
{
|
||||||
type: "NP",
|
type: "NP",
|
||||||
block: {
|
selection: {
|
||||||
type: "noun",
|
type: "noun",
|
||||||
entry: {"ts":1527812817,"i":9999,"p":"کتاب","f":"kitáab","g":"kitaab","e":"book","c":"n. m."},
|
entry: {"ts":1527812817,"i":9999,"p":"کتاب","f":"kitáab","g":"kitaab","e":"book","c":"n. m."},
|
||||||
gender: "masc",
|
gender: "masc",
|
||||||
|
@ -70,7 +70,7 @@ We can also **extend our noun by adding *adjectives***. Let's add the *adjective
|
||||||
entry: {"ts":1527815451,"i":7245,"p":"زوړ","f":"zoR","g":"zoR","e":"old","c":"adj. irreg.","infap":"زاړه","infaf":"zaaRu","infbp":"زړ","infbf":"zaR"},
|
entry: {"ts":1527815451,"i":7245,"p":"زوړ","f":"zoR","g":"zoR","e":"old","c":"adj. irreg.","infap":"زاړه","infaf":"zaaRu","infbp":"زړ","infbf":"zaR"},
|
||||||
}],
|
}],
|
||||||
possesor: undefined,
|
possesor: undefined,
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
]}</EditablePhraseDiagram>
|
]}</EditablePhraseDiagram>
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ Now we have two words, but it's still **one NP**, one building block. We can add
|
||||||
<EditablePhraseDiagram opts={opts}>{[
|
<EditablePhraseDiagram opts={opts}>{[
|
||||||
{
|
{
|
||||||
type: "NP",
|
type: "NP",
|
||||||
block: {
|
selection: {
|
||||||
type: "noun",
|
type: "noun",
|
||||||
entry: {"ts":1527812817,"i":9999,"p":"کتاب","f":"kitáab","g":"kitaab","e":"book","c":"n. m."},
|
entry: {"ts":1527812817,"i":9999,"p":"کتاب","f":"kitáab","g":"kitaab","e":"book","c":"n. m."},
|
||||||
gender: "masc",
|
gender: "masc",
|
||||||
|
@ -101,7 +101,7 @@ Now we have two words, but it's still **one NP**, one building block. We can add
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
possesor: undefined,
|
possesor: undefined,
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
]}</EditablePhraseDiagram>
|
]}</EditablePhraseDiagram>
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ We can also add a **possesor** by adding another NP <Link to="/sandwiches/sandwi
|
||||||
<EditablePhraseDiagram opts={opts}>{[
|
<EditablePhraseDiagram opts={opts}>{[
|
||||||
{
|
{
|
||||||
type: "NP",
|
type: "NP",
|
||||||
block: {
|
selection: {
|
||||||
type: "noun",
|
type: "noun",
|
||||||
entry: {"ts":1527812817,"i":9999,"p":"کتاب","f":"kitáab","g":"kitaab","e":"book","c":"n. m."},
|
entry: {"ts":1527812817,"i":9999,"p":"کتاب","f":"kitáab","g":"kitaab","e":"book","c":"n. m."},
|
||||||
gender: "masc",
|
gender: "masc",
|
||||||
|
@ -126,6 +126,8 @@ We can also add a **possesor** by adding another NP <Link to="/sandwiches/sandwi
|
||||||
possesor: {
|
possesor: {
|
||||||
shrunken: false,
|
shrunken: false,
|
||||||
np: {
|
np: {
|
||||||
|
type: "NP",
|
||||||
|
selection: {
|
||||||
type: "noun",
|
type: "noun",
|
||||||
entry: {"ts":1527812881,"i":11694,"p":"ماشوم","f":"maashoom","g":"maashoom","e":"child, kid","c":"n. m. anim. unisex","ec":"child","ep":"children"},
|
entry: {"ts":1527812881,"i":11694,"p":"ماشوم","f":"maashoom","g":"maashoom","e":"child, kid","c":"n. m. anim. unisex","ec":"child","ep":"children"},
|
||||||
gender: "masc",
|
gender: "masc",
|
||||||
|
@ -133,6 +135,7 @@ We can also add a **possesor** by adding another NP <Link to="/sandwiches/sandwi
|
||||||
number: "singular",
|
number: "singular",
|
||||||
numberCanChange: true,
|
numberCanChange: true,
|
||||||
adjectives: [],
|
adjectives: [],
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -144,7 +147,7 @@ If our possesor is a noun, we can add a possesor to *it*. Try clicking the <Edit
|
||||||
<EditablePhraseDiagram opts={opts}>{[
|
<EditablePhraseDiagram opts={opts}>{[
|
||||||
{
|
{
|
||||||
type: "NP",
|
type: "NP",
|
||||||
block: {
|
selection: {
|
||||||
type: "noun",
|
type: "noun",
|
||||||
entry: {"ts":1527812817,"i":9999,"p":"کتاب","f":"kitáab","g":"kitaab","e":"book","c":"n. m."},
|
entry: {"ts":1527812817,"i":9999,"p":"کتاب","f":"kitáab","g":"kitaab","e":"book","c":"n. m."},
|
||||||
gender: "masc",
|
gender: "masc",
|
||||||
|
@ -160,6 +163,8 @@ If our possesor is a noun, we can add a possesor to *it*. Try clicking the <Edit
|
||||||
possesor: {
|
possesor: {
|
||||||
shrunken: false,
|
shrunken: false,
|
||||||
np: {
|
np: {
|
||||||
|
type: "NP",
|
||||||
|
selection: {
|
||||||
type: "noun",
|
type: "noun",
|
||||||
entry: {"ts":1527812881,"i":11694,"p":"ماشوم","f":"maashoom","g":"maashoom","e":"child, kid","c":"n. m. anim. unisex","ec":"child","ep":"children"},
|
entry: {"ts":1527812881,"i":11694,"p":"ماشوم","f":"maashoom","g":"maashoom","e":"child, kid","c":"n. m. anim. unisex","ec":"child","ep":"children"},
|
||||||
gender: "masc",
|
gender: "masc",
|
||||||
|
@ -170,6 +175,8 @@ If our possesor is a noun, we can add a possesor to *it*. Try clicking the <Edit
|
||||||
possesor: {
|
possesor: {
|
||||||
shrunken: false,
|
shrunken: false,
|
||||||
np: {
|
np: {
|
||||||
|
type: "NP",
|
||||||
|
selection: {
|
||||||
type: "noun",
|
type: "noun",
|
||||||
entry: {"ts":1527815177,"i":2530,"p":"پلار","f":"plaar","g":"plaar","e":"father","c":"n. m."},
|
entry: {"ts":1527815177,"i":2530,"p":"پلار","f":"plaar","g":"plaar","e":"father","c":"n. m."},
|
||||||
gender: "masc",
|
gender: "masc",
|
||||||
|
@ -183,6 +190,8 @@ If our possesor is a noun, we can add a possesor to *it*. Try clicking the <Edit
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
]}</EditablePhraseDiagram>
|
]}</EditablePhraseDiagram>
|
||||||
|
|
||||||
A possesor can have another possesor which can have another posseser and so-on and on *forever*. The nerdy word for this phenomenon where things reference/repeat themselves is [recursion](https://en.wikipedia.org/wiki/Recursion). 🤓
|
A possesor can have another possesor which can have another posseser and so-on and on *forever*. The nerdy word for this phenomenon where things reference/repeat themselves is [recursion](https://en.wikipedia.org/wiki/Recursion). 🤓
|
||||||
|
@ -206,23 +215,21 @@ You can't add any adjectives or possesors to pronouns in Pashto. They just stand
|
||||||
<EditablePhraseDiagram opts={opts}>{[
|
<EditablePhraseDiagram opts={opts}>{[
|
||||||
{
|
{
|
||||||
type: "NP",
|
type: "NP",
|
||||||
block: {
|
selection: {
|
||||||
type: "pronoun",
|
type: "pronoun",
|
||||||
person: 0,
|
person: 0,
|
||||||
distance: "far",
|
distance: "far",
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
]}</EditablePhraseDiagram>
|
]}</EditablePhraseDiagram>
|
||||||
|
|
||||||
<EditablePhraseDiagram opts={opts}>{[
|
<EditablePhraseDiagram opts={opts}>{[
|
||||||
|
{type: "NP", selection:
|
||||||
{
|
{
|
||||||
type: "NP",
|
|
||||||
block: {
|
|
||||||
type: "pronoun",
|
type: "pronoun",
|
||||||
person: 11,
|
person: 11,
|
||||||
distance: "far",
|
distance: "far",
|
||||||
},
|
}},
|
||||||
},
|
|
||||||
]}</EditablePhraseDiagram>
|
]}</EditablePhraseDiagram>
|
||||||
|
|
||||||
### Participle
|
### Participle
|
||||||
|
@ -235,12 +242,12 @@ In Pashto you can use the infinitive form of a verb as a participle, meaning you
|
||||||
<EditablePhraseDiagram opts={opts}>{[
|
<EditablePhraseDiagram opts={opts}>{[
|
||||||
{
|
{
|
||||||
type: "NP",
|
type: "NP",
|
||||||
block: {
|
selection: {
|
||||||
type: "participle",
|
type: "participle",
|
||||||
verb: {
|
verb: {
|
||||||
entry: {"ts":1527812856,"i":11617,"p":"لیکل","f":"leekul","g":"leekul","e":"to write","c":"v. trans./gramm. trans.","ec":"write,writes,writing,wrote,written"},
|
entry: {"ts":1527812856,"i":11617,"p":"لیکل","f":"leekul","g":"leekul","e":"to write","c":"v. trans./gramm. trans.","ec":"write,writes,writing,wrote,written"},
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
]}</EditablePhraseDiagram>
|
]}</EditablePhraseDiagram>
|
||||||
|
|
||||||
|
@ -291,12 +298,12 @@ For example, if we take the participle <InlinePs opts={opts} ps={{ p: "وهل",
|
||||||
<EditablePhraseDiagram opts={opts}>{[
|
<EditablePhraseDiagram opts={opts}>{[
|
||||||
{
|
{
|
||||||
type: "NP",
|
type: "NP",
|
||||||
block: {
|
selection: {
|
||||||
type: "participle",
|
type: "participle",
|
||||||
verb: {
|
verb: {
|
||||||
entry: {"ts":1527815399,"i":14463,"p":"وهل","f":"wahul","g":"wahul","e":"to hit","c":"v. trans.","tppp":"واهه","tppf":"waahu","ec":"hit,hits,hitting,hit,hit"},
|
entry: {"ts":1527815399,"i":14463,"p":"وهل","f":"wahul","g":"wahul","e":"to hit","c":"v. trans.","tppp":"واهه","tppf":"waahu","ec":"hit,hits,hitting,hit,hit"},
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
]}</EditablePhraseDiagram>
|
]}</EditablePhraseDiagram>
|
||||||
|
|
||||||
|
@ -305,7 +312,7 @@ And we can add the word <InlinePs opts={opts} ps={{ p: "ماشومان", f: "maa
|
||||||
<EditablePhraseDiagram opts={opts}>{[
|
<EditablePhraseDiagram opts={opts}>{[
|
||||||
{
|
{
|
||||||
type: "NP",
|
type: "NP",
|
||||||
block: {
|
selection: {
|
||||||
type: "participle",
|
type: "participle",
|
||||||
verb: {
|
verb: {
|
||||||
entry: {"ts":1527815399,"i":14463,"p":"وهل","f":"wahul","g":"wahul","e":"to hit","c":"v. trans.","tppp":"واهه","tppf":"waahu","ec":"hit,hits,hitting,hit,hit"},
|
entry: {"ts":1527815399,"i":14463,"p":"وهل","f":"wahul","g":"wahul","e":"to hit","c":"v. trans.","tppp":"واهه","tppf":"waahu","ec":"hit,hits,hitting,hit,hit"},
|
||||||
|
@ -313,6 +320,8 @@ And we can add the word <InlinePs opts={opts} ps={{ p: "ماشومان", f: "maa
|
||||||
possesor: {
|
possesor: {
|
||||||
shrunken: false,
|
shrunken: false,
|
||||||
np: {
|
np: {
|
||||||
|
type: "NP",
|
||||||
|
selection: {
|
||||||
type: "noun",
|
type: "noun",
|
||||||
entry: {"ts":1527812881,"i":11694,"p":"ماشوم","f":"maashoom","g":"maashoom","e":"child, kid","c":"n. m. anim. unisex","ec":"child","ep":"children"},
|
entry: {"ts":1527812881,"i":11694,"p":"ماشوم","f":"maashoom","g":"maashoom","e":"child, kid","c":"n. m. anim. unisex","ec":"child","ep":"children"},
|
||||||
gender: "masc",
|
gender: "masc",
|
||||||
|
@ -324,6 +333,7 @@ And we can add the word <InlinePs opts={opts} ps={{ p: "ماشومان", f: "maa
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
]}</EditablePhraseDiagram>
|
]}</EditablePhraseDiagram>
|
||||||
|
|
||||||
The noun we just attached can be a subject *or* an object of the participle. You just have to know from context. So this NP can mean either:
|
The noun we just attached can be a subject *or* an object of the participle. You just have to know from context. So this NP can mean either:
|
||||||
|
|
|
@ -218,12 +218,15 @@ export default function EquativeGame({ id, link, level }: { id: string, link: st
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
function makeRandomEPS(l: T.EquativeTense | "allIdentify" | "allProduce"): T.EPSelectionComplete {
|
function makeRandomEPS(l: T.EquativeTense | "allIdentify" | "allProduce"): T.EPSelectionComplete {
|
||||||
const subj = randFromArray([
|
const subj: T.NPSelection = {
|
||||||
|
type: "NP",
|
||||||
|
selection: randFromArray([
|
||||||
makeRandPronoun,
|
makeRandPronoun,
|
||||||
makeRandPronoun,
|
makeRandPronoun,
|
||||||
makeRandomNoun,
|
makeRandomNoun,
|
||||||
makeRandPronoun,
|
makeRandPronoun,
|
||||||
])();
|
])(),
|
||||||
|
};
|
||||||
const pred = randFromArray([...adjectives, ...locAdverbs]);
|
const pred = randFromArray([...adjectives, ...locAdverbs]);
|
||||||
const tense = (l === "allIdentify" || l === "allProduce")
|
const tense = (l === "allIdentify" || l === "allProduce")
|
||||||
? randFromArray(tenses)
|
? randFromArray(tenses)
|
||||||
|
@ -258,7 +261,7 @@ export default function EquativeGame({ id, link, level }: { id: string, link: st
|
||||||
question: {
|
question: {
|
||||||
EPS,
|
EPS,
|
||||||
phrase,
|
phrase,
|
||||||
equative: EP.equative,
|
equative: getEqFromRendered(EP),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -478,7 +481,9 @@ function makeEPS(subject: T.NPSelection, predicate: T.AdjectiveEntry | T.Locativ
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
predicate: {
|
predicate: {
|
||||||
type: "Complement",
|
type: "predicateSelection",
|
||||||
|
selection: {
|
||||||
|
type: "EQComp",
|
||||||
selection: tp.isAdjectiveEntry(predicate) ? {
|
selection: tp.isAdjectiveEntry(predicate) ? {
|
||||||
type: "adjective",
|
type: "adjective",
|
||||||
entry: predicate,
|
entry: predicate,
|
||||||
|
@ -488,6 +493,7 @@ function makeEPS(subject: T.NPSelection, predicate: T.AdjectiveEntry | T.Locativ
|
||||||
entry: predicate,
|
entry: predicate,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
equative: {
|
equative: {
|
||||||
tense,
|
tense,
|
||||||
negative: false,
|
negative: false,
|
||||||
|
@ -495,3 +501,9 @@ function makeEPS(subject: T.NPSelection, predicate: T.AdjectiveEntry | T.Locativ
|
||||||
omitSubject: false,
|
omitSubject: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getEqFromRendered(e: T.EPRendered): T.EquativeRendered {
|
||||||
|
const eblock = e.blocks.find(x => x.type === "equative");
|
||||||
|
if (!eblock || eblock.type !== "equative") throw new Error("Error getting equative block");
|
||||||
|
return eblock.equative;
|
||||||
|
}
|
|
@ -4,10 +4,3 @@ type Pronoun = {
|
||||||
person: import("@lingdocs/pashto-inflector").Types.Person,
|
person: import("@lingdocs/pashto-inflector").Types.Person,
|
||||||
};
|
};
|
||||||
|
|
||||||
type BlockInput = {
|
|
||||||
type: "NP",
|
|
||||||
block: import("@lingdocs/pashto-inflector").Types.NPSelection,
|
|
||||||
} | {
|
|
||||||
type: "AP",
|
|
||||||
block: import("@lingdocs/pashto-inflector").Types.APSelection,
|
|
||||||
};
|
|
||||||
|
|
|
@ -1695,10 +1695,10 @@
|
||||||
rambda "^6.7.0"
|
rambda "^6.7.0"
|
||||||
react-select "^5.2.2"
|
react-select "^5.2.2"
|
||||||
|
|
||||||
"@lingdocs/pashto-inflector@^2.6.8":
|
"@lingdocs/pashto-inflector@^2.8.2":
|
||||||
version "2.6.8"
|
version "2.8.2"
|
||||||
resolved "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-2.6.8.tgz#d104620a75a4f034d3dcd9d8a097eab40b77024d"
|
resolved "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-2.8.2.tgz#006f1f3f8223f5ea67ac75106369c3f6072441a3"
|
||||||
integrity sha512-z2RetX9mRgZxM0FIX8R3cgCF+Exof/OigMDZIlEHLhBAljSwaojA9ZdXnyKP1zW8EDtjLIqsr3rWQre6niU80w==
|
integrity sha512-mA9L37+Tq5teDTxczjfIBMfOStfqAzn7QFUNoRSEXl7ci4Yo+5bomHf2sjGDr0ZbneFAyp0K05tVJCWi8SBkeg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@formkit/auto-animate" "^1.0.0-beta.1"
|
"@formkit/auto-animate" "^1.0.0-beta.1"
|
||||||
classnames "^2.2.6"
|
classnames "^2.2.6"
|
||||||
|
|
Loading…
Reference in New Issue