Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 109 additions & 33 deletions src/Options.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,43 @@
* `.reset` functions.
*/

const BASESIZE = 6;

const sizeStyleMap = [
// Each element contains [textsize, scriptsize, scriptscriptsize].
// The size mappings are taken from TeX with \normalsize=10pt.
[1, 1, 1], // size1: [5, 5, 5] \tiny
[2, 1, 1], // size2: [6, 5, 5]
[3, 1, 1], // size3: [7, 5, 5] \scriptsize
[4, 2, 1], // size4: [8, 6, 5] \footnotesize
[5, 2, 1], // size5: [9, 6, 5] \small
[6, 3, 1], // size6: [10, 7, 5] \normalsize
[7, 4, 2], // size7: [12, 8, 6] \large
[8, 6, 3], // size8: [14.4, 10, 7] \Large
[9, 7, 6], // size9: [17.28, 12, 10] \LARGE
[10, 8, 7], // size10: [20.74, 14.4, 12] \huge
[11, 10, 9], // size11: [24.88, 20.74, 17.28] \HUGE
];

const sizeMultipliers = [
0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.2, 1.44, 1.728, 2.074, 2.488,
];

/**
* This is the main options class. It contains the style, size, color, and font
* of the current parse level. It also contains the style and size of the parent
* parse level, so size changes can be handled efficiently.
* This is the main options class. It contains the current style, size, color,
* and font.
*
* Each of the `.with*` and `.reset` functions passes its current style and size
* as the parentStyle and parentSize of the new options class, so parent
* handling is taken care of automatically.
* Options objects should not be modified. To create a new Options with
* different properties, call a `.having*` method.
*/
function Options(data) {
this.style = data.style;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The doc string for this function references a .reset function with doesn't currently exist. It needs to be updated.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. The whole comment refers to “parent” functionality that is no longer present or needed. I'll replace this comment with a comment about it being readonly.

this.color = data.color;
this.size = data.size;
this.size = data.size || BASESIZE;
this.textSize = data.textSize || this.size;
this.phantom = data.phantom;
this.font = data.font;

if (data.parentStyle === undefined) {
this.parentStyle = data.style;
} else {
this.parentStyle = data.parentStyle;
}

if (data.parentSize === undefined) {
this.parentSize = data.size;
} else {
this.parentSize = data.parentSize;
}
this.sizeMultiplier = sizeMultipliers[this.size - 1];
}

