Add sizing functions (like \small)
Summary: Right now, when the size gets bigger, this still doesn't work, so there's a check to prevent that. However, functions that go smaller (like `\small`, `\tiny`, etc) do work. Also, we can't seem to use the sizing functions inside of fractions (so something like `\dfrac{\small\frac{x}{y}}{z}` doesn't work). However, the most prominent use case is `\small` as the outer-most object, so this is still helpful. This commit has the parsing and stuff to handle all of it, but it'll throw an error if you try to do something that doesn't work. (For the record, "doesn't work" means "looks bad", not "throws an unexpected error"). Test Plan: Make sure things like `\small x` work, and things like `\Huge x` and `\frac{\small x}{y}` don't. Reviewers: alpert Reviewed By: alpert Differential Revision: http://phabricator.khanacademy.org/D3619
This commit is contained in:
parent
944b55a6b0
commit
387c159a8e
28
Options.js
28
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;
|
||||
|
|
20
Parser.js
20
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);
|
||||
|
|
43
buildTree.js
43
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);
|
||||
|
|
|
@ -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; }
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user