diff --git a/Options.js b/Options.js index 96a74eb8c..a65ca3ff2 100644 --- a/Options.js +++ b/Options.js @@ -1,23 +1,43 @@ -function Options(style, color, parentStyle) { +function Options(style, size, color, depth, parentStyle, parentSize) { this.style = style; this.color = color; + this.size = size; + + // TODO(emily): Get rid of depth when we can actually use sizing everywhere + if (!depth) { + depth = 0; + } + this.depth = depth; if (!parentStyle) { parentStyle = style; } this.parentStyle = parentStyle; + + if (!parentSize) { + parentSize = size; + } + this.parentSize = parentSize; } Options.prototype.withStyle = function(style) { - return new Options(style, this.color, this.style); + return new Options(style, this.size, this.color, this.depth + 1, + this.style, this.size); +}; + +Options.prototype.withSize = function(size) { + return new Options(this.style, size, this.color, this.depth + 1, + this.style, this.size); }; Options.prototype.withColor = function(color) { - return new Options(this.style, color, this.style); + return new Options(this.style, this.size, color, this.depth + 1, + this.style, this.size); }; Options.prototype.reset = function() { - return new Options(this.style, this.color, this.style); + return new Options(this.style, this.size, this.color, this.depth + 1, + this.style, this.size); }; module.exports = Options; diff --git a/Parser.js b/Parser.js index 2c6a7b5a4..af24b26fe 100644 --- a/Parser.js +++ b/Parser.js @@ -183,6 +183,12 @@ var colorFuncs = [ "\\blue", "\\orange", "\\pink", "\\red", "\\green", "\\gray", "\\purple" ]; +// A list of 1-argument sizing functions +var sizeFuncs = [ + "\\tiny", "\\scriptsize", "\\footnotesize", "\\small", "\\normalsize", + "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge" +]; + // A map of elements that don't have arguments, and should simply be placed // into a group depending on their type. The keys are the groups that items can // be placed in, and the values are lists of element types that should be @@ -344,6 +350,20 @@ Parser.prototype.parseNucleus = function(pos) { throw new ParseError( "Expected group after '" + nucleus.text + "'"); } + } else if (utils.contains(sizeFuncs, nucleus.type)) { + // If this is a color function, parse its argument and return + var group = this.parseGroup(nucleus.position); + if (group) { + return new ParseResult( + new ParseNode("sizing", { + size: "size" + (sizeFuncs.indexOf(nucleus.type) + 1), + value: group.result + }), + group.position); + } else { + throw new ParseError( + "Expected group after '" + nucleus.text + "'"); + } } else if (nucleus.type === "\\llap" || nucleus.type === "\\rlap") { // If this is an llap or rlap, parse its argument and return var group = this.parseGroup(nucleus.position); diff --git a/buildTree.js b/buildTree.js index 008c493bf..b5f2dcac0 100644 --- a/buildTree.js +++ b/buildTree.js @@ -339,9 +339,32 @@ var groupTypes = { var x = makeSpan(["x"], [mathrm("X")]); return makeSpan(["katex-logo", options.color], [k, a, t, e, x]); + }, + + sizing: function(group, options, prev) { + var inner = buildGroup(group.value.value, + options.withSize(group.value.size), prev); + + return makeSpan( + ["reset-" + options.size, group.value.size, + getTypeOfGroup(group.value.value)], + [inner]); } }; +var sizingMultiplier = { + size1: 0.5, + size2: 0.7, + size3: 0.8, + size4: 0.9, + size5: 1.0, + size6: 1.2, + size7: 1.44, + size8: 1.73, + size9: 2.07, + size10: 2.49 +}; + var buildGroup = function(group, options, prev) { if (!group) { return makeSpan(); @@ -363,6 +386,24 @@ var buildGroup = function(group, options, prev) { groupNode.depth *= multiplier; } + if (options.size !== options.parentSize) { + var multiplier = sizingMultiplier[options.size] / + sizingMultiplier[options.parentSize]; + + if (multiplier > 1) { + throw new ParseError( + "Error: Can't go from small to large size"); + } + + if (options.depth > 1) { + throw new ParseError( + "Error: Can't use sizing outside of the root node"); + } + + groupNode.height *= multiplier; + groupNode.depth *= multiplier; + } + return groupNode; } else { throw new ParseError( @@ -481,7 +522,7 @@ var amsrm = function(value) { var buildTree = function(tree) { // Setup the default options - var options = new Options(Style.TEXT, ""); + var options = new Options(Style.TEXT, "size5", ""); var expression = buildExpression(tree, options); var span = makeSpan(["base", options.style.cls()], expression); diff --git a/static/katex.less b/static/katex.less index e77a05448..f026bd474 100644 --- a/static/katex.less +++ b/static/katex.less @@ -288,4 +288,15 @@ big parens margin-left: -0.125em; } } + + .reset-size5.size1 { font-size: 0.5em; } + .reset-size5.size2 { font-size: 0.7em; } + .reset-size5.size3 { font-size: 0.8em; } + .reset-size5.size4 { font-size: 0.9em; } + .reset-size5.size5 { font-size: 1.0em; } + .reset-size5.size6 { font-size: 1.2em; } + .reset-size5.size7 { font-size: 1.44em; } + .reset-size5.size8 { font-size: 1.73em; } + .reset-size5.size9 { font-size: 2.07em; } + .reset-size5.size10 { font-size: 2.49em; } }