commit fe6b67817c88c249d01415fd88a3ab51f9cae158
parent 5756be048cb69a2b3e250f2470c4e45f0b8f7dd6
Author: Emily Eisenberg <emily@khanacademy.org>
Date: Tue, 5 Aug 2014 17:48:10 -0700
Add support for \overline
Summary:
Follow the instructions in the TeX book for drawing \overlines. This uses the
same code as fractions to produce the bars. Also added the ability to cramp
styles (i.e. T -> T' and T' -> T').
Test Plan:
- Look at `\overline{x}`, `\overline{\dfrac{x}{y}+z}`, and
`\blue{\overline{x}}` to make sure they look good.
- Make sure the tests work
- Make sure the huxley tests look good (Not here yet :( )
Reviewers: alpert
Reviewed By: alpert
Differential Revision: http://phabricator.khanacademy.org/D11604
Diffstat:
8 files changed, 107 insertions(+), 1 deletion(-)
diff --git a/Parser.js b/Parser.js
@@ -466,6 +466,19 @@ Parser.prototype.parseNucleus = function(pos, mode) {
new ParseNode("katex", null, mode),
nucleus.position
);
+ } else if (mode === "math" && nucleus.type === "\\overline") {
+ // If this is an overline, parse its argument and return
+ var group = this.parseGroup(nucleus.position, mode);
+ if (group) {
+ return new ParseResult(
+ new ParseNode("overline", group, mode),
+ group.position);
+ } else {
+ throw new ParseError("Expected group after '" +
+ nucleus.type + "'",
+ this.lexer, nucleus.position
+ );
+ }
} else if (symbols[mode][nucleus.text]) {
// Otherwise if this is a no-argument function, find the type it
// corresponds to in the symbols map
diff --git a/Style.js b/Style.js
@@ -21,6 +21,10 @@ Style.prototype.fracDen = function() {
return styles[fracDen[this.id]];
};
+Style.prototype.cramp = function() {
+ return styles[cramp[this.id]];
+};
+
// HTML class name, like "displaystyle cramped"
Style.prototype.cls = function() {
return sizeNames[this.size] + (this.cramped ? " cramped" : " uncramped");
@@ -69,6 +73,7 @@ var sup = [S, Sc, S, Sc, SS, SSc, SS, SSc];
var sub = [Sc, Sc, Sc, Sc, SSc, SSc, SSc, SSc];
var fracNum = [T, Tc, S, Sc, SS, SSc, SS, SSc];
var fracDen = [Tc, Tc, Sc, Sc, SSc, SSc, SSc, SSc];
+var cramp = [Dc, Dc, Tc, Tc, Sc, Sc, SSc, SSc];
module.exports = {
DISPLAY: styles[D],
diff --git a/buildTree.js b/buildTree.js
@@ -55,7 +55,8 @@ var groupToType = {
punct: "mpunct",
ordgroup: "mord",
namedfn: "mop",
- katex: "mord"
+ katex: "mord",
+ overline: "mord"
};
var getTypeOfGroup = function(group) {
@@ -419,6 +420,27 @@ var groupTypes = {
return makeSpan(["katex-logo"], [k, a, t, e, x], options.getColor());
},
+ overline: function(group, options, prev) {
+ var innerGroup = buildGroup(group.value.result,
+ options.withStyle(options.style.cramp()).deepen());
+
+ // The theta variable in the TeXbook
+ var lineWidth = fontMetrics.metrics.defaultRuleThickness;
+
+ var line = makeSpan(["overline-line"], [makeSpan([])]);
+ var inner = makeSpan(["overline-inner"], [innerGroup]);
+ var fixIE = makeSpan(["fix-ie"], []);
+
+ line.style.top = (-inner.height - 3 * lineWidth) + "em";
+ // The line is supposed to have 1 extra line width above it in height
+ // (TeXbook pg. 443, nr. 9)
+ line.height = inner.height + 5 * lineWidth;
+
+ return makeSpan(["overline", "mord"], [
+ line, inner, fixIE
+ ], options.getColor());
+ },
+
sizing: function(group, options, prev) {
var inner = buildGroup(group.value.value,
options.withSize(group.value.size), prev);
diff --git a/static/katex.less b/static/katex.less
@@ -308,6 +308,45 @@ big parens
}
}
+ .overline {
+ .baseline-align-hack-outer;
+
+ > .overline-line,
+ > .overline-inner,
+ > .fix-ie {
+ .baseline-align-hack-middle;
+ position: relative;
+ text-align: center;
+
+ > span {
+ .baseline-align-hack-inner;
+ }
+ }
+
+ > .fix-ie {
+ display: inline-block;
+ }
+
+ > .overline-line > span {
+ width: 100%;
+
+ &:before {
+ border-bottom-style: solid;
+ border-bottom-width: 1px;
+ content: "";
+ display: block;
+ }
+
+ &:after {
+ border-bottom-style: solid;
+ border-bottom-width: 0.04em;
+ content: "";
+ display: block;
+ margin-top: -1px;
+ }
+ }
+ }
+
.sizing {
display: inline-block;
diff --git a/test/huxley/Huxleyfile.json b/test/huxley/Huxleyfile.json
@@ -99,5 +99,11 @@
"name": "DelimiterSizing",
"screenSize": [1024, 768],
"url": "http://localhost:7936/test/huxley/test.html?m=\\bigl\\uparrow\\Bigl\\downarrow\\biggl\\updownarrow\\Biggl\\Uparrow\\Biggr\\Downarrow\\biggr\\langle\\Bigr\\}\\bigr\\rfloor"
+ },
+
+ {
+ "name": "Overline",
+ "screenSize": [1024, 768],
+ "url": "http://localhost:7936/test/huxley/test.html?m=\\overline{x}\\overline{x}\\overline{x^{x^{x^x}}} \\blue\\overline{y}"
}
]
diff --git a/test/huxley/Overline.hux/firefox-1.png b/test/huxley/Overline.hux/firefox-1.png
Binary files differ.
diff --git a/test/huxley/Overline.hux/record.json b/test/huxley/Overline.hux/record.json
@@ -0,0 +1,5 @@
+[
+ {
+ "action": "screenshot"
+ }
+]
diff --git a/test/katex-tests.js b/test/katex-tests.js
@@ -667,3 +667,19 @@ describe("A delimiter sizing parser", function() {
expect(bigParse.value.size).toEqual(4);
});
});
+
+describe("An overline parser", function() {
+ var overline = "\\overline{x}";
+
+ it("should not fail", function() {
+ expect(function() {
+ parseTree(overline);
+ }).not.toThrow();
+ });
+
+ it("should produce an overline", function() {
+ var parse = parseTree(overline)[0];
+
+ expect(parse.type).toMatch("overline");
+ });
+});