Turn var into const or let

This commit is contained in:
Martin von Gagern
2017-01-07 02:25:50 +01:00
committed by Kevin Barabash
parent 9b565a6375
commit bd9db332d2
33 changed files with 1308 additions and 1318 deletions

View File

@@ -35,6 +35,7 @@
"no-unreachable": 2, "no-unreachable": 2,
"no-unused-vars": [2, {"args": "none", "varsIgnorePattern": "^_*$"}], "no-unused-vars": [2, {"args": "none", "varsIgnorePattern": "^_*$"}],
"no-useless-call": 2, "no-useless-call": 2,
"no-var": 2,
"no-with": 2, "no-with": 2,
"one-var": [2, "never"], "one-var": [2, "never"],
"prefer-const": 2, "prefer-const": 2,
@@ -52,9 +53,6 @@
// We've decided explicitly not to care about this. // We've decided explicitly not to care about this.
"arrow-parens": 0, "arrow-parens": 0,
// --------------------------------------- // ---------------------------------------
// Stuff that's disabled for now, but maybe shouldn't be.
// disabled because KaTeX doesn't use ES6
"no-var": 0,
// TODO(csilvers): enable these if/when community agrees on it. // TODO(csilvers): enable these if/when community agrees on it.
"prefer-arrow-callback": 0, "prefer-arrow-callback": 0,
"object-curly-spacing": [0, "always"], "object-curly-spacing": [0, "always"],

10
cli.js
View File

@@ -3,11 +3,11 @@
// Reads TeX from stdin, outputs HTML to stdout. // Reads TeX from stdin, outputs HTML to stdout.
/* eslint no-console:0 */ /* eslint no-console:0 */
var katex = require("./"); const katex = require("./");
var input = ""; let input = "";
// Skip the first two args, which are just "node" and "cli.js" // Skip the first two args, which are just "node" and "cli.js"
var args = process.argv.slice(2); const args = process.argv.slice(2);
if (args.indexOf("--help") !== -1) { if (args.indexOf("--help") !== -1) {
console.log(process.argv[0] + " " + process.argv[1] + console.log(process.argv[0] + " " + process.argv[1] +
@@ -26,7 +26,7 @@ process.stdin.on("data", function(chunk) {
}); });
process.stdin.on("end", function() { process.stdin.on("end", function() {
var options = { displayMode: args.indexOf("--display-mode") !== -1 }; const options = { displayMode: args.indexOf("--display-mode") !== -1 };
var output = katex.renderToString(input, options); const output = katex.renderToString(input, options);
console.log(output); console.log(output);
}); });

View File

@@ -4,21 +4,21 @@
/* global it: false */ /* global it: false */
/* global describe: false */ /* global describe: false */
var splitAtDelimiters = require("./splitAtDelimiters"); const splitAtDelimiters = require("./splitAtDelimiters");
beforeEach(function() { beforeEach(function() {
jasmine.addMatchers({ jasmine.addMatchers({
toSplitInto: function() { toSplitInto: function() {
return { return {
compare: function(actual, left, right, result) { compare: function(actual, left, right, result) {
var message = { const message = {
pass: true, pass: true,
message: "'" + actual + "' split correctly", message: "'" + actual + "' split correctly",
}; };
var startData = [{type: "text", data: actual}]; const startData = [{type: "text", data: actual}];
var split = const split =
splitAtDelimiters(startData, left, right, false); splitAtDelimiters(startData, left, right, false);
if (split.length !== result.length) { if (split.length !== result.length) {
@@ -30,12 +30,12 @@ beforeEach(function() {
return message; return message;
} }
for (var i = 0; i < split.length; i++) { for (let i = 0; i < split.length; i++) {
var real = split[i]; const real = split[i];
var correct = result[i]; const correct = result[i];
var good = true; let good = true;
var diff; let diff;
if (real.type !== correct.type) { if (real.type !== correct.type) {
good = false; good = false;
@@ -189,7 +189,7 @@ describe("A delimiter splitter", function() {
}); });
it("remembers which delimiters are display-mode", function() { it("remembers which delimiters are display-mode", function() {
var startData = [{type: "text", data: "hello ( world ) boo"}]; const startData = [{type: "text", data: "hello ( world ) boo"}];
expect(splitAtDelimiters(startData, "(", ")", true)).toEqual( expect(splitAtDelimiters(startData, "(", ")", true)).toEqual(
[ [
@@ -201,7 +201,7 @@ describe("A delimiter splitter", function() {
}); });
it("works with more than one start datum", function() { it("works with more than one start datum", function() {
var startData = [ const startData = [
{type: "text", data: "hello ( world ) boo"}, {type: "text", data: "hello ( world ) boo"},
{type: "math", data: "math", rawData: "(math)", display: true}, {type: "math", data: "math", rawData: "(math)", display: true},
{type: "text", data: "hello ( world ) boo"}, {type: "text", data: "hello ( world ) boo"},
@@ -222,7 +222,7 @@ describe("A delimiter splitter", function() {
}); });
it("doesn't do splitting inside of math nodes", function() { it("doesn't do splitting inside of math nodes", function() {
var startData = [ const startData = [
{type: "text", data: "hello ( world ) boo"}, {type: "text", data: "hello ( world ) boo"},
{type: "math", data: "hello ( world ) boo", {type: "math", data: "hello ( world ) boo",
rawData: "(hello ( world ) boo)", display: true}, rawData: "(hello ( world ) boo)", display: true},

View File

@@ -1,12 +1,12 @@
/* eslint no-console:0 */ /* eslint no-console:0 */
/* global katex */ /* global katex */
var splitAtDelimiters = require("./splitAtDelimiters"); const splitAtDelimiters = require("./splitAtDelimiters");
var splitWithDelimiters = function(text, delimiters) { const splitWithDelimiters = function(text, delimiters) {
var data = [{type: "text", data: text}]; let data = [{type: "text", data: text}];
for (var i = 0; i < delimiters.length; i++) { for (let i = 0; i < delimiters.length; i++) {
var delimiter = delimiters[i]; const delimiter = delimiters[i];
data = splitAtDelimiters( data = splitAtDelimiters(
data, delimiter.left, delimiter.right, data, delimiter.left, delimiter.right,
delimiter.display || false); delimiter.display || false);
@@ -14,17 +14,17 @@ var splitWithDelimiters = function(text, delimiters) {
return data; return data;
}; };
var renderMathInText = function(text, delimiters) { const renderMathInText = function(text, delimiters) {
var data = splitWithDelimiters(text, delimiters); const data = splitWithDelimiters(text, delimiters);
var fragment = document.createDocumentFragment(); const fragment = document.createDocumentFragment();
for (var i = 0; i < data.length; i++) { for (let i = 0; i < data.length; i++) {
if (data[i].type === "text") { if (data[i].type === "text") {
fragment.appendChild(document.createTextNode(data[i].data)); fragment.appendChild(document.createTextNode(data[i].data));
} else { } else {
var span = document.createElement("span"); const span = document.createElement("span");
var math = data[i].data; const math = data[i].data;
try { try {
katex.render(math, span, { katex.render(math, span, {
displayMode: data[i].display, displayMode: data[i].display,
@@ -48,17 +48,17 @@ var renderMathInText = function(text, delimiters) {
return fragment; return fragment;
}; };
var renderElem = function(elem, delimiters, ignoredTags) { const renderElem = function(elem, delimiters, ignoredTags) {
for (var i = 0; i < elem.childNodes.length; i++) { for (let i = 0; i < elem.childNodes.length; i++) {
var childNode = elem.childNodes[i]; const childNode = elem.childNodes[i];
if (childNode.nodeType === 3) { if (childNode.nodeType === 3) {
// Text node // Text node
var frag = renderMathInText(childNode.textContent, delimiters); const frag = renderMathInText(childNode.textContent, delimiters);
i += frag.childNodes.length - 1; i += frag.childNodes.length - 1;
elem.replaceChild(frag, childNode); elem.replaceChild(frag, childNode);
} else if (childNode.nodeType === 1) { } else if (childNode.nodeType === 1) {
// Element node // Element node
var shouldRender = ignoredTags.indexOf( const shouldRender = ignoredTags.indexOf(
childNode.nodeName.toLowerCase()) === -1; childNode.nodeName.toLowerCase()) === -1;
if (shouldRender) { if (shouldRender) {
@@ -69,7 +69,7 @@ var renderElem = function(elem, delimiters, ignoredTags) {
} }
}; };
var defaultOptions = { const defaultOptions = {
delimiters: [ delimiters: [
{left: "$$", right: "$$", display: true}, {left: "$$", right: "$$", display: true},
{left: "\\[", right: "\\]", display: true}, {left: "\\[", right: "\\]", display: true},
@@ -83,11 +83,12 @@ var defaultOptions = {
], ],
}; };
var extend = function(obj) { const extend = function(obj) {
// Adapted from underscore.js' `_.extend`. See LICENSE.txt for license. // Adapted from underscore.js' `_.extend`. See LICENSE.txt for license.
var source; let source;
var prop; let prop;
for (var i = 1, length = arguments.length; i < length; i++) { const length = arguments.length;
for (let i = 1; i < length; i++) {
source = arguments[i]; source = arguments[i];
for (prop in source) { for (prop in source) {
if (Object.prototype.hasOwnProperty.call(source, prop)) { if (Object.prototype.hasOwnProperty.call(source, prop)) {
@@ -98,7 +99,7 @@ var extend = function(obj) {
return obj; return obj;
}; };
var renderMathInElement = function(elem, options) { const renderMathInElement = function(elem, options) {
if (!elem) { if (!elem) {
throw new Error("No element provided to render"); throw new Error("No element provided to render");
} }

View File

@@ -1,14 +1,14 @@
/* eslint no-constant-condition:0 */ /* eslint no-constant-condition:0 */
var findEndOfMath = function(delimiter, text, startIndex) { const findEndOfMath = function(delimiter, text, startIndex) {
// Adapted from // Adapted from
// https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx // https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx
var index = startIndex; let index = startIndex;
var braceLevel = 0; let braceLevel = 0;
var delimLength = delimiter.length; const delimLength = delimiter.length;
while (index < text.length) { while (index < text.length) {
var character = text[index]; const character = text[index];
if (braceLevel <= 0 && if (braceLevel <= 0 &&
text.slice(index, index + delimLength) === delimiter) { text.slice(index, index + delimLength) === delimiter) {
@@ -27,16 +27,16 @@ var findEndOfMath = function(delimiter, text, startIndex) {
return -1; return -1;
}; };
var splitAtDelimiters = function(startData, leftDelim, rightDelim, display) { const splitAtDelimiters = function(startData, leftDelim, rightDelim, display) {
var finalData = []; const finalData = [];
for (var i = 0; i < startData.length; i++) { for (let i = 0; i < startData.length; i++) {
if (startData[i].type === "text") { if (startData[i].type === "text") {
var text = startData[i].data; const text = startData[i].data;
var lookingForLeft = true; let lookingForLeft = true;
var currIndex = 0; let currIndex = 0;
var nextIndex; let nextIndex;
nextIndex = text.indexOf(leftDelim); nextIndex = text.indexOf(leftDelim);
if (nextIndex !== -1) { if (nextIndex !== -1) {

View File

@@ -1,27 +1,27 @@
/* eslint no-console:0, prefer-spread:0 */ /* eslint no-console:0, prefer-spread:0 */
"use strict"; "use strict";
var childProcess = require("child_process"); const childProcess = require("child_process");
var fs = require("fs"); const fs = require("fs");
var http = require("http"); const http = require("http");
var jspngopt = require("jspngopt"); const jspngopt = require("jspngopt");
var net = require("net"); const net = require("net");
var os = require("os"); const os = require("os");
var pako = require("pako"); const pako = require("pako");
var path = require("path"); const path = require("path");
var selenium = require("selenium-webdriver"); const selenium = require("selenium-webdriver");
var firefox = require("selenium-webdriver/firefox"); const firefox = require("selenium-webdriver/firefox");
var app = require("../../server"); const app = require("../../server");
var data = require("../../test/screenshotter/ss_data"); const data = require("../../test/screenshotter/ss_data");
var dstDir = path.normalize( const dstDir = path.normalize(
path.join(__dirname, "..", "..", "test", "screenshotter", "images")); path.join(__dirname, "..", "..", "test", "screenshotter", "images"));
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Process command line arguments // Process command line arguments
var opts = require("nomnom") const opts = require("nomnom")
.option("browser", { .option("browser", {
abbr: "b", abbr: "b",
"default": "firefox", "default": "firefox",
@@ -74,25 +74,25 @@ var opts = require("nomnom")
}) })
.parse(); .parse();
var listOfCases; let listOfCases;
if (opts.include) { if (opts.include) {
listOfCases = opts.include.split(","); listOfCases = opts.include.split(",");
} else { } else {
listOfCases = Object.keys(data); listOfCases = Object.keys(data);
} }
if (opts.exclude) { if (opts.exclude) {
var exclude = opts.exclude.split(","); const exclude = opts.exclude.split(",");
listOfCases = listOfCases.filter(function(key) { listOfCases = listOfCases.filter(function(key) {
return exclude.indexOf(key) === -1; return exclude.indexOf(key) === -1;
}); });
} }
var seleniumURL = opts.seleniumURL; let seleniumURL = opts.seleniumURL;
var seleniumIP = opts.seleniumIP; let seleniumIP = opts.seleniumIP;
var seleniumPort = opts.seleniumPort; let seleniumPort = opts.seleniumPort;
var katexURL = opts.katexURL; let katexURL = opts.katexURL;
var katexIP = opts.katexIP; let katexIP = opts.katexIP;
var katexPort = opts.katexPort; let katexPort = opts.katexPort;
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Work out connection to selenium docker container // Work out connection to selenium docker container
@@ -107,15 +107,15 @@ function check(err) {
} }
function cmd() { function cmd() {
var args = Array.prototype.slice.call(arguments); const args = Array.prototype.slice.call(arguments);
var cmd = args.shift(); const cmd = args.shift();
return childProcess.execFileSync( return childProcess.execFileSync(
cmd, args, { encoding: "utf-8" }).replace(/\n$/, ""); cmd, args, { encoding: "utf-8" }).replace(/\n$/, "");
} }
function guessDockerIPs() { function guessDockerIPs() {
if (process.env.DOCKER_MACHINE_NAME) { if (process.env.DOCKER_MACHINE_NAME) {
var machine = process.env.DOCKER_MACHINE_NAME; const machine = process.env.DOCKER_MACHINE_NAME;
seleniumIP = seleniumIP || cmd("docker-machine", "ip", machine); seleniumIP = seleniumIP || cmd("docker-machine", "ip", machine);
katexIP = katexIP || cmd("docker-machine", "ssh", machine, katexIP = katexIP || cmd("docker-machine", "ssh", machine,
"echo ${SSH_CONNECTION%% *}"); "echo ${SSH_CONNECTION%% *}");
@@ -124,7 +124,7 @@ function guessDockerIPs() {
try { try {
// When using boot2docker, seleniumIP and katexIP are distinct. // When using boot2docker, seleniumIP and katexIP are distinct.
seleniumIP = seleniumIP || cmd("boot2docker", "ip"); seleniumIP = seleniumIP || cmd("boot2docker", "ip");
var config = cmd("boot2docker", "config"); let config = cmd("boot2docker", "config");
config = (/^HostIP = "(.*)"$/m).exec(config); config = (/^HostIP = "(.*)"$/m).exec(config);
if (!config) { if (!config) {
console.error("Failed to find HostIP"); console.error("Failed to find HostIP");
@@ -142,7 +142,7 @@ function guessDockerIPs() {
return; return;
} }
// Native Docker on Linux or remote Docker daemon or similar // Native Docker on Linux or remote Docker daemon or similar
var gatewayIP = cmd("docker", "inspect", const gatewayIP = cmd("docker", "inspect",
"-f", "{{.NetworkSettings.Gateway}}", opts.container); "-f", "{{.NetworkSettings.Gateway}}", opts.container);
seleniumIP = seleniumIP || gatewayIP; seleniumIP = seleniumIP || gatewayIP;
katexIP = katexIP || gatewayIP; katexIP = katexIP || gatewayIP;
@@ -165,22 +165,22 @@ if (seleniumURL) {
} }
process.nextTick(startServer); process.nextTick(startServer);
var attempts = 0; let attempts = 0;
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Start up development server // Start up development server
var devServer = null; let devServer = null;
var minPort = 32768; const minPort = 32768;
var maxPort = 61000; const maxPort = 61000;
function startServer() { function startServer() {
if (katexURL || katexPort) { if (katexURL || katexPort) {
process.nextTick(tryConnect); process.nextTick(tryConnect);
return; return;
} }
var port = Math.floor(Math.random() * (maxPort - minPort)) + minPort; const port = Math.floor(Math.random() * (maxPort - minPort)) + minPort;
var server = http.createServer(app).listen(port); const server = http.createServer(app).listen(port);
server.once("listening", function() { server.once("listening", function() {
devServer = server; devServer = server;
katexPort = port; katexPort = port;
@@ -206,7 +206,7 @@ function tryConnect() {
process.nextTick(buildDriver); process.nextTick(buildDriver);
return; return;
} }
var sock = net.connect({ const sock = net.connect({
host: seleniumIP, host: seleniumIP,
port: +seleniumPort, port: +seleniumPort,
}); });
@@ -225,21 +225,21 @@ function tryConnect() {
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Build the web driver // Build the web driver
var driver; let driver;
function buildDriver() { function buildDriver() {
var builder = new selenium.Builder().forBrowser(opts.browser); const builder = new selenium.Builder().forBrowser(opts.browser);
var ffProfile = new firefox.Profile(); const ffProfile = new firefox.Profile();
ffProfile.setPreference( ffProfile.setPreference(
"browser.startup.homepage_override.mstone", "ignore"); "browser.startup.homepage_override.mstone", "ignore");
ffProfile.setPreference("browser.startup.page", 0); ffProfile.setPreference("browser.startup.page", 0);
var ffOptions = new firefox.Options().setProfile(ffProfile); const ffOptions = new firefox.Options().setProfile(ffProfile);
builder.setFirefoxOptions(ffOptions); builder.setFirefoxOptions(ffOptions);
if (seleniumURL) { if (seleniumURL) {
builder.usingServer(seleniumURL); builder.usingServer(seleniumURL);
} }
driver = builder.build(); driver = builder.build();
driver.manage().timeouts().setScriptTimeout(3000).then(function() { driver.manage().timeouts().setScriptTimeout(3000).then(function() {
var html = '<!DOCTYPE html>' + let html = '<!DOCTYPE html>' +
'<html><head><style type="text/css">html,body{' + '<html><head><style type="text/css">html,body{' +
'width:100%;height:100%;margin:0;padding:0;overflow:hidden;' + 'width:100%;height:100%;margin:0;padding:0;overflow:hidden;' +
'}</style></head><body><p>Test</p></body></html>'; '}</style></head><body><p>Test</p></body></html>';
@@ -253,15 +253,15 @@ function buildDriver() {
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Set the screen size // Set the screen size
var targetW = 1024; const targetW = 1024;
var targetH = 768; const targetH = 768;
function setSize(reqW, reqH) { function setSize(reqW, reqH) {
return driver.manage().window().setSize(reqW, reqH).then(function() { return driver.manage().window().setSize(reqW, reqH).then(function() {
return driver.takeScreenshot(); return driver.takeScreenshot();
}).then(function(img) { }).then(function(img) {
img = imageDimensions(img); img = imageDimensions(img);
var actualW = img.width; const actualW = img.width;
var actualH = img.height; const actualH = img.height;
if (actualW === targetW && actualH === targetH) { if (actualW === targetW && actualH === targetH) {
findHostIP(); findHostIP();
return; return;
@@ -274,7 +274,7 @@ function setSize(reqW, reqH) {
} }
function imageDimensions(img) { function imageDimensions(img) {
var buf = new Buffer(img, "base64"); const buf = new Buffer(img, "base64");
return { return {
buf: buf, buf: buf,
width: buf.readUInt32BE(16), width: buf.readUInt32BE(16),
@@ -312,13 +312,13 @@ function findHostIP() {
}); });
// Next, enumerate all network addresses // Next, enumerate all network addresses
var ips = []; const ips = [];
var devs = os.networkInterfaces(); const devs = os.networkInterfaces();
for (var dev in devs) { for (const dev in devs) {
if (devs.hasOwnProperty(dev)) { if (devs.hasOwnProperty(dev)) {
var addrs = devs[dev]; const addrs = devs[dev];
for (var i = 0; i < addrs.length; ++i) { for (let i = 0; i < addrs.length; ++i) {
var addr = addrs[i].address; let addr = addrs[i].address;
if (/:/.test(addr)) { if (/:/.test(addr)) {
addr = "[" + addr + "]"; addr = "[" + addr + "]";
} }
@@ -329,7 +329,7 @@ function findHostIP() {
console.log("Looking for host IP among " + ips.join(", ")); console.log("Looking for host IP among " + ips.join(", "));
// Load a data: URI document which attempts to contact each of these IPs // Load a data: URI document which attempts to contact each of these IPs
var html = "<!doctype html>\n<html><body>\n"; let html = "<!doctype html>\n<html><body>\n";
html += ips.map(function(ip) { html += ips.map(function(ip) {
return '<script src="http://' + ip + ':' + katexPort + return '<script src="http://' + ip + ':' + katexPort +
'/ss-connect.js?ip=' + encodeURIComponent(ip) + '/ss-connect.js?ip=' + encodeURIComponent(ip) +
@@ -343,17 +343,17 @@ function findHostIP() {
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Take the screenshots // Take the screenshots
var countdown = listOfCases.length; let countdown = listOfCases.length;
var exitStatus = 0; let exitStatus = 0;
var listOfFailed = []; const listOfFailed = [];
function takeScreenshots() { function takeScreenshots() {
listOfCases.forEach(takeScreenshot); listOfCases.forEach(takeScreenshot);
} }
function takeScreenshot(key) { function takeScreenshot(key) {
var itm = data[key]; const itm = data[key];
if (!itm) { if (!itm) {
console.error("Test case " + key + " not known!"); console.error("Test case " + key + " not known!");
listOfFailed.push(key); listOfFailed.push(key);
@@ -364,14 +364,14 @@ function takeScreenshot(key) {
return; return;
} }
var file = path.join(dstDir, key + "-" + opts.browser + ".png"); let file = path.join(dstDir, key + "-" + opts.browser + ".png");
var retry = 0; let retry = 0;
var loadExpected = null; let loadExpected = null;
if (opts.verify) { if (opts.verify) {
loadExpected = promisify(fs.readFile, file); loadExpected = promisify(fs.readFile, file);
} }
var url = katexURL + "test/screenshotter/test.html?" + itm.query; const url = katexURL + "test/screenshotter/test.html?" + itm.query;
driver.get(url); driver.get(url);
if (opts.wait) { if (opts.wait) {
browserSideWait(1000 * opts.wait); browserSideWait(1000 * opts.wait);
@@ -398,10 +398,10 @@ function takeScreenshot(key) {
loadExpected = promisify(fs.readFile, file); loadExpected = promisify(fs.readFile, file);
} }
} }
var opt = new jspngopt.Optimizer({ const opt = new jspngopt.Optimizer({
pako: pako, pako: pako,
}); });
var buf = opt.bufferSync(img.buf); const buf = opt.bufferSync(img.buf);
if (loadExpected) { if (loadExpected) {
return loadExpected.then(function(expected) { return loadExpected.then(function(expected) {
if (!buf.equals(expected)) { if (!buf.equals(expected)) {
@@ -451,8 +451,8 @@ function browserSideWait(milliseconds) {
// Second and later arguments are passed to the function named in the // Second and later arguments are passed to the function named in the
// first argument, and a callback is added as last argument. // first argument, and a callback is added as last argument.
function promisify(f) { function promisify(f) {
var args = Array.prototype.slice.call(arguments, 1); const args = Array.prototype.slice.call(arguments, 1);
var deferred = new selenium.promise.Deferred(); const deferred = new selenium.promise.Deferred();
args.push(function(err, val) { args.push(function(err, val) {
if (err) { if (err) {
deferred.reject(err); deferred.reject(err);

View File

@@ -2,22 +2,22 @@
/* eslint-disable no-console */ /* eslint-disable no-console */
"use strict"; "use strict";
var childProcess = require("child_process"); const childProcess = require("child_process");
var fs = require("fs"); const fs = require("fs");
var path = require("path"); const path = require("path");
var Q = require("q"); // To debug, pass Q_DEBUG=1 in the environment const Q = require("q"); // To debug, pass Q_DEBUG=1 in the environment
var pngparse = require("pngparse"); const pngparse = require("pngparse");
var fft = require("ndarray-fft"); const fft = require("ndarray-fft");
var ndarray = require("ndarray-fft/node_modules/ndarray"); const ndarray = require("ndarray-fft/node_modules/ndarray");
var data = require("../../test/screenshotter/ss_data"); const data = require("../../test/screenshotter/ss_data");
// Adapt node functions to Q promises // Adapt node functions to Q promises
var readFile = Q.denodeify(fs.readFile); const readFile = Q.denodeify(fs.readFile);
var writeFile = Q.denodeify(fs.writeFile); const writeFile = Q.denodeify(fs.writeFile);
var mkdir = Q.denodeify(fs.mkdir); const mkdir = Q.denodeify(fs.mkdir);
var todo; let todo;
if (process.argv.length > 2) { if (process.argv.length > 2) {
todo = process.argv.slice(2); todo = process.argv.slice(2);
} else { } else {
@@ -27,23 +27,23 @@ if (process.argv.length > 2) {
} }
// Dimensions used when we do the FFT-based alignment computation // Dimensions used when we do the FFT-based alignment computation
var alignWidth = 2048; // should be at least twice the width resp. height const alignWidth = 2048; // should be at least twice the width resp. height
var alignHeight = 2048; // of the screenshots, and a power of two. const alignHeight = 2048; // of the screenshots, and a power of two.
// Compute required resolution to match test.html. 16px default font, // Compute required resolution to match test.html. 16px default font,
// scaled to 4em in test.html, and to 1.21em in katex.css. Corresponding // scaled to 4em in test.html, and to 1.21em in katex.css. Corresponding
// LaTeX font size is 10pt. There are 72.27pt per inch. // LaTeX font size is 10pt. There are 72.27pt per inch.
var pxPerEm = 16 * 4 * 1.21; const pxPerEm = 16 * 4 * 1.21;
var pxPerPt = pxPerEm / 10; const pxPerPt = pxPerEm / 10;
var dpi = pxPerPt * 72.27; const dpi = pxPerPt * 72.27;
var tmpDir = "/tmp/texcmp"; const tmpDir = "/tmp/texcmp";
var ssDir = path.normalize( const ssDir = path.normalize(
path.join(__dirname, "..", "..", "test", "screenshotter")); path.join(__dirname, "..", "..", "test", "screenshotter"));
var imagesDir = path.join(ssDir, "images"); const imagesDir = path.join(ssDir, "images");
var teximgDir = path.join(ssDir, "tex"); const teximgDir = path.join(ssDir, "tex");
var diffDir = path.join(ssDir, "diff"); const diffDir = path.join(ssDir, "diff");
var template; let template;
Q.all([ Q.all([
readFile(path.join(ssDir, "test.tex"), "utf-8"), readFile(path.join(ssDir, "test.tex"), "utf-8"),
@@ -58,8 +58,8 @@ Q.all([
// Process a single test case: rasterize, then create diff // Process a single test case: rasterize, then create diff
function processTestCase(key) { function processTestCase(key) {
var itm = data[key]; const itm = data[key];
var tex = "$" + itm.tex + "$"; let tex = "$" + itm.tex + "$";
if (itm.display) { if (itm.display) {
tex = "\\[" + itm.tex + "\\]"; tex = "\\[" + itm.tex + "\\]";
} }
@@ -70,14 +70,14 @@ function processTestCase(key) {
tex = tex + itm.post.replace("<br>", "\\\\"); tex = tex + itm.post.replace("<br>", "\\\\");
} }
tex = template.replace(/\$.*\$/, tex.replace(/\$/g, "$$$$")); tex = template.replace(/\$.*\$/, tex.replace(/\$/g, "$$$$"));
var texFile = path.join(tmpDir, key + ".tex"); const texFile = path.join(tmpDir, key + ".tex");
var pdfFile = path.join(tmpDir, key + ".pdf"); const pdfFile = path.join(tmpDir, key + ".pdf");
var pngFile = path.join(teximgDir, key + "-pdflatex.png"); const pngFile = path.join(teximgDir, key + "-pdflatex.png");
var browserFile = path.join(imagesDir, key + "-firefox.png"); const browserFile = path.join(imagesDir, key + "-firefox.png");
var diffFile = path.join(diffDir, key + ".png"); const diffFile = path.join(diffDir, key + ".png");
// Step 1: write key.tex file // Step 1: write key.tex file
var fftLatex = writeFile(texFile, tex).then(function() { const fftLatex = writeFile(texFile, tex).then(function() {
// Step 2: call "pdflatex key" to create key.pdf // Step 2: call "pdflatex key" to create key.pdf
return execFile("pdflatex", [ return execFile("pdflatex", [
"-interaction", "nonstopmode", key, "-interaction", "nonstopmode", key,
@@ -95,24 +95,24 @@ function processTestCase(key) {
return readPNG(pngFile).then(fftImage); return readPNG(pngFile).then(fftImage);
}); });
// Step 5: apply FFT to reference image as well // Step 5: apply FFT to reference image as well
var fftBrowser = readPNG(browserFile).then(fftImage); const fftBrowser = readPNG(browserFile).then(fftImage);
return Q.all([fftBrowser, fftLatex]).spread(function(browser, latex) { return Q.all([fftBrowser, fftLatex]).spread(function(browser, latex) {
// Now we have the FFT result from both // Now we have the FFT result from both
// Step 6: find alignment which maximizes overlap. // Step 6: find alignment which maximizes overlap.
// This uses a FFT-based correlation computation. // This uses a FFT-based correlation computation.
var x; let x;
var y; let y;
var real = createMatrix(); const real = createMatrix();
var imag = createMatrix(); const imag = createMatrix();
// Step 6a: (real + i*imag) = latex * conjugate(browser) // Step 6a: (real + i*imag) = latex * conjugate(browser)
for (y = 0; y < alignHeight; ++y) { for (y = 0; y < alignHeight; ++y) {
for (x = 0; x < alignWidth; ++x) { for (x = 0; x < alignWidth; ++x) {
var br = browser.real.get(y, x); const br = browser.real.get(y, x);
var bi = browser.imag.get(y, x); const bi = browser.imag.get(y, x);
var lr = latex.real.get(y, x); const lr = latex.real.get(y, x);
var li = latex.imag.get(y, x); const li = latex.imag.get(y, x);
real.set(y, x, br * lr + bi * li); real.set(y, x, br * lr + bi * li);
imag.set(y, x, br * li - bi * lr); imag.set(y, x, br * li - bi * lr);
} }
@@ -122,14 +122,14 @@ function processTestCase(key) {
fft(-1, real, imag); fft(-1, real, imag);
// Step 6c: find position where the (squared) absolute value is maximal // Step 6c: find position where the (squared) absolute value is maximal
var offsetX = 0; let offsetX = 0;
var offsetY = 0; let offsetY = 0;
var maxSquaredNorm = -1; // any result is greater than initial value let maxSquaredNorm = -1; // any result is greater than initial value
for (y = 0; y < alignHeight; ++y) { for (y = 0; y < alignHeight; ++y) {
for (x = 0; x < alignWidth; ++x) { for (x = 0; x < alignWidth; ++x) {
var or = real.get(y, x); const or = real.get(y, x);
var oi = imag.get(y, x); const oi = imag.get(y, x);
var squaredNorm = or * or + oi * oi; const squaredNorm = or * or + oi * oi;
if (maxSquaredNorm < squaredNorm) { if (maxSquaredNorm < squaredNorm) {
maxSquaredNorm = squaredNorm; maxSquaredNorm = squaredNorm;
offsetX = x; offsetX = x;
@@ -148,12 +148,12 @@ function processTestCase(key) {
console.log("Positioned " + key + ": " + offsetX + ", " + offsetY); console.log("Positioned " + key + ": " + offsetX + ", " + offsetY);
// Step 7: use these offsets to compute difference illustration // Step 7: use these offsets to compute difference illustration
var bx = Math.max(offsetX, 0); // browser left padding const bx = Math.max(offsetX, 0); // browser left padding
var by = Math.max(offsetY, 0); // browser top padding const by = Math.max(offsetY, 0); // browser top padding
var lx = Math.max(-offsetX, 0); // latex left padding const lx = Math.max(-offsetX, 0); // latex left padding
var ly = Math.max(-offsetY, 0); // latex top padding const ly = Math.max(-offsetY, 0); // latex top padding
var uw = Math.max(browser.width + bx, latex.width + lx); // union width const uw = Math.max(browser.width + bx, latex.width + lx); // union w.
var uh = Math.max(browser.height + by, latex.height + ly); // u. height const uh = Math.max(browser.height + by, latex.height + ly); // u. h.
return execFile("convert", [ return execFile("convert", [
// First image: latex rendering, converted to grayscale and padded // First image: latex rendering, converted to grayscale and padded
"(", pngFile, "-grayscale", "Rec709Luminance", "(", pngFile, "-grayscale", "Rec709Luminance",
@@ -187,7 +187,7 @@ function ensureDir(dir) {
// Execute a given command, and return a promise to its output. // Execute a given command, and return a promise to its output.
// Don't denodeify here, since fail branch needs access to stderr. // Don't denodeify here, since fail branch needs access to stderr.
function execFile(cmd, args, opts) { function execFile(cmd, args, opts) {
var deferred = Q.defer(); const deferred = Q.defer();
childProcess.execFile(cmd, args, opts, function(err, stdout, stderr) { childProcess.execFile(cmd, args, opts, function(err, stdout, stderr) {
if (err) { if (err) {
console.error("Error executing " + cmd + " " + args.join(" ")); console.error("Error executing " + cmd + " " + args.join(" "));
@@ -204,9 +204,9 @@ function execFile(cmd, args, opts) {
// Read given file and parse it as a PNG file. // Read given file and parse it as a PNG file.
function readPNG(file) { function readPNG(file) {
var deferred = Q.defer(); const deferred = Q.defer();
var onerror = deferred.reject.bind(deferred); const onerror = deferred.reject.bind(deferred);
var stream = fs.createReadStream(file); const stream = fs.createReadStream(file);
stream.on("error", onerror); stream.on("error", onerror);
pngparse.parseStream(stream, function(err, image) { pngparse.parseStream(stream, function(err, image) {
if (err) { if (err) {
@@ -221,20 +221,19 @@ function readPNG(file) {
// Take a parsed image data structure and apply FFT transformation to it // Take a parsed image data structure and apply FFT transformation to it
function fftImage(image) { function fftImage(image) {
var real = createMatrix(); const real = createMatrix();
var imag = createMatrix(); const imag = createMatrix();
var idx = 0; let idx = 0;
var nchan = image.channels; const nchan = image.channels;
var alphachan = 1 - (nchan % 2); const alphachan = 1 - (nchan % 2);
var colorchan = nchan - alphachan; const colorchan = nchan - alphachan;
for (var y = 0; y < image.height; ++y) { for (let y = 0; y < image.height; ++y) {
for (var x = 0; x < image.width; ++x) { for (let x = 0; x < image.width; ++x) {
var c; let v = 0;
var v = 0; for (let c = 0; c < colorchan; ++c) {
for (c = 0; c < colorchan; ++c) {
v += 255 - image.data[idx++]; v += 255 - image.data[idx++];
} }
for (c = 0; c < alphachan; ++c) { for (let c = 0; c < alphachan; ++c) {
v += image.data[idx++]; v += image.data[idx++];
} }
real.set(y, x, v); real.set(y, x, v);
@@ -251,6 +250,6 @@ function fftImage(image) {
// Create a new matrix of preconfigured dimensions, initialized to zero // Create a new matrix of preconfigured dimensions, initialized to zero
function createMatrix() { function createMatrix() {
var array = new Float64Array(alignWidth * alignHeight); const array = new Float64Array(alignWidth * alignHeight);
return new ndarray(array, [alignWidth, alignHeight]); return new ndarray(array, [alignWidth, alignHeight]);
} }

View File

@@ -7,24 +7,24 @@
* errors in the expression, or errors in javascript handling. * errors in the expression, or errors in javascript handling.
*/ */
var ParseError = require("./src/ParseError"); const ParseError = require("./src/ParseError");
var Settings = require("./src/Settings"); const Settings = require("./src/Settings");
var buildTree = require("./src/buildTree"); const buildTree = require("./src/buildTree");
var parseTree = require("./src/parseTree"); const parseTree = require("./src/parseTree");
var utils = require("./src/utils"); const utils = require("./src/utils");
/** /**
* Parse and build an expression, and place that expression in the DOM node * Parse and build an expression, and place that expression in the DOM node
* given. * given.
*/ */
var render = function(expression, baseNode, options) { let render = function(expression, baseNode, options) {
utils.clearNode(baseNode); utils.clearNode(baseNode);
var settings = new Settings(options); const settings = new Settings(options);
var tree = parseTree(expression, settings); const tree = parseTree(expression, settings);
var node = buildTree(tree, expression, settings).toNode(); const node = buildTree(tree, expression, settings).toNode();
baseNode.appendChild(node); baseNode.appendChild(node);
}; };
@@ -46,18 +46,18 @@ if (typeof document !== "undefined") {
/** /**
* Parse and build an expression, and return the markup for that. * Parse and build an expression, and return the markup for that.
*/ */
var renderToString = function(expression, options) { const renderToString = function(expression, options) {
var settings = new Settings(options); const settings = new Settings(options);
var tree = parseTree(expression, settings); const tree = parseTree(expression, settings);
return buildTree(tree, expression, settings).toMarkup(); return buildTree(tree, expression, settings).toMarkup();
}; };
/** /**
* Parse an expression and return the parse tree. * Parse an expression and return the parse tree.
*/ */
var generateParseTree = function(expression, options) { const generateParseTree = function(expression, options) {
var settings = new Settings(options); const settings = new Settings(options);
return parseTree(expression, settings); return parseTree(expression, settings);
}; };

View File

@@ -1,14 +1,14 @@
/* eslint no-console:0 */ /* eslint no-console:0 */
var fs = require("fs"); const fs = require("fs");
var path = require("path"); const path = require("path");
var babelify = require("babelify"); const babelify = require("babelify");
var browserify = require("browserify"); const browserify = require("browserify");
var express = require("express"); const express = require("express");
var glob = require("glob"); const glob = require("glob");
var less = require("less"); const less = require("less");
var app = express(); const app = express();
if (require.main === module) { if (require.main === module) {
app.use(require("morgan")( app.use(require("morgan")(
@@ -17,7 +17,7 @@ if (require.main === module) {
var serveBrowserified = function(file, standaloneName) { var serveBrowserified = function(file, standaloneName) {
return function(req, res, next) { return function(req, res, next) {
var files; let files;
if (Array.isArray(file)) { if (Array.isArray(file)) {
files = file.map(function(f) { return path.join(__dirname, f); }); files = file.map(function(f) { return path.join(__dirname, f); });
} else if (file.indexOf("*") !== -1) { } else if (file.indexOf("*") !== -1) {
@@ -26,16 +26,16 @@ var serveBrowserified = function(file, standaloneName) {
files = [path.join(__dirname, file)]; files = [path.join(__dirname, file)];
} }
var options = { const options = {
transform: [babelify] transform: [babelify]
}; };
if (standaloneName) { if (standaloneName) {
options.standalone = standaloneName; options.standalone = standaloneName;
} }
var b = browserify(files, options); const b = browserify(files, options);
var stream = b.bundle(); const stream = b.bundle();
var body = ""; let body = "";
stream.on("data", function(s) { body += s; }); stream.on("data", function(s) { body += s; });
stream.on("error", function(e) { next(e); }); stream.on("error", function(e) { next(e); });
stream.on("end", function() { stream.on("end", function() {
@@ -59,7 +59,7 @@ app.get("/contrib/auto-render/auto-render.js",
"renderMathInElement")); "renderMathInElement"));
app.get("/katex.css", function(req, res, next) { app.get("/katex.css", function(req, res, next) {
var lessfile = path.join(__dirname, "static", "katex.less"); const lessfile = path.join(__dirname, "static", "katex.less");
fs.readFile(lessfile, {encoding: "utf8"}, function(err, data) { fs.readFile(lessfile, {encoding: "utf8"}, function(err, data) {
if (err) { if (err) {
next(err); next(err);

View File

@@ -11,9 +11,9 @@
* kinds. * kinds.
*/ */
var matchAt = require("match-at"); const matchAt = require("match-at");
var ParseError = require("./ParseError"); const ParseError = require("./ParseError");
// The main lexer class // The main lexer class
function Lexer(input) { function Lexer(input) {
@@ -76,7 +76,7 @@ Token.prototype.range = function(endToken, text) {
* If there is no matching function or symbol definition, the Parser will * If there is no matching function or symbol definition, the Parser will
* still reject the input. * still reject the input.
*/ */
var tokenRegex = new RegExp( const tokenRegex = new RegExp(
"([ \r\n\t]+)|" + // whitespace "([ \r\n\t]+)|" + // whitespace
"([!-\\[\\]-\u2027\u202A-\uD7FF\uF900-\uFFFF]" + // single codepoint "([!-\\[\\]-\u2027\u202A-\uD7FF\uF900-\uFFFF]" + // single codepoint
"|[\uD800-\uDBFF][\uDC00-\uDFFF]" + // surrogate pair "|[\uD800-\uDBFF][\uDC00-\uDFFF]" + // surrogate pair
@@ -88,21 +88,21 @@ var tokenRegex = new RegExp(
* This function lexes a single token. * This function lexes a single token.
*/ */
Lexer.prototype.lex = function() { Lexer.prototype.lex = function() {
var input = this.input; const input = this.input;
var pos = this.pos; const pos = this.pos;
if (pos === input.length) { if (pos === input.length) {
return new Token("EOF", pos, pos, this); return new Token("EOF", pos, pos, this);
} }
var match = matchAt(tokenRegex, input, pos); const match = matchAt(tokenRegex, input, pos);
if (match === null) { if (match === null) {
throw new ParseError( throw new ParseError(
"Unexpected character: '" + input[pos] + "'", "Unexpected character: '" + input[pos] + "'",
new Token(input[pos], pos, pos + 1, this)); new Token(input[pos], pos, pos + 1, this));
} }
var text = match[2] || " "; const text = match[2] || " ";
var start = this.pos; const start = this.pos;
this.pos += match[0].length; this.pos += match[0].length;
var end = this.pos; const end = this.pos;
return new Token(text, start, end, this); return new Token(text, start, end, this);
}; };

View File

@@ -3,7 +3,7 @@
* until only non-macro tokens remain. * until only non-macro tokens remain.
*/ */
var Lexer = require("./Lexer"); const Lexer = require("./Lexer");
function MacroExpander(input, macros) { function MacroExpander(input, macros) {
this.lexer = new Lexer(input); this.lexer = new Lexer(input);
@@ -20,16 +20,16 @@ MacroExpander.prototype.nextToken = function() {
if (this.stack.length === 0) { if (this.stack.length === 0) {
this.stack.push(this.lexer.lex()); this.stack.push(this.lexer.lex());
} }
var topToken = this.stack.pop(); const topToken = this.stack.pop();
var name = topToken.text; const name = topToken.text;
if (!(name.charAt(0) === "\\" && this.macros.hasOwnProperty(name))) { if (!(name.charAt(0) === "\\" && this.macros.hasOwnProperty(name))) {
return topToken; return topToken;
} }
var expansion = this.macros[name]; let expansion = this.macros[name];
if (typeof expansion === "string") { if (typeof expansion === "string") {
var bodyLexer = new Lexer(expansion); const bodyLexer = new Lexer(expansion);
expansion = []; expansion = [];
var tok = bodyLexer.lex(); let tok = bodyLexer.lex();
while (tok.text !== "EOF") { while (tok.text !== "EOF") {
expansion.push(tok); expansion.push(tok);
tok = bodyLexer.lex(); tok = bodyLexer.lex();
@@ -43,7 +43,7 @@ MacroExpander.prototype.nextToken = function() {
MacroExpander.prototype.get = function(ignoreSpace) { MacroExpander.prototype.get = function(ignoreSpace) {
this.discardedWhiteSpace = []; this.discardedWhiteSpace = [];
var token = this.nextToken(); let token = this.nextToken();
if (ignoreSpace) { if (ignoreSpace) {
while (token.text === " ") { while (token.text === " ") {
this.discardedWhiteSpace.push(token); this.discardedWhiteSpace.push(token);

View File

@@ -39,7 +39,7 @@ function Options(data) {
* from "extension" will be copied to the new options object. * from "extension" will be copied to the new options object.
*/ */
Options.prototype.extend = function(extension) { Options.prototype.extend = function(extension) {
var data = { const data = {
style: this.style, style: this.style,
size: this.size, size: this.size,
color: this.color, color: this.color,
@@ -49,7 +49,7 @@ Options.prototype.extend = function(extension) {
font: this.font, font: this.font,
}; };
for (var key in extension) { for (const key in extension) {
if (extension.hasOwnProperty(key)) { if (extension.hasOwnProperty(key)) {
data[key] = extension[key]; data[key] = extension[key];
} }
@@ -115,7 +115,7 @@ Options.prototype.reset = function() {
* A map of color names to CSS colors. * A map of color names to CSS colors.
* TODO(emily): Remove this when we have real macros * TODO(emily): Remove this when we have real macros
*/ */
var colorMap = { const colorMap = {
"katex-blue": "#6495ed", "katex-blue": "#6495ed",
"katex-orange": "#ffa500", "katex-orange": "#ffa500",
"katex-pink": "#ff00af", "katex-pink": "#ff00af",

View File

@@ -10,15 +10,15 @@
* @param {(Token|ParseNode)=} token An object providing position information * @param {(Token|ParseNode)=} token An object providing position information
*/ */
function ParseError(message, token) { function ParseError(message, token) {
var error = "KaTeX parse error: " + message; let error = "KaTeX parse error: " + message;
var start; let start;
var end; let end;
if (token && token.lexer && token.start <= token.end) { if (token && token.lexer && token.start <= token.end) {
// If we have the input and a position, make the error a bit fancier // If we have the input and a position, make the error a bit fancier
// Get the input // Get the input
var input = token.lexer.input; const input = token.lexer.input;
// Prepend some information // Prepend some information
start = token.start; start = token.start;
@@ -30,16 +30,16 @@ function ParseError(message, token) {
} }
// Underline token in question using combining underscores // Underline token in question using combining underscores
var underlined = input.slice(start, end).replace(/[^]/g, "$&\u0332"); const underlined = input.slice(start, end).replace(/[^]/g, "$&\u0332");
// Extract some context from the input and add it to the error // Extract some context from the input and add it to the error
var left; let left;
if (start > 15) { if (start > 15) {
left = "…" + input.slice(start - 15, start); left = "…" + input.slice(start - 15, start);
} else { } else {
left = input.slice(0, start); left = input.slice(0, start);
} }
var right; let right;
if (end + 15 < input.length) { if (end + 15 < input.length) {
right = input.slice(end, end + 15) + "…"; right = input.slice(end, end + 15) + "…";
} else { } else {
@@ -50,7 +50,7 @@ function ParseError(message, token) {
// Some hackery to make ParseError a prototype of Error // Some hackery to make ParseError a prototype of Error
// See http://stackoverflow.com/a/8460753 // See http://stackoverflow.com/a/8460753
var self = new Error(error); const self = new Error(error);
self.name = "ParseError"; self.name = "ParseError";
self.__proto__ = ParseError.prototype; self.__proto__ = ParseError.prototype;

View File

@@ -1,13 +1,13 @@
/* eslint no-constant-condition:0 */ /* eslint no-constant-condition:0 */
var functions = require("./functions"); const functions = require("./functions");
var environments = require("./environments"); const environments = require("./environments");
var MacroExpander = require("./MacroExpander"); const MacroExpander = require("./MacroExpander");
var symbols = require("./symbols"); const symbols = require("./symbols");
var utils = require("./utils"); const utils = require("./utils");
var cjkRegex = require("./unicodeRegexes").cjkRegex; const cjkRegex = require("./unicodeRegexes").cjkRegex;
var parseData = require("./parseData"); const parseData = require("./parseData");
var ParseError = require("./ParseError"); const ParseError = require("./ParseError");
/** /**
* This file contains the parser used to parse out a TeX expression from the * This file contains the parser used to parse out a TeX expression from the
@@ -56,7 +56,7 @@ function Parser(input, settings) {
this.leftrightDepth = 0; this.leftrightDepth = 0;
} }
var ParseNode = parseData.ParseNode; const ParseNode = parseData.ParseNode;
/** /**
* An initial function (without its arguments), or an argument to a function. * An initial function (without its arguments), or an argument to a function.
@@ -111,7 +111,7 @@ Parser.prototype.parse = function() {
// Try to parse the input // Try to parse the input
this.mode = "math"; this.mode = "math";
this.consume(); this.consume();
var parse = this.parseInput(); const parse = this.parseInput();
return parse; return parse;
}; };
@@ -120,13 +120,13 @@ Parser.prototype.parse = function() {
*/ */
Parser.prototype.parseInput = function() { Parser.prototype.parseInput = function() {
// Parse an expression // Parse an expression
var expression = this.parseExpression(false); const expression = this.parseExpression(false);
// If we succeeded, make sure there's an EOF at the end // If we succeeded, make sure there's an EOF at the end
this.expect("EOF", false); this.expect("EOF", false);
return expression; return expression;
}; };
var endOfExpression = ["}", "\\end", "\\right", "&", "\\\\", "\\cr"]; const endOfExpression = ["}", "\\end", "\\right", "&", "\\\\", "\\cr"];
/** /**
* Parses an "expression", which is a list of atoms. * Parses an "expression", which is a list of atoms.
@@ -142,11 +142,11 @@ var endOfExpression = ["}", "\\end", "\\right", "&", "\\\\", "\\cr"];
* @return {ParseNode} * @return {ParseNode}
*/ */
Parser.prototype.parseExpression = function(breakOnInfix, breakOnTokenText) { Parser.prototype.parseExpression = function(breakOnInfix, breakOnTokenText) {
var body = []; const body = [];
// Keep adding atoms to the body until we can't parse any more atoms (either // Keep adding atoms to the body until we can't parse any more atoms (either
// we reached the end, a }, or a \right) // we reached the end, a }, or a \right)
while (true) { while (true) {
var lex = this.nextToken; const lex = this.nextToken;
if (endOfExpression.indexOf(lex.text) !== -1) { if (endOfExpression.indexOf(lex.text) !== -1) {
break; break;
} }
@@ -156,10 +156,10 @@ Parser.prototype.parseExpression = function(breakOnInfix, breakOnTokenText) {
if (breakOnInfix && functions[lex.text] && functions[lex.text].infix) { if (breakOnInfix && functions[lex.text] && functions[lex.text].infix) {
break; break;
} }
var atom = this.parseAtom(); const atom = this.parseAtom();
if (!atom) { if (!atom) {
if (!this.settings.throwOnError && lex.text[0] === "\\") { if (!this.settings.throwOnError && lex.text[0] === "\\") {
var errorNode = this.handleUnsupportedCmd(); const errorNode = this.handleUnsupportedCmd();
body.push(errorNode); body.push(errorNode);
continue; continue;
} }
@@ -181,11 +181,11 @@ Parser.prototype.parseExpression = function(breakOnInfix, breakOnTokenText) {
* @returns {Array} * @returns {Array}
*/ */
Parser.prototype.handleInfixNodes = function(body) { Parser.prototype.handleInfixNodes = function(body) {
var overIndex = -1; let overIndex = -1;
var funcName; let funcName;
for (var i = 0; i < body.length; i++) { for (let i = 0; i < body.length; i++) {
var node = body[i]; const node = body[i];
if (node.type === "infix") { if (node.type === "infix") {
if (overIndex !== -1) { if (overIndex !== -1) {
throw new ParseError( throw new ParseError(
@@ -198,11 +198,11 @@ Parser.prototype.handleInfixNodes = function(body) {
} }
if (overIndex !== -1) { if (overIndex !== -1) {
var numerNode; let numerNode;
var denomNode; let denomNode;
var numerBody = body.slice(0, overIndex); const numerBody = body.slice(0, overIndex);
var denomBody = body.slice(overIndex + 1); const denomBody = body.slice(overIndex + 1);
if (numerBody.length === 1 && numerBody[0].type === "ordgroup") { if (numerBody.length === 1 && numerBody[0].type === "ordgroup") {
numerNode = numerBody[0]; numerNode = numerBody[0];
@@ -216,7 +216,7 @@ Parser.prototype.handleInfixNodes = function(body) {
denomNode = new ParseNode("ordgroup", denomBody, this.mode); denomNode = new ParseNode("ordgroup", denomBody, this.mode);
} }
var value = this.callFunction( const value = this.callFunction(
funcName, [numerNode, denomNode], null); funcName, [numerNode, denomNode], null);
return [new ParseNode(value.type, value, this.mode)]; return [new ParseNode(value.type, value, this.mode)];
} else { } else {
@@ -225,16 +225,16 @@ Parser.prototype.handleInfixNodes = function(body) {
}; };
// The greediness of a superscript or subscript // The greediness of a superscript or subscript
var SUPSUB_GREEDINESS = 1; const SUPSUB_GREEDINESS = 1;
/** /**
* Handle a subscript or superscript with nice errors. * Handle a subscript or superscript with nice errors.
*/ */
Parser.prototype.handleSupSubscript = function(name) { Parser.prototype.handleSupSubscript = function(name) {
var symbolToken = this.nextToken; const symbolToken = this.nextToken;
var symbol = symbolToken.text; const symbol = symbolToken.text;
this.consume(); this.consume();
var group = this.parseGroup(); const group = this.parseGroup();
if (!group) { if (!group) {
if (!this.settings.throwOnError && this.nextToken.text[0] === "\\") { if (!this.settings.throwOnError && this.nextToken.text[0] === "\\") {
@@ -248,7 +248,7 @@ Parser.prototype.handleSupSubscript = function(name) {
} else if (group.isFunction) { } else if (group.isFunction) {
// ^ and _ have a greediness, so handle interactions with functions' // ^ and _ have a greediness, so handle interactions with functions'
// greediness // greediness
var funcGreediness = functions[group.result].greediness; const funcGreediness = functions[group.result].greediness;
if (funcGreediness > SUPSUB_GREEDINESS) { if (funcGreediness > SUPSUB_GREEDINESS) {
return this.parseFunction(group); return this.parseFunction(group);
} else { } else {
@@ -266,14 +266,14 @@ Parser.prototype.handleSupSubscript = function(name) {
* contained within a color node whose color is determined by errorColor * contained within a color node whose color is determined by errorColor
*/ */
Parser.prototype.handleUnsupportedCmd = function() { Parser.prototype.handleUnsupportedCmd = function() {
var text = this.nextToken.text; const text = this.nextToken.text;
var textordArray = []; const textordArray = [];
for (var i = 0; i < text.length; i++) { for (let i = 0; i < text.length; i++) {
textordArray.push(new ParseNode("textord", text[i], "text")); textordArray.push(new ParseNode("textord", text[i], "text"));
} }
var textNode = new ParseNode( const textNode = new ParseNode(
"text", "text",
{ {
body: textordArray, body: textordArray,
@@ -281,7 +281,7 @@ Parser.prototype.handleUnsupportedCmd = function() {
}, },
this.mode); this.mode);
var colorNode = new ParseNode( const colorNode = new ParseNode(
"color", "color",
{ {
color: this.settings.errorColor, color: this.settings.errorColor,
@@ -302,7 +302,7 @@ Parser.prototype.handleUnsupportedCmd = function() {
Parser.prototype.parseAtom = function() { Parser.prototype.parseAtom = function() {
// The body of an atom is an implicit group, so that things like // The body of an atom is an implicit group, so that things like
// \left(x\right)^2 work correctly. // \left(x\right)^2 work correctly.
var base = this.parseImplicitGroup(); const base = this.parseImplicitGroup();
// In text mode, we don't have superscripts or subscripts // In text mode, we don't have superscripts or subscripts
if (this.mode === "text") { if (this.mode === "text") {
@@ -311,11 +311,11 @@ Parser.prototype.parseAtom = function() {
// Note that base may be empty (i.e. null) at this point. // Note that base may be empty (i.e. null) at this point.
var superscript; let superscript;
var subscript; let subscript;
while (true) { while (true) {
// Lex the first token // Lex the first token
var lex = this.nextToken; const lex = this.nextToken;
if (lex.text === "\\limits" || lex.text === "\\nolimits") { if (lex.text === "\\limits" || lex.text === "\\nolimits") {
// We got a limit control // We got a limit control
@@ -324,7 +324,7 @@ Parser.prototype.parseAtom = function() {
"Limit controls must follow a math operator", "Limit controls must follow a math operator",
lex); lex);
} else { } else {
var limits = lex.text === "\\limits"; const limits = lex.text === "\\limits";
base.value.limits = limits; base.value.limits = limits;
base.value.alwaysHandleSupSub = true; base.value.alwaysHandleSupSub = true;
} }
@@ -343,10 +343,10 @@ Parser.prototype.parseAtom = function() {
subscript = this.handleSupSubscript("subscript"); subscript = this.handleSupSubscript("subscript");
} else if (lex.text === "'") { } else if (lex.text === "'") {
// We got a prime // We got a prime
var prime = new ParseNode("textord", "\\prime", this.mode); const prime = new ParseNode("textord", "\\prime", this.mode);
// Many primes can be grouped together, so we handle this here // Many primes can be grouped together, so we handle this here
var primes = [prime]; const primes = [prime];
this.consume(); this.consume();
// Keep lexing tokens until we get something that's not a prime // Keep lexing tokens until we get something that's not a prime
while (this.nextToken.text === "'") { while (this.nextToken.text === "'") {
@@ -376,13 +376,13 @@ Parser.prototype.parseAtom = function() {
}; };
// A list of the size-changing functions, for use in parseImplicitGroup // A list of the size-changing functions, for use in parseImplicitGroup
var sizeFuncs = [ const sizeFuncs = [
"\\tiny", "\\scriptsize", "\\footnotesize", "\\small", "\\normalsize", "\\tiny", "\\scriptsize", "\\footnotesize", "\\small", "\\normalsize",
"\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge", "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge",
]; ];
// A list of the style-changing functions, for use in parseImplicitGroup // A list of the style-changing functions, for use in parseImplicitGroup
var styleFuncs = [ const styleFuncs = [
"\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle", "\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle",
]; ];
@@ -398,27 +398,26 @@ var styleFuncs = [
* @return {?ParseNode} * @return {?ParseNode}
*/ */
Parser.prototype.parseImplicitGroup = function() { Parser.prototype.parseImplicitGroup = function() {
var start = this.parseSymbol(); const start = this.parseSymbol();
if (start == null) { if (start == null) {
// If we didn't get anything we handle, fall back to parseFunction // If we didn't get anything we handle, fall back to parseFunction
return this.parseFunction(); return this.parseFunction();
} }
var func = start.result; const func = start.result;
var body;
if (func === "\\left") { if (func === "\\left") {
// If we see a left: // If we see a left:
// Parse the entire left function (including the delimiter) // Parse the entire left function (including the delimiter)
var left = this.parseFunction(start); const left = this.parseFunction(start);
// Parse out the implicit body // Parse out the implicit body
++this.leftrightDepth; ++this.leftrightDepth;
body = this.parseExpression(false); const body = this.parseExpression(false);
--this.leftrightDepth; --this.leftrightDepth;
// Check the next token // Check the next token
this.expect("\\right", false); this.expect("\\right", false);
var right = this.parseFunction(); const right = this.parseFunction();
return new ParseNode("leftright", { return new ParseNode("leftright", {
body: body, body: body,
left: left.value.value, left: left.value.value,
@@ -426,26 +425,26 @@ Parser.prototype.parseImplicitGroup = function() {
}, this.mode); }, this.mode);
} else if (func === "\\begin") { } else if (func === "\\begin") {
// begin...end is similar to left...right // begin...end is similar to left...right
var begin = this.parseFunction(start); const begin = this.parseFunction(start);
var envName = begin.value.name; const envName = begin.value.name;
if (!environments.hasOwnProperty(envName)) { if (!environments.hasOwnProperty(envName)) {
throw new ParseError( throw new ParseError(
"No such environment: " + envName, begin.value.nameGroup); "No such environment: " + envName, begin.value.nameGroup);
} }
// Build the environment object. Arguments and other information will // Build the environment object. Arguments and other information will
// be made available to the begin and end methods using properties. // be made available to the begin and end methods using properties.
var env = environments[envName]; const env = environments[envName];
var args = this.parseArguments("\\begin{" + envName + "}", env); const args = this.parseArguments("\\begin{" + envName + "}", env);
var context = { const context = {
mode: this.mode, mode: this.mode,
envName: envName, envName: envName,
parser: this, parser: this,
positions: args.pop(), positions: args.pop(),
}; };
var result = env.handler(context, args); const result = env.handler(context, args);
this.expect("\\end", false); this.expect("\\end", false);
var endNameToken = this.nextToken; const endNameToken = this.nextToken;
var end = this.parseFunction(); const end = this.parseFunction();
if (end.value.name !== envName) { if (end.value.name !== envName) {
throw new ParseError( throw new ParseError(
"Mismatch: \\begin{" + envName + "} matched " + "Mismatch: \\begin{" + envName + "} matched " +
@@ -456,7 +455,7 @@ Parser.prototype.parseImplicitGroup = function() {
return result; return result;
} else if (utils.contains(sizeFuncs, func)) { } else if (utils.contains(sizeFuncs, func)) {
// If we see a sizing function, parse out the implict body // If we see a sizing function, parse out the implict body
body = this.parseExpression(false); const body = this.parseExpression(false);
return new ParseNode("sizing", { return new ParseNode("sizing", {
// Figure out what size to use based on the list of functions above // Figure out what size to use based on the list of functions above
size: "size" + (utils.indexOf(sizeFuncs, func) + 1), size: "size" + (utils.indexOf(sizeFuncs, func) + 1),
@@ -464,7 +463,7 @@ Parser.prototype.parseImplicitGroup = function() {
}, this.mode); }, this.mode);
} else if (utils.contains(styleFuncs, func)) { } else if (utils.contains(styleFuncs, func)) {
// If we see a styling function, parse out the implict body // If we see a styling function, parse out the implict body
body = this.parseExpression(true); const body = this.parseExpression(true);
return new ParseNode("styling", { return new ParseNode("styling", {
// Figure out what style to use by pulling out the style from // Figure out what style to use by pulling out the style from
// the function name // the function name
@@ -492,17 +491,17 @@ Parser.prototype.parseFunction = function(baseGroup) {
if (baseGroup) { if (baseGroup) {
if (baseGroup.isFunction) { if (baseGroup.isFunction) {
var func = baseGroup.result; const func = baseGroup.result;
var funcData = functions[func]; const funcData = functions[func];
if (this.mode === "text" && !funcData.allowedInText) { if (this.mode === "text" && !funcData.allowedInText) {
throw new ParseError( throw new ParseError(
"Can't use function '" + func + "' in text mode", "Can't use function '" + func + "' in text mode",
baseGroup.token); baseGroup.token);
} }
var args = this.parseArguments(func, funcData); const args = this.parseArguments(func, funcData);
var token = baseGroup.token; const token = baseGroup.token;
var result = this.callFunction(func, args, args.pop(), token); const result = this.callFunction(func, args, args.pop(), token);
return new ParseNode(result.type, result, this.mode); return new ParseNode(result.type, result, this.mode);
} else { } else {
return baseGroup.result; return baseGroup.result;
@@ -516,7 +515,7 @@ Parser.prototype.parseFunction = function(baseGroup) {
* Call a function handler with a suitable context and arguments. * Call a function handler with a suitable context and arguments.
*/ */
Parser.prototype.callFunction = function(name, args, positions, token) { Parser.prototype.callFunction = function(name, args, positions, token) {
var context = { const context = {
funcName: name, funcName: name,
parser: this, parser: this,
positions: positions, positions: positions,
@@ -533,19 +532,19 @@ Parser.prototype.callFunction = function(name, args, positions, token) {
* @return the array of arguments, with the list of positions as last element * @return the array of arguments, with the list of positions as last element
*/ */
Parser.prototype.parseArguments = function(func, funcData) { Parser.prototype.parseArguments = function(func, funcData) {
var totalArgs = funcData.numArgs + funcData.numOptionalArgs; const totalArgs = funcData.numArgs + funcData.numOptionalArgs;
if (totalArgs === 0) { if (totalArgs === 0) {
return [[this.pos]]; return [[this.pos]];
} }
var baseGreediness = funcData.greediness; const baseGreediness = funcData.greediness;
var positions = [this.pos]; const positions = [this.pos];
var args = []; const args = [];
for (var i = 0; i < totalArgs; i++) { for (let i = 0; i < totalArgs; i++) {
var nextToken = this.nextToken; const nextToken = this.nextToken;
var argType = funcData.argTypes && funcData.argTypes[i]; const argType = funcData.argTypes && funcData.argTypes[i];
var arg; let arg;
if (i < funcData.numOptionalArgs) { if (i < funcData.numOptionalArgs) {
if (argType) { if (argType) {
arg = this.parseGroupOfType(argType, true); arg = this.parseGroupOfType(argType, true);
@@ -575,9 +574,9 @@ Parser.prototype.parseArguments = function(func, funcData) {
} }
} }
} }
var argNode; let argNode;
if (arg.isFunction) { if (arg.isFunction) {
var argGreediness = const argGreediness =
functions[arg.result].greediness; functions[arg.result].greediness;
if (argGreediness > baseGreediness) { if (argGreediness > baseGreediness) {
argNode = this.parseFunction(arg); argNode = this.parseFunction(arg);
@@ -605,7 +604,7 @@ Parser.prototype.parseArguments = function(func, funcData) {
* @return {?ParseFuncOrArgument} * @return {?ParseFuncOrArgument}
*/ */
Parser.prototype.parseGroupOfType = function(innerMode, optional) { Parser.prototype.parseGroupOfType = function(innerMode, optional) {
var outerMode = this.mode; const outerMode = this.mode;
// Handle `original` argTypes // Handle `original` argTypes
if (innerMode === "original") { if (innerMode === "original") {
innerMode = outerMode; innerMode = outerMode;
@@ -628,7 +627,7 @@ Parser.prototype.parseGroupOfType = function(innerMode, optional) {
} }
// By the time we get here, innerMode is one of "text" or "math". // By the time we get here, innerMode is one of "text" or "math".
// We switch the mode of the parser, recurse, then restore the old mode. // We switch the mode of the parser, recurse, then restore the old mode.
var res = this.parseGroup(optional); const res = this.parseGroup(optional);
this.switchMode(outerMode); this.switchMode(outerMode);
return res; return res;
}; };
@@ -644,12 +643,12 @@ Parser.prototype.parseStringGroup = function(modeName, optional) {
if (optional && this.nextToken.text !== "[") { if (optional && this.nextToken.text !== "[") {
return null; return null;
} }
var outerMode = this.mode; const outerMode = this.mode;
this.mode = "text"; this.mode = "text";
this.expect(optional ? "[" : "{"); this.expect(optional ? "[" : "{");
var str = ""; let str = "";
var firstToken = this.nextToken; const firstToken = this.nextToken;
var lastToken = firstToken; let lastToken = firstToken;
while (this.nextToken.text !== (optional ? "]" : "}")) { while (this.nextToken.text !== (optional ? "]" : "}")) {
if (this.nextToken.text === "EOF") { if (this.nextToken.text === "EOF") {
throw new ParseError( throw new ParseError(
@@ -674,11 +673,11 @@ Parser.prototype.parseStringGroup = function(modeName, optional) {
* @param {string} modeName Used to describe the mode in error messages * @param {string} modeName Used to describe the mode in error messages
*/ */
Parser.prototype.parseRegexGroup = function(regex, modeName) { Parser.prototype.parseRegexGroup = function(regex, modeName) {
var outerMode = this.mode; const outerMode = this.mode;
this.mode = "text"; this.mode = "text";
var firstToken = this.nextToken; const firstToken = this.nextToken;
var lastToken = firstToken; let lastToken = firstToken;
var str = ""; let str = "";
while (this.nextToken.text !== "EOF" while (this.nextToken.text !== "EOF"
&& regex.test(str + this.nextToken.text)) { && regex.test(str + this.nextToken.text)) {
lastToken = this.nextToken; lastToken = this.nextToken;
@@ -698,11 +697,11 @@ Parser.prototype.parseRegexGroup = function(regex, modeName) {
* Parses a color description. * Parses a color description.
*/ */
Parser.prototype.parseColorGroup = function(optional) { Parser.prototype.parseColorGroup = function(optional) {
var res = this.parseStringGroup("color", optional); const res = this.parseStringGroup("color", optional);
if (!res) { if (!res) {
return null; return null;
} }
var match = (/^(#[a-z0-9]+|[a-z]+)$/i).exec(res.text); const match = (/^(#[a-z0-9]+|[a-z]+)$/i).exec(res.text);
if (!match) { if (!match) {
throw new ParseError("Invalid color: '" + res.text + "'", res); throw new ParseError("Invalid color: '" + res.text + "'", res);
} }
@@ -715,7 +714,7 @@ Parser.prototype.parseColorGroup = function(optional) {
* Parses a size specification, consisting of magnitude and unit. * Parses a size specification, consisting of magnitude and unit.
*/ */
Parser.prototype.parseSizeGroup = function(optional) { Parser.prototype.parseSizeGroup = function(optional) {
var res; let res;
if (!optional && this.nextToken.text !== "{") { if (!optional && this.nextToken.text !== "{") {
res = this.parseRegexGroup( res = this.parseRegexGroup(
/^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2}$/, "size"); /^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2}$/, "size");
@@ -725,11 +724,11 @@ Parser.prototype.parseSizeGroup = function(optional) {
if (!res) { if (!res) {
return null; return null;
} }
var match = (/([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/).exec(res.text); const match = (/([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/).exec(res.text);
if (!match) { if (!match) {
throw new ParseError("Invalid size: '" + res.text + "'", res); throw new ParseError("Invalid size: '" + res.text + "'", res);
} }
var data = { const data = {
number: +(match[1] + match[2]), // sign + magnitude, cast to number number: +(match[1] + match[2]), // sign + magnitude, cast to number
unit: match[3], unit: match[3],
}; };
@@ -753,13 +752,13 @@ Parser.prototype.parseSizeGroup = function(optional) {
* @return {?ParseFuncOrArgument} * @return {?ParseFuncOrArgument}
*/ */
Parser.prototype.parseGroup = function(optional) { Parser.prototype.parseGroup = function(optional) {
var firstToken = this.nextToken; const firstToken = this.nextToken;
// Try to parse an open brace // Try to parse an open brace
if (this.nextToken.text === (optional ? "[" : "{")) { if (this.nextToken.text === (optional ? "[" : "{")) {
// If we get a brace, parse an expression // If we get a brace, parse an expression
this.consume(); this.consume();
var expression = this.parseExpression(false, optional ? "]" : null); const expression = this.parseExpression(false, optional ? "]" : null);
var lastToken = this.nextToken; const lastToken = this.nextToken;
// Make sure we get a close brace // Make sure we get a close brace
this.expect(optional ? "]" : "}"); this.expect(optional ? "]" : "}");
if (this.mode === "text") { if (this.mode === "text") {
@@ -786,11 +785,10 @@ Parser.prototype.parseGroup = function(optional) {
* list will be moified in place * list will be moified in place
*/ */
Parser.prototype.formLigatures = function(group) { Parser.prototype.formLigatures = function(group) {
var i; let n = group.length - 1;
var n = group.length - 1; for (let i = 0; i < n; ++i) {
for (i = 0; i < n; ++i) { const a = group[i];
var a = group[i]; const v = a.value;
var v = a.value;
if (v === "-" && group[i + 1].value === "-") { if (v === "-" && group[i + 1].value === "-") {
if (i + 1 < n && group[i + 2].value === "-") { if (i + 1 < n && group[i + 2].value === "-") {
group.splice(i, 3, new ParseNode( group.splice(i, 3, new ParseNode(
@@ -817,7 +815,7 @@ Parser.prototype.formLigatures = function(group) {
* @return {?ParseFuncOrArgument} * @return {?ParseFuncOrArgument}
*/ */
Parser.prototype.parseSymbol = function() { Parser.prototype.parseSymbol = function() {
var nucleus = this.nextToken; const nucleus = this.nextToken;
if (functions[nucleus.text]) { if (functions[nucleus.text]) {
this.consume(); this.consume();

View File

@@ -6,18 +6,17 @@
* information about them. * information about them.
*/ */
var sigmas = require("./fontMetrics.js").sigmas; const sigmas = require("./fontMetrics.js").sigmas;
var metrics = [{}, {}, {}]; const metrics = [{}, {}, {}];
var i; for (const key in sigmas) {
for (var key in sigmas) {
if (sigmas.hasOwnProperty(key)) { if (sigmas.hasOwnProperty(key)) {
for (i = 0; i < 3; i++) { for (let i = 0; i < 3; i++) {
metrics[i][key] = sigmas[key][i]; metrics[i][key] = sigmas[key][i];
} }
} }
} }
for (i = 0; i < 3; i++) { for (let i = 0; i < 3; i++) {
metrics[i].emPerEx = sigmas.xHeight[i] / sigmas.quad[i]; metrics[i].emPerEx = sigmas.xHeight[i] / sigmas.quad[i];
} }
@@ -95,17 +94,17 @@ Style.prototype.isTight = function() {
}; };
// IDs of the different styles // IDs of the different styles
var D = 0; const D = 0;
var Dc = 1; const Dc = 1;
var T = 2; const T = 2;
var Tc = 3; const Tc = 3;
var S = 4; const S = 4;
var Sc = 5; const Sc = 5;
var SS = 6; const SS = 6;
var SSc = 7; const SSc = 7;
// String names for the different sizes // String names for the different sizes
var sizeNames = [ const sizeNames = [
"displaystyle textstyle", "displaystyle textstyle",
"textstyle", "textstyle",
"scriptstyle", "scriptstyle",
@@ -113,7 +112,7 @@ var sizeNames = [
]; ];
// Reset names for the different sizes // Reset names for the different sizes
var resetNames = [ const resetNames = [
"reset-textstyle", "reset-textstyle",
"reset-textstyle", "reset-textstyle",
"reset-scriptstyle", "reset-scriptstyle",
@@ -121,7 +120,7 @@ var resetNames = [
]; ];
// Instances of the different styles // Instances of the different styles
var styles = [ const styles = [
new Style(D, 0, 1.0, false), new Style(D, 0, 1.0, false),
new Style(Dc, 0, 1.0, true), new Style(Dc, 0, 1.0, true),
new Style(T, 1, 1.0, false), new Style(T, 1, 1.0, false),
@@ -133,11 +132,11 @@ var styles = [
]; ];
// Lookup tables for switching from one style to another // Lookup tables for switching from one style to another
var sup = [S, Sc, S, Sc, SS, SSc, SS, SSc]; const sup = [S, Sc, S, Sc, SS, SSc, SS, SSc];
var sub = [Sc, Sc, Sc, Sc, SSc, SSc, SSc, SSc]; const sub = [Sc, Sc, Sc, Sc, SSc, SSc, SSc, SSc];
var fracNum = [T, Tc, S, Sc, SS, SSc, SS, SSc]; const fracNum = [T, Tc, S, Sc, SS, SSc, SS, SSc];
var fracDen = [Tc, Tc, Sc, Sc, SSc, SSc, SSc, SSc]; const fracDen = [Tc, Tc, Sc, Sc, SSc, SSc, SSc, SSc];
var cramp = [Dc, Dc, Tc, Tc, Sc, Sc, SSc, SSc]; const 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 // We only export some of the styles. Also, we don't export the `Style` class so
// no more styles can be generated. // no more styles can be generated.

View File

@@ -4,12 +4,12 @@
* different kinds of domTree nodes in a consistent manner. * different kinds of domTree nodes in a consistent manner.
*/ */
var domTree = require("./domTree"); const domTree = require("./domTree");
var fontMetrics = require("./fontMetrics"); const fontMetrics = require("./fontMetrics");
var symbols = require("./symbols"); const symbols = require("./symbols");
var utils = require("./utils"); const utils = require("./utils");
var greekCapitals = [ const greekCapitals = [
"\\Gamma", "\\Gamma",
"\\Delta", "\\Delta",
"\\Theta", "\\Theta",
@@ -24,7 +24,7 @@ var greekCapitals = [
]; ];
// The following have to be loaded from Main-Italic font, using class mainit // The following have to be loaded from Main-Italic font, using class mainit
var mainitLetters = [ const mainitLetters = [
"\u0131", // dotless i, \imath "\u0131", // dotless i, \imath
"\u0237", // dotless j, \jmath "\u0237", // dotless j, \jmath
"\u00a3", // \pounds "\u00a3", // \pounds
@@ -39,17 +39,17 @@ var mainitLetters = [
* TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which * TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which
* should if present come first in `classes`. * should if present come first in `classes`.
*/ */
var makeSymbol = function(value, fontFamily, mode, options, classes) { const makeSymbol = function(value, fontFamily, mode, options, classes) {
// Replace the value with its replaced value from symbol.js // Replace the value with its replaced value from symbol.js
if (symbols[mode][value] && symbols[mode][value].replace) { if (symbols[mode][value] && symbols[mode][value].replace) {
value = symbols[mode][value].replace; value = symbols[mode][value].replace;
} }
var metrics = fontMetrics.getCharacterMetrics(value, fontFamily); const metrics = fontMetrics.getCharacterMetrics(value, fontFamily);
var symbolNode; let symbolNode;
if (metrics) { if (metrics) {
var italic = metrics.italic; let italic = metrics.italic;
if (mode === "text") { if (mode === "text") {
italic = 0; italic = 0;
} }
@@ -80,7 +80,7 @@ var makeSymbol = function(value, fontFamily, mode, options, classes) {
* Makes a symbol in Main-Regular or AMS-Regular. * Makes a symbol in Main-Regular or AMS-Regular.
* Used for rel, bin, open, close, inner, and punct. * Used for rel, bin, open, close, inner, and punct.
*/ */
var mathsym = function(value, mode, options, classes) { const mathsym = function(value, mode, options, classes) {
// Decide what font to render the symbol in by its entry in the symbols // Decide what font to render the symbol in by its entry in the symbols
// table. // table.
// Have a special case for when the value = \ because the \ is used as a // Have a special case for when the value = \ because the \ is used as a
@@ -98,7 +98,7 @@ var mathsym = function(value, mode, options, classes) {
/** /**
* Makes a symbol in the default font for mathords and textords. * Makes a symbol in the default font for mathords and textords.
*/ */
var mathDefault = function(value, mode, options, classes, type) { const mathDefault = function(value, mode, options, classes, type) {
if (type === "mathord") { if (type === "mathord") {
return mathit(value, mode, options, classes); return mathit(value, mode, options, classes);
} else if (type === "textord") { } else if (type === "textord") {
@@ -112,7 +112,7 @@ var mathDefault = function(value, mode, options, classes, type) {
/** /**
* Makes a symbol in the italic math font. * Makes a symbol in the italic math font.
*/ */
var mathit = function(value, mode, options, classes) { const mathit = function(value, mode, options, classes) {
if (/[0-9]/.test(value.charAt(0)) || if (/[0-9]/.test(value.charAt(0)) ||
// glyphs for \imath and \jmath do not exist in Math-Italic so we // glyphs for \imath and \jmath do not exist in Math-Italic so we
// need to use Main-Italic instead // need to use Main-Italic instead
@@ -129,21 +129,21 @@ var mathit = function(value, mode, options, classes) {
/** /**
* Makes either a mathord or textord in the correct font and color. * Makes either a mathord or textord in the correct font and color.
*/ */
var makeOrd = function(group, options, type) { const makeOrd = function(group, options, type) {
var mode = group.mode; const mode = group.mode;
var value = group.value; let value = group.value;
if (symbols[mode][value] && symbols[mode][value].replace) { if (symbols[mode][value] && symbols[mode][value].replace) {
value = symbols[mode][value].replace; value = symbols[mode][value].replace;
} }
var classes = ["mord"]; const classes = ["mord"];
var font = options.font; const font = options.font;
if (font) { if (font) {
if (font === "mathit" || utils.contains(mainitLetters, value)) { if (font === "mathit" || utils.contains(mainitLetters, value)) {
return mathit(value, mode, options, classes); return mathit(value, mode, options, classes);
} else { } else {
var fontName = fontMap[font].fontName; const fontName = fontMap[font].fontName;
if (fontMetrics.getCharacterMetrics(value, fontName)) { if (fontMetrics.getCharacterMetrics(value, fontName)) {
return makeSymbol( return makeSymbol(
value, fontName, mode, options, classes.concat([font])); value, fontName, mode, options, classes.concat([font]));
@@ -160,13 +160,13 @@ var makeOrd = function(group, options, type) {
* Calculate the height, depth, and maxFontSize of an element based on its * Calculate the height, depth, and maxFontSize of an element based on its
* children. * children.
*/ */
var sizeElementFromChildren = function(elem) { const sizeElementFromChildren = function(elem) {
var height = 0; let height = 0;
var depth = 0; let depth = 0;
var maxFontSize = 0; let maxFontSize = 0;
if (elem.children) { if (elem.children) {
for (var i = 0; i < elem.children.length; i++) { for (let i = 0; i < elem.children.length; i++) {
if (elem.children[i].height > height) { if (elem.children[i].height > height) {
height = elem.children[i].height; height = elem.children[i].height;
} }
@@ -192,8 +192,8 @@ var sizeElementFromChildren = function(elem) {
* TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which * TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which
* should if present come first in `classes`. * should if present come first in `classes`.
*/ */
var makeSpan = function(classes, children, options) { const makeSpan = function(classes, children, options) {
var span = new domTree.span(classes, children, options); const span = new domTree.span(classes, children, options);
sizeElementFromChildren(span); sizeElementFromChildren(span);
@@ -204,7 +204,7 @@ var makeSpan = function(classes, children, options) {
* Prepends the given children to the given span, updating height, depth, and * Prepends the given children to the given span, updating height, depth, and
* maxFontSize. * maxFontSize.
*/ */
var prependChildren = function(span, children) { const prependChildren = function(span, children) {
span.children = children.concat(span.children); span.children = children.concat(span.children);
sizeElementFromChildren(span); sizeElementFromChildren(span);
@@ -213,8 +213,8 @@ var prependChildren = function(span, children) {
/** /**
* Makes a document fragment with the given list of children. * Makes a document fragment with the given list of children.
*/ */
var makeFragment = function(children) { const makeFragment = function(children) {
var fragment = new domTree.documentFragment(children); const fragment = new domTree.documentFragment(children);
sizeElementFromChildren(fragment); sizeElementFromChildren(fragment);
@@ -226,12 +226,12 @@ var makeFragment = function(children) {
* element has the same max font size. To do this, we create a zero-width space * element has the same max font size. To do this, we create a zero-width space
* with the correct font size. * with the correct font size.
*/ */
var makeFontSizer = function(options, fontSize) { const makeFontSizer = function(options, fontSize) {
var fontSizeInner = makeSpan([], [new domTree.symbolNode("\u200b")]); const fontSizeInner = makeSpan([], [new domTree.symbolNode("\u200b")]);
fontSizeInner.style.fontSize = fontSizeInner.style.fontSize =
(fontSize / options.style.sizeMultiplier) + "em"; (fontSize / options.style.sizeMultiplier) + "em";
var fontSizer = makeSpan( const fontSizer = makeSpan(
["fontsize-ensurer", "reset-" + options.size, "size5"], ["fontsize-ensurer", "reset-" + options.size, "size5"],
[fontSizeInner]); [fontSizeInner]);
@@ -277,12 +277,12 @@ var makeFontSizer = function(options, fontSize) {
* - options: An Options object * - options: An Options object
* *
*/ */
var makeVList = function(children, positionType, positionData, options) { const makeVList = function(children, positionType, positionData, options) {
var depth; let depth;
var currPos; let currPos;
var i; let i;
if (positionType === "individualShift") { if (positionType === "individualShift") {
var oldChildren = children; const oldChildren = children;
children = [oldChildren[0]]; children = [oldChildren[0]];
// Add in kerns to the list of children to get each element to be // Add in kerns to the list of children to get each element to be
@@ -290,9 +290,9 @@ var makeVList = function(children, positionType, positionData, options) {
depth = -oldChildren[0].shift - oldChildren[0].elem.depth; depth = -oldChildren[0].shift - oldChildren[0].elem.depth;
currPos = depth; currPos = depth;
for (i = 1; i < oldChildren.length; i++) { for (i = 1; i < oldChildren.length; i++) {
var diff = -oldChildren[i].shift - currPos - const diff = -oldChildren[i].shift - currPos -
oldChildren[i].elem.depth; oldChildren[i].elem.depth;
var size = diff - const size = diff -
(oldChildren[i - 1].elem.height + (oldChildren[i - 1].elem.height +
oldChildren[i - 1].elem.depth); oldChildren[i - 1].elem.depth);
@@ -304,7 +304,7 @@ var makeVList = function(children, positionType, positionData, options) {
} else if (positionType === "top") { } else if (positionType === "top") {
// We always start at the bottom, so calculate the bottom by adding up // We always start at the bottom, so calculate the bottom by adding up
// all the sizes // all the sizes
var bottom = positionData; let bottom = positionData;
for (i = 0; i < children.length; i++) { for (i = 0; i < children.length; i++) {
if (children[i].type === "kern") { if (children[i].type === "kern") {
bottom -= children[i].size; bottom -= children[i].size;
@@ -324,27 +324,27 @@ var makeVList = function(children, positionType, positionData, options) {
} }
// Make the fontSizer // Make the fontSizer
var maxFontSize = 0; let maxFontSize = 0;
for (i = 0; i < children.length; i++) { for (i = 0; i < children.length; i++) {
if (children[i].type === "elem") { if (children[i].type === "elem") {
maxFontSize = Math.max(maxFontSize, children[i].elem.maxFontSize); maxFontSize = Math.max(maxFontSize, children[i].elem.maxFontSize);
} }
} }
var fontSizer = makeFontSizer(options, maxFontSize); const fontSizer = makeFontSizer(options, maxFontSize);
// Create a new list of actual children at the correct offsets // Create a new list of actual children at the correct offsets
var realChildren = []; const realChildren = [];
currPos = depth; currPos = depth;
for (i = 0; i < children.length; i++) { for (i = 0; i < children.length; i++) {
if (children[i].type === "kern") { if (children[i].type === "kern") {
currPos += children[i].size; currPos += children[i].size;
} else { } else {
var child = children[i].elem; const child = children[i].elem;
var shift = -child.depth - currPos; const shift = -child.depth - currPos;
currPos += child.height + child.depth; currPos += child.height + child.depth;
var childWrap = makeSpan([], [fontSizer, child]); const childWrap = makeSpan([], [fontSizer, child]);
childWrap.height -= shift; childWrap.height -= shift;
childWrap.depth += shift; childWrap.depth += shift;
childWrap.style.top = shift + "em"; childWrap.style.top = shift + "em";
@@ -355,11 +355,11 @@ var makeVList = function(children, positionType, positionData, options) {
// Add in an element at the end with no offset to fix the calculation of // Add in an element at the end with no offset to fix the calculation of
// baselines in some browsers (namely IE, sometimes safari) // baselines in some browsers (namely IE, sometimes safari)
var baselineFix = makeSpan( const baselineFix = makeSpan(
["baseline-fix"], [fontSizer, new domTree.symbolNode("\u200b")]); ["baseline-fix"], [fontSizer, new domTree.symbolNode("\u200b")]);
realChildren.push(baselineFix); realChildren.push(baselineFix);
var vlist = makeSpan(["vlist"], realChildren); const vlist = makeSpan(["vlist"], realChildren);
// Fix the final height and depth, in case there were kerns at the ends // Fix the final height and depth, in case there were kerns at the ends
// since the makeSpan calculation won't take that in to account. // since the makeSpan calculation won't take that in to account.
vlist.height = Math.max(currPos, vlist.height); vlist.height = Math.max(currPos, vlist.height);
@@ -368,7 +368,7 @@ var makeVList = function(children, positionType, positionData, options) {
}; };
// A table of size -> font size for the different sizing functions // A table of size -> font size for the different sizing functions
var sizingMultiplier = { const sizingMultiplier = {
size1: 0.5, size1: 0.5,
size2: 0.7, size2: 0.7,
size3: 0.8, size3: 0.8,
@@ -383,7 +383,7 @@ var sizingMultiplier = {
// A map of spacing functions to their attributes, like size and corresponding // A map of spacing functions to their attributes, like size and corresponding
// CSS class // CSS class
var spacingFunctions = { const spacingFunctions = {
"\\qquad": { "\\qquad": {
size: "2em", size: "2em",
className: "qquad", className: "qquad",
@@ -420,7 +420,7 @@ var spacingFunctions = {
* - fontName: the "style" parameter to fontMetrics.getCharacterMetrics * - fontName: the "style" parameter to fontMetrics.getCharacterMetrics
*/ */
// A map between tex font commands an MathML mathvariant attribute values // A map between tex font commands an MathML mathvariant attribute values
var fontMap = { const fontMap = {
// styles // styles
"mathbf": { "mathbf": {
variant: "bold", variant: "bold",

File diff suppressed because it is too large Load Diff

View File

@@ -4,21 +4,21 @@
* parser. * parser.
*/ */
var buildCommon = require("./buildCommon"); const buildCommon = require("./buildCommon");
var fontMetrics = require("./fontMetrics"); const fontMetrics = require("./fontMetrics");
var mathMLTree = require("./mathMLTree"); const mathMLTree = require("./mathMLTree");
var ParseError = require("./ParseError"); const ParseError = require("./ParseError");
var symbols = require("./symbols"); const symbols = require("./symbols");
var utils = require("./utils"); const utils = require("./utils");
var makeSpan = buildCommon.makeSpan; const makeSpan = buildCommon.makeSpan;
var fontMap = buildCommon.fontMap; const fontMap = buildCommon.fontMap;
/** /**
* Takes a symbol and converts it into a MathML text node after performing * Takes a symbol and converts it into a MathML text node after performing
* optional replacement from symbols.js. * optional replacement from symbols.js.
*/ */
var makeText = function(text, mode) { const makeText = function(text, mode) {
if (symbols[mode][text] && symbols[mode][text].replace) { if (symbols[mode][text] && symbols[mode][text].replace) {
text = symbols[mode][text].replace; text = symbols[mode][text].replace;
} }
@@ -29,18 +29,18 @@ var makeText = function(text, mode) {
/** /**
* Returns the math variant as a string or null if none is required. * Returns the math variant as a string or null if none is required.
*/ */
var getVariant = function(group, options) { const getVariant = function(group, options) {
var font = options.font; const font = options.font;
if (!font) { if (!font) {
return null; return null;
} }
var mode = group.mode; const mode = group.mode;
if (font === "mathit") { if (font === "mathit") {
return "italic"; return "italic";
} }
var value = group.value; let value = group.value;
if (utils.contains(["\\imath", "\\jmath"], value)) { if (utils.contains(["\\imath", "\\jmath"], value)) {
return null; return null;
} }
@@ -49,7 +49,7 @@ var getVariant = function(group, options) {
value = symbols[mode][value].replace; value = symbols[mode][value].replace;
} }
var fontName = fontMap[font].fontName; const fontName = fontMap[font].fontName;
if (fontMetrics.getCharacterMetrics(value, fontName)) { if (fontMetrics.getCharacterMetrics(value, fontName)) {
return fontMap[options.font].variant; return fontMap[options.font].variant;
} }
@@ -61,14 +61,14 @@ var getVariant = function(group, options) {
* Functions for handling the different types of groups found in the parse * Functions for handling the different types of groups found in the parse
* tree. Each function should take a parse group and return a MathML node. * tree. Each function should take a parse group and return a MathML node.
*/ */
var groupTypes = {}; const groupTypes = {};
groupTypes.mathord = function(group, options) { groupTypes.mathord = function(group, options) {
var node = new mathMLTree.MathNode( const node = new mathMLTree.MathNode(
"mi", "mi",
[makeText(group.value, group.mode)]); [makeText(group.value, group.mode)]);
var variant = getVariant(group, options); const variant = getVariant(group, options);
if (variant) { if (variant) {
node.setAttribute("mathvariant", variant); node.setAttribute("mathvariant", variant);
} }
@@ -76,11 +76,11 @@ groupTypes.mathord = function(group, options) {
}; };
groupTypes.textord = function(group, options) { groupTypes.textord = function(group, options) {
var text = makeText(group.value, group.mode); const text = makeText(group.value, group.mode);
var variant = getVariant(group, options) || "normal"; const variant = getVariant(group, options) || "normal";
var node; let node;
if (/[0-9]/.test(group.value)) { if (/[0-9]/.test(group.value)) {
// TODO(kevinb) merge adjacent <mn> nodes // TODO(kevinb) merge adjacent <mn> nodes
// do it as a post processing step // do it as a post processing step
@@ -97,42 +97,42 @@ groupTypes.textord = function(group, options) {
}; };
groupTypes.bin = function(group) { groupTypes.bin = function(group) {
var node = new mathMLTree.MathNode( const node = new mathMLTree.MathNode(
"mo", [makeText(group.value, group.mode)]); "mo", [makeText(group.value, group.mode)]);
return node; return node;
}; };
groupTypes.rel = function(group) { groupTypes.rel = function(group) {
var node = new mathMLTree.MathNode( const node = new mathMLTree.MathNode(
"mo", [makeText(group.value, group.mode)]); "mo", [makeText(group.value, group.mode)]);
return node; return node;
}; };
groupTypes.open = function(group) { groupTypes.open = function(group) {
var node = new mathMLTree.MathNode( const node = new mathMLTree.MathNode(
"mo", [makeText(group.value, group.mode)]); "mo", [makeText(group.value, group.mode)]);
return node; return node;
}; };
groupTypes.close = function(group) { groupTypes.close = function(group) {
var node = new mathMLTree.MathNode( const node = new mathMLTree.MathNode(
"mo", [makeText(group.value, group.mode)]); "mo", [makeText(group.value, group.mode)]);
return node; return node;
}; };
groupTypes.inner = function(group) { groupTypes.inner = function(group) {
var node = new mathMLTree.MathNode( const node = new mathMLTree.MathNode(
"mo", [makeText(group.value, group.mode)]); "mo", [makeText(group.value, group.mode)]);
return node; return node;
}; };
groupTypes.punct = function(group) { groupTypes.punct = function(group) {
var node = new mathMLTree.MathNode( const node = new mathMLTree.MathNode(
"mo", [makeText(group.value, group.mode)]); "mo", [makeText(group.value, group.mode)]);
node.setAttribute("separator", "true"); node.setAttribute("separator", "true");
@@ -141,25 +141,25 @@ groupTypes.punct = function(group) {
}; };
groupTypes.ordgroup = function(group, options) { groupTypes.ordgroup = function(group, options) {
var inner = buildExpression(group.value, options); const inner = buildExpression(group.value, options);
var node = new mathMLTree.MathNode("mrow", inner); const node = new mathMLTree.MathNode("mrow", inner);
return node; return node;
}; };
groupTypes.text = function(group, options) { groupTypes.text = function(group, options) {
var inner = buildExpression(group.value.body, options); const inner = buildExpression(group.value.body, options);
var node = new mathMLTree.MathNode("mtext", inner); const node = new mathMLTree.MathNode("mtext", inner);
return node; return node;
}; };
groupTypes.color = function(group, options) { groupTypes.color = function(group, options) {
var inner = buildExpression(group.value.value, options); const inner = buildExpression(group.value.value, options);
var node = new mathMLTree.MathNode("mstyle", inner); const node = new mathMLTree.MathNode("mstyle", inner);
node.setAttribute("mathcolor", group.value.color); node.setAttribute("mathcolor", group.value.color);
@@ -167,7 +167,7 @@ groupTypes.color = function(group, options) {
}; };
groupTypes.supsub = function(group, options) { groupTypes.supsub = function(group, options) {
var children = [buildGroup(group.value.base, options)]; const children = [buildGroup(group.value.base, options)];
if (group.value.sub) { if (group.value.sub) {
children.push(buildGroup(group.value.sub, options)); children.push(buildGroup(group.value.sub, options));
@@ -177,7 +177,7 @@ groupTypes.supsub = function(group, options) {
children.push(buildGroup(group.value.sup, options)); children.push(buildGroup(group.value.sup, options));
} }
var nodeType; let nodeType;
if (!group.value.sub) { if (!group.value.sub) {
nodeType = "msup"; nodeType = "msup";
} else if (!group.value.sup) { } else if (!group.value.sup) {
@@ -186,13 +186,13 @@ groupTypes.supsub = function(group, options) {
nodeType = "msubsup"; nodeType = "msubsup";
} }
var node = new mathMLTree.MathNode(nodeType, children); const node = new mathMLTree.MathNode(nodeType, children);
return node; return node;
}; };
groupTypes.genfrac = function(group, options) { groupTypes.genfrac = function(group, options) {
var node = new mathMLTree.MathNode( const node = new mathMLTree.MathNode(
"mfrac", "mfrac",
[ [
buildGroup(group.value.numer, options), buildGroup(group.value.numer, options),
@@ -204,10 +204,10 @@ groupTypes.genfrac = function(group, options) {
} }
if (group.value.leftDelim != null || group.value.rightDelim != null) { if (group.value.leftDelim != null || group.value.rightDelim != null) {
var withDelims = []; const withDelims = [];
if (group.value.leftDelim != null) { if (group.value.leftDelim != null) {
var leftOp = new mathMLTree.MathNode( const leftOp = new mathMLTree.MathNode(
"mo", [new mathMLTree.TextNode(group.value.leftDelim)]); "mo", [new mathMLTree.TextNode(group.value.leftDelim)]);
leftOp.setAttribute("fence", "true"); leftOp.setAttribute("fence", "true");
@@ -218,7 +218,7 @@ groupTypes.genfrac = function(group, options) {
withDelims.push(node); withDelims.push(node);
if (group.value.rightDelim != null) { if (group.value.rightDelim != null) {
var rightOp = new mathMLTree.MathNode( const rightOp = new mathMLTree.MathNode(
"mo", [new mathMLTree.TextNode(group.value.rightDelim)]); "mo", [new mathMLTree.TextNode(group.value.rightDelim)]);
rightOp.setAttribute("fence", "true"); rightOp.setAttribute("fence", "true");
@@ -226,7 +226,7 @@ groupTypes.genfrac = function(group, options) {
withDelims.push(rightOp); withDelims.push(rightOp);
} }
var outerNode = new mathMLTree.MathNode("mrow", withDelims); const outerNode = new mathMLTree.MathNode("mrow", withDelims);
return outerNode; return outerNode;
} }
@@ -246,7 +246,7 @@ groupTypes.array = function(group, options) {
}; };
groupTypes.sqrt = function(group, options) { groupTypes.sqrt = function(group, options) {
var node; let node;
if (group.value.index) { if (group.value.index) {
node = new mathMLTree.MathNode( node = new mathMLTree.MathNode(
"mroot", [ "mroot", [
@@ -262,10 +262,10 @@ groupTypes.sqrt = function(group, options) {
}; };
groupTypes.leftright = function(group, options) { groupTypes.leftright = function(group, options) {
var inner = buildExpression(group.value.body, options); const inner = buildExpression(group.value.body, options);
if (group.value.left !== ".") { if (group.value.left !== ".") {
var leftNode = new mathMLTree.MathNode( const leftNode = new mathMLTree.MathNode(
"mo", [makeText(group.value.left, group.mode)]); "mo", [makeText(group.value.left, group.mode)]);
leftNode.setAttribute("fence", "true"); leftNode.setAttribute("fence", "true");
@@ -274,7 +274,7 @@ groupTypes.leftright = function(group, options) {
} }
if (group.value.right !== ".") { if (group.value.right !== ".") {
var rightNode = new mathMLTree.MathNode( const rightNode = new mathMLTree.MathNode(
"mo", [makeText(group.value.right, group.mode)]); "mo", [makeText(group.value.right, group.mode)]);
rightNode.setAttribute("fence", "true"); rightNode.setAttribute("fence", "true");
@@ -282,23 +282,23 @@ groupTypes.leftright = function(group, options) {
inner.push(rightNode); inner.push(rightNode);
} }
var outerNode = new mathMLTree.MathNode("mrow", inner); const outerNode = new mathMLTree.MathNode("mrow", inner);
return outerNode; return outerNode;
}; };
groupTypes.middle = function(group, options) { groupTypes.middle = function(group, options) {
var middleNode = new mathMLTree.MathNode( const middleNode = new mathMLTree.MathNode(
"mo", [makeText(group.value.middle, group.mode)]); "mo", [makeText(group.value.middle, group.mode)]);
middleNode.setAttribute("fence", "true"); middleNode.setAttribute("fence", "true");
return middleNode; return middleNode;
}; };
groupTypes.accent = function(group, options) { groupTypes.accent = function(group, options) {
var accentNode = new mathMLTree.MathNode( const accentNode = new mathMLTree.MathNode(
"mo", [makeText(group.value.accent, group.mode)]); "mo", [makeText(group.value.accent, group.mode)]);
var node = new mathMLTree.MathNode( const node = new mathMLTree.MathNode(
"mover", "mover",
[buildGroup(group.value.base, options), accentNode]); [buildGroup(group.value.base, options), accentNode]);
@@ -308,7 +308,7 @@ groupTypes.accent = function(group, options) {
}; };
groupTypes.spacing = function(group) { groupTypes.spacing = function(group) {
var node; let node;
if (group.value === "\\ " || group.value === "\\space" || if (group.value === "\\ " || group.value === "\\space" ||
group.value === " " || group.value === "~") { group.value === " " || group.value === "~") {
@@ -325,7 +325,7 @@ groupTypes.spacing = function(group) {
}; };
groupTypes.op = function(group, options) { groupTypes.op = function(group, options) {
var node; let node;
// TODO(emily): handle big operators using the `largeop` attribute // TODO(emily): handle big operators using the `largeop` attribute
@@ -350,7 +350,7 @@ groupTypes.op = function(group, options) {
}; };
groupTypes.mod = function(group, options) { groupTypes.mod = function(group, options) {
var inner = []; let inner = [];
if (group.value.modType === "pod" || group.value.modType === "pmod") { if (group.value.modType === "pod" || group.value.modType === "pmod") {
inner.push(new mathMLTree.MathNode( inner.push(new mathMLTree.MathNode(
@@ -361,7 +361,7 @@ groupTypes.mod = function(group, options) {
"mo", [makeText("mod", group.mode)])); "mo", [makeText("mod", group.mode)]));
} }
if (group.value.value) { if (group.value.value) {
var space = new mathMLTree.MathNode("mspace"); const space = new mathMLTree.MathNode("mspace");
space.setAttribute("width", "0.333333em"); space.setAttribute("width", "0.333333em");
inner.push(space); inner.push(space);
inner = inner.concat(buildExpression(group.value.value, options)); inner = inner.concat(buildExpression(group.value.value, options));
@@ -375,25 +375,25 @@ groupTypes.mod = function(group, options) {
}; };
groupTypes.katex = function(group) { groupTypes.katex = function(group) {
var node = new mathMLTree.MathNode( const node = new mathMLTree.MathNode(
"mtext", [new mathMLTree.TextNode("KaTeX")]); "mtext", [new mathMLTree.TextNode("KaTeX")]);
return node; return node;
}; };
groupTypes.font = function(group, options) { groupTypes.font = function(group, options) {
var font = group.value.font; const font = group.value.font;
return buildGroup(group.value.body, options.withFont(font)); return buildGroup(group.value.body, options.withFont(font));
}; };
groupTypes.delimsizing = function(group) { groupTypes.delimsizing = function(group) {
var children = []; const children = [];
if (group.value.value !== ".") { if (group.value.value !== ".") {
children.push(makeText(group.value.value, group.mode)); children.push(makeText(group.value.value, group.mode));
} }
var node = new mathMLTree.MathNode("mo", children); const node = new mathMLTree.MathNode("mo", children);
if (group.value.mclass === "mopen" || if (group.value.mclass === "mopen" ||
group.value.mclass === "mclose") { group.value.mclass === "mclose") {
@@ -410,18 +410,18 @@ groupTypes.delimsizing = function(group) {
}; };
groupTypes.styling = function(group, options) { groupTypes.styling = function(group, options) {
var inner = buildExpression(group.value.value, options); const inner = buildExpression(group.value.value, options);
var node = new mathMLTree.MathNode("mstyle", inner); const node = new mathMLTree.MathNode("mstyle", inner);
var styleAttributes = { const styleAttributes = {
"display": ["0", "true"], "display": ["0", "true"],
"text": ["0", "false"], "text": ["0", "false"],
"script": ["1", "false"], "script": ["1", "false"],
"scriptscript": ["2", "false"], "scriptscript": ["2", "false"],
}; };
var attr = styleAttributes[group.value.style]; const attr = styleAttributes[group.value.style];
node.setAttribute("scriptlevel", attr[0]); node.setAttribute("scriptlevel", attr[0]);
node.setAttribute("displaystyle", attr[1]); node.setAttribute("displaystyle", attr[1]);
@@ -430,9 +430,9 @@ groupTypes.styling = function(group, options) {
}; };
groupTypes.sizing = function(group, options) { groupTypes.sizing = function(group, options) {
var inner = buildExpression(group.value.value, options); const inner = buildExpression(group.value.value, options);
var node = new mathMLTree.MathNode("mstyle", inner); const node = new mathMLTree.MathNode("mstyle", inner);
// TODO(emily): This doesn't produce the correct size for nested size // TODO(emily): This doesn't produce the correct size for nested size
// changes, because we don't keep state of what style we're currently // changes, because we don't keep state of what style we're currently
@@ -446,11 +446,11 @@ groupTypes.sizing = function(group, options) {
}; };
groupTypes.overline = function(group, options) { groupTypes.overline = function(group, options) {
var operator = new mathMLTree.MathNode( const operator = new mathMLTree.MathNode(
"mo", [new mathMLTree.TextNode("\u203e")]); "mo", [new mathMLTree.TextNode("\u203e")]);
operator.setAttribute("stretchy", "true"); operator.setAttribute("stretchy", "true");
var node = new mathMLTree.MathNode( const node = new mathMLTree.MathNode(
"mover", "mover",
[buildGroup(group.value.body, options), operator]); [buildGroup(group.value.body, options), operator]);
node.setAttribute("accent", "true"); node.setAttribute("accent", "true");
@@ -459,11 +459,11 @@ groupTypes.overline = function(group, options) {
}; };
groupTypes.underline = function(group, options) { groupTypes.underline = function(group, options) {
var operator = new mathMLTree.MathNode( const operator = new mathMLTree.MathNode(
"mo", [new mathMLTree.TextNode("\u203e")]); "mo", [new mathMLTree.TextNode("\u203e")]);
operator.setAttribute("stretchy", "true"); operator.setAttribute("stretchy", "true");
var node = new mathMLTree.MathNode( const node = new mathMLTree.MathNode(
"munder", "munder",
[buildGroup(group.value.body, options), operator]); [buildGroup(group.value.body, options), operator]);
node.setAttribute("accentunder", "true"); node.setAttribute("accentunder", "true");
@@ -474,20 +474,20 @@ groupTypes.underline = function(group, options) {
groupTypes.rule = function(group) { groupTypes.rule = function(group) {
// TODO(emily): Figure out if there's an actual way to draw black boxes // TODO(emily): Figure out if there's an actual way to draw black boxes
// in MathML. // in MathML.
var node = new mathMLTree.MathNode("mrow"); const node = new mathMLTree.MathNode("mrow");
return node; return node;
}; };
groupTypes.kern = function(group) { groupTypes.kern = function(group) {
// TODO(kevin): Figure out if there's a way to add space in MathML // TODO(kevin): Figure out if there's a way to add space in MathML
var node = new mathMLTree.MathNode("mrow"); const node = new mathMLTree.MathNode("mrow");
return node; return node;
}; };
groupTypes.llap = function(group, options) { groupTypes.llap = function(group, options) {
var node = new mathMLTree.MathNode( const node = new mathMLTree.MathNode(
"mpadded", [buildGroup(group.value.body, options)]); "mpadded", [buildGroup(group.value.body, options)]);
node.setAttribute("lspace", "-1width"); node.setAttribute("lspace", "-1width");
@@ -497,7 +497,7 @@ groupTypes.llap = function(group, options) {
}; };
groupTypes.rlap = function(group, options) { groupTypes.rlap = function(group, options) {
var node = new mathMLTree.MathNode( const node = new mathMLTree.MathNode(
"mpadded", [buildGroup(group.value.body, options)]); "mpadded", [buildGroup(group.value.body, options)]);
node.setAttribute("width", "0px"); node.setAttribute("width", "0px");
@@ -506,12 +506,12 @@ groupTypes.rlap = function(group, options) {
}; };
groupTypes.phantom = function(group, options) { groupTypes.phantom = function(group, options) {
var inner = buildExpression(group.value.value, options); const inner = buildExpression(group.value.value, options);
return new mathMLTree.MathNode("mphantom", inner); return new mathMLTree.MathNode("mphantom", inner);
}; };
groupTypes.mclass = function(group, options) { groupTypes.mclass = function(group, options) {
var inner = buildExpression(group.value.value, options); const inner = buildExpression(group.value.value, options);
return new mathMLTree.MathNode("mstyle", inner); return new mathMLTree.MathNode("mstyle", inner);
}; };
@@ -520,10 +520,10 @@ groupTypes.mclass = function(group, options) {
* MathML nodes. A little simpler than the HTML version because we don't do any * MathML nodes. A little simpler than the HTML version because we don't do any
* previous-node handling. * previous-node handling.
*/ */
var buildExpression = function(expression, options) { const buildExpression = function(expression, options) {
var groups = []; const groups = [];
for (var i = 0; i < expression.length; i++) { for (let i = 0; i < expression.length; i++) {
var group = expression[i]; const group = expression[i];
groups.push(buildGroup(group, options)); groups.push(buildGroup(group, options));
} }
return groups; return groups;
@@ -533,7 +533,7 @@ var buildExpression = function(expression, options) {
* Takes a group from the parser and calls the appropriate groupTypes function * Takes a group from the parser and calls the appropriate groupTypes function
* on it to produce a MathML node. * on it to produce a MathML node.
*/ */
var buildGroup = function(group, options) { const buildGroup = function(group, options) {
if (!group) { if (!group) {
return new mathMLTree.MathNode("mrow"); return new mathMLTree.MathNode("mrow");
} }
@@ -555,23 +555,23 @@ var buildGroup = function(group, options) {
* Note that we actually return a domTree element with a `<math>` inside it so * Note that we actually return a domTree element with a `<math>` inside it so
* we can do appropriate styling. * we can do appropriate styling.
*/ */
var buildMathML = function(tree, texExpression, options) { const buildMathML = function(tree, texExpression, options) {
var expression = buildExpression(tree, options); const expression = buildExpression(tree, options);
// Wrap up the expression in an mrow so it is presented in the semantics // Wrap up the expression in an mrow so it is presented in the semantics
// tag correctly. // tag correctly.
var wrapper = new mathMLTree.MathNode("mrow", expression); const wrapper = new mathMLTree.MathNode("mrow", expression);
// Build a TeX annotation of the source // Build a TeX annotation of the source
var annotation = new mathMLTree.MathNode( const annotation = new mathMLTree.MathNode(
"annotation", [new mathMLTree.TextNode(texExpression)]); "annotation", [new mathMLTree.TextNode(texExpression)]);
annotation.setAttribute("encoding", "application/x-tex"); annotation.setAttribute("encoding", "application/x-tex");
var semantics = new mathMLTree.MathNode( const semantics = new mathMLTree.MathNode(
"semantics", [wrapper, annotation]); "semantics", [wrapper, annotation]);
var math = new mathMLTree.MathNode("math", [semantics]); const math = new mathMLTree.MathNode("math", [semantics]);
// You can't style <math> nodes, so we wrap the node in a span. // You can't style <math> nodes, so we wrap the node in a span.
return makeSpan(["katex-mathml"], [math]); return makeSpan(["katex-mathml"], [math]);

View File

@@ -1,32 +1,32 @@
var buildHTML = require("./buildHTML"); const buildHTML = require("./buildHTML");
var buildMathML = require("./buildMathML"); const buildMathML = require("./buildMathML");
var buildCommon = require("./buildCommon"); const buildCommon = require("./buildCommon");
var Options = require("./Options"); const Options = require("./Options");
var Settings = require("./Settings"); const Settings = require("./Settings");
var Style = require("./Style"); const Style = require("./Style");
var makeSpan = buildCommon.makeSpan; const makeSpan = buildCommon.makeSpan;
var buildTree = function(tree, expression, settings) { const buildTree = function(tree, expression, settings) {
settings = settings || new Settings({}); settings = settings || new Settings({});
var startStyle = Style.TEXT; let startStyle = Style.TEXT;
if (settings.displayMode) { if (settings.displayMode) {
startStyle = Style.DISPLAY; startStyle = Style.DISPLAY;
} }
// Setup the default options // Setup the default options
var options = new Options({ const options = new Options({
style: startStyle, style: startStyle,
size: "size5", size: "size5",
}); });
// `buildHTML` sometimes messes with the parse tree (like turning bins -> // `buildHTML` sometimes messes with the parse tree (like turning bins ->
// ords), so we build the MathML version first. // ords), so we build the MathML version first.
var mathMLNode = buildMathML(tree, expression, options); const mathMLNode = buildMathML(tree, expression, options);
var htmlNode = buildHTML(tree, options); const htmlNode = buildHTML(tree, options);
var katexNode = makeSpan(["katex"], [ const katexNode = makeSpan(["katex"], [
mathMLNode, htmlNode, mathMLNode, htmlNode,
]); ]);

View File

@@ -20,21 +20,21 @@
* used in `\left` and `\right`. * used in `\left` and `\right`.
*/ */
var ParseError = require("./ParseError"); const ParseError = require("./ParseError");
var Style = require("./Style"); const Style = require("./Style");
var buildCommon = require("./buildCommon"); const buildCommon = require("./buildCommon");
var fontMetrics = require("./fontMetrics"); const fontMetrics = require("./fontMetrics");
var symbols = require("./symbols"); const symbols = require("./symbols");
var utils = require("./utils"); const utils = require("./utils");
var makeSpan = buildCommon.makeSpan; const makeSpan = buildCommon.makeSpan;
/** /**
* Get the metrics for a given symbol and font, after transformation (i.e. * Get the metrics for a given symbol and font, after transformation (i.e.
* after following replacement from symbols.js) * after following replacement from symbols.js)
*/ */
var getMetrics = function(symbol, font) { const getMetrics = function(symbol, font) {
if (symbols.math[symbol] && symbols.math[symbol].replace) { if (symbols.math[symbol] && symbols.math[symbol].replace) {
return fontMetrics.getCharacterMetrics( return fontMetrics.getCharacterMetrics(
symbols.math[symbol].replace, font); symbols.math[symbol].replace, font);
@@ -47,7 +47,7 @@ var getMetrics = function(symbol, font) {
/** /**
* Builds a symbol in the given font size (note size is an integer) * Builds a symbol in the given font size (note size is an integer)
*/ */
var mathrmSize = function(value, size, mode, options) { const mathrmSize = function(value, size, mode, options) {
return buildCommon.makeSymbol(value, "Size" + size + "-Regular", return buildCommon.makeSymbol(value, "Size" + size + "-Regular",
mode, options); mode, options);
}; };
@@ -56,13 +56,13 @@ var mathrmSize = function(value, size, mode, options) {
* Puts a delimiter span in a given style, and adds appropriate height, depth, * Puts a delimiter span in a given style, and adds appropriate height, depth,
* and maxFontSizes. * and maxFontSizes.
*/ */
var styleWrap = function(delim, toStyle, options, classes) { const styleWrap = function(delim, toStyle, options, classes) {
classes = classes || []; classes = classes || [];
var span = makeSpan( const span = makeSpan(
classes.concat(["style-wrap", options.style.reset(), toStyle.cls()]), classes.concat(["style-wrap", options.style.reset(), toStyle.cls()]),
[delim], options); [delim], options);
var multiplier = toStyle.sizeMultiplier / options.style.sizeMultiplier; const multiplier = toStyle.sizeMultiplier / options.style.sizeMultiplier;
span.height *= multiplier; span.height *= multiplier;
span.depth *= multiplier; span.depth *= multiplier;
@@ -76,13 +76,13 @@ var styleWrap = function(delim, toStyle, options, classes) {
* font, but is restyled to either be in textstyle, scriptstyle, or * font, but is restyled to either be in textstyle, scriptstyle, or
* scriptscriptstyle. * scriptscriptstyle.
*/ */
var makeSmallDelim = function(delim, style, center, options, mode, classes) { const makeSmallDelim = function(delim, style, center, options, mode, classes) {
var text = buildCommon.makeSymbol(delim, "Main-Regular", mode, options); const text = buildCommon.makeSymbol(delim, "Main-Regular", mode, options);
var span = styleWrap(text, style, options, classes); const span = styleWrap(text, style, options, classes);
if (center) { if (center) {
var shift = const shift =
(1 - options.style.sizeMultiplier / style.sizeMultiplier) * (1 - options.style.sizeMultiplier / style.sizeMultiplier) *
options.style.metrics.axisHeight; options.style.metrics.axisHeight;
@@ -98,15 +98,15 @@ var makeSmallDelim = function(delim, style, center, options, mode, classes) {
* Makes a large delimiter. This is a delimiter that comes in the Size1, Size2, * Makes a large delimiter. This is a delimiter that comes in the Size1, Size2,
* Size3, or Size4 fonts. It is always rendered in textstyle. * Size3, or Size4 fonts. It is always rendered in textstyle.
*/ */
var makeLargeDelim = function(delim, size, center, options, mode, classes) { const makeLargeDelim = function(delim, size, center, options, mode, classes) {
var inner = mathrmSize(delim, size, mode, options); const inner = mathrmSize(delim, size, mode, options);
var span = styleWrap( const span = styleWrap(
makeSpan(["delimsizing", "size" + size], [inner], options), makeSpan(["delimsizing", "size" + size], [inner], options),
Style.TEXT, options, classes); Style.TEXT, options, classes);
if (center) { if (center) {
var shift = (1 - options.style.sizeMultiplier) * const shift = (1 - options.style.sizeMultiplier) *
options.style.metrics.axisHeight; options.style.metrics.axisHeight;
span.style.top = shift + "em"; span.style.top = shift + "em";
@@ -121,8 +121,8 @@ var makeLargeDelim = function(delim, size, center, options, mode, classes) {
* Make an inner span with the given offset and in the given font. This is used * Make an inner span with the given offset and in the given font. This is used
* in `makeStackedDelim` to make the stacking pieces for the delimiter. * in `makeStackedDelim` to make the stacking pieces for the delimiter.
*/ */
var makeInner = function(symbol, font, mode) { const makeInner = function(symbol, font, mode) {
var sizeClass; let sizeClass;
// Apply the correct CSS class to choose the right font. // Apply the correct CSS class to choose the right font.
if (font === "Size1-Regular") { if (font === "Size1-Regular") {
sizeClass = "delim-size1"; sizeClass = "delim-size1";
@@ -130,7 +130,7 @@ var makeInner = function(symbol, font, mode) {
sizeClass = "delim-size4"; sizeClass = "delim-size4";
} }
var inner = makeSpan( const inner = makeSpan(
["delimsizinginner", sizeClass], ["delimsizinginner", sizeClass],
[makeSpan([], [buildCommon.makeSymbol(symbol, font, mode)])]); [makeSpan([], [buildCommon.makeSymbol(symbol, font, mode)])]);
@@ -143,18 +143,18 @@ var makeInner = function(symbol, font, mode) {
* Make a stacked delimiter out of a given delimiter, with the total height at * Make a stacked delimiter out of a given delimiter, with the total height at
* least `heightTotal`. This routine is mentioned on page 442 of the TeXbook. * least `heightTotal`. This routine is mentioned on page 442 of the TeXbook.
*/ */
var makeStackedDelim = function(delim, heightTotal, center, options, mode, const makeStackedDelim = function(delim, heightTotal, center, options, mode,
classes) { classes) {
// There are four parts, the top, an optional middle, a repeated part, and a // There are four parts, the top, an optional middle, a repeated part, and a
// bottom. // bottom.
var top; let top;
var middle; let middle;
var repeat; let repeat;
var bottom; let bottom;
top = repeat = bottom = delim; top = repeat = bottom = delim;
middle = null; middle = null;
// Also keep track of what font the delimiters are in // Also keep track of what font the delimiters are in
var font = "Size1-Regular"; let font = "Size1-Regular";
// We set the parts and font based on the symbol. Note that we use // We set the parts and font based on the symbol. Note that we use
// '\u23d0' instead of '|' and '\u2016' instead of '\\|' for the // '\u23d0' instead of '|' and '\u2016' instead of '\\|' for the
@@ -251,65 +251,64 @@ var makeStackedDelim = function(delim, heightTotal, center, options, mode,
} }
// Get the metrics of the four sections // Get the metrics of the four sections
var topMetrics = getMetrics(top, font); const topMetrics = getMetrics(top, font);
var topHeightTotal = topMetrics.height + topMetrics.depth; const topHeightTotal = topMetrics.height + topMetrics.depth;
var repeatMetrics = getMetrics(repeat, font); const repeatMetrics = getMetrics(repeat, font);
var repeatHeightTotal = repeatMetrics.height + repeatMetrics.depth; const repeatHeightTotal = repeatMetrics.height + repeatMetrics.depth;
var bottomMetrics = getMetrics(bottom, font); const bottomMetrics = getMetrics(bottom, font);
var bottomHeightTotal = bottomMetrics.height + bottomMetrics.depth; const bottomHeightTotal = bottomMetrics.height + bottomMetrics.depth;
var middleHeightTotal = 0; let middleHeightTotal = 0;
var middleFactor = 1; let middleFactor = 1;
if (middle !== null) { if (middle !== null) {
var middleMetrics = getMetrics(middle, font); const middleMetrics = getMetrics(middle, font);
middleHeightTotal = middleMetrics.height + middleMetrics.depth; middleHeightTotal = middleMetrics.height + middleMetrics.depth;
middleFactor = 2; // repeat symmetrically above and below middle middleFactor = 2; // repeat symmetrically above and below middle
} }
// Calcuate the minimal height that the delimiter can have. // Calcuate the minimal height that the delimiter can have.
// It is at least the size of the top, bottom, and optional middle combined. // It is at least the size of the top, bottom, and optional middle combined.
var minHeight = topHeightTotal + bottomHeightTotal + middleHeightTotal; const minHeight = topHeightTotal + bottomHeightTotal + middleHeightTotal;
// Compute the number of copies of the repeat symbol we will need // Compute the number of copies of the repeat symbol we will need
var repeatCount = Math.ceil( const repeatCount = Math.ceil(
(heightTotal - minHeight) / (middleFactor * repeatHeightTotal)); (heightTotal - minHeight) / (middleFactor * repeatHeightTotal));
// Compute the total height of the delimiter including all the symbols // Compute the total height of the delimiter including all the symbols
var realHeightTotal = const realHeightTotal =
minHeight + repeatCount * middleFactor * repeatHeightTotal; minHeight + repeatCount * middleFactor * repeatHeightTotal;
// The center of the delimiter is placed at the center of the axis. Note // The center of the delimiter is placed at the center of the axis. Note
// that in this context, "center" means that the delimiter should be // that in this context, "center" means that the delimiter should be
// centered around the axis in the current style, while normally it is // centered around the axis in the current style, while normally it is
// centered around the axis in textstyle. // centered around the axis in textstyle.
var axisHeight = options.style.metrics.axisHeight; let axisHeight = options.style.metrics.axisHeight;
if (center) { if (center) {
axisHeight *= options.style.sizeMultiplier; axisHeight *= options.style.sizeMultiplier;
} }
// Calculate the depth // Calculate the depth
var depth = realHeightTotal / 2 - axisHeight; const depth = realHeightTotal / 2 - axisHeight;
// Now, we start building the pieces that will go into the vlist // Now, we start building the pieces that will go into the vlist
// Keep a list of the inner pieces // Keep a list of the inner pieces
var inners = []; const inners = [];
// Add the bottom symbol // Add the bottom symbol
inners.push(makeInner(bottom, font, mode)); inners.push(makeInner(bottom, font, mode));
var i;
if (middle === null) { if (middle === null) {
// Add that many symbols // Add that many symbols
for (i = 0; i < repeatCount; i++) { for (let i = 0; i < repeatCount; i++) {
inners.push(makeInner(repeat, font, mode)); inners.push(makeInner(repeat, font, mode));
} }
} else { } else {
// When there is a middle bit, we need the middle part and two repeated // When there is a middle bit, we need the middle part and two repeated
// sections // sections
for (i = 0; i < repeatCount; i++) { for (let i = 0; i < repeatCount; i++) {
inners.push(makeInner(repeat, font, mode)); inners.push(makeInner(repeat, font, mode));
} }
inners.push(makeInner(middle, font, mode)); inners.push(makeInner(middle, font, mode));
for (i = 0; i < repeatCount; i++) { for (let i = 0; i < repeatCount; i++) {
inners.push(makeInner(repeat, font, mode)); inners.push(makeInner(repeat, font, mode));
} }
} }
@@ -318,7 +317,7 @@ var makeStackedDelim = function(delim, heightTotal, center, options, mode,
inners.push(makeInner(top, font, mode)); inners.push(makeInner(top, font, mode));
// Finally, build the vlist // Finally, build the vlist
var inner = buildCommon.makeVList(inners, "bottom", depth, options); const inner = buildCommon.makeVList(inners, "bottom", depth, options);
return styleWrap( return styleWrap(
makeSpan(["delimsizing", "mult"], [inner], options), makeSpan(["delimsizing", "mult"], [inner], options),
@@ -327,7 +326,7 @@ var makeStackedDelim = function(delim, heightTotal, center, options, mode,
// There are three kinds of delimiters, delimiters that stack when they become // There are three kinds of delimiters, delimiters that stack when they become
// too large // too large
var stackLargeDelimiters = [ const stackLargeDelimiters = [
"(", ")", "[", "\\lbrack", "]", "\\rbrack", "(", ")", "[", "\\lbrack", "]", "\\rbrack",
"\\{", "\\lbrace", "\\}", "\\rbrace", "\\{", "\\lbrace", "\\}", "\\rbrace",
"\\lfloor", "\\rfloor", "\\lceil", "\\rceil", "\\lfloor", "\\rfloor", "\\lceil", "\\rceil",
@@ -335,7 +334,7 @@ var stackLargeDelimiters = [
]; ];
// delimiters that always stack // delimiters that always stack
var stackAlwaysDelimiters = [ const stackAlwaysDelimiters = [
"\\uparrow", "\\downarrow", "\\updownarrow", "\\uparrow", "\\downarrow", "\\updownarrow",
"\\Uparrow", "\\Downarrow", "\\Updownarrow", "\\Uparrow", "\\Downarrow", "\\Updownarrow",
"|", "\\|", "\\vert", "\\Vert", "|", "\\|", "\\vert", "\\Vert",
@@ -344,19 +343,19 @@ var stackAlwaysDelimiters = [
]; ];
// and delimiters that never stack // and delimiters that never stack
var stackNeverDelimiters = [ const stackNeverDelimiters = [
"<", ">", "\\langle", "\\rangle", "/", "\\backslash", "\\lt", "\\gt", "<", ">", "\\langle", "\\rangle", "/", "\\backslash", "\\lt", "\\gt",
]; ];
// Metrics of the different sizes. Found by looking at TeX's output of // Metrics of the different sizes. Found by looking at TeX's output of
// $\bigl| // \Bigl| \biggl| \Biggl| \showlists$ // $\bigl| // \Bigl| \biggl| \Biggl| \showlists$
// Used to create stacked delimiters of appropriate sizes in makeSizedDelim. // Used to create stacked delimiters of appropriate sizes in makeSizedDelim.
var sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0]; const sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0];
/** /**
* Used to create a delimiter of a specific size, where `size` is 1, 2, 3, or 4. * Used to create a delimiter of a specific size, where `size` is 1, 2, 3, or 4.
*/ */
var makeSizedDelim = function(delim, size, options, mode, classes) { const makeSizedDelim = function(delim, size, options, mode, classes) {
// < and > turn into \langle and \rangle in delimiters // < and > turn into \langle and \rangle in delimiters
if (delim === "<" || delim === "\\lt") { if (delim === "<" || delim === "\\lt") {
delim = "\\langle"; delim = "\\langle";
@@ -389,7 +388,7 @@ var makeSizedDelim = function(delim, size, options, mode, classes) {
*/ */
// Delimiters that never stack try small delimiters and large delimiters only // Delimiters that never stack try small delimiters and large delimiters only
var stackNeverDelimiterSequence = [ const stackNeverDelimiterSequence = [
{type: "small", style: Style.SCRIPTSCRIPT}, {type: "small", style: Style.SCRIPTSCRIPT},
{type: "small", style: Style.SCRIPT}, {type: "small", style: Style.SCRIPT},
{type: "small", style: Style.TEXT}, {type: "small", style: Style.TEXT},
@@ -400,7 +399,7 @@ var stackNeverDelimiterSequence = [
]; ];
// Delimiters that always stack try the small delimiters first, then stack // Delimiters that always stack try the small delimiters first, then stack
var stackAlwaysDelimiterSequence = [ const stackAlwaysDelimiterSequence = [
{type: "small", style: Style.SCRIPTSCRIPT}, {type: "small", style: Style.SCRIPTSCRIPT},
{type: "small", style: Style.SCRIPT}, {type: "small", style: Style.SCRIPT},
{type: "small", style: Style.TEXT}, {type: "small", style: Style.TEXT},
@@ -409,7 +408,7 @@ var stackAlwaysDelimiterSequence = [
// Delimiters that stack when large try the small and then large delimiters, and // Delimiters that stack when large try the small and then large delimiters, and
// stack afterwards // stack afterwards
var stackLargeDelimiterSequence = [ const stackLargeDelimiterSequence = [
{type: "small", style: Style.SCRIPTSCRIPT}, {type: "small", style: Style.SCRIPTSCRIPT},
{type: "small", style: Style.SCRIPT}, {type: "small", style: Style.SCRIPT},
{type: "small", style: Style.TEXT}, {type: "small", style: Style.TEXT},
@@ -423,7 +422,7 @@ var stackLargeDelimiterSequence = [
/** /**
* Get the font used in a delimiter based on what kind of delimiter it is. * Get the font used in a delimiter based on what kind of delimiter it is.
*/ */
var delimTypeToFont = function(type) { const delimTypeToFont = function(type) {
if (type.type === "small") { if (type.type === "small") {
return "Main-Regular"; return "Main-Regular";
} else if (type.type === "large") { } else if (type.type === "large") {
@@ -437,20 +436,20 @@ var delimTypeToFont = function(type) {
* Traverse a sequence of types of delimiters to decide what kind of delimiter * Traverse a sequence of types of delimiters to decide what kind of delimiter
* should be used to create a delimiter of the given height+depth. * should be used to create a delimiter of the given height+depth.
*/ */
var traverseSequence = function(delim, height, sequence, options) { const traverseSequence = function(delim, height, sequence, options) {
// Here, we choose the index we should start at in the sequences. In smaller // Here, we choose the index we should start at in the sequences. In smaller
// sizes (which correspond to larger numbers in style.size) we start earlier // sizes (which correspond to larger numbers in style.size) we start earlier
// in the sequence. Thus, scriptscript starts at index 3-3=0, script starts // in the sequence. Thus, scriptscript starts at index 3-3=0, script starts
// at index 3-2=1, text starts at 3-1=2, and display starts at min(2,3-0)=2 // at index 3-2=1, text starts at 3-1=2, and display starts at min(2,3-0)=2
var start = Math.min(2, 3 - options.style.size); const start = Math.min(2, 3 - options.style.size);
for (var i = start; i < sequence.length; i++) { for (let i = start; i < sequence.length; i++) {
if (sequence[i].type === "stack") { if (sequence[i].type === "stack") {
// This is always the last delimiter, so we just break the loop now. // This is always the last delimiter, so we just break the loop now.
break; break;
} }
var metrics = getMetrics(delim, delimTypeToFont(sequence[i])); const metrics = getMetrics(delim, delimTypeToFont(sequence[i]));
var heightDepth = metrics.height + metrics.depth; let heightDepth = metrics.height + metrics.depth;
// Small delimiters are scaled down versions of the same font, so we // Small delimiters are scaled down versions of the same font, so we
// account for the style change size. // account for the style change size.
@@ -473,7 +472,7 @@ var traverseSequence = function(delim, height, sequence, options) {
* Make a delimiter of a given height+depth, with optional centering. Here, we * Make a delimiter of a given height+depth, with optional centering. Here, we
* traverse the sequences, and create a delimiter that the sequence tells us to. * traverse the sequences, and create a delimiter that the sequence tells us to.
*/ */
var makeCustomSizedDelim = function(delim, height, center, options, mode, const makeCustomSizedDelim = function(delim, height, center, options, mode,
classes) { classes) {
if (delim === "<" || delim === "\\lt") { if (delim === "<" || delim === "\\lt") {
delim = "\\langle"; delim = "\\langle";
@@ -482,7 +481,7 @@ var makeCustomSizedDelim = function(delim, height, center, options, mode,
} }
// Decide what sequence to use // Decide what sequence to use
var sequence; let sequence;
if (utils.contains(stackNeverDelimiters, delim)) { if (utils.contains(stackNeverDelimiters, delim)) {
sequence = stackNeverDelimiterSequence; sequence = stackNeverDelimiterSequence;
} else if (utils.contains(stackLargeDelimiters, delim)) { } else if (utils.contains(stackLargeDelimiters, delim)) {
@@ -492,7 +491,7 @@ var makeCustomSizedDelim = function(delim, height, center, options, mode,
} }
// Look through the sequence // Look through the sequence
var delimType = traverseSequence(delim, height, sequence, options); const delimType = traverseSequence(delim, height, sequence, options);
// Depending on the sequence element we decided on, call the appropriate // Depending on the sequence element we decided on, call the appropriate
// function. // function.
@@ -511,20 +510,20 @@ var makeCustomSizedDelim = function(delim, height, center, options, mode,
* Make a delimiter for use with `\left` and `\right`, given a height and depth * Make a delimiter for use with `\left` and `\right`, given a height and depth
* of an expression that the delimiters surround. * of an expression that the delimiters surround.
*/ */
var makeLeftRightDelim = function(delim, height, depth, options, mode, const makeLeftRightDelim = function(delim, height, depth, options, mode,
classes) { classes) {
// We always center \left/\right delimiters, so the axis is always shifted // We always center \left/\right delimiters, so the axis is always shifted
var axisHeight = const axisHeight =
options.style.metrics.axisHeight * options.style.sizeMultiplier; options.style.metrics.axisHeight * options.style.sizeMultiplier;
// Taken from TeX source, tex.web, function make_left_right // Taken from TeX source, tex.web, function make_left_right
var delimiterFactor = 901; const delimiterFactor = 901;
var delimiterExtend = 5.0 / fontMetrics.metrics.ptPerEm; const delimiterExtend = 5.0 / fontMetrics.metrics.ptPerEm;
var maxDistFromAxis = Math.max( const maxDistFromAxis = Math.max(
height - axisHeight, depth + axisHeight); height - axisHeight, depth + axisHeight);
var totalHeight = Math.max( const totalHeight = Math.max(
// In real TeX, calculations are done using integral values which are // In real TeX, calculations are done using integral values which are
// 65536 per pt, or 655360 per em. So, the division here truncates in // 65536 per pt, or 655360 per em. So, the division here truncates in
// TeX but doesn't here, producing different results. If we wanted to // TeX but doesn't here, producing different results. If we wanted to

View File

@@ -7,16 +7,16 @@
* *
* Similar functions for working with MathML nodes exist in mathMLTree.js. * Similar functions for working with MathML nodes exist in mathMLTree.js.
*/ */
var unicodeRegexes = require("./unicodeRegexes"); const unicodeRegexes = require("./unicodeRegexes");
var utils = require("./utils"); const utils = require("./utils");
/** /**
* Create an HTML className based on a list of classes. In addition to joining * Create an HTML className based on a list of classes. In addition to joining
* with spaces, we also remove null or empty classes. * with spaces, we also remove null or empty classes.
*/ */
var createClass = function(classes) { const createClass = function(classes) {
classes = classes.slice(); classes = classes.slice();
for (var i = classes.length - 1; i >= 0; i--) { for (let i = classes.length - 1; i >= 0; i--) {
if (!classes[i]) { if (!classes[i]) {
classes.splice(i, 1); classes.splice(i, 1);
} }
@@ -65,27 +65,27 @@ span.prototype.tryCombine = function(sibling) {
* Convert the span into an HTML node * Convert the span into an HTML node
*/ */
span.prototype.toNode = function() { span.prototype.toNode = function() {
var span = document.createElement("span"); const span = document.createElement("span");
// Apply the class // Apply the class
span.className = createClass(this.classes); span.className = createClass(this.classes);
// Apply inline styles // Apply inline styles
for (var style in this.style) { for (const style in this.style) {
if (Object.prototype.hasOwnProperty.call(this.style, style)) { if (Object.prototype.hasOwnProperty.call(this.style, style)) {
span.style[style] = this.style[style]; span.style[style] = this.style[style];
} }
} }
// Apply attributes // Apply attributes
for (var attr in this.attributes) { for (const attr in this.attributes) {
if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
span.setAttribute(attr, this.attributes[attr]); span.setAttribute(attr, this.attributes[attr]);
} }
} }
// Append the children, also as HTML nodes // Append the children, also as HTML nodes
for (var i = 0; i < this.children.length; i++) { for (let i = 0; i < this.children.length; i++) {
span.appendChild(this.children[i].toNode()); span.appendChild(this.children[i].toNode());
} }
@@ -96,7 +96,7 @@ span.prototype.toNode = function() {
* Convert the span into an HTML markup string * Convert the span into an HTML markup string
*/ */
span.prototype.toMarkup = function() { span.prototype.toMarkup = function() {
var markup = "<span"; let markup = "<span";
// Add the class // Add the class
if (this.classes.length) { if (this.classes.length) {
@@ -105,10 +105,10 @@ span.prototype.toMarkup = function() {
markup += "\""; markup += "\"";
} }
var styles = ""; let styles = "";
// Add the styles, after hyphenation // Add the styles, after hyphenation
for (var style in this.style) { for (const style in this.style) {
if (this.style.hasOwnProperty(style)) { if (this.style.hasOwnProperty(style)) {
styles += utils.hyphenate(style) + ":" + this.style[style] + ";"; styles += utils.hyphenate(style) + ":" + this.style[style] + ";";
} }
@@ -119,7 +119,7 @@ span.prototype.toMarkup = function() {
} }
// Add the attributes // Add the attributes
for (var attr in this.attributes) { for (const attr in this.attributes) {
if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
markup += " " + attr + "=\""; markup += " " + attr + "=\"";
markup += utils.escape(this.attributes[attr]); markup += utils.escape(this.attributes[attr]);
@@ -130,7 +130,7 @@ span.prototype.toMarkup = function() {
markup += ">"; markup += ">";
// Add the markup of the children, also as markup // Add the markup of the children, also as markup
for (var i = 0; i < this.children.length; i++) { for (let i = 0; i < this.children.length; i++) {
markup += this.children[i].toMarkup(); markup += this.children[i].toMarkup();
} }
@@ -157,10 +157,10 @@ function documentFragment(children) {
*/ */
documentFragment.prototype.toNode = function() { documentFragment.prototype.toNode = function() {
// Create a fragment // Create a fragment
var frag = document.createDocumentFragment(); const frag = document.createDocumentFragment();
// Append the children // Append the children
for (var i = 0; i < this.children.length; i++) { for (let i = 0; i < this.children.length; i++) {
frag.appendChild(this.children[i].toNode()); frag.appendChild(this.children[i].toNode());
} }
@@ -171,17 +171,17 @@ documentFragment.prototype.toNode = function() {
* Convert the fragment into HTML markup * Convert the fragment into HTML markup
*/ */
documentFragment.prototype.toMarkup = function() { documentFragment.prototype.toMarkup = function() {
var markup = ""; let markup = "";
// Simply concatenate the markup for the children together // Simply concatenate the markup for the children together
for (var i = 0; i < this.children.length; i++) { for (let i = 0; i < this.children.length; i++) {
markup += this.children[i].toMarkup(); markup += this.children[i].toMarkup();
} }
return markup; return markup;
}; };
var iCombinations = { const iCombinations = {
'î': '\u0131\u0302', 'î': '\u0131\u0302',
'ï': '\u0131\u0308', 'ï': '\u0131\u0308',
'í': '\u0131\u0301', 'í': '\u0131\u0301',
@@ -233,13 +233,13 @@ symbolNode.prototype.tryCombine = function(sibling) {
|| this.maxFontSize !== sibling.maxFontSize) { || this.maxFontSize !== sibling.maxFontSize) {
return false; return false;
} }
for (var style in this.style) { for (const style in this.style) {
if (this.style.hasOwnProperty(style) if (this.style.hasOwnProperty(style)
&& this.style[style] !== sibling.style[style]) { && this.style[style] !== sibling.style[style]) {
return false; return false;
} }
} }
for (style in sibling.style) { for (const style in sibling.style) {
if (sibling.style.hasOwnProperty(style) if (sibling.style.hasOwnProperty(style)
&& this.style[style] !== sibling.style[style]) { && this.style[style] !== sibling.style[style]) {
return false; return false;
@@ -257,8 +257,8 @@ symbolNode.prototype.tryCombine = function(sibling) {
* created if it is needed. * created if it is needed.
*/ */
symbolNode.prototype.toNode = function() { symbolNode.prototype.toNode = function() {
var node = document.createTextNode(this.value); const node = document.createTextNode(this.value);
var span = null; let span = null;
if (this.italic > 0) { if (this.italic > 0) {
span = document.createElement("span"); span = document.createElement("span");
@@ -270,7 +270,7 @@ symbolNode.prototype.toNode = function() {
span.className = createClass(this.classes); span.className = createClass(this.classes);
} }
for (var style in this.style) { for (const style in this.style) {
if (this.style.hasOwnProperty(style)) { if (this.style.hasOwnProperty(style)) {
span = span || document.createElement("span"); span = span || document.createElement("span");
span.style[style] = this.style[style]; span.style[style] = this.style[style];
@@ -291,9 +291,9 @@ symbolNode.prototype.toNode = function() {
symbolNode.prototype.toMarkup = function() { symbolNode.prototype.toMarkup = function() {
// TODO(alpert): More duplication than I'd like from // TODO(alpert): More duplication than I'd like from
// span.prototype.toMarkup and symbolNode.prototype.toNode... // span.prototype.toMarkup and symbolNode.prototype.toNode...
var needsSpan = false; let needsSpan = false;
var markup = "<span"; let markup = "<span";
if (this.classes.length) { if (this.classes.length) {
needsSpan = true; needsSpan = true;
@@ -302,12 +302,12 @@ symbolNode.prototype.toMarkup = function() {
markup += "\""; markup += "\"";
} }
var styles = ""; let styles = "";
if (this.italic > 0) { if (this.italic > 0) {
styles += "margin-right:" + this.italic + "em;"; styles += "margin-right:" + this.italic + "em;";
} }
for (var style in this.style) { for (const style in this.style) {
if (this.style.hasOwnProperty(style)) { if (this.style.hasOwnProperty(style)) {
styles += utils.hyphenate(style) + ":" + this.style[style] + ";"; styles += utils.hyphenate(style) + ":" + this.style[style] + ";";
} }
@@ -318,7 +318,7 @@ symbolNode.prototype.toMarkup = function() {
markup += " style=\"" + utils.escape(styles) + "\""; markup += " style=\"" + utils.escape(styles) + "\"";
} }
var escaped = utils.escape(this.value); const escaped = utils.escape(this.value);
if (needsSpan) { if (needsSpan) {
markup += ">"; markup += ">";
markup += escaped; markup += escaped;

View File

@@ -1,9 +1,9 @@
/* eslint no-constant-condition:0 */ /* eslint no-constant-condition:0 */
var parseData = require("./parseData"); const parseData = require("./parseData");
var ParseError = require("./ParseError"); const ParseError = require("./ParseError");
var Style = require("./Style"); const Style = require("./Style");
var ParseNode = parseData.ParseNode; const ParseNode = parseData.ParseNode;
/** /**
* Parse the body of the environment, with rows delimited by \\ and * Parse the body of the environment, with rows delimited by \\ and
@@ -11,19 +11,19 @@ var ParseNode = parseData.ParseNode;
* with one group per cell. * with one group per cell.
*/ */
function parseArray(parser, result) { function parseArray(parser, result) {
var row = []; let row = [];
var body = [row]; const body = [row];
var rowGaps = []; const rowGaps = [];
while (true) { while (true) {
var cell = parser.parseExpression(false, null); const cell = parser.parseExpression(false, null);
row.push(new ParseNode("ordgroup", cell, parser.mode)); row.push(new ParseNode("ordgroup", cell, parser.mode));
var next = parser.nextToken.text; const next = parser.nextToken.text;
if (next === "&") { if (next === "&") {
parser.consume(); parser.consume();
} else if (next === "\\end") { } else if (next === "\\end") {
break; break;
} else if (next === "\\\\" || next === "\\cr") { } else if (next === "\\\\" || next === "\\cr") {
var cr = parser.parseFunction(); const cr = parser.parseFunction();
rowGaps.push(cr.value.size); rowGaps.push(cr.value.size);
row = []; row = [];
body.push(row); body.push(row);
@@ -69,7 +69,7 @@ function defineEnvironment(names, props, handler) {
props = { numArgs: props }; props = { numArgs: props };
} }
// Set default values of environments // Set default values of environments
var data = { const data = {
numArgs: props.numArgs || 0, numArgs: props.numArgs || 0,
argTypes: props.argTypes, argTypes: props.argTypes,
greediness: 1, greediness: 1,
@@ -77,7 +77,7 @@ function defineEnvironment(names, props, handler) {
numOptionalArgs: props.numOptionalArgs || 0, numOptionalArgs: props.numOptionalArgs || 0,
handler: handler, handler: handler,
}; };
for (var i = 0; i < names.length; ++i) { for (let i = 0; i < names.length; ++i) {
module.exports[names[i]] = data; module.exports[names[i]] = data;
} }
} }
@@ -87,10 +87,10 @@ function defineEnvironment(names, props, handler) {
defineEnvironment("array", { defineEnvironment("array", {
numArgs: 1, numArgs: 1,
}, function(context, args) { }, function(context, args) {
var colalign = args[0]; let colalign = args[0];
colalign = colalign.value.map ? colalign.value : [colalign]; colalign = colalign.value.map ? colalign.value : [colalign];
var cols = colalign.map(function(node) { const cols = colalign.map(function(node) {
var ca = node.value; const ca = node.value;
if ("lcr".indexOf(ca) !== -1) { if ("lcr".indexOf(ca) !== -1) {
return { return {
type: "align", type: "align",
@@ -106,7 +106,7 @@ defineEnvironment("array", {
"Unknown column alignment: " + node.value, "Unknown column alignment: " + node.value,
node); node);
}); });
var res = { let res = {
type: "array", type: "array",
cols: cols, cols: cols,
hskipBeforeAndAfter: true, // \@preamble in lttab.dtx hskipBeforeAndAfter: true, // \@preamble in lttab.dtx
@@ -126,7 +126,7 @@ defineEnvironment([
"Vmatrix", "Vmatrix",
], { ], {
}, function(context) { }, function(context) {
var delimiters = { const delimiters = {
"matrix": null, "matrix": null,
"pmatrix": ["(", ")"], "pmatrix": ["(", ")"],
"bmatrix": ["[", "]"], "bmatrix": ["[", "]"],
@@ -134,7 +134,7 @@ defineEnvironment([
"vmatrix": ["|", "|"], "vmatrix": ["|", "|"],
"Vmatrix": ["\\Vert", "\\Vert"], "Vmatrix": ["\\Vert", "\\Vert"],
}[context.envName]; }[context.envName];
var res = { let res = {
type: "array", type: "array",
hskipBeforeAndAfter: false, // \hskip -\arraycolsep in amsmath hskipBeforeAndAfter: false, // \hskip -\arraycolsep in amsmath
}; };
@@ -154,7 +154,7 @@ defineEnvironment([
// \left\{\begin{array}{@{}l@{\quad}l@{}} … \end{array}\right. // \left\{\begin{array}{@{}l@{\quad}l@{}} … \end{array}\right.
defineEnvironment("cases", { defineEnvironment("cases", {
}, function(context) { }, function(context) {
var res = { let res = {
type: "array", type: "array",
arraystretch: 1.2, arraystretch: 1.2,
cols: [{ cols: [{
@@ -188,25 +188,24 @@ defineEnvironment("cases", {
// so that \strut@ is the same as \strut. // so that \strut@ is the same as \strut.
defineEnvironment("aligned", { defineEnvironment("aligned", {
}, function(context) { }, function(context) {
var res = { let res = {
type: "array", type: "array",
cols: [], cols: [],
}; };
res = parseArray(context.parser, res); res = parseArray(context.parser, res);
var emptyGroup = new ParseNode("ordgroup", [], context.mode); const emptyGroup = new ParseNode("ordgroup", [], context.mode);
var numCols = 0; let numCols = 0;
res.value.body.forEach(function(row) { res.value.body.forEach(function(row) {
var i; for (let i = 1; i < row.length; i += 2) {
for (i = 1; i < row.length; i += 2) {
row[i].value.unshift(emptyGroup); row[i].value.unshift(emptyGroup);
} }
if (numCols < row.length) { if (numCols < row.length) {
numCols = row.length; numCols = row.length;
} }
}); });
for (var i = 0; i < numCols; ++i) { for (let i = 0; i < numCols; ++i) {
var align = "r"; let align = "r";
var pregap = 0; let pregap = 0;
if (i % 2 === 1) { if (i % 2 === 1) {
align = "l"; align = "l";
} else if (i > 0) { } else if (i > 0) {

View File

@@ -1,7 +1,7 @@
/* eslint no-unused-vars:0 */ /* eslint no-unused-vars:0 */
var Style = require("./Style"); const Style = require("./Style");
var cjkRegex = require("./unicodeRegexes").cjkRegex; const cjkRegex = require("./unicodeRegexes").cjkRegex;
/** /**
* This file contains metrics regarding fonts and individual symbols. The sigma * This file contains metrics regarding fonts and individual symbols. The sigma
@@ -32,7 +32,7 @@ var cjkRegex = require("./unicodeRegexes").cjkRegex;
// //
// The output of each of these commands is quite lengthy. The only part we // The output of each of these commands is quite lengthy. The only part we
// care about is the FONTDIMEN section. Each value is measured in EMs. // care about is the FONTDIMEN section. Each value is measured in EMs.
var sigmas = { const sigmas = {
slant: [0.250, 0.250, 0.250], // sigma1 slant: [0.250, 0.250, 0.250], // sigma1
space: [0.000, 0.000, 0.000], // sigma2 space: [0.000, 0.000, 0.000], // sigma2
stretch: [0.000, 0.000, 0.000], // sigma3 stretch: [0.000, 0.000, 0.000], // sigma3
@@ -62,34 +62,34 @@ var sigmas = {
// \showthe\fontdimenX\a // \showthe\fontdimenX\a
// where X is the corresponding variable number. These correspond to the font // where X is the corresponding variable number. These correspond to the font
// parameters of the extension fonts (family 3). See the TeXbook, page 441. // parameters of the extension fonts (family 3). See the TeXbook, page 441.
var xi1 = 0; const xi1 = 0;
var xi2 = 0; const xi2 = 0;
var xi3 = 0; const xi3 = 0;
var xi4 = 0; const xi4 = 0;
var xi5 = 0.431; const xi5 = 0.431;
var xi6 = 1; const xi6 = 1;
var xi7 = 0; const xi7 = 0;
var xi8 = 0.04; const xi8 = 0.04;
var xi9 = 0.111; const xi9 = 0.111;
var xi10 = 0.166; const xi10 = 0.166;
var xi11 = 0.2; const xi11 = 0.2;
var xi12 = 0.6; const xi12 = 0.6;
var xi13 = 0.1; const xi13 = 0.1;
// This value determines how large a pt is, for metrics which are defined in // This value determines how large a pt is, for metrics which are defined in
// terms of pts. // terms of pts.
// This value is also used in katex.less; if you change it make sure the values // This value is also used in katex.less; if you change it make sure the values
// match. // match.
var ptPerEm = 10.0; const ptPerEm = 10.0;
// The space between adjacent `|` columns in an array definition. From // The space between adjacent `|` columns in an array definition. From
// `\showthe\doublerulesep` in LaTeX. // `\showthe\doublerulesep` in LaTeX.
var doubleRuleSep = 2.0 / ptPerEm; const doubleRuleSep = 2.0 / ptPerEm;
/** /**
* This is just a mapping from common names to real metrics * This is just a mapping from common names to real metrics
*/ */
var metrics = { const metrics = {
defaultRuleThickness: xi8, defaultRuleThickness: xi8,
bigOpSpacing1: xi9, bigOpSpacing1: xi9,
bigOpSpacing2: xi10, bigOpSpacing2: xi10,
@@ -104,7 +104,7 @@ var metrics = {
// metrics, including height, depth, italic correction, and skew (kern from the // metrics, including height, depth, italic correction, and skew (kern from the
// character to the corresponding \skewchar) // character to the corresponding \skewchar)
// This map is generated via `make metrics`. It should not be changed manually. // This map is generated via `make metrics`. It should not be changed manually.
var metricMap = require("./fontMetricsData"); const metricMap = require("./fontMetricsData");
// These are very rough approximations. We default to Times New Roman which // These are very rough approximations. We default to Times New Roman which
// should have Latin-1 and Cyrillic characters, but may not depending on the // should have Latin-1 and Cyrillic characters, but may not depending on the
@@ -113,7 +113,7 @@ var metricMap = require("./fontMetricsData");
// descenders we prefer approximations with ascenders, primarily to prevent // descenders we prefer approximations with ascenders, primarily to prevent
// the fraction bar or root line from intersecting the glyph. // the fraction bar or root line from intersecting the glyph.
// TODO(kevinb) allow union of multiple glyph metrics for better accuracy. // TODO(kevinb) allow union of multiple glyph metrics for better accuracy.
var extraCharacterMap = { const extraCharacterMap = {
// Latin-1 // Latin-1
'À': 'A', 'À': 'A',
'Á': 'A', 'Á': 'A',
@@ -252,14 +252,14 @@ var extraCharacterMap = {
* Note: the `width` property may be undefined if fontMetricsData.js wasn't * Note: the `width` property may be undefined if fontMetricsData.js wasn't
* built using `Make extended_metrics`. * built using `Make extended_metrics`.
*/ */
var getCharacterMetrics = function(character, style) { const getCharacterMetrics = function(character, style) {
var ch = character.charCodeAt(0); let ch = character.charCodeAt(0);
if (character[0] in extraCharacterMap) { if (character[0] in extraCharacterMap) {
ch = extraCharacterMap[character[0]].charCodeAt(0); ch = extraCharacterMap[character[0]].charCodeAt(0);
} else if (cjkRegex.test(character[0])) { } else if (cjkRegex.test(character[0])) {
ch = 'M'.charCodeAt(0); ch = 'M'.charCodeAt(0);
} }
var metrics = metricMap[style][ch]; const metrics = metricMap[style][ch];
if (metrics) { if (metrics) {
return { return {
depth: metrics[0], depth: metrics[0],

View File

@@ -1,7 +1,7 @@
var utils = require("./utils"); const utils = require("./utils");
var ParseError = require("./ParseError"); const ParseError = require("./ParseError");
var parseData = require("./parseData"); const parseData = require("./parseData");
var ParseNode = parseData.ParseNode; const ParseNode = parseData.ParseNode;
/* This file contains a list of functions that we parse, identified by /* This file contains a list of functions that we parse, identified by
* the calls to defineFunction. * the calls to defineFunction.
@@ -88,7 +88,7 @@ function defineFunction(names, props, handler) {
props = { numArgs: props }; props = { numArgs: props };
} }
// Set default values of functions // Set default values of functions
var data = { const data = {
numArgs: props.numArgs, numArgs: props.numArgs,
argTypes: props.argTypes, argTypes: props.argTypes,
greediness: (props.greediness === undefined) ? 1 : props.greediness, greediness: (props.greediness === undefined) ? 1 : props.greediness,
@@ -97,14 +97,14 @@ function defineFunction(names, props, handler) {
infix: !!props.infix, infix: !!props.infix,
handler: handler, handler: handler,
}; };
for (var i = 0; i < names.length; ++i) { for (let i = 0; i < names.length; ++i) {
module.exports[names[i]] = data; module.exports[names[i]] = data;
} }
} }
// Since the corresponding buildHTML/buildMathML function expects a // Since the corresponding buildHTML/buildMathML function expects a
// list of elements, we normalize for different kinds of arguments // list of elements, we normalize for different kinds of arguments
var ordargument = function(arg) { const ordargument = function(arg) {
if (arg.type === "ordgroup") { if (arg.type === "ordgroup") {
return arg.value; return arg.value;
} else { } else {
@@ -117,8 +117,8 @@ defineFunction("\\sqrt", {
numArgs: 1, numArgs: 1,
numOptionalArgs: 1, numOptionalArgs: 1,
}, function(context, args) { }, function(context, args) {
var index = args[0]; const index = args[0];
var body = args[1]; const body = args[1];
return { return {
type: "sqrt", type: "sqrt",
body: body, body: body,
@@ -127,7 +127,7 @@ defineFunction("\\sqrt", {
}); });
// Non-mathy text, possibly in a font // Non-mathy text, possibly in a font
var textFunctionStyles = { const textFunctionStyles = {
"\\text": undefined, "\\textrm": "mathrm", "\\textsf": "mathsf", "\\text": undefined, "\\textrm": "mathrm", "\\textsf": "mathsf",
"\\texttt": "mathtt", "\\textnormal": "mathrm", "\\textbf": "mathbf", "\\texttt": "mathtt", "\\textnormal": "mathrm", "\\textbf": "mathbf",
"\\textit": "textit", "\\textit": "textit",
@@ -142,7 +142,7 @@ defineFunction([
greediness: 2, greediness: 2,
allowedInText: true, allowedInText: true,
}, function(context, args) { }, function(context, args) {
var body = args[0]; const body = args[0];
return { return {
type: "text", type: "text",
body: ordargument(body), body: ordargument(body),
@@ -157,8 +157,8 @@ defineFunction("\\color", {
greediness: 3, greediness: 3,
argTypes: ["color", "original"], argTypes: ["color", "original"],
}, function(context, args) { }, function(context, args) {
var color = args[0]; const color = args[0];
var body = args[1]; const body = args[1];
return { return {
type: "color", type: "color",
color: color.value, color: color.value,
@@ -170,7 +170,7 @@ defineFunction("\\color", {
defineFunction("\\overline", { defineFunction("\\overline", {
numArgs: 1, numArgs: 1,
}, function(context, args) { }, function(context, args) {
var body = args[0]; const body = args[0];
return { return {
type: "overline", type: "overline",
body: body, body: body,
@@ -181,7 +181,7 @@ defineFunction("\\overline", {
defineFunction("\\underline", { defineFunction("\\underline", {
numArgs: 1, numArgs: 1,
}, function(context, args) { }, function(context, args) {
var body = args[0]; const body = args[0];
return { return {
type: "underline", type: "underline",
body: body, body: body,
@@ -194,9 +194,9 @@ defineFunction("\\rule", {
numOptionalArgs: 1, numOptionalArgs: 1,
argTypes: ["size", "size", "size"], argTypes: ["size", "size", "size"],
}, function(context, args) { }, function(context, args) {
var shift = args[0]; const shift = args[0];
var width = args[1]; const width = args[1];
var height = args[2]; const height = args[2];
return { return {
type: "rule", type: "rule",
shift: shift && shift.value, shift: shift && shift.value,
@@ -229,7 +229,7 @@ defineFunction("\\KaTeX", {
defineFunction("\\phantom", { defineFunction("\\phantom", {
numArgs: 1, numArgs: 1,
}, function(context, args) { }, function(context, args) {
var body = args[0]; const body = args[0];
return { return {
type: "phantom", type: "phantom",
value: ordargument(body), value: ordargument(body),
@@ -243,7 +243,7 @@ defineFunction([
], { ], {
numArgs: 1, numArgs: 1,
}, function(context, args) { }, function(context, args) {
var body = args[0]; const body = args[0];
return { return {
type: "mclass", type: "mclass",
mclass: "m" + context.funcName.substr(5), mclass: "m" + context.funcName.substr(5),
@@ -255,10 +255,10 @@ defineFunction([
defineFunction("\\stackrel", { defineFunction("\\stackrel", {
numArgs: 2, numArgs: 2,
}, function(context, args) { }, function(context, args) {
var top = args[0]; const top = args[0];
var bottom = args[1]; const bottom = args[1];
var bottomop = new ParseNode("op", { const bottomop = new ParseNode("op", {
type: "op", type: "op",
limits: true, limits: true,
alwaysHandleSupSub: true, alwaysHandleSupSub: true,
@@ -266,7 +266,7 @@ defineFunction("\\stackrel", {
value: ordargument(bottom), value: ordargument(bottom),
}, bottom.mode); }, bottom.mode);
var supsub = new ParseNode("supsub", { const supsub = new ParseNode("supsub", {
base: bottomop, base: bottomop,
sup: top, sup: top,
sub: null, sub: null,
@@ -293,7 +293,7 @@ defineFunction("\\bmod", {
defineFunction(["\\pod", "\\pmod", "\\mod"], { defineFunction(["\\pod", "\\pmod", "\\mod"], {
numArgs: 1, numArgs: 1,
}, function(context, args) { }, function(context, args) {
var body = args[0]; const body = args[0];
return { return {
type: "mod", type: "mod",
modType: context.funcName.substr(1), modType: context.funcName.substr(1),
@@ -302,7 +302,7 @@ defineFunction(["\\pod", "\\pmod", "\\mod"], {
}); });
// Extra data needed for the delimiter handler down below // Extra data needed for the delimiter handler down below
var delimiterSizes = { const delimiterSizes = {
"\\bigl" : {mclass: "mopen", size: 1}, "\\bigl" : {mclass: "mopen", size: 1},
"\\Bigl" : {mclass: "mopen", size: 2}, "\\Bigl" : {mclass: "mopen", size: 2},
"\\biggl": {mclass: "mopen", size: 3}, "\\biggl": {mclass: "mopen", size: 3},
@@ -321,7 +321,7 @@ var delimiterSizes = {
"\\Bigg" : {mclass: "mord", size: 4}, "\\Bigg" : {mclass: "mord", size: 4},
}; };
var delimiters = [ const delimiters = [
"(", ")", "[", "\\lbrack", "]", "\\rbrack", "(", ")", "[", "\\lbrack", "]", "\\rbrack",
"\\{", "\\lbrace", "\\}", "\\rbrace", "\\{", "\\lbrace", "\\}", "\\rbrace",
"\\lfloor", "\\rfloor", "\\lceil", "\\rceil", "\\lfloor", "\\rfloor", "\\lceil", "\\rceil",
@@ -336,7 +336,7 @@ var delimiters = [
".", ".",
]; ];
var fontAliases = { const fontAliases = {
"\\Bbb": "\\mathbb", "\\Bbb": "\\mathbb",
"\\bold": "\\mathbf", "\\bold": "\\mathbf",
"\\frak": "\\mathfrak", "\\frak": "\\mathfrak",
@@ -362,7 +362,7 @@ defineFunction([
allowedInText: true, allowedInText: true,
greediness: 3, greediness: 3,
}, function(context, args) { }, function(context, args) {
var body = args[0]; const body = args[0];
return { return {
type: "color", type: "color",
color: "katex-" + context.funcName.slice(1), color: "katex-" + context.funcName.slice(1),
@@ -440,7 +440,7 @@ defineFunction([
defineFunction("\\mathop", { defineFunction("\\mathop", {
numArgs: 1, numArgs: 1,
}, function(context, args) { }, function(context, args) {
var body = args[0]; const body = args[0];
return { return {
type: "op", type: "op",
limits: false, limits: false,
@@ -458,12 +458,12 @@ defineFunction([
numArgs: 2, numArgs: 2,
greediness: 2, greediness: 2,
}, function(context, args) { }, function(context, args) {
var numer = args[0]; const numer = args[0];
var denom = args[1]; const denom = args[1];
var hasBarLine; let hasBarLine;
var leftDelim = null; let leftDelim = null;
var rightDelim = null; let rightDelim = null;
var size = "auto"; let size = "auto";
switch (context.funcName) { switch (context.funcName) {
case "\\dfrac": case "\\dfrac":
@@ -512,7 +512,7 @@ defineFunction(["\\llap", "\\rlap"], {
numArgs: 1, numArgs: 1,
allowedInText: true, allowedInText: true,
}, function(context, args) { }, function(context, args) {
var body = args[0]; const body = args[0];
return { return {
type: context.funcName.slice(1), type: context.funcName.slice(1),
body: body, body: body,
@@ -520,7 +520,7 @@ defineFunction(["\\llap", "\\rlap"], {
}); });
// Delimiter functions // Delimiter functions
var checkDelimiter = function(delim, context) { const checkDelimiter = function(delim, context) {
if (utils.contains(delimiters, delim.value)) { if (utils.contains(delimiters, delim.value)) {
return delim; return delim;
} else { } else {
@@ -538,7 +538,7 @@ defineFunction([
], { ], {
numArgs: 1, numArgs: 1,
}, function(context, args) { }, function(context, args) {
var delim = checkDelimiter(args[0], context); const delim = checkDelimiter(args[0], context);
return { return {
type: "delimsizing", type: "delimsizing",
@@ -553,7 +553,7 @@ defineFunction([
], { ], {
numArgs: 1, numArgs: 1,
}, function(context, args) { }, function(context, args) {
var delim = checkDelimiter(args[0], context); const delim = checkDelimiter(args[0], context);
// \left and \right are caught somewhere in Parser.js, which is // \left and \right are caught somewhere in Parser.js, which is
// why this data doesn't match what is in buildHTML. // why this data doesn't match what is in buildHTML.
@@ -566,7 +566,7 @@ defineFunction([
defineFunction("\\middle", { defineFunction("\\middle", {
numArgs: 1, numArgs: 1,
}, function(context, args) { }, function(context, args) {
var delim = checkDelimiter(args[0], context); const delim = checkDelimiter(args[0], context);
if (!context.parser.leftrightDepth) { if (!context.parser.leftrightDepth) {
throw new ParseError("\\middle without preceding \\left", delim); throw new ParseError("\\middle without preceding \\left", delim);
} }
@@ -604,8 +604,8 @@ defineFunction([
numArgs: 1, numArgs: 1,
greediness: 2, greediness: 2,
}, function(context, args) { }, function(context, args) {
var body = args[0]; const body = args[0];
var func = context.funcName; let func = context.funcName;
if (func in fontAliases) { if (func in fontAliases) {
func = fontAliases[func]; func = fontAliases[func];
} }
@@ -625,7 +625,7 @@ defineFunction([
], { ], {
numArgs: 1, numArgs: 1,
}, function(context, args) { }, function(context, args) {
var base = args[0]; const base = args[0];
return { return {
type: "accent", type: "accent",
accent: context.funcName, accent: context.funcName,
@@ -638,7 +638,7 @@ defineFunction(["\\over", "\\choose", "\\atop"], {
numArgs: 0, numArgs: 0,
infix: true, infix: true,
}, function(context) { }, function(context) {
var replaceWith; let replaceWith;
switch (context.funcName) { switch (context.funcName) {
case "\\over": case "\\over":
replaceWith = "\\frac"; replaceWith = "\\frac";
@@ -665,7 +665,7 @@ defineFunction(["\\\\", "\\cr"], {
numOptionalArgs: 1, numOptionalArgs: 1,
argTypes: ["size"], argTypes: ["size"],
}, function(context, args) { }, function(context, args) {
var size = args[0]; const size = args[0];
return { return {
type: "cr", type: "cr",
size: size, size: size,
@@ -677,12 +677,12 @@ defineFunction(["\\begin", "\\end"], {
numArgs: 1, numArgs: 1,
argTypes: ["text"], argTypes: ["text"],
}, function(context, args) { }, function(context, args) {
var nameGroup = args[0]; const nameGroup = args[0];
if (nameGroup.type !== "ordgroup") { if (nameGroup.type !== "ordgroup") {
throw new ParseError("Invalid environment name", nameGroup); throw new ParseError("Invalid environment name", nameGroup);
} }
var name = ""; let name = "";
for (var i = 0; i < nameGroup.value.length; ++i) { for (let i = 0; i < nameGroup.value.length; ++i) {
name += nameGroup.value[i].value; name += nameGroup.value[i].value;
} }
return { return {

View File

@@ -8,7 +8,7 @@
* domTree.js, creating namespaced DOM nodes and HTML text markup respectively. * domTree.js, creating namespaced DOM nodes and HTML text markup respectively.
*/ */
var utils = require("./utils"); const utils = require("./utils");
/** /**
* This node represents a general purpose MathML node of any type. The * This node represents a general purpose MathML node of any type. The
@@ -33,16 +33,16 @@ MathNode.prototype.setAttribute = function(name, value) {
* Converts the math node into a MathML-namespaced DOM element. * Converts the math node into a MathML-namespaced DOM element.
*/ */
MathNode.prototype.toNode = function() { MathNode.prototype.toNode = function() {
var node = document.createElementNS( const node = document.createElementNS(
"http://www.w3.org/1998/Math/MathML", this.type); "http://www.w3.org/1998/Math/MathML", this.type);
for (var attr in this.attributes) { for (const attr in this.attributes) {
if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
node.setAttribute(attr, this.attributes[attr]); node.setAttribute(attr, this.attributes[attr]);
} }
} }
for (var i = 0; i < this.children.length; i++) { for (let i = 0; i < this.children.length; i++) {
node.appendChild(this.children[i].toNode()); node.appendChild(this.children[i].toNode());
} }
@@ -53,10 +53,10 @@ MathNode.prototype.toNode = function() {
* Converts the math node into an HTML markup string. * Converts the math node into an HTML markup string.
*/ */
MathNode.prototype.toMarkup = function() { MathNode.prototype.toMarkup = function() {
var markup = "<" + this.type; let markup = "<" + this.type;
// Add the attributes // Add the attributes
for (var attr in this.attributes) { for (const attr in this.attributes) {
if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
markup += " " + attr + "=\""; markup += " " + attr + "=\"";
markup += utils.escape(this.attributes[attr]); markup += utils.escape(this.attributes[attr]);
@@ -66,7 +66,7 @@ MathNode.prototype.toMarkup = function() {
markup += ">"; markup += ">";
for (var i = 0; i < this.children.length; i++) { for (let i = 0; i < this.children.length; i++) {
markup += this.children[i].toMarkup(); markup += this.children[i].toMarkup();
} }

View File

@@ -3,16 +3,16 @@
* TODO(emily): Remove this * TODO(emily): Remove this
*/ */
var Parser = require("./Parser"); const Parser = require("./Parser");
/** /**
* Parses an expression using a Parser, then returns the parsed result. * Parses an expression using a Parser, then returns the parsed result.
*/ */
var parseTree = function(toParse, settings) { const parseTree = function(toParse, settings) {
if (!(typeof toParse === 'string' || toParse instanceof String)) { if (!(typeof toParse === 'string' || toParse instanceof String)) {
throw new TypeError('KaTeX can only parse string typed expression'); throw new TypeError('KaTeX can only parse string typed expression');
} }
var parser = new Parser(toParse, settings); const parser = new Parser(toParse, settings);
return parser.parse(); return parser.parse();
}; };

View File

@@ -33,25 +33,25 @@ function defineSymbol(mode, font, group, replace, name) {
// This helps minify the code, and also spotting typos using jshint. // This helps minify the code, and also spotting typos using jshint.
// modes: // modes:
var math = "math"; const math = "math";
var text = "text"; const text = "text";
// fonts: // fonts:
var main = "main"; const main = "main";
var ams = "ams"; const ams = "ams";
// groups: // groups:
var accent = "accent"; const accent = "accent";
var bin = "bin"; const bin = "bin";
var close = "close"; const close = "close";
var inner = "inner"; const inner = "inner";
var mathord = "mathord"; const mathord = "mathord";
var op = "op"; const op = "op";
var open = "open"; const open = "open";
var punct = "punct"; const punct = "punct";
var rel = "rel"; const rel = "rel";
var spacing = "spacing"; const spacing = "spacing";
var textord = "textord"; const textord = "textord";
// Now comes the symbol table // Now comes the symbol table
@@ -616,50 +616,48 @@ defineSymbol(text, main, spacing, "\u00a0", " ");
defineSymbol(text, main, spacing, "\u00a0", "~"); defineSymbol(text, main, spacing, "\u00a0", "~");
// There are lots of symbols which are the same, so we add them in afterwards. // There are lots of symbols which are the same, so we add them in afterwards.
var i;
var ch;
// All of these are textords in math mode // All of these are textords in math mode
var mathTextSymbols = "0123456789/@.\""; const mathTextSymbols = "0123456789/@.\"";
for (i = 0; i < mathTextSymbols.length; i++) { for (let i = 0; i < mathTextSymbols.length; i++) {
ch = mathTextSymbols.charAt(i); const ch = mathTextSymbols.charAt(i);
defineSymbol(math, main, textord, ch, ch); defineSymbol(math, main, textord, ch, ch);
} }
// All of these are textords in text mode // All of these are textords in text mode
var textSymbols = "0123456789!@*()-=+[]\";:?/.,"; const textSymbols = "0123456789!@*()-=+[]\";:?/.,";
for (i = 0; i < textSymbols.length; i++) { for (let i = 0; i < textSymbols.length; i++) {
ch = textSymbols.charAt(i); const ch = textSymbols.charAt(i);
defineSymbol(text, main, textord, ch, ch); defineSymbol(text, main, textord, ch, ch);
} }
// All of these are textords in text mode, and mathords in math mode // All of these are textords in text mode, and mathords in math mode
var letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (i = 0; i < letters.length; i++) { for (let i = 0; i < letters.length; i++) {
ch = letters.charAt(i); const ch = letters.charAt(i);
defineSymbol(math, main, mathord, ch, ch); defineSymbol(math, main, mathord, ch, ch);
defineSymbol(text, main, textord, ch, ch); defineSymbol(text, main, textord, ch, ch);
} }
// Latin-1 letters // Latin-1 letters
for (i = 0x00C0; i <= 0x00D6; i++) { for (let i = 0x00C0; i <= 0x00D6; i++) {
ch = String.fromCharCode(i); const ch = String.fromCharCode(i);
defineSymbol(text, main, textord, ch, ch); defineSymbol(text, main, textord, ch, ch);
} }
for (i = 0x00D8; i <= 0x00F6; i++) { for (let i = 0x00D8; i <= 0x00F6; i++) {
ch = String.fromCharCode(i); const ch = String.fromCharCode(i);
defineSymbol(text, main, textord, ch, ch); defineSymbol(text, main, textord, ch, ch);
} }
for (i = 0x00F8; i <= 0x00FF; i++) { for (let i = 0x00F8; i <= 0x00FF; i++) {
ch = String.fromCharCode(i); const ch = String.fromCharCode(i);
defineSymbol(text, main, textord, ch, ch); defineSymbol(text, main, textord, ch, ch);
} }
// Cyrillic // Cyrillic
for (i = 0x0410; i <= 0x044F; i++) { for (let i = 0x0410; i <= 0x044F; i++) {
ch = String.fromCharCode(i); const ch = String.fromCharCode(i);
defineSymbol(text, main, textord, ch, ch); defineSymbol(text, main, textord, ch, ch);
} }

View File

@@ -1,4 +1,4 @@
var hangulRegex = /[\uAC00-\uD7AF]/; const hangulRegex = /[\uAC00-\uD7AF]/;
// This regex combines // This regex combines
// - Hiragana: [\u3040-\u309F] // - Hiragana: [\u3040-\u309F]
@@ -6,7 +6,7 @@ var hangulRegex = /[\uAC00-\uD7AF]/;
// - CJK ideograms: [\u4E00-\u9FAF] // - CJK ideograms: [\u4E00-\u9FAF]
// - Hangul syllables: [\uAC00-\uD7AF] // - Hangul syllables: [\uAC00-\uD7AF]
// Notably missing are halfwidth Katakana and Romanji glyphs. // Notably missing are halfwidth Katakana and Romanji glyphs.
var cjkRegex = const cjkRegex =
/[\u3040-\u309F]|[\u30A0-\u30FF]|[\u4E00-\u9FAF]|[\uAC00-\uD7AF]/; /[\u3040-\u309F]|[\u30A0-\u30FF]|[\u4E00-\u9FAF]|[\uAC00-\uD7AF]/;
module.exports = { module.exports = {

View File

@@ -7,17 +7,16 @@
* Provide an `indexOf` function which works in IE8, but defers to native if * Provide an `indexOf` function which works in IE8, but defers to native if
* possible. * possible.
*/ */
var nativeIndexOf = Array.prototype.indexOf; const nativeIndexOf = Array.prototype.indexOf;
var indexOf = function(list, elem) { const indexOf = function(list, elem) {
if (list == null) { if (list == null) {
return -1; return -1;
} }
if (nativeIndexOf && list.indexOf === nativeIndexOf) { if (nativeIndexOf && list.indexOf === nativeIndexOf) {
return list.indexOf(elem); return list.indexOf(elem);
} }
var i = 0; const l = list.length;
var l = list.length; for (let i = 0; i < l; i++) {
for (; i < l; i++) {
if (list[i] === elem) { if (list[i] === elem) {
return i; return i;
} }
@@ -28,25 +27,25 @@ var indexOf = function(list, elem) {
/** /**
* Return whether an element is contained in a list * Return whether an element is contained in a list
*/ */
var contains = function(list, elem) { const contains = function(list, elem) {
return indexOf(list, elem) !== -1; return indexOf(list, elem) !== -1;
}; };
/** /**
* Provide a default value if a setting is undefined * Provide a default value if a setting is undefined
*/ */
var deflt = function(setting, defaultIfUndefined) { const deflt = function(setting, defaultIfUndefined) {
return setting === undefined ? defaultIfUndefined : setting; return setting === undefined ? defaultIfUndefined : setting;
}; };
// hyphenate and escape adapted from Facebook's React under Apache 2 license // hyphenate and escape adapted from Facebook's React under Apache 2 license
var uppercase = /([A-Z])/g; const uppercase = /([A-Z])/g;
var hyphenate = function(str) { const hyphenate = function(str) {
return str.replace(uppercase, "-$1").toLowerCase(); return str.replace(uppercase, "-$1").toLowerCase();
}; };
var ESCAPE_LOOKUP = { const ESCAPE_LOOKUP = {
"&": "&amp;", "&": "&amp;",
">": "&gt;", ">": "&gt;",
"<": "&lt;", "<": "&lt;",
@@ -54,7 +53,7 @@ var ESCAPE_LOOKUP = {
"'": "&#x27;", "'": "&#x27;",
}; };
var ESCAPE_REGEX = /[&><"']/g; const ESCAPE_REGEX = /[&><"']/g;
function escaper(match) { function escaper(match) {
return ESCAPE_LOOKUP[match]; return ESCAPE_LOOKUP[match];
@@ -74,9 +73,9 @@ function escape(text) {
* A function to set the text content of a DOM element in all supported * A function to set the text content of a DOM element in all supported
* browsers. Note that we don't define this if there is no document. * browsers. Note that we don't define this if there is no document.
*/ */
var setTextContent; let setTextContent;
if (typeof document !== "undefined") { if (typeof document !== "undefined") {
var testNode = document.createElement("span"); const testNode = document.createElement("span");
if ("textContent" in testNode) { if ("textContent" in testNode) {
setTextContent = function(node, text) { setTextContent = function(node, text) {
node.textContent = text; node.textContent = text;

View File

@@ -4,15 +4,15 @@
/* global it: false */ /* global it: false */
/* global describe: false */ /* global describe: false */
var parseTree = require("../src/parseTree"); const parseTree = require("../src/parseTree");
var Settings = require("../src/Settings"); const Settings = require("../src/Settings");
var defaultSettings = new Settings({}); const defaultSettings = new Settings({});
beforeEach(function() { beforeEach(function() {
jasmine.addMatchers({ jasmine.addMatchers({
toFailWithParseError: function(util, customEqualityTesters) { toFailWithParseError: function(util, customEqualityTesters) {
var prefix = "KaTeX parse error: "; const prefix = "KaTeX parse error: ";
return { return {
compare: function(actual, expected) { compare: function(actual, expected) {
try { try {
@@ -28,8 +28,8 @@ beforeEach(function() {
message: "'" + actual + "' parsed with error", message: "'" + actual + "' parsed with error",
}; };
} }
var msg = e.message; const msg = e.message;
var exp = prefix + expected; const exp = prefix + expected;
if (msg === exp) { if (msg === exp) {
return { return {
pass: true, pass: true,

File diff suppressed because it is too large Load Diff

View File

@@ -1,20 +1,20 @@
/* eslint no-console:0 */ /* eslint no-console:0 */
"use strict"; "use strict";
var fs = require("fs"); const fs = require("fs");
var childProcess = require("child_process"); const childProcess = require("child_process");
var opts = require("nomnom") const opts = require("nomnom")
.option("spacing", { .option("spacing", {
flag: true, flag: true,
help: "Print mismatches involving spacing commands", help: "Print mismatches involving spacing commands",
}) })
.parse(); .parse();
var symbols = require("../src/symbols"); const symbols = require("../src/symbols");
var keys = Object.keys(symbols.math); const keys = Object.keys(symbols.math);
keys.sort(); keys.sort();
var types = [ const types = [
"mathord", "op", "bin", "rel", "open", "close", "punct", "inner", "mathord", "op", "bin", "rel", "open", "close", "punct", "inner",
"spacing", "accent", "textord", "spacing", "accent", "textord",
]; ];
@@ -22,22 +22,22 @@ var types = [
process.nextTick(writeTexFile); process.nextTick(writeTexFile);
function writeTexFile() { function writeTexFile() {
var tex = fs.createWriteStream("symgroups.tex"); const tex = fs.createWriteStream("symgroups.tex");
tex.on("finish", typeset); tex.on("finish", typeset);
tex.write("\\documentclass{article}\n" + tex.write("\\documentclass{article}\n" +
"\\usepackage{textcomp,amsmath,amssymb,gensymb}\n" + "\\usepackage{textcomp,amsmath,amssymb,gensymb}\n" +
"\\begin{document}\n" + "\\begin{document}\n" +
"\\showboxbreadth=\\maxdimen\\showboxdepth=\\maxdimen\n\n"); "\\showboxbreadth=\\maxdimen\\showboxdepth=\\maxdimen\n\n");
keys.forEach(function(key, idx) { keys.forEach(function(key, idx) {
var sym = symbols.math[key]; const sym = symbols.math[key];
var type = types.indexOf(sym.group) + 1; const type = types.indexOf(sym.group) + 1;
tex.write("$" + idx + "+" + key + "+" + type + "\\showlists$\n\n"); tex.write("$" + idx + "+" + key + "+" + type + "\\showlists$\n\n");
}); });
tex.end("\\end{document}\n"); tex.end("\\end{document}\n");
} }
function typeset() { function typeset() {
var proc = childProcess.spawn( const proc = childProcess.spawn(
"pdflatex", ["--interaction=nonstopmode", "symgroups"], "pdflatex", ["--interaction=nonstopmode", "symgroups"],
{stdio: "ignore"}); {stdio: "ignore"});
proc.on("exit", function(code, signal) { proc.on("exit", function(code, signal) {
@@ -76,29 +76,29 @@ function typeset() {
*/ */
// Extract individual blocks, from switch to math mode up to switch back. // Extract individual blocks, from switch to math mode up to switch back.
var reMM = /^### math mode entered.*\n([^]*?)###/mg; const reMM = /^### math mode entered.*\n([^]*?)###/mg;
// Identify the parts separated by the plus signs // Identify the parts separated by the plus signs
var reParts = /([^]*^\.\\fam0 \+\n)([^]+)(\\mathbin\n\.+\\fam0 \+[^]*)/m; const reParts = /([^]*^\.\\fam0 \+\n)([^]+)(\\mathbin\n\.+\\fam0 \+[^]*)/m;
// Variation of the above in case we have nothing between the plus signs // Variation of the above in case we have nothing between the plus signs
var reEmpty = /^\.\\fam0 \+\n\\mathbin\n\.\\fam0 \+/m; const reEmpty = /^\.\\fam0 \+\n\\mathbin\n\.\\fam0 \+/m;
// Match any printed digit in the first or last of these parts // Match any printed digit in the first or last of these parts
var reDigit = /^\.\\fam0 ([0-9])/mg; const reDigit = /^\.\\fam0 ([0-9])/mg;
// Match the atom type, i.e. "\mathrel" in the above example // Match the atom type, i.e. "\mathrel" in the above example
var reAtom = /\\([a-z]+)/; const reAtom = /\\([a-z]+)/;
function evaluate(err, log) { function evaluate(err, log) {
if (err) { if (err) {
throw err; throw err;
} }
var match; let match;
var nextIndex = 0; let nextIndex = 0;
while ((match = reMM.exec(log)) !== null) { while ((match = reMM.exec(log)) !== null) {
var list = match[1]; const list = match[1];
match = reParts.exec(list); match = reParts.exec(list);
if (!match) { if (!match) {
match = reEmpty.exec(list); match = reEmpty.exec(list);
@@ -113,9 +113,9 @@ function evaluate(err, log) {
console.error(list); console.error(list);
process.exit(2); process.exit(2);
} }
var idx = extractDigits(match[1]); const idx = extractDigits(match[1]);
var atom = match[2]; const atom = match[2];
var katexType = types[extractDigits(match[3]) - 1] || "???"; const katexType = types[extractDigits(match[3]) - 1] || "???";
match = reAtom.exec(atom); match = reAtom.exec(atom);
if (!match) { if (!match) {
console.error("Failed to find atom type"); console.error("Failed to find atom type");
@@ -123,7 +123,7 @@ function evaluate(err, log) {
console.error(list); console.error(list);
process.exit(3); process.exit(3);
} }
var latexType = match[1]; const latexType = match[1];
if (katexType !== latexType && "math" + katexType !== latexType && if (katexType !== latexType && "math" + katexType !== latexType &&
(katexType !== "textord" || latexType !== "mathord") && (katexType !== "textord" || latexType !== "mathord") &&
(katexType !== "spacing" || opts.spacing)) { (katexType !== "spacing" || opts.spacing)) {
@@ -145,8 +145,8 @@ function evaluate(err, log) {
} }
function extractDigits(str) { function extractDigits(str) {
var match; let match;
var res = ""; let res = "";
while ((match = reDigit.exec(str)) !== null) { while ((match = reDigit.exec(str)) !== null) {
res += match[1]; res += match[1];
} }

View File

@@ -4,13 +4,13 @@
/* global expect: false */ /* global expect: false */
/* global it: false */ /* global it: false */
/* global describe: false */ /* global describe: false */
var ParseError = require("../src/ParseError"); const ParseError = require("../src/ParseError");
var parseTree = require("../src/parseTree"); const parseTree = require("../src/parseTree");
var Settings = require("../src/Settings"); const Settings = require("../src/Settings");
var defaultSettings = new Settings({}); const defaultSettings = new Settings({});
var parseAndSetResult = function(expr, result, settings) { const parseAndSetResult = function(expr, result, settings) {
try { try {
return parseTree(expr, settings || defaultSettings); return parseTree(expr, settings || defaultSettings);
} catch (e) { } catch (e) {
@@ -32,9 +32,9 @@ describe("unicode", function() {
toParse: function() { toParse: function() {
return { return {
compare: function(actual, settings) { compare: function(actual, settings) {
var usedSettings = settings ? settings : defaultSettings; const usedSettings = settings ? settings : defaultSettings;
var result = { const result = {
pass: true, pass: true,
message: "'" + actual + "' succeeded parsing", message: "'" + actual + "' succeeded parsing",
}; };
@@ -47,9 +47,9 @@ describe("unicode", function() {
toNotParse: function() { toNotParse: function() {
return { return {
compare: function(actual, settings) { compare: function(actual, settings) {
var usedSettings = settings ? settings : defaultSettings; const usedSettings = settings ? settings : defaultSettings;
var result = { const result = {
pass: false, pass: false,
message: "Expected '" + actual + "' to fail " + message: "Expected '" + actual + "' to fail " +
"parsing, but it succeeded", "parsing, but it succeeded",