mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-06 11:48:41 +00:00
feat: Support {CD} (#2396)
* Support {CD} * Edit screenshotter test to fit on one page * Update screenshots * Remove bogus Safari screenshot * Edit documentation to avoid tag conflicts and explain delimiters * Add type annotations * Add bogus safari screenshot * Update with real Safari screenshot * Set label vertical alignment * Revise call to parseExpression() per PR 2085 changes to macro parsing * Update Firefox screenshot * Pick up review comments * Add unit tests and snapshot. * Tighten up label collection. * Better loop index * remove extra space * Picked up comments. Added a parse check. Added a test. Co-authored-by: ylemkimon <y@ylem.kim> Co-authored-by: Kevin Barabash <kevinb@khanacademy.org> Co-authored-by: Kevin Barabash <kevinb7@gmail.com>
This commit is contained in:
@@ -204,6 +204,211 @@ exports[`A MathML builder normal spaces render normally 1`] = `
|
||||
</math>
|
||||
`;
|
||||
|
||||
exports[`A MathML builder should build the CD environment properly 1`] = `
|
||||
<math xmlns="http://www.w3.org/1998/Math/MathML"
|
||||
display="block"
|
||||
>
|
||||
<semantics>
|
||||
<mtable rowspacing="0.2500em"
|
||||
columnalign="center center center"
|
||||
columnspacing="0.5em"
|
||||
>
|
||||
<mtr>
|
||||
<mtd>
|
||||
<mstyle scriptlevel="0"
|
||||
displaystyle="true"
|
||||
>
|
||||
<mi>
|
||||
A
|
||||
</mi>
|
||||
</mstyle>
|
||||
</mtd>
|
||||
<mtd>
|
||||
<mstyle scriptlevel="0"
|
||||
displaystyle="true"
|
||||
>
|
||||
<munderover>
|
||||
<mo stretchy="true"
|
||||
minsize="3.0em"
|
||||
>
|
||||
→
|
||||
</mo>
|
||||
<mpadded width="+0.6em"
|
||||
lspace="0.3em"
|
||||
>
|
||||
<mrow>
|
||||
</mrow>
|
||||
</mpadded>
|
||||
<mpadded width="+0.6em"
|
||||
lspace="0.3em"
|
||||
>
|
||||
<mi>
|
||||
a
|
||||
</mi>
|
||||
</mpadded>
|
||||
</munderover>
|
||||
</mstyle>
|
||||
</mtd>
|
||||
<mtd>
|
||||
<mstyle scriptlevel="0"
|
||||
displaystyle="true"
|
||||
>
|
||||
<mi>
|
||||
B
|
||||
</mi>
|
||||
</mstyle>
|
||||
</mtd>
|
||||
</mtr>
|
||||
<mtr>
|
||||
<mtd>
|
||||
<mstyle scriptlevel="0"
|
||||
displaystyle="true"
|
||||
>
|
||||
<mrow>
|
||||
<mrow>
|
||||
<mstyle displaystyle="false"
|
||||
scriptlevel="1"
|
||||
>
|
||||
<mpadded width="0"
|
||||
lspace="-1width"
|
||||
voffset="0.7em"
|
||||
>
|
||||
<mrow>
|
||||
<mrow>
|
||||
</mrow>
|
||||
</mrow>
|
||||
</mpadded>
|
||||
</mstyle>
|
||||
<mo fence="false"
|
||||
stretchy="true"
|
||||
minsize="1.8em"
|
||||
maxsize="1.8em"
|
||||
>
|
||||
↓
|
||||
</mo>
|
||||
<mstyle displaystyle="false"
|
||||
scriptlevel="1"
|
||||
>
|
||||
<mpadded width="0"
|
||||
voffset="0.7em"
|
||||
>
|
||||
<mrow>
|
||||
<mi>
|
||||
b
|
||||
</mi>
|
||||
</mrow>
|
||||
</mpadded>
|
||||
</mstyle>
|
||||
</mrow>
|
||||
</mrow>
|
||||
</mstyle>
|
||||
</mtd>
|
||||
<mtd>
|
||||
<mstyle scriptlevel="0"
|
||||
displaystyle="true"
|
||||
>
|
||||
</mstyle>
|
||||
</mtd>
|
||||
<mtd>
|
||||
<mstyle scriptlevel="0"
|
||||
displaystyle="true"
|
||||
>
|
||||
<mrow>
|
||||
<mrow>
|
||||
<mstyle displaystyle="false"
|
||||
scriptlevel="1"
|
||||
>
|
||||
<mpadded width="0"
|
||||
lspace="-1width"
|
||||
voffset="0.7em"
|
||||
>
|
||||
<mrow>
|
||||
<mrow>
|
||||
</mrow>
|
||||
</mrow>
|
||||
</mpadded>
|
||||
</mstyle>
|
||||
<mo fence="false"
|
||||
stretchy="true"
|
||||
minsize="1.8em"
|
||||
maxsize="1.8em"
|
||||
>
|
||||
↓
|
||||
</mo>
|
||||
<mstyle displaystyle="false"
|
||||
scriptlevel="1"
|
||||
>
|
||||
<mpadded width="0"
|
||||
voffset="0.7em"
|
||||
>
|
||||
<mrow>
|
||||
<mi>
|
||||
c
|
||||
</mi>
|
||||
</mrow>
|
||||
</mpadded>
|
||||
</mstyle>
|
||||
</mrow>
|
||||
</mrow>
|
||||
</mstyle>
|
||||
</mtd>
|
||||
</mtr>
|
||||
<mtr>
|
||||
<mtd>
|
||||
<mstyle scriptlevel="0"
|
||||
displaystyle="true"
|
||||
>
|
||||
<mi>
|
||||
C
|
||||
</mi>
|
||||
</mstyle>
|
||||
</mtd>
|
||||
<mtd>
|
||||
<mstyle scriptlevel="0"
|
||||
displaystyle="true"
|
||||
>
|
||||
<munderover>
|
||||
<mo stretchy="true"
|
||||
minsize="3.0em"
|
||||
>
|
||||
→
|
||||
</mo>
|
||||
<mpadded width="+0.6em"
|
||||
lspace="0.3em"
|
||||
>
|
||||
<mrow>
|
||||
</mrow>
|
||||
</mpadded>
|
||||
<mpadded width="+0.6em"
|
||||
lspace="0.3em"
|
||||
>
|
||||
<mi>
|
||||
d
|
||||
</mi>
|
||||
</mpadded>
|
||||
</munderover>
|
||||
</mstyle>
|
||||
</mtd>
|
||||
<mtd>
|
||||
<mstyle scriptlevel="0"
|
||||
displaystyle="true"
|
||||
>
|
||||
<mi>
|
||||
D
|
||||
</mi>
|
||||
</mstyle>
|
||||
</mtd>
|
||||
</mtr>
|
||||
<mtr>
|
||||
</mtr>
|
||||
</mtable>
|
||||
<annotation encoding="application/x-tex">
|
||||
\\begin{CD} A @>a>> B\\\\ @VVbV @VVcV\\\\ C @>d>> D \\end{CD}
|
||||
</annotation>
|
||||
</semantics>
|
||||
</math>
|
||||
`;
|
||||
|
||||
exports[`A MathML builder should concatenate digits into single <mn> 1`] = `
|
||||
<math xmlns="http://www.w3.org/1998/Math/MathML">
|
||||
<semantics>
|
||||
|
@@ -2778,6 +2778,7 @@ describe("AMS environments", function() {
|
||||
expect`\begin{alignat*}{2}10&x+ &3&y = 2\\3&x+&13&y = 4\end{alignat*}`.not.toParse(nonstrictSettings);
|
||||
expect`\begin{equation}a=b+c\end{equation}`.not.toParse(nonstrictSettings);
|
||||
expect`\begin{split}a &=b+c\\&=e+f\end{split}`.not.toParse(nonstrictSettings);
|
||||
expect`\begin{CD}A @>a>> B \\@VbVV @AAcA\\C @= D\end{CD}`.not.toParse(nonstrictSettings);
|
||||
});
|
||||
|
||||
const nonStrictDisplay = new Settings({displayMode: true, strict: false});
|
||||
@@ -2791,6 +2792,7 @@ describe("AMS environments", function() {
|
||||
expect`\begin{equation}a=b+c\end{equation}`.toBuild(nonStrictDisplay);
|
||||
expect`\begin{equation}\begin{split}a &=b+c\\&=e+f\end{split}\end{equation}`.toBuild(nonStrictDisplay);
|
||||
expect`\begin{split}a &=b+c\\&=e+f\end{split}`.toBuild(nonStrictDisplay);
|
||||
expect`\begin{CD}A @<a<< B @>>b> C @>>> D\\@. @| @AcAA @VVdV \\@. E @= F @>>> G\end{CD}`.toBuild(nonStrictDisplay);
|
||||
});
|
||||
|
||||
it("{equation} should fail if argument contains two rows.", () => {
|
||||
@@ -2807,6 +2809,29 @@ describe("AMS environments", function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe("The CD environment", function() {
|
||||
it("should fail if not is display mode", function() {
|
||||
expect(`\\begin{CD}A @<a<< B @>>b> C @>>> D\\\\@. @| @AcAA @VVdV \\\\@. E @= F @>>> G\\end{CD}`).not.toParse(
|
||||
new Settings({displayMode: false, strict: false})
|
||||
);
|
||||
});
|
||||
const displaySettings = new Settings({displayMode: true, strict: false});
|
||||
it("should fail if the character after '@' is not in <>AV=|.", function() {
|
||||
expect(`\\begin{CD}A @X<a<< B @>>b> C @>>> D\\\\@. @| @AcAA @VVdV \\\\@. E @= F @>>> G\\end{CD}`).not.toParse(displaySettings);
|
||||
});
|
||||
it("should fail if an arrow does not have its final character.", function() {
|
||||
expect(`\\begin{CD}A @<a< B @>>b> C @>>> D\\\\@. @| @AcAA @VVdV \\\\@. E @= F @>>> G\\end{CD}`).not.toParse(displaySettings);
|
||||
expect(`\\begin{CD}A @<a<< B @>>b C @>>> D\\\\@. @| @AcAA @VVdV \\\\@. E @= F @>>> G\\end{CD}`).not.toParse(displaySettings);
|
||||
});
|
||||
it("should fail without an \\\\end.", function() {
|
||||
expect(`\\begin{CD}A @<a<< B @>>b> C @>>> D\\\\@. @| @AcAA @VVdV \\\\@. E @= F @>>> G`).not.toParse(displaySettings);
|
||||
});
|
||||
|
||||
it("should succeed without the flaws noted above.", function() {
|
||||
expect(`\\begin{CD}A @<a<< B @>>b> C @>>> D\\\\@. @| @AcAA @VVdV \\\\@. E @= F @>>> G\\end{CD}`).toBuild(displaySettings);
|
||||
});
|
||||
});
|
||||
|
||||
describe("operatorname support", function() {
|
||||
it("should not fail", function() {
|
||||
expect("\\operatorname{x*Π∑\\Pi\\sum\\frac a b}").toBuild();
|
||||
|
@@ -79,6 +79,13 @@ describe("A MathML builder", function() {
|
||||
expect(getMathML("\\colorbox{red}{b}")).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should build the CD environment properly', () => {
|
||||
const displaySettings = new Settings({displayMode: true, strict: false});
|
||||
const mathml = getMathML("\\begin{CD} A @>a>> B\\\\ @VVbV @VVcV\\\\" +
|
||||
" C @>d>> D \\end{CD}", displaySettings);
|
||||
expect(mathml).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should set href attribute for href appropriately', () => {
|
||||
expect(
|
||||
getMathML("\\href{http://example.org}{\\alpha}", new Settings({trust: true})),
|
||||
|
BIN
test/screenshotter/images/CD-chrome.png
Normal file
BIN
test/screenshotter/images/CD-chrome.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
test/screenshotter/images/CD-firefox.png
Normal file
BIN
test/screenshotter/images/CD-firefox.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
test/screenshotter/images/CD-safari.png
Normal file
BIN
test/screenshotter/images/CD-safari.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
@@ -86,6 +86,9 @@ Cases: |
|
||||
a &\text{if } b \\
|
||||
c &\text{if } d
|
||||
\end{rcases}⇒…
|
||||
CD:
|
||||
tex: \begin{CD} A @<a<< B @>>b> C \\ @| @AcAA @VVdV \\ D @= E @>>> F \end{CD}
|
||||
display: 1
|
||||
Colors:
|
||||
tex: \blue{a}\textcolor{#0f0}{b}\textcolor{red}{c}
|
||||
nolatex: different syntax and different scope
|
||||
|
Reference in New Issue
Block a user