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|<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$||
|
||||
|\approx|$\approx$||
|
||||
|\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}}`
|
||||
|$\xcancel{ABC}$ `\xcancel{ABC}`|$\not =$ `\not =`
|
||||
|$\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}$$
|
||||
|
@@ -40,12 +40,15 @@ const htmlBuilder = (group, options) => {
|
||||
if (!isSingleChar) {
|
||||
inner.classes.push("cancel-pad");
|
||||
}
|
||||
} else if (label === "angl") {
|
||||
inner.classes.push("anglpad");
|
||||
} else {
|
||||
inner.classes.push("boxpad");
|
||||
}
|
||||
|
||||
// Add vertical padding
|
||||
let vertPad = 0;
|
||||
let topPad = 0;
|
||||
let bottomPad = 0;
|
||||
let ruleThickness = 0;
|
||||
// ref: cancel package: \advance\totalheight2\p@ % "+2"
|
||||
if (/box/.test(label)) {
|
||||
@@ -53,18 +56,30 @@ const htmlBuilder = (group, options) => {
|
||||
options.fontMetrics().fboxrule, // default
|
||||
options.minRuleThickness, // User override.
|
||||
);
|
||||
vertPad = options.fontMetrics().fboxsep +
|
||||
topPad = options.fontMetrics().fboxsep +
|
||||
(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 {
|
||||
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)) {
|
||||
img.style.borderStyle = "solid";
|
||||
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) {
|
||||
img.style.backgroundColor = group.backgroundColor;
|
||||
@@ -138,6 +153,9 @@ const mathmlBuilder = (group, options) => {
|
||||
case "\\fbox":
|
||||
node.setAttribute("notation", "box");
|
||||
break;
|
||||
case "\\angl":
|
||||
node.setAttribute("notation", "actuarial");
|
||||
break;
|
||||
case "\\fcolorbox":
|
||||
case "\\colorbox":
|
||||
// <menclose> doesn't have a good notation option. So use <mpadded>
|
||||
@@ -253,3 +271,21 @@ defineFunction({
|
||||
htmlBuilder,
|
||||
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-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 {
|
||||
|
@@ -987,6 +987,10 @@ defineMacro("\\braket", "\\mathinner{\\langle{#1}\\rangle}");
|
||||
defineMacro("\\Bra", "\\left\\langle#1\\right|");
|
||||
defineMacro("\\Ket", "\\left|#1\\right\\rangle");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// actuarialangle.dtx
|
||||
defineMacro("\\angln", "{\\angl n}");
|
||||
|
||||
// Custom Khan Academy colors, should be moved to an optional package
|
||||
defineMacro("\\blue", "\\textcolor{##6495ed}{#1}");
|
||||
defineMacro("\\orange", "\\textcolor{##ffa500}{#1}");
|
||||
|
@@ -304,14 +304,15 @@ const svgSpan = function(
|
||||
const encloseSpan = function(
|
||||
inner: HtmlDomNode,
|
||||
label: string,
|
||||
pad: number,
|
||||
topPad: number,
|
||||
bottomPad: number,
|
||||
options: Options,
|
||||
): 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;
|
||||
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);
|
||||
|
||||
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() {
|
||||
it("should not fail", function() {
|
||||
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 + {}} \\
|
||||
\boldsymbol{\lim_{x \to \infty} \log Ax2k\omega\Omega\imath+} \\
|
||||
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: |
|
||||
f(a,b)=\begin{cases}
|
||||
a+1&\text{if }b\text{ is odd} \\
|
||||
|
Reference in New Issue
Block a user