/**
Expand All @@ -42,6 +52,7 @@ Options.prototype.extend = function(extension) {
const data = {
style: this.style,
size: this.size,
textSize: this.textSize,
color: this.color,
parentStyle: this.style,
parentSize: this.size,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get rid of parentSize?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, good catch. parentStyle too.

Expand All @@ -58,22 +69,66 @@ Options.prototype.extend = function(extension) {
return new Options(data);
};

function sizeAtStyle(size, style) {
return style.size < 2 ? size : sizeStyleMap[size - 1][style.size - 1];
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this equivalent to the following?

return sizeStyleMap[size - 1][style.size - 1];

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No because style.size might be 0 (DISPLAY).

It would be equivalent to sizeStyleMap[size - 1][Math.max(0, style.size - 1)] but I find this easier to understand

Copy link
Copy Markdown
Member

@k4b7 k4b7 Jun 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason I thought the sizes where started counting from 1. I think my reason for confusion is that I was conflating sizing command sizes with style command sizes. :( The fact that we're accessing values in sizeStyleMap should've clued me in.

}

/**
* Create a new options object with the given style.
* Return an options object with the given style. If `this.style === style`,
* returns `this`.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems functionally equivalent as long as we don't mutate these objects. Can you add a warning somewhere not to mutate these objects and to only use the functions provided to create new Option instances from existing ones?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure.

FWIW it would also be OK to use the old .with* names. The .having* names were very useful during auditing.

*/
Options.prototype.withStyle = function(style) {
return this.extend({
style: style,
});
Options.prototype.havingStyle = function(style) {
if (this.style === style) {
return this;
} else {
return this.extend({
style: style,
size: sizeAtStyle(this.textSize, style),
});
}
};

/**
* Create a new options object with the given size.
* Return an options object with a cramped version of the current style. If
* the current style is cramped, returns `this`.
*/
Options.prototype.withSize = function(size) {
return this.extend({
size: size,
});
Options.prototype.havingCrampedStyle = function() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this used?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

buildHTML uses it for convenience.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I totally missed that file b/c github auto-collapsed it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll try to review the changes to buildHTML.js over the next couple of days.

return this.havingStyle(this.style.cramp());
};

/**
* Return an options object with the given size and in at least `\textstyle`.
* Returns `this` if appropriate.
*/
Options.prototype.havingSize = function(size) {
if (this.size === size && this.textSize === size) {
return this;
} else {
return this.extend({
style: this.style.text(),
size: size,
textSize: size,
});
}
};

/**
* Like `this.havingSize(BASESIZE).havingStyle(style)`. If `style` is omitted,
* changes to at least `\textstyle`.
*/
Options.prototype.havingBaseStyle = function(style) {
style = style || this.style.text();
const wantSize = sizeAtStyle(BASESIZE, style);
if (this.size === wantSize && this.textSize === BASESIZE
&& this.style === style) {
return this;
} else {
return this.extend({
style: style,
size: wantSize,
baseSize: BASESIZE,
});
}
};

/**
Expand Down Expand Up @@ -104,11 +159,27 @@ Options.prototype.withFont = function(font) {
};

/**
* Create a new options object with the same style, size, and color. This is
* used so that parent style and size changes are handled correctly.
* Return the CSS sizing classes required to switch from enclosing options
* `oldOptions` to `this`. Returns an array of classes.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice comment.

*/
Options.prototype.sizingClasses = function(oldOptions) {
if (oldOptions.size !== this.size) {
return ["sizing", "reset-size" + oldOptions.size, "size" + this.size];
} else {
return [];
}
};

/**
* Return the CSS sizing classes required to switch to the base size. Like
* `this.havingSize(BASESIZE).sizingClasses(this)`.
*/
Options.prototype.reset = function() {
return this.extend({});
Options.prototype.baseSizingClasses = function() {
if (this.size !== BASESIZE) {
return ["sizing", "reset-size" + this.size, "size" + BASESIZE];
} else {
return [];
}
};

/**
Expand Down Expand Up @@ -186,4 +257,9 @@ Options.prototype.getColor = function() {
}
};

/**
* The base size index.
*/
Options.BASESIZE = BASESIZE;

module.exports = Options;
6 changes: 3 additions & 3 deletions src/Parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -390,8 +390,8 @@ Parser.prototype.parseAtom = function() {

// A list of the size-changing functions, for use in parseImplicitGroup
const sizeFuncs = [
"\\tiny", "\\scriptsize", "\\footnotesize", "\\small", "\\normalsize",
"\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge",
"\\tiny", "\\sixptsize", "\\scriptsize", "\\footnotesize", "\\small",
"\\normalsize", "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge",
];

// A list of the style-changing functions, for use in parseImplicitGroup
Expand Down Expand Up @@ -483,7 +483,7 @@ Parser.prototype.parseImplicitGroup = function() {
const body = this.parseExpression(false);
return new ParseNode("sizing", {
// Figure out what size to use based on the list of functions above
size: "size" + (utils.indexOf(sizeFuncs, func) + 1),
size: utils.indexOf(sizeFuncs, func) + 1,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice cleanup

value: body,
}, this.mode);
} else if (utils.contains(styleFuncs, func)) {
Expand Down
53 changes: 14 additions & 39 deletions src/Style.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,12 @@ for (let i = 0; i < 3; i++) {

/**
* The main style class. Contains a unique id for the style, a size (which is
* the same for cramped and uncramped version of a style), a cramped flag, and a
* size multiplier, which gives the size difference between a style and
* textstyle.
* the same for cramped and uncramped version of a style), and a cramped flag.
*/
function Style(id, size, multiplier, cramped) {
function Style(id, size, cramped) {
this.id = id;
this.size = size;
this.cramped = cramped;
this.sizeMultiplier = multiplier;
this.metrics = metrics[size > 0 ? size - 1 : 0];
}

Expand Down Expand Up @@ -73,17 +70,10 @@ Style.prototype.cramp = function() {
};

/**
* HTML class name, like "displaystyle cramped"
* Get a text or display version of this style.
*/
Style.prototype.cls = function() {
return sizeNames[this.size] + (this.cramped ? " cramped" : " uncramped");
};

/**
* HTML Reset class name, like "reset-textstyle"
*/
Style.prototype.reset = function() {
return resetNames[this.size];
Style.prototype.text = function() {
return styles[text[this.id]];
};

/**
Expand All @@ -103,32 +93,16 @@ const Sc = 5;
const SS = 6;
const SSc = 7;

// String names for the different sizes
const sizeNames = [
"displaystyle textstyle",
"textstyle",
"scriptstyle",
"scriptscriptstyle",
];

// Reset names for the different sizes
const resetNames = [
"reset-textstyle",
"reset-textstyle",
"reset-scriptstyle",
"reset-scriptscriptstyle",
];

// Instances of the different styles
const styles = [
new Style(D, 0, 1.0, false),
new Style(Dc, 0, 1.0, true),
new Style(T, 1, 1.0, false),
new Style(Tc, 1, 1.0, true),
new Style(S, 2, 0.7, false),
new Style(Sc, 2, 0.7, true),
new Style(SS, 3, 0.5, false),
new Style(SSc, 3, 0.5, true),
new Style(D, 0, false),
new Style(Dc, 0, true),
new Style(T, 1, false),
new Style(Tc, 1, true),
new Style(S, 2, false),
new Style(Sc, 2, true),
new Style(SS, 3, false),
new Style(SSc, 3, true),
];

// Lookup tables for switching from one style to another
Expand All @@ -137,6 +111,7 @@ const sub = [Sc, Sc, Sc, Sc, SSc, SSc, SSc, SSc];
const fracNum = [T, Tc, S, Sc, SS, SSc, SS, SSc];
const fracDen = [Tc, Tc, Sc, Sc, SSc, SSc, SSc, SSc];
const cramp = [Dc, Dc, Tc, Tc, Sc, Sc, SSc, SSc];
const text = [D, Dc, T, Tc, T, Tc, T, Tc];

// We only export some of the styles. Also, we don't export the `Style` class so
// no more styles can be generated.
Expand Down
21 changes: 3 additions & 18 deletions src/buildCommon.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const makeSymbol = function(value, fontFamily, mode, options, classes) {
}

if (options) {
symbolNode.maxFontSize = options.sizeMultiplier;
if (options.style.isTight()) {
symbolNode.classes.push("mtight");
}
Expand Down Expand Up @@ -239,11 +240,10 @@ const makeFragment = function(children) {
*/
const makeFontSizer = function(options, fontSize) {
const fontSizeInner = makeSpan([], [new domTree.symbolNode("\u200b")]);
fontSizeInner.style.fontSize =
(fontSize / options.style.sizeMultiplier) + "em";
fontSizeInner.style.fontSize = fontSize + "em";

const fontSizer = makeSpan(
["fontsize-ensurer", "reset-" + options.size, "size5"],
["fontsize-ensurer"].concat(options.baseSizingClasses()),
[fontSizeInner]);

return fontSizer;
Expand Down Expand Up @@ -378,20 +378,6 @@ const makeVList = function(children, positionType, positionData, options) {
return vlist;
};

// A table of size -> font size for the different sizing functions
const 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,
};

// A map of spacing functions to their attributes, like size and corresponding
// CSS class
const spacingFunctions = {
Expand Down Expand Up @@ -486,6 +472,5 @@ module.exports = {
makeVList: makeVList,
makeOrd: makeOrd,
prependChildren: prependChildren,
sizingMultiplier: sizingMultiplier,
spacingFunctions: spacingFunctions,
};
Loading