diff --git a/src/buildHTML.js b/src/buildHTML.js index dbd33a3fc..a0e2d5220 100644 --- a/src/buildHTML.js +++ b/src/buildHTML.js @@ -1178,6 +1178,25 @@ groupTypes.rule = function(group, options, prev) { return rule; }; +groupTypes.kern = function(group, options, prev) { + // Make an empty span for the rule + var rule = makeSpan(["mord", "rule"], [], options.getColor()); + + var dimension = 0; + if (group.value.dimension) { + dimension = group.value.dimension.number; + if (group.value.dimension.unit === "ex") { + dimension *= fontMetrics.metrics.xHeight; + } + } + + dimension /= options.style.sizeMultiplier; + + rule.style.marginLeft = dimension + "em"; + + return rule; +}; + groupTypes.accent = function(group, options, prev) { // Accents are handled in the TeXbook pg. 443, rule 12. var base = group.value.base; diff --git a/src/buildMathML.js b/src/buildMathML.js index f3c7c5e1c..0a4d54455 100644 --- a/src/buildMathML.js +++ b/src/buildMathML.js @@ -430,6 +430,13 @@ groupTypes.rule = function(group) { return node; }; +groupTypes.kern = function(group) { + // TODO(kevin): Figure out if there's a way to add space in MathML + var node = new mathMLTree.MathNode("mrow"); + + return node; +}; + groupTypes.llap = function(group, options) { var node = new mathMLTree.MathNode( "mpadded", [buildGroup(group.value.body, options)]); diff --git a/src/functions.js b/src/functions.js index 2fa124d3b..ea5c33ea7 100644 --- a/src/functions.js +++ b/src/functions.js @@ -187,6 +187,16 @@ defineFunction("\\rule", { }; }); +defineFunction("\\kern", { + numArgs: 1, + argTypes: ["size"], +}, function(context, args) { + return { + type: "kern", + dimension: args[0].value, + }; +}); + // A KaTeX logo defineFunction("\\KaTeX", { numArgs: 0, diff --git a/test/katex-spec.js b/test/katex-spec.js index 75a0d393e..b6ac37e34 100644 --- a/test/katex-spec.js +++ b/test/katex-spec.js @@ -909,6 +909,31 @@ describe("A rule parser", function() { }); }); +describe("A kern parser", function() { + var emKern = "\\kern{1em}"; + var exKern = "\\kern{1ex}"; + var badUnitRule = "\\kern{1px}"; + var noNumberRule = "\\kern{em}"; + + it("should list the correct units", function() { + var emParse = getParsed(emKern)[0]; + var exParse = getParsed(exKern)[0]; + + expect(emParse.value.dimension.unit).toEqual("em"); + expect(exParse.value.dimension.unit).toEqual("ex"); + }); + + it("should not parse invalid units", function() { + expect(badUnitRule).toNotParse(); + expect(noNumberRule).toNotParse(); + }); + + it("should parse negative sizes", function() { + var parse = getParsed("\\kern{-1em}")[0]; + expect(parse.value.dimension.number).toBeCloseTo(-1); + }); +}); + describe("A left/right parser", function() { var normalLeftRight = "\\left( \\dfrac{x}{y} \\right)"; var emptyRight = "\\left( \\dfrac{x}{y} \\right."; diff --git a/test/screenshotter/images/Kern-chrome.png b/test/screenshotter/images/Kern-chrome.png new file mode 100644 index 000000000..232ace52c Binary files /dev/null and b/test/screenshotter/images/Kern-chrome.png differ diff --git a/test/screenshotter/images/Kern-firefox.png b/test/screenshotter/images/Kern-firefox.png new file mode 100644 index 000000000..e33835dd4 Binary files /dev/null and b/test/screenshotter/images/Kern-firefox.png differ diff --git a/test/screenshotter/ss_data.yaml b/test/screenshotter/ss_data.yaml index d5e8736fa..6b41de8d5 100644 --- a/test/screenshotter/ss_data.yaml +++ b/test/screenshotter/ss_data.yaml @@ -58,6 +58,7 @@ FractionTest: \dfrac{a}{b}\frac{a}{b}\tfrac{a}{b}\;-\dfrac12\;1\tfrac12 Functions: \sin\cos\tan\ln\log GreekLetters: \alpha\beta\gamma\omega KaTeX: \KaTeX +Kern: \frac{a\kern{1em}b}{c}a\kern{1em}b\kern{1ex}c\kern{-0.25em}d Lap: ab\llap{f}cd\rlap{g}h LeftRight: \left( x^2 \right) \left\{ x^{x^{x^{x^x}}} \right. LeftRightListStyling: a+\left(x+y\right)-x