Commit bffed0fe authored by dengjb's avatar dengjb
Browse files

update

parents
This diff is collapsed.
/**
* This is a module for storing settings passed into KaTeX. It correctly handles
* default settings.
*/
/**
* Helper function for getting a default value if the value is undefined
*/
function get(option, defaultValue) {
return option === undefined ? defaultValue : option;
}
/**
* The main Settings object
*
* The current options stored are:
* - displayMode: Whether the expression should be typeset by default in
* textstyle or displaystyle (default false)
*/
function Settings(options) {
// allow null options
options = options || {};
this.displayMode = get(options.displayMode, false);
this.throwOnError = get(options.throwOnError, true);
this.errorColor = get(options.errorColor, "#cc0000");
}
module.exports = Settings;
/**
* This file contains information and classes for the various kinds of styles
* used in TeX. It provides a generic `Style` class, which holds information
* about a specific style. It then provides instances of all the different kinds
* of styles possible, and provides functions to move between them and get
* information about them.
*/
/**
* 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.
*/
function Style(id, size, multiplier, cramped) {
this.id = id;
this.size = size;
this.cramped = cramped;
this.sizeMultiplier = multiplier;
}
/**
* Get the style of a superscript given a base in the current style.
*/
Style.prototype.sup = function() {
return styles[sup[this.id]];
};
/**
* Get the style of a subscript given a base in the current style.
*/
Style.prototype.sub = function() {
return styles[sub[this.id]];
};
/**
* Get the style of a fraction numerator given the fraction in the current
* style.
*/
Style.prototype.fracNum = function() {
return styles[fracNum[this.id]];
};
/**
* Get the style of a fraction denominator given the fraction in the current
* style.
*/
Style.prototype.fracDen = function() {
return styles[fracDen[this.id]];
};
/**
* Get the cramped version of a style (in particular, cramping a cramped style
* doesn't change the style).
*/
Style.prototype.cramp = function() {
return styles[cramp[this.id]];
};
/**
* HTML class name, like "displaystyle cramped"
*/
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];
};
// IDs of the different styles
var D = 0;
var Dc = 1;
var T = 2;
var Tc = 3;
var S = 4;
var Sc = 5;
var SS = 6;
var SSc = 7;
// String names for the different sizes
var sizeNames = [
"displaystyle textstyle",
"textstyle",
"scriptstyle",
"scriptscriptstyle",
];
// Reset names for the different sizes
var resetNames = [
"reset-textstyle",
"reset-textstyle",
"reset-scriptstyle",
"reset-scriptscriptstyle",
];
// Instances of the different styles
var 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),
];
// Lookup tables for switching from one style to another
var sup = [S, Sc, S, Sc, SS, SSc, SS, SSc];
var sub = [Sc, Sc, Sc, Sc, SSc, SSc, SSc, SSc];
var fracNum = [T, Tc, S, Sc, SS, SSc, SS, SSc];
var fracDen = [Tc, Tc, Sc, Sc, SSc, SSc, SSc, SSc];
var cramp = [Dc, Dc, Tc, Tc, Sc, Sc, SSc, SSc];
// We only export some of the styles. Also, we don't export the `Style` class so
// no more styles can be generated.
module.exports = {
DISPLAY: styles[D],
TEXT: styles[T],
SCRIPT: styles[S],
SCRIPTSCRIPT: styles[SS],
};
This diff is collapsed.
var buildHTML = require("./buildHTML");
var buildMathML = require("./buildMathML");
var buildCommon = require("./buildCommon");
var Options = require("./Options");
var Settings = require("./Settings");
var Style = require("./Style");
var makeSpan = buildCommon.makeSpan;
var buildTree = function(tree, expression, settings) {
settings = settings || new Settings({});
var startStyle = Style.TEXT;
if (settings.displayMode) {
startStyle = Style.DISPLAY;
}
// Setup the default options
var options = new Options({
style: startStyle,
size: "size5",
});
// `buildHTML` sometimes messes with the parse tree (like turning bins ->
// ords), so we build the MathML version first.
var mathMLNode = buildMathML(tree, expression, options);
var htmlNode = buildHTML(tree, options);
var katexNode = makeSpan(["katex"], [
mathMLNode, htmlNode,
]);
if (settings.displayMode) {
return makeSpan(["katex-display"], [katexNode]);
} else {
return katexNode;
}
};
module.exports = buildTree;
This diff is collapsed.
/**
* These objects store the data about the DOM nodes we create, as well as some
* extra data. They can then be transformed into real DOM nodes with the
* `toNode` function or HTML markup using `toMarkup`. They are useful for both
* storing extra properties on the nodes, as well as providing a way to easily
* work with the DOM.
*
* Similar functions for working with MathML nodes exist in mathMLTree.js.
*/
var utils = require("./utils");
/**
* Create an HTML className based on a list of classes. In addition to joining
* with spaces, we also remove null or empty classes.
*/
var createClass = function(classes) {
classes = classes.slice();
for (var i = classes.length - 1; i >= 0; i--) {
if (!classes[i]) {
classes.splice(i, 1);
}
}
return classes.join(" ");
};
/**
* This node represents a span node, with a className, a list of children, and
* an inline style. It also contains information about its height, depth, and
* maxFontSize.
*/
function span(classes, children, height, depth, maxFontSize, style) {
this.classes = classes || [];
this.children = children || [];
this.height = height || 0;
this.depth = depth || 0;
this.maxFontSize = maxFontSize || 0;
this.style = style || {};
this.attributes = {};
}
/**
* Sets an arbitrary attribute on the span. Warning: use this wisely. Not all
* browsers support attributes the same, and having too many custom attributes
* is probably bad.
*/
span.prototype.setAttribute = function(attribute, value) {
this.attributes[attribute] = value;
};
/**
* Convert the span into an HTML node
*/
span.prototype.toNode = function() {
var span = document.createElement("span");
// Apply the class
span.className = createClass(this.classes);
// Apply inline styles
for (var style in this.style) {
if (Object.prototype.hasOwnProperty.call(this.style, style)) {
span.style[style] = this.style[style];
}
}
// Apply attributes
for (var attr in this.attributes) {
if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
span.setAttribute(attr, this.attributes[attr]);
}
}
// Append the children, also as HTML nodes
for (var i = 0; i < this.children.length; i++) {
span.appendChild(this.children[i].toNode());
}
return span;
};
/**
* Convert the span into an HTML markup string
*/
span.prototype.toMarkup = function() {
var markup = "<span";
// Add the class
if (this.classes.length) {
markup += " class=\"";
markup += utils.escape(createClass(this.classes));
markup += "\"";
}
var styles = "";
// Add the styles, after hyphenation
for (var style in this.style) {
if (this.style.hasOwnProperty(style)) {
styles += utils.hyphenate(style) + ":" + this.style[style] + ";";
}
}
if (styles) {
markup += " style=\"" + utils.escape(styles) + "\"";
}
// Add the attributes
for (var attr in this.attributes) {
if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
markup += " " + attr + "=\"";
markup += utils.escape(this.attributes[attr]);
markup += "\"";
}
}
markup += ">";
// Add the markup of the children, also as markup
for (var i = 0; i < this.children.length; i++) {
markup += this.children[i].toMarkup();
}
markup += "</span>";
return markup;
};
/**
* This node represents a document fragment, which contains elements, but when
* placed into the DOM doesn't have any representation itself. Thus, it only
* contains children and doesn't have any HTML properties. It also keeps track
* of a height, depth, and maxFontSize.
*/
function documentFragment(children, height, depth, maxFontSize) {
this.children = children || [];
this.height = height || 0;
this.depth = depth || 0;
this.maxFontSize = maxFontSize || 0;
}
/**
* Convert the fragment into a node
*/
documentFragment.prototype.toNode = function() {
// Create a fragment
var frag = document.createDocumentFragment();
// Append the children
for (var i = 0; i < this.children.length; i++) {
frag.appendChild(this.children[i].toNode());
}
return frag;
};
/**
* Convert the fragment into HTML markup
*/
documentFragment.prototype.toMarkup = function() {
var markup = "";
// Simply concatenate the markup for the children together
for (var i = 0; i < this.children.length; i++) {
markup += this.children[i].toMarkup();
}
return markup;
};
/**
* A symbol node contains information about a single symbol. It either renders
* to a single text node, or a span with a single text node in it, depending on
* whether it has CSS classes, styles, or needs italic correction.
*/
function symbolNode(value, height, depth, italic, skew, classes, style) {
this.value = value || "";
this.height = height || 0;
this.depth = depth || 0;
this.italic = italic || 0;
this.skew = skew || 0;
this.classes = classes || [];
this.style = style || {};
this.maxFontSize = 0;
}
/**
* Creates a text node or span from a symbol node. Note that a span is only
* created if it is needed.
*/
symbolNode.prototype.toNode = function() {
var node = document.createTextNode(this.value);
var span = null;
if (this.italic > 0) {
span = document.createElement("span");
span.style.marginRight = this.italic + "em";
}
if (this.classes.length > 0) {
span = span || document.createElement("span");
span.className = createClass(this.classes);
}
for (var style in this.style) {
if (this.style.hasOwnProperty(style)) {
span = span || document.createElement("span");
span.style[style] = this.style[style];
}
}
if (span) {
span.appendChild(node);
return span;
} else {
return node;
}
};
/**
* Creates markup for a symbol node.
*/
symbolNode.prototype.toMarkup = function() {
// TODO(alpert): More duplication than I'd like from
// span.prototype.toMarkup and symbolNode.prototype.toNode...
var needsSpan = false;
var markup = "<span";
if (this.classes.length) {
needsSpan = true;
markup += " class=\"";
markup += utils.escape(createClass(this.classes));
markup += "\"";
}
var styles = "";
if (this.italic > 0) {
styles += "margin-right:" + this.italic + "em;";
}
for (var style in this.style) {
if (this.style.hasOwnProperty(style)) {
styles += utils.hyphenate(style) + ":" + this.style[style] + ";";
}
}
if (styles) {
needsSpan = true;
markup += " style=\"" + utils.escape(styles) + "\"";
}
var escaped = utils.escape(this.value);
if (needsSpan) {
markup += ">";
markup += escaped;
markup += "</span>";
return markup;
} else {
return escaped;
}
};
module.exports = {
span: span,
documentFragment: documentFragment,
symbolNode: symbolNode,
};
This diff is collapsed.
/**
* These objects store data about MathML nodes. This is the MathML equivalent
* of the types in domTree.js. Since MathML handles its own rendering, and
* since we're mainly using MathML to improve accessibility, we don't manage
* any of the styling state that the plain DOM nodes do.
*
* The `toNode` and `toMarkup` functions work simlarly to how they do in
* domTree.js, creating namespaced DOM nodes and HTML text markup respectively.
*/
var utils = require("./utils");
/**
* This node represents a general purpose MathML node of any type. The
* constructor requires the type of node to create (for example, `"mo"` or
* `"mspace"`, corresponding to `<mo>` and `<mspace>` tags).
*/
function MathNode(type, children) {
this.type = type;
this.attributes = {};
this.children = children || [];
}
/**
* Sets an attribute on a MathML node. MathML depends on attributes to convey a
* semantic content, so this is used heavily.
*/
MathNode.prototype.setAttribute = function(name, value) {
this.attributes[name] = value;
};
/**
* Converts the math node into a MathML-namespaced DOM element.
*/
MathNode.prototype.toNode = function() {
var node = document.createElementNS(
"http://www.w3.org/1998/Math/MathML", this.type);
for (var attr in this.attributes) {
if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
node.setAttribute(attr, this.attributes[attr]);
}
}
for (var i = 0; i < this.children.length; i++) {
node.appendChild(this.children[i].toNode());
}
return node;
};
/**
* Converts the math node into an HTML markup string.
*/
MathNode.prototype.toMarkup = function() {
var markup = "<" + this.type;
// Add the attributes
for (var attr in this.attributes) {
if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
markup += " " + attr + "=\"";
markup += utils.escape(this.attributes[attr]);
markup += "\"";
}
}
markup += ">";
for (var i = 0; i < this.children.length; i++) {
markup += this.children[i].toMarkup();
}
markup += "</" + this.type + ">";
return markup;
};
/**
* This node represents a piece of text.
*/
function TextNode(text) {
this.text = text;
}
/**
* Converts the text node into a DOM text node.
*/
TextNode.prototype.toNode = function() {
return document.createTextNode(this.text);
};
/**
* Converts the text node into HTML markup (which is just the text itself).
*/
TextNode.prototype.toMarkup = function() {
return utils.escape(this.text);
};
module.exports = {
MathNode: MathNode,
TextNode: TextNode,
};
/**
* The resulting parse tree nodes of the parse tree.
*/
function ParseNode(type, value, mode) {
this.type = type;
this.value = value;
this.mode = mode;
}
module.exports = {
ParseNode: ParseNode,
};
/**
* Provides a single function for parsing an expression using a Parser
* TODO(emily): Remove this
*/
var Parser = require("./Parser");
/**
* Parses an expression using a Parser, then returns the parsed result.
*/
var parseTree = function(toParse, settings) {
var parser = new Parser(toParse, settings);
return parser.parse();
};
module.exports = parseTree;
This diff is collapsed.
This diff is collapsed.
# match-at [![Build Status](https://travis-ci.org/spicyj/match-at.svg?branch=master)](https://travis-ci.org/spicyj/match-at)
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment