mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-05 19:28:39 +00:00
feat: support \angl and \angln (#2334)
* Support \angl and \angln * Update screenshots * Update documentation
This commit is contained in:
@@ -84,7 +84,8 @@ table td {
|
|||||||
|\And|$\And$||
|
|\And|$\And$||
|
||||||
|\and|<span style="color:firebrick;">Not supported</span>|[Deprecated](https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax)|
|
|\and|<span style="color:firebrick;">Not supported</span>|[Deprecated](https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax)|
|
||||||
|\ang|<span style="color:firebrick;">Not supported</span>|[Deprecated](https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax)|
|
|\ang|<span style="color:firebrick;">Not supported</span>|[Deprecated](https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax)|
|
||||||
|\angl|<span style="color:firebrick;">Not supported</span>||
|
|\angl|$a_{\angl n}$||
|
||||||
|
|\angln|$a_\angln$||
|
||||||
|\angle|$\angle$||
|
|\angle|$\angle$||
|
||||||
|\approx|$\approx$||
|
|\approx|$\approx$||
|
||||||
|\approxeq|$\approxeq$||
|
|\approxeq|$\approxeq$||
|
||||||
|
@@ -207,6 +207,7 @@ For Persian composite characters, a user-supplied [plug-in](https://github.com/
|
|||||||
|$\bcancel{5}$ `\bcancel{5}` |$\underbrace{a+b+c}_{\text{note}}$ `\underbrace{a+b+c}_{\text{note}}`
|
|$\bcancel{5}$ `\bcancel{5}` |$\underbrace{a+b+c}_{\text{note}}$ `\underbrace{a+b+c}_{\text{note}}`
|
||||||
|$\xcancel{ABC}$ `\xcancel{ABC}`|$\not =$ `\not =`
|
|$\xcancel{ABC}$ `\xcancel{ABC}`|$\not =$ `\not =`
|
||||||
|$\sout{abc}$ `\sout{abc}`|$\boxed{\pi=\frac c d}$ `\boxed{\pi=\frac c d}`
|
|$\sout{abc}$ `\sout{abc}`|$\boxed{\pi=\frac c d}$ `\boxed{\pi=\frac c d}`
|
||||||
|
|$a_{\angl n}$ `$a_{\angl n}`|$a_\angln$ `a_\angln`
|
||||||
|
|
||||||
`\tag{hi} x+y^{2x}`
|
`\tag{hi} x+y^{2x}`
|
||||||
$$\tag{hi} x+y^{2x}$$
|
$$\tag{hi} x+y^{2x}$$
|
||||||
|
@@ -40,12 +40,15 @@ const htmlBuilder = (group, options) => {
|
|||||||
if (!isSingleChar) {
|
if (!isSingleChar) {
|
||||||
inner.classes.push("cancel-pad");
|
inner.classes.push("cancel-pad");
|
||||||
}
|
}
|
||||||
|
} else if (label === "angl") {
|
||||||
|
inner.classes.push("anglpad");
|
||||||
} else {
|
} else {
|
||||||
inner.classes.push("boxpad");
|
inner.classes.push("boxpad");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add vertical padding
|
// Add vertical padding
|
||||||
let vertPad = 0;
|
let topPad = 0;
|
||||||
|
let bottomPad = 0;
|
||||||
let ruleThickness = 0;
|
let ruleThickness = 0;
|
||||||
// ref: cancel package: \advance\totalheight2\p@ % "+2"
|
// ref: cancel package: \advance\totalheight2\p@ % "+2"
|
||||||
if (/box/.test(label)) {
|
if (/box/.test(label)) {
|
||||||
@@ -53,18 +56,30 @@ const htmlBuilder = (group, options) => {
|
|||||||
options.fontMetrics().fboxrule, // default
|
options.fontMetrics().fboxrule, // default
|
||||||
options.minRuleThickness, // User override.
|
options.minRuleThickness, // User override.
|
||||||
);
|
);
|
||||||
vertPad = options.fontMetrics().fboxsep +
|
topPad = options.fontMetrics().fboxsep +
|
||||||
(label === "colorbox" ? 0 : ruleThickness);
|
(label === "colorbox" ? 0 : ruleThickness);
|
||||||
|
bottomPad = topPad;
|
||||||
|
} else if (label === "angl") {
|
||||||
|
ruleThickness = Math.max(
|
||||||
|
options.fontMetrics().defaultRuleThickness,
|
||||||
|
options.minRuleThickness
|
||||||
|
);
|
||||||
|
topPad = 4 * ruleThickness; // gap = 3 × line, plus the line itself.
|
||||||
|
bottomPad = Math.max(0, 0.25 - inner.depth);
|
||||||
} else {
|
} else {
|
||||||
vertPad = isSingleChar ? 0.2 : 0;
|
topPad = isSingleChar ? 0.2 : 0;
|
||||||
|
bottomPad = topPad;
|
||||||
}
|
}
|
||||||
|
|
||||||
img = stretchy.encloseSpan(inner, label, vertPad, options);
|
img = stretchy.encloseSpan(inner, label, topPad, bottomPad, options);
|
||||||
if (/fbox|boxed|fcolorbox/.test(label)) {
|
if (/fbox|boxed|fcolorbox/.test(label)) {
|
||||||
img.style.borderStyle = "solid";
|
img.style.borderStyle = "solid";
|
||||||
img.style.borderWidth = `${ruleThickness}em`;
|
img.style.borderWidth = `${ruleThickness}em`;
|
||||||
|
} else if (label === "angl" && ruleThickness !== 0.049) {
|
||||||
|
img.style.borderTopWidth = `${ruleThickness}em`;
|
||||||
|
img.style.borderRightWidth = `${ruleThickness}em`;
|
||||||
}
|
}
|
||||||
imgShift = inner.depth + vertPad;
|
imgShift = inner.depth + bottomPad;
|
||||||
|
|
||||||
if (group.backgroundColor) {
|
if (group.backgroundColor) {
|
||||||
img.style.backgroundColor = group.backgroundColor;
|
img.style.backgroundColor = group.backgroundColor;
|
||||||
@@ -138,6 +153,9 @@ const mathmlBuilder = (group, options) => {
|
|||||||
case "\\fbox":
|
case "\\fbox":
|
||||||
node.setAttribute("notation", "box");
|
node.setAttribute("notation", "box");
|
||||||
break;
|
break;
|
||||||
|
case "\\angl":
|
||||||
|
node.setAttribute("notation", "actuarial");
|
||||||
|
break;
|
||||||
case "\\fcolorbox":
|
case "\\fcolorbox":
|
||||||
case "\\colorbox":
|
case "\\colorbox":
|
||||||
// <menclose> doesn't have a good notation option. So use <mpadded>
|
// <menclose> doesn't have a good notation option. So use <mpadded>
|
||||||
@@ -253,3 +271,21 @@ defineFunction({
|
|||||||
htmlBuilder,
|
htmlBuilder,
|
||||||
mathmlBuilder,
|
mathmlBuilder,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
defineFunction({
|
||||||
|
type: "enclose",
|
||||||
|
names: ["\\angl"],
|
||||||
|
props: {
|
||||||
|
numArgs: 1,
|
||||||
|
argTypes: ["hbox"],
|
||||||
|
allowedInText: false,
|
||||||
|
},
|
||||||
|
handler({parser}, args) {
|
||||||
|
return {
|
||||||
|
type: "enclose",
|
||||||
|
mode: parser.mode,
|
||||||
|
label: "\\angl",
|
||||||
|
body: args[0],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
@@ -588,6 +588,18 @@
|
|||||||
border-bottom-style: solid;
|
border-bottom-style: solid;
|
||||||
border-bottom-width: 0.08em;
|
border-bottom-width: 0.08em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.angl {
|
||||||
|
// from package actuarialangle, which is always used in a subscript.
|
||||||
|
box-sizing: border-content;
|
||||||
|
border-top: 0.049em solid; // defaultRuleThickness in scriptstyle
|
||||||
|
border-right: 0.049em solid; // ditto
|
||||||
|
margin-right: 0.03889em; // 1 mu
|
||||||
|
}
|
||||||
|
|
||||||
|
.anglpad {
|
||||||
|
padding: 0 0.03889em 0 0.03889em; // pad 1mu left and right (in scriptstyle)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.katex-display {
|
.katex-display {
|
||||||
|
@@ -987,6 +987,10 @@ defineMacro("\\braket", "\\mathinner{\\langle{#1}\\rangle}");
|
|||||||
defineMacro("\\Bra", "\\left\\langle#1\\right|");
|
defineMacro("\\Bra", "\\left\\langle#1\\right|");
|
||||||
defineMacro("\\Ket", "\\left|#1\\right\\rangle");
|
defineMacro("\\Ket", "\\left|#1\\right\\rangle");
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// actuarialangle.dtx
|
||||||
|
defineMacro("\\angln", "{\\angl n}");
|
||||||
|
|
||||||
// Custom Khan Academy colors, should be moved to an optional package
|
// Custom Khan Academy colors, should be moved to an optional package
|
||||||
defineMacro("\\blue", "\\textcolor{##6495ed}{#1}");
|
defineMacro("\\blue", "\\textcolor{##6495ed}{#1}");
|
||||||
defineMacro("\\orange", "\\textcolor{##ffa500}{#1}");
|
defineMacro("\\orange", "\\textcolor{##ffa500}{#1}");
|
||||||
|
@@ -304,14 +304,15 @@ const svgSpan = function(
|
|||||||
const encloseSpan = function(
|
const encloseSpan = function(
|
||||||
inner: HtmlDomNode,
|
inner: HtmlDomNode,
|
||||||
label: string,
|
label: string,
|
||||||
pad: number,
|
topPad: number,
|
||||||
|
bottomPad: number,
|
||||||
options: Options,
|
options: Options,
|
||||||
): DomSpan | SvgSpan {
|
): DomSpan | SvgSpan {
|
||||||
// Return an image span for \cancel, \bcancel, \xcancel, or \fbox
|
// Return an image span for \cancel, \bcancel, \xcancel, \fbox, or \angl
|
||||||
let img;
|
let img;
|
||||||
const totalHeight = inner.height + inner.depth + 2 * pad;
|
const totalHeight = inner.height + inner.depth + topPad + bottomPad;
|
||||||
|
|
||||||
if (/fbox|color/.test(label)) {
|
if (/fbox|color|angl/.test(label)) {
|
||||||
img = buildCommon.makeSpan(["stretchy", label], [], options);
|
img = buildCommon.makeSpan(["stretchy", label], [], options);
|
||||||
|
|
||||||
if (label === "fbox") {
|
if (label === "fbox") {
|
||||||
|
@@ -2465,6 +2465,24 @@ describe("A strike-through builder", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("A actuarial angle parser", function() {
|
||||||
|
it("should not fail in math mode", function() {
|
||||||
|
expect`a_{\angl{n}}`.toParse();
|
||||||
|
});
|
||||||
|
it("should fail in text mode", function() {
|
||||||
|
expect`\text{a_{\angl{n}}}`.not.toParse();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("A actuarial angle builder", function() {
|
||||||
|
it("should not fail", function() {
|
||||||
|
expect`a_{\angl{n}}`.toBuild();
|
||||||
|
expect`a_{\angl{n}i}`.toBuild();
|
||||||
|
expect`a_{\angl n}`.toBuild();
|
||||||
|
expect`a_\angln`.toBuild();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("A phantom parser", function() {
|
describe("A phantom parser", function() {
|
||||||
it("should not fail", function() {
|
it("should not fail", function() {
|
||||||
expect`\phantom{x}`.toParse();
|
expect`\phantom{x}`.toParse();
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 24 KiB |
Binary file not shown.
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 23 KiB |
@@ -68,7 +68,11 @@ BoldSymbol: |
|
|||||||
\sum_{\boldsymbol{\alpha}}^{\boldsymbol{\beta}} \boldsymbol{\omega}+ \boldsymbol{\int_\alpha^\beta} \boldsymbol{\Omega + {}} \\
|
\sum_{\boldsymbol{\alpha}}^{\boldsymbol{\beta}} \boldsymbol{\omega}+ \boldsymbol{\int_\alpha^\beta} \boldsymbol{\Omega + {}} \\
|
||||||
\boldsymbol{\lim_{x \to \infty} \log Ax2k\omega\Omega\imath+} \\
|
\boldsymbol{\lim_{x \to \infty} \log Ax2k\omega\Omega\imath+} \\
|
||||||
x \boldsymbol{+} y \boldsymbol{=} z
|
x \boldsymbol{+} y \boldsymbol{=} z
|
||||||
Boxed: \boxed{F=ma} \quad \boxed{ac}\color{magenta}{\boxed{F}}\boxed{F=mg}
|
Boxed: |
|
||||||
|
\begin{array}{l}
|
||||||
|
\boxed{F=ma} \quad \boxed{ac}\color{magenta}{\boxed{F}}\boxed{F=mg} \\[2em]
|
||||||
|
A_{\angl n} + B_{\angl g} + C_\angln
|
||||||
|
\end{array}
|
||||||
Cases: |
|
Cases: |
|
||||||
f(a,b)=\begin{cases}
|
f(a,b)=\begin{cases}
|
||||||
a+1&\text{if }b\text{ is odd} \\
|
a+1&\text{if }b\text{ is odd} \\
|
||||||
|
Reference in New Issue
Block a user