Skip to content

Commit

Permalink
improvements to label state variables and update functions
Browse files Browse the repository at this point in the history
  • Loading branch information
dqnykamp committed Nov 16, 2024
1 parent ff1c444 commit 8847802
Show file tree
Hide file tree
Showing 4 changed files with 501 additions and 41 deletions.
111 changes: 85 additions & 26 deletions packages/doenetml-worker/src/components/Label.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
returnAnchorStateVariableDefinition,
} from "../utils/graphical";
import { textFromChildren } from "../utils/text";
import { latexToText, textToLatex } from "../utils/math";

export default class Label extends InlineComponent {
constructor(args) {
Expand Down Expand Up @@ -222,72 +223,93 @@ export default class Label extends InlineComponent {
variableName: "hasLatex",
},
}),
definition: function ({ dependencyValues }) {
definition: function ({ dependencyValues, componentName }) {
if (
dependencyValues.inlineChildren.length === 0 &&
dependencyValues.valueShadow !== null
) {
let value = dependencyValues.valueShadow;
let text = value;
let latex = value;
if (dependencyValues.hasLatex) {
text = text.replace(/\\\(/g, "");
text = text.replace(/\\\)/g, "");
latex = latex.replace(/\\\(/g, "");
latex = latex.replace(/\\\)/g, "");

text = extractTextFromLabel(text);
}
return { setValue: { text, latex: text, value } };

return { setValue: { text, latex, value } };
}

let textFromComponentConverter = function (
comp,
getValue = true,
) {
let valueFromComponentConverter = function (comp) {
if (typeof comp !== "object") {
return comp.toString();
} else if (comp.stateValues.hidden) {
return "";
} else if (
typeof comp.stateValues.hasLatex === "boolean" &&
typeof comp.stateValues.value === "string" &&
typeof comp.stateValues.text === "string"
typeof comp.stateValues.value === "string"
) {
// if component has a boolean hasLatex state variable
// and value and text are strings
// then use value and text directly
return getValue
? comp.stateValues.value
: comp.stateValues.text;
// and value is string
// then use value directly
// (as it is a label or similar)
return comp.stateValues.value;
} else if (
typeof comp.stateValues.renderAsMath === "boolean" &&
typeof comp.stateValues.latex === "string" &&
typeof comp.stateValues.text === "string"
) {
// if have both latex and string,
// use render as math, if exists, to decide which to use
// and renderAsMath exists, then we'll use renderAsMath
// to decide which to use
if (comp.stateValues.renderAsMath) {
return getValue
? "\\(" + comp.stateValues.latex + "\\)"
: comp.stateValues.latex;
return "\\(" + comp.stateValues.latex + "\\)";
} else {
return comp.stateValues.text;
}
} else if (typeof comp.stateValues.latex === "string") {
return getValue
? "\\(" + comp.stateValues.latex + "\\)"
: comp.stateValues.latex;
// if no renderAsMath, then we'll use latex if it exists
return "\\(" + comp.stateValues.latex + "\\)";
} else if (typeof comp.stateValues.text === "string") {
return comp.stateValues.text;
}
};

let textFromComponentConverter = function (
comp,
preferLatex = false,
) {
if (typeof comp !== "object") {
return comp.toString();
} else if (comp.stateValues.hidden) {
return "";
} else if (
typeof comp.stateValues.text === "string" &&
!preferLatex
) {
return comp.stateValues.text;
} else if (typeof comp.stateValues.latex === "string") {
return comp.stateValues.latex;
} else if (typeof comp.stateValues.text === "string") {
return comp.stateValues.text;
}
};

let value = textFromChildren(
dependencyValues.inlineChildren,
(x) => textFromComponentConverter(x, true),
valueFromComponentConverter,
);
let text = textFromChildren(
dependencyValues.inlineChildren,
(x) => textFromComponentConverter(x, false),
);
let latex = textFromChildren(
dependencyValues.inlineChildren,
(x) => textFromComponentConverter(x, true),
);

return { setValue: { text, latex: text, value } };
return { setValue: { text, latex, value } };
},
inverseDefinition: function ({
desiredStateVariableValues,
Expand All @@ -300,7 +322,16 @@ export default class Label extends InlineComponent {
} else if (
typeof desiredStateVariableValues.text === "string"
) {
desiredValue = desiredStateVariableValues.text;
if (dependencyValues.hasLatex) {
// if hasLatex is set, then the only invertible form is where there is a single
// latex expression.
// Attempt to convert text into latex.
desiredValue = textToLatex(
desiredStateVariableValues.text,
);
} else {
desiredValue = desiredStateVariableValues.text;
}
} else if (
typeof desiredStateVariableValues.latex === "string"
) {
Expand All @@ -324,7 +355,6 @@ export default class Label extends InlineComponent {
};
} else if (dependencyValues.inlineChildren.length === 1) {
let comp = dependencyValues.inlineChildren[0];
let desiredValue = desiredStateVariableValues.value;

if (typeof comp !== "object") {
return {
Expand Down Expand Up @@ -518,3 +548,32 @@ export default class Label extends InlineComponent {
}
}
}

/**
* Extract text from a label string consisting of regular text and latex snippets enclosed by `\(` and `\)`.
*
* For each latex string delimited by `\(` and `\)`, attempt to create a math expression from that latex.
*/
function extractTextFromLabel(labelValue) {
let unprocessedText = labelValue;
let text = "";
let match = unprocessedText.match(/\\\((.*?)\\\)/);
while (match) {
let preChars = match.index;

// add text before the latex piece found
text += unprocessedText.slice(0, preChars);

// attempt to convert the latex piece found
text += latexToText(match[1]);

// remove processed text and continue
unprocessedText = unprocessedText.slice(preChars + match[0].length);
match = unprocessedText.match(/\\\((.*?)\\\)/);
}

// add any leftover text after all latex pieces
text += unprocessedText;

return text;
}
16 changes: 2 additions & 14 deletions packages/doenetml-worker/src/components/MMeMen.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
returnAnchorAttributes,
returnAnchorStateVariableDefinition,
} from "../utils/graphical";
import { latexToAst, superSubscriptsToUnicode } from "../utils/math";
import { latexToText } from "../utils/math";
import { createInputStringFromChildren } from "../utils/parseMath";

export class M extends InlineComponent {
Expand Down Expand Up @@ -197,20 +197,8 @@ export class M extends InlineComponent {
},
}),
definition: function ({ dependencyValues }) {
let expression;
try {
expression = me.fromAst(
latexToAst.convert(dependencyValues.latex),
);
} catch (e) {
// just return latex if can't parse with math-expressions
return { setValue: { text: dependencyValues.latex } };
}

return {
setValue: {
text: superSubscriptsToUnicode(expression.toString()),
},
setValue: { text: latexToText(dependencyValues.latex) },
};
},
};
Expand Down
Loading

0 comments on commit 8847802

Please sign in to comment.