From 925c96dbe24080bfc7b98a08ecdc4110a9fa01a6 Mon Sep 17 00:00:00 2001 From: Emily Eisenberg Date: Sat, 6 Sep 2014 15:08:23 -0700 Subject: [PATCH] Add square roots (\sqrt) Summary: Follow the TeXbook instructions on how to construct square roots. Using makeCustomSizedDelim, this becomes nearly trivial. Test Plan: - Make sure normal tests work - Make sure the new huxley test looks good, and other huxley tests haven't changed. Reviewers: alpert Reviewed By: alpert Differential Revision: http://phabricator.khanacademy.org/D12918 --- Parser.js | 13 ++++++ buildTree.js | 65 ++++++++++++++++++++++++++++- delimiter.js | 9 +++- static/katex.less | 40 ++++++++++++++++++ symbols.js | 5 +++ test/huxley/Huxleyfile.json | 6 +++ test/huxley/Sqrt.hux/firefox-1.png | Bin 0 -> 30876 bytes test/huxley/Sqrt.hux/record.json | 5 +++ test/katex-tests.js | 23 ++++++++++ 9 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 test/huxley/Sqrt.hux/firefox-1.png create mode 100644 test/huxley/Sqrt.hux/record.json diff --git a/Parser.js b/Parser.js index 6a3d097..f24c2d2 100644 --- a/Parser.js +++ b/Parser.js @@ -535,6 +535,19 @@ Parser.prototype.parseNucleus = function(pos, mode) { this.lexer, nucleus.position ); } + } else if (mode === "math" && nucleus.type === "\\sqrt") { + // If this is a square root, parse its argument and return + var group = this.parseGroup(nucleus.position, mode); + if (group) { + return new ParseResult( + new ParseNode("sqrt", group, mode), + group.position); + } else { + throw new ParseError("Expected group after '" + + nucleus.type + "'", + this.lexer, nucleus.position + ); + } } else if (mode === "math" && nucleus.type === "\\rule") { // Parse the width of the rule var widthGroup = this.parseSizeGroup(nucleus.position, mode); diff --git a/buildTree.js b/buildTree.js index a523548..4d7a6cc 100644 --- a/buildTree.js +++ b/buildTree.js @@ -38,7 +38,8 @@ var groupToType = { katex: "mord", overline: "mord", rule: "mord", - leftright: "minner" + leftright: "minner", + sqrt: "mord" }; var getTypeOfGroup = function(group) { @@ -429,6 +430,68 @@ var groupTypes = { ["katex-logo"], [k, a, t, e, x], options.getColor()); }, + sqrt: function(group, options, prev) { + var innerGroup = buildGroup(group.value.result, + options.withStyle(options.style.cramp())); + + var fontSizer = buildCommon.makeFontSizer( + options, Math.max(innerGroup.maxFontSize, 1.0)); + + // The theta variable in the TeXbook + var lineWidth = fontMetrics.metrics.defaultRuleThickness; + + var lineInner = + makeSpan([options.style.reset(), Style.TEXT.cls(), "line"]); + lineInner.maxFontSize = 1.0; + var line = makeSpan(["sqrt-line"], [fontSizer, lineInner]); + + var inner = makeSpan(["sqrt-inner"], [fontSizer, innerGroup]); + var fixIE = makeSpan( + ["fix-ie"], [fontSizer, new domTree.textNode("\u00a0")]); + + var theta = fontMetrics.metrics.defaultRuleThickness / + options.style.sizeMultiplier; + var phi = theta; + if (options.style.id < Style.TEXT.id) { + phi = fontMetrics.metrics.xHeight; + } + + var psi = theta + phi / 4; + + var innerHeight = + (inner.height + inner.depth) * options.style.sizeMultiplier; + var minDelimiterHeight = innerHeight + psi + theta; + + var delim = makeSpan(["sqrt-sign"], [ + delimiter.customSizedDelim("\\surd", minDelimiterHeight, + false, options, group.mode)]); + + var delimDepth = delim.height + delim.depth; + + if (delimDepth > inner.height + inner.depth + psi) { + psi = (psi + delimDepth - inner.height - inner.depth) / 2; + } + + delim.style.top = (-inner.height - psi + delim.height - theta) + "em"; + + line.style.top = (-inner.height - psi) + "em"; + line.height = inner.height + psi + 2 * theta; + + // We add a special case here, because even when `inner` is empty, we + // still get a line. So, we use a simple heuristic to decide if we + // should omit the body entirely. (note this doesn't work for something + // like `\sqrt{\rlap{x}}`, but if someone is doing that they deserve for + // it not to work. + var body; + if (inner.height === 0 && inner.depth === 0) { + body = makeSpan(); + } else { + body = makeSpan(["sqrt-body"], [line, inner, fixIE]); + } + + return makeSpan(["sqrt", "mord"], [delim, body]); + }, + overline: function(group, options, prev) { var innerGroup = buildGroup(group.value.result, options.withStyle(options.style.cramp())); diff --git a/delimiter.js b/delimiter.js index de5dda0..b5f786e 100644 --- a/delimiter.js +++ b/delimiter.js @@ -191,6 +191,12 @@ var makeStackedDelim = function(delim, heightTotal, center, options, mode) { bottom = "\u23ad"; repeat = "\u23aa"; font = "Size4-Regular"; + } else if (delim === "\\surd") { + top = "\ue001"; + bottom = "\u23b7"; + repeat = "\ue000"; + font = "Size4-Regular"; + overlap = true; } // Get the metrics of the three sections @@ -312,7 +318,8 @@ var normalDelimiters = [ "(", ")", "[", "\\lbrack", "]", "\\rbrack", "\\{", "\\lbrace", "\\}", "\\rbrace", "\\lfloor", "\\rfloor", "\\lceil", "\\rceil", - "<", ">", "\\langle", "\\rangle", "/", "\\backslash" + "<", ">", "\\langle", "\\rangle", "/", "\\backslash", + "\\surd" ]; var stackDelimiters = [ diff --git a/static/katex.less b/static/katex.less index df8bc8b..3ad5e52 100644 --- a/static/katex.less +++ b/static/katex.less @@ -350,6 +350,46 @@ big parens } } + .sqrt { + > .sqrt-sign { + position: relative; + } + + > .sqrt-body { + .baseline-align-hack-outer; + + > .sqrt-line, + > .sqrt-inner, + > .fix-ie { + .baseline-align-hack-middle; + position: relative; + + > span { + .baseline-align-hack-inner; + } + } + + > .sqrt-line > .line { + 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, .fontsize-ensurer { display: inline-block; diff --git a/symbols.js b/symbols.js index 41631e7..377dafa 100644 --- a/symbols.js +++ b/symbols.js @@ -298,6 +298,11 @@ var symbols = { group: "bin", replace: "\u00d7" }, + "\\surd": { + font: "main", + group: "textord", + replace: "\u221a" + }, "(": { font: "main", group: "open" diff --git a/test/huxley/Huxleyfile.json b/test/huxley/Huxleyfile.json index 0fe4604..18b1ca7 100644 --- a/test/huxley/Huxleyfile.json +++ b/test/huxley/Huxleyfile.json @@ -153,5 +153,11 @@ "name": "NullDelimiterInteraction", "screenSize": [1024, 768], "url": "http://localhost:7936/test/huxley/test.html?m=a \\bigl. + 2 \\quad \\left. + a \\right)" + }, + + { + "name": "Sqrt", + "screenSize": [1024, 768], + "url": "http://localhost:7936/test/huxley/test.html?m=\\sqrt{\\sqrt{\\sqrt{x}}}_{\\sqrt{\\sqrt{x}}}^{\\sqrt{\\sqrt{\\sqrt{x}}}^{\\sqrt{\\sqrt{\\sqrt{x}}}}}" } ] diff --git a/test/huxley/Sqrt.hux/firefox-1.png b/test/huxley/Sqrt.hux/firefox-1.png new file mode 100644 index 0000000000000000000000000000000000000000..d22c3229bf01cc82615bf26cabd805d771241f94 GIT binary patch literal 30876 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

q=y14xcHlD+Kw2sGHI`dy7EZ#I)@f@6 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 V3Nds3d8(iybJKAqF(YTK|36j0!YTj& literal 0 HcmV?d00001 diff --git a/test/huxley/Sqrt.hux/record.json b/test/huxley/Sqrt.hux/record.json new file mode 100644 index 0000000..3cae6ac --- /dev/null +++ b/test/huxley/Sqrt.hux/record.json @@ -0,0 +1,5 @@ +[ + { + "action": "screenshot" + } +] diff --git a/test/katex-tests.js b/test/katex-tests.js index 92bbf99..a804f80 100644 --- a/test/katex-tests.js +++ b/test/katex-tests.js @@ -798,3 +798,26 @@ describe("A left/right parser", function() { }).not.toThrow(); }); }); + +describe("A sqrt parser", function() { + var sqrt = "\\sqrt{x}"; + var missingGroup = "\\sqrt"; + + it("should parse square roots", function() { + expect(function() { + parseTree(sqrt); + }).not.toThrow(); + }); + + it("should error when there is no group", function() { + expect(function() { + parseTree(missingGroup); + }).toThrow(); + }); + + it("should produce sqrts", function() { + var parse = parseTree(sqrt)[0]; + + expect(parse.type).toMatch("sqrt"); + }); +});