www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit bd9db332d2887d884ec7ab3ca68488314b8618da
parent 9b565a6375d72932878b16c7d6eeb5fec6d7444f
Author: Martin von Gagern <gagern@ma.tum.de>
Date:   Sat,  7 Jan 2017 02:25:50 +0100

Turn var into const or let

Diffstat:
M.eslintrc | 4+---
Mcli.js | 10+++++-----
Mcontrib/auto-render/auto-render-spec.js | 24++++++++++++------------
Mcontrib/auto-render/auto-render.js | 45+++++++++++++++++++++++----------------------
Mcontrib/auto-render/splitAtDelimiters.js | 24++++++++++++------------
Mdockers/Screenshotter/screenshotter.js | 130++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mdockers/texcmp/texcmp.js | 137+++++++++++++++++++++++++++++++++++++++----------------------------------------
Mkatex.js | 28++++++++++++++--------------
Mserver.js | 28++++++++++++++--------------
Msrc/Lexer.js | 18+++++++++---------
Msrc/MacroExpander.js | 14+++++++-------
Msrc/Options.js | 6+++---
Msrc/ParseError.js | 16++++++++--------
Msrc/Parser.js | 198+++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/Style.js | 43+++++++++++++++++++++----------------------
Msrc/buildCommon.js | 102++++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/buildHTML.js | 448++++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/buildMathML.js | 166++++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/buildTree.js | 26+++++++++++++-------------
Msrc/delimiter.js | 143+++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/domTree.js | 56++++++++++++++++++++++++++++----------------------------
Msrc/environments.js | 53++++++++++++++++++++++++++---------------------------
Msrc/fontMetrics.js | 48++++++++++++++++++++++++------------------------
Msrc/functions.js | 98++++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/mathMLTree.js | 14+++++++-------
Msrc/parseTree.js | 6+++---
Msrc/symbols.js | 66++++++++++++++++++++++++++++++++----------------------------------
Msrc/unicodeRegexes.js | 4++--
Msrc/utils.js | 25++++++++++++-------------
Mtest/errors-spec.js | 12++++++------
Mtest/katex-spec.js | 574++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mtest/symgroups.js | 48++++++++++++++++++++++++------------------------
Mtest/unicode-spec.js | 18+++++++++---------
33 files changed, 1311 insertions(+), 1321 deletions(-)

diff --git a/.eslintrc b/.eslintrc @@ -35,6 +35,7 @@ "no-unreachable": 2, "no-unused-vars": [2, {"args": "none", "varsIgnorePattern": "^_*$"}], "no-useless-call": 2, + "no-var": 2, "no-with": 2, "one-var": [2, "never"], "prefer-const": 2, @@ -52,9 +53,6 @@ // We've decided explicitly not to care about this. "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. "prefer-arrow-callback": 0, "object-curly-spacing": [0, "always"], diff --git a/cli.js b/cli.js @@ -3,11 +3,11 @@ // Reads TeX from stdin, outputs HTML to stdout. /* eslint no-console:0 */ -var katex = require("./"); -var input = ""; +const katex = require("./"); +let input = ""; // 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) { console.log(process.argv[0] + " " + process.argv[1] + @@ -26,7 +26,7 @@ process.stdin.on("data", function(chunk) { }); process.stdin.on("end", function() { - var options = { displayMode: args.indexOf("--display-mode") !== -1 }; - var output = katex.renderToString(input, options); + const options = { displayMode: args.indexOf("--display-mode") !== -1 }; + const output = katex.renderToString(input, options); console.log(output); }); diff --git a/contrib/auto-render/auto-render-spec.js b/contrib/auto-render/auto-render-spec.js @@ -4,21 +4,21 @@ /* global it: false */ /* global describe: false */ -var splitAtDelimiters = require("./splitAtDelimiters"); +const splitAtDelimiters = require("./splitAtDelimiters"); beforeEach(function() { jasmine.addMatchers({ toSplitInto: function() { return { compare: function(actual, left, right, result) { - var message = { + const message = { pass: true, 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); if (split.length !== result.length) { @@ -30,12 +30,12 @@ beforeEach(function() { return message; } - for (var i = 0; i < split.length; i++) { - var real = split[i]; - var correct = result[i]; + for (let i = 0; i < split.length; i++) { + const real = split[i]; + const correct = result[i]; - var good = true; - var diff; + let good = true; + let diff; if (real.type !== correct.type) { good = false; @@ -189,7 +189,7 @@ describe("A delimiter splitter", 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( [ @@ -201,7 +201,7 @@ describe("A delimiter splitter", function() { }); it("works with more than one start datum", function() { - var startData = [ + const startData = [ {type: "text", data: "hello ( world ) boo"}, {type: "math", data: "math", rawData: "(math)", display: true}, {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() { - var startData = [ + const startData = [ {type: "text", data: "hello ( world ) boo"}, {type: "math", data: "hello ( world ) boo", rawData: "(hello ( world ) boo)", display: true}, diff --git a/contrib/auto-render/auto-render.js b/contrib/auto-render/auto-render.js @@ -1,12 +1,12 @@ /* eslint no-console:0 */ /* global katex */ -var splitAtDelimiters = require("./splitAtDelimiters"); +const splitAtDelimiters = require("./splitAtDelimiters"); -var splitWithDelimiters = function(text, delimiters) { - var data = [{type: "text", data: text}]; - for (var i = 0; i < delimiters.length; i++) { - var delimiter = delimiters[i]; +const splitWithDelimiters = function(text, delimiters) { + let data = [{type: "text", data: text}]; + for (let i = 0; i < delimiters.length; i++) { + const delimiter = delimiters[i]; data = splitAtDelimiters( data, delimiter.left, delimiter.right, delimiter.display || false); @@ -14,17 +14,17 @@ var splitWithDelimiters = function(text, delimiters) { return data; }; -var renderMathInText = function(text, delimiters) { - var data = splitWithDelimiters(text, delimiters); +const renderMathInText = function(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") { fragment.appendChild(document.createTextNode(data[i].data)); } else { - var span = document.createElement("span"); - var math = data[i].data; + const span = document.createElement("span"); + const math = data[i].data; try { katex.render(math, span, { displayMode: data[i].display, @@ -48,17 +48,17 @@ var renderMathInText = function(text, delimiters) { return fragment; }; -var renderElem = function(elem, delimiters, ignoredTags) { - for (var i = 0; i < elem.childNodes.length; i++) { - var childNode = elem.childNodes[i]; +const renderElem = function(elem, delimiters, ignoredTags) { + for (let i = 0; i < elem.childNodes.length; i++) { + const childNode = elem.childNodes[i]; if (childNode.nodeType === 3) { // Text node - var frag = renderMathInText(childNode.textContent, delimiters); + const frag = renderMathInText(childNode.textContent, delimiters); i += frag.childNodes.length - 1; elem.replaceChild(frag, childNode); } else if (childNode.nodeType === 1) { // Element node - var shouldRender = ignoredTags.indexOf( + const shouldRender = ignoredTags.indexOf( childNode.nodeName.toLowerCase()) === -1; if (shouldRender) { @@ -69,7 +69,7 @@ var renderElem = function(elem, delimiters, ignoredTags) { } }; -var defaultOptions = { +const defaultOptions = { delimiters: [ {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. - var source; - var prop; - for (var i = 1, length = arguments.length; i < length; i++) { + let source; + let prop; + const length = arguments.length; + for (let i = 1; i < length; i++) { source = arguments[i]; for (prop in source) { if (Object.prototype.hasOwnProperty.call(source, prop)) { @@ -98,7 +99,7 @@ var extend = function(obj) { return obj; }; -var renderMathInElement = function(elem, options) { +const renderMathInElement = function(elem, options) { if (!elem) { throw new Error("No element provided to render"); } diff --git a/contrib/auto-render/splitAtDelimiters.js b/contrib/auto-render/splitAtDelimiters.js @@ -1,14 +1,14 @@ /* eslint no-constant-condition:0 */ -var findEndOfMath = function(delimiter, text, startIndex) { +const findEndOfMath = function(delimiter, text, startIndex) { // Adapted from // https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx - var index = startIndex; - var braceLevel = 0; + let index = startIndex; + let braceLevel = 0; - var delimLength = delimiter.length; + const delimLength = delimiter.length; while (index < text.length) { - var character = text[index]; + const character = text[index]; if (braceLevel <= 0 && text.slice(index, index + delimLength) === delimiter) { @@ -27,16 +27,16 @@ var findEndOfMath = function(delimiter, text, startIndex) { return -1; }; -var splitAtDelimiters = function(startData, leftDelim, rightDelim, display) { - var finalData = []; +const splitAtDelimiters = function(startData, leftDelim, rightDelim, display) { + const finalData = []; - for (var i = 0; i < startData.length; i++) { + for (let i = 0; i < startData.length; i++) { if (startData[i].type === "text") { - var text = startData[i].data; + const text = startData[i].data; - var lookingForLeft = true; - var currIndex = 0; - var nextIndex; + let lookingForLeft = true; + let currIndex = 0; + let nextIndex; nextIndex = text.indexOf(leftDelim); if (nextIndex !== -1) { diff --git a/dockers/Screenshotter/screenshotter.js b/dockers/Screenshotter/screenshotter.js @@ -1,27 +1,27 @@ /* eslint no-console:0, prefer-spread:0 */ "use strict"; -var childProcess = require("child_process"); -var fs = require("fs"); -var http = require("http"); -var jspngopt = require("jspngopt"); -var net = require("net"); -var os = require("os"); -var pako = require("pako"); -var path = require("path"); -var selenium = require("selenium-webdriver"); -var firefox = require("selenium-webdriver/firefox"); - -var app = require("../../server"); -var data = require("../../test/screenshotter/ss_data"); - -var dstDir = path.normalize( +const childProcess = require("child_process"); +const fs = require("fs"); +const http = require("http"); +const jspngopt = require("jspngopt"); +const net = require("net"); +const os = require("os"); +const pako = require("pako"); +const path = require("path"); +const selenium = require("selenium-webdriver"); +const firefox = require("selenium-webdriver/firefox"); + +const app = require("../../server"); +const data = require("../../test/screenshotter/ss_data"); + +const dstDir = path.normalize( path.join(__dirname, "..", "..", "test", "screenshotter", "images")); ////////////////////////////////////////////////////////////////////// // Process command line arguments -var opts = require("nomnom") +const opts = require("nomnom") .option("browser", { abbr: "b", "default": "firefox", @@ -74,25 +74,25 @@ var opts = require("nomnom") }) .parse(); -var listOfCases; +let listOfCases; if (opts.include) { listOfCases = opts.include.split(","); } else { listOfCases = Object.keys(data); } if (opts.exclude) { - var exclude = opts.exclude.split(","); + const exclude = opts.exclude.split(","); listOfCases = listOfCases.filter(function(key) { return exclude.indexOf(key) === -1; }); } -var seleniumURL = opts.seleniumURL; -var seleniumIP = opts.seleniumIP; -var seleniumPort = opts.seleniumPort; -var katexURL = opts.katexURL; -var katexIP = opts.katexIP; -var katexPort = opts.katexPort; +let seleniumURL = opts.seleniumURL; +let seleniumIP = opts.seleniumIP; +let seleniumPort = opts.seleniumPort; +let katexURL = opts.katexURL; +let katexIP = opts.katexIP; +let katexPort = opts.katexPort; ////////////////////////////////////////////////////////////////////// // Work out connection to selenium docker container @@ -107,15 +107,15 @@ function check(err) { } function cmd() { - var args = Array.prototype.slice.call(arguments); - var cmd = args.shift(); + const args = Array.prototype.slice.call(arguments); + const cmd = args.shift(); return childProcess.execFileSync( cmd, args, { encoding: "utf-8" }).replace(/\n$/, ""); } function guessDockerIPs() { 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); katexIP = katexIP || cmd("docker-machine", "ssh", machine, "echo ${SSH_CONNECTION%% *}"); @@ -124,7 +124,7 @@ function guessDockerIPs() { try { // When using boot2docker, seleniumIP and katexIP are distinct. seleniumIP = seleniumIP || cmd("boot2docker", "ip"); - var config = cmd("boot2docker", "config"); + let config = cmd("boot2docker", "config"); config = (/^HostIP = "(.*)"$/m).exec(config); if (!config) { console.error("Failed to find HostIP"); @@ -142,7 +142,7 @@ function guessDockerIPs() { return; } // 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); seleniumIP = seleniumIP || gatewayIP; katexIP = katexIP || gatewayIP; @@ -165,22 +165,22 @@ if (seleniumURL) { } process.nextTick(startServer); -var attempts = 0; +let attempts = 0; ////////////////////////////////////////////////////////////////////// // Start up development server -var devServer = null; -var minPort = 32768; -var maxPort = 61000; +let devServer = null; +const minPort = 32768; +const maxPort = 61000; function startServer() { if (katexURL || katexPort) { process.nextTick(tryConnect); return; } - var port = Math.floor(Math.random() * (maxPort - minPort)) + minPort; - var server = http.createServer(app).listen(port); + const port = Math.floor(Math.random() * (maxPort - minPort)) + minPort; + const server = http.createServer(app).listen(port); server.once("listening", function() { devServer = server; katexPort = port; @@ -206,7 +206,7 @@ function tryConnect() { process.nextTick(buildDriver); return; } - var sock = net.connect({ + const sock = net.connect({ host: seleniumIP, port: +seleniumPort, }); @@ -225,21 +225,21 @@ function tryConnect() { ////////////////////////////////////////////////////////////////////// // Build the web driver -var driver; +let driver; function buildDriver() { - var builder = new selenium.Builder().forBrowser(opts.browser); - var ffProfile = new firefox.Profile(); + const builder = new selenium.Builder().forBrowser(opts.browser); + const ffProfile = new firefox.Profile(); ffProfile.setPreference( "browser.startup.homepage_override.mstone", "ignore"); ffProfile.setPreference("browser.startup.page", 0); - var ffOptions = new firefox.Options().setProfile(ffProfile); + const ffOptions = new firefox.Options().setProfile(ffProfile); builder.setFirefoxOptions(ffOptions); if (seleniumURL) { builder.usingServer(seleniumURL); } driver = builder.build(); driver.manage().timeouts().setScriptTimeout(3000).then(function() { - var html = '<!DOCTYPE html>' + + let html = '<!DOCTYPE html>' + '<html><head><style type="text/css">html,body{' + 'width:100%;height:100%;margin:0;padding:0;overflow:hidden;' + '}</style></head><body><p>Test</p></body></html>'; @@ -253,15 +253,15 @@ function buildDriver() { ////////////////////////////////////////////////////////////////////// // Set the screen size -var targetW = 1024; -var targetH = 768; +const targetW = 1024; +const targetH = 768; function setSize(reqW, reqH) { return driver.manage().window().setSize(reqW, reqH).then(function() { return driver.takeScreenshot(); }).then(function(img) { img = imageDimensions(img); - var actualW = img.width; - var actualH = img.height; + const actualW = img.width; + const actualH = img.height; if (actualW === targetW && actualH === targetH) { findHostIP(); return; @@ -274,7 +274,7 @@ function setSize(reqW, reqH) { } function imageDimensions(img) { - var buf = new Buffer(img, "base64"); + const buf = new Buffer(img, "base64"); return { buf: buf, width: buf.readUInt32BE(16), @@ -312,13 +312,13 @@ function findHostIP() { }); // Next, enumerate all network addresses - var ips = []; - var devs = os.networkInterfaces(); - for (var dev in devs) { + const ips = []; + const devs = os.networkInterfaces(); + for (const dev in devs) { if (devs.hasOwnProperty(dev)) { - var addrs = devs[dev]; - for (var i = 0; i < addrs.length; ++i) { - var addr = addrs[i].address; + const addrs = devs[dev]; + for (let i = 0; i < addrs.length; ++i) { + let addr = addrs[i].address; if (/:/.test(addr)) { addr = "[" + addr + "]"; } @@ -329,7 +329,7 @@ function findHostIP() { console.log("Looking for host IP among " + ips.join(", ")); // 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) { return '<script src="http://' + ip + ':' + katexPort + '/ss-connect.js?ip=' + encodeURIComponent(ip) + @@ -343,17 +343,17 @@ function findHostIP() { ////////////////////////////////////////////////////////////////////// // Take the screenshots -var countdown = listOfCases.length; +let countdown = listOfCases.length; -var exitStatus = 0; -var listOfFailed = []; +let exitStatus = 0; +const listOfFailed = []; function takeScreenshots() { listOfCases.forEach(takeScreenshot); } function takeScreenshot(key) { - var itm = data[key]; + const itm = data[key]; if (!itm) { console.error("Test case " + key + " not known!"); listOfFailed.push(key); @@ -364,14 +364,14 @@ function takeScreenshot(key) { return; } - var file = path.join(dstDir, key + "-" + opts.browser + ".png"); - var retry = 0; - var loadExpected = null; + let file = path.join(dstDir, key + "-" + opts.browser + ".png"); + let retry = 0; + let loadExpected = null; if (opts.verify) { 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); if (opts.wait) { browserSideWait(1000 * opts.wait); @@ -398,10 +398,10 @@ function takeScreenshot(key) { loadExpected = promisify(fs.readFile, file); } } - var opt = new jspngopt.Optimizer({ + const opt = new jspngopt.Optimizer({ pako: pako, }); - var buf = opt.bufferSync(img.buf); + const buf = opt.bufferSync(img.buf); if (loadExpected) { return loadExpected.then(function(expected) { if (!buf.equals(expected)) { @@ -451,8 +451,8 @@ function browserSideWait(milliseconds) { // Second and later arguments are passed to the function named in the // first argument, and a callback is added as last argument. function promisify(f) { - var args = Array.prototype.slice.call(arguments, 1); - var deferred = new selenium.promise.Deferred(); + const args = Array.prototype.slice.call(arguments, 1); + const deferred = new selenium.promise.Deferred(); args.push(function(err, val) { if (err) { deferred.reject(err); diff --git a/dockers/texcmp/texcmp.js b/dockers/texcmp/texcmp.js @@ -2,22 +2,22 @@ /* eslint-disable no-console */ "use strict"; -var childProcess = require("child_process"); -var fs = require("fs"); -var path = require("path"); -var Q = require("q"); // To debug, pass Q_DEBUG=1 in the environment -var pngparse = require("pngparse"); -var fft = require("ndarray-fft"); -var ndarray = require("ndarray-fft/node_modules/ndarray"); +const childProcess = require("child_process"); +const fs = require("fs"); +const path = require("path"); +const Q = require("q"); // To debug, pass Q_DEBUG=1 in the environment +const pngparse = require("pngparse"); +const fft = require("ndarray-fft"); +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 -var readFile = Q.denodeify(fs.readFile); -var writeFile = Q.denodeify(fs.writeFile); -var mkdir = Q.denodeify(fs.mkdir); +const readFile = Q.denodeify(fs.readFile); +const writeFile = Q.denodeify(fs.writeFile); +const mkdir = Q.denodeify(fs.mkdir); -var todo; +let todo; if (process.argv.length > 2) { todo = process.argv.slice(2); } else { @@ -27,23 +27,23 @@ if (process.argv.length > 2) { } // Dimensions used when we do the FFT-based alignment computation -var alignWidth = 2048; // should be at least twice the width resp. height -var alignHeight = 2048; // of the screenshots, and a power of two. +const alignWidth = 2048; // should be at least twice the width resp. height +const alignHeight = 2048; // of the screenshots, and a power of two. // Compute required resolution to match test.html. 16px default font, // 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. -var pxPerEm = 16 * 4 * 1.21; -var pxPerPt = pxPerEm / 10; -var dpi = pxPerPt * 72.27; +const pxPerEm = 16 * 4 * 1.21; +const pxPerPt = pxPerEm / 10; +const dpi = pxPerPt * 72.27; -var tmpDir = "/tmp/texcmp"; -var ssDir = path.normalize( +const tmpDir = "/tmp/texcmp"; +const ssDir = path.normalize( path.join(__dirname, "..", "..", "test", "screenshotter")); -var imagesDir = path.join(ssDir, "images"); -var teximgDir = path.join(ssDir, "tex"); -var diffDir = path.join(ssDir, "diff"); -var template; +const imagesDir = path.join(ssDir, "images"); +const teximgDir = path.join(ssDir, "tex"); +const diffDir = path.join(ssDir, "diff"); +let template; Q.all([ readFile(path.join(ssDir, "test.tex"), "utf-8"), @@ -58,8 +58,8 @@ Q.all([ // Process a single test case: rasterize, then create diff function processTestCase(key) { - var itm = data[key]; - var tex = "$" + itm.tex + "$"; + const itm = data[key]; + let tex = "$" + itm.tex + "$"; if (itm.display) { tex = "\\[" + itm.tex + "\\]"; } @@ -70,14 +70,14 @@ function processTestCase(key) { tex = tex + itm.post.replace("<br>", "\\\\"); } tex = template.replace(/\$.*\$/, tex.replace(/\$/g, "$$$$")); - var texFile = path.join(tmpDir, key + ".tex"); - var pdfFile = path.join(tmpDir, key + ".pdf"); - var pngFile = path.join(teximgDir, key + "-pdflatex.png"); - var browserFile = path.join(imagesDir, key + "-firefox.png"); - var diffFile = path.join(diffDir, key + ".png"); + const texFile = path.join(tmpDir, key + ".tex"); + const pdfFile = path.join(tmpDir, key + ".pdf"); + const pngFile = path.join(teximgDir, key + "-pdflatex.png"); + const browserFile = path.join(imagesDir, key + "-firefox.png"); + const diffFile = path.join(diffDir, key + ".png"); // 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 return execFile("pdflatex", [ "-interaction", "nonstopmode", key, @@ -95,24 +95,24 @@ function processTestCase(key) { return readPNG(pngFile).then(fftImage); }); // 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) { // Now we have the FFT result from both // Step 6: find alignment which maximizes overlap. // This uses a FFT-based correlation computation. - var x; - var y; - var real = createMatrix(); - var imag = createMatrix(); + let x; + let y; + const real = createMatrix(); + const imag = createMatrix(); // Step 6a: (real + i*imag) = latex * conjugate(browser) for (y = 0; y < alignHeight; ++y) { for (x = 0; x < alignWidth; ++x) { - var br = browser.real.get(y, x); - var bi = browser.imag.get(y, x); - var lr = latex.real.get(y, x); - var li = latex.imag.get(y, x); + const br = browser.real.get(y, x); + const bi = browser.imag.get(y, x); + const lr = latex.real.get(y, x); + const li = latex.imag.get(y, x); real.set(y, x, br * lr + bi * li); imag.set(y, x, br * li - bi * lr); } @@ -122,14 +122,14 @@ function processTestCase(key) { fft(-1, real, imag); // Step 6c: find position where the (squared) absolute value is maximal - var offsetX = 0; - var offsetY = 0; - var maxSquaredNorm = -1; // any result is greater than initial value + let offsetX = 0; + let offsetY = 0; + let maxSquaredNorm = -1; // any result is greater than initial value for (y = 0; y < alignHeight; ++y) { for (x = 0; x < alignWidth; ++x) { - var or = real.get(y, x); - var oi = imag.get(y, x); - var squaredNorm = or * or + oi * oi; + const or = real.get(y, x); + const oi = imag.get(y, x); + const squaredNorm = or * or + oi * oi; if (maxSquaredNorm < squaredNorm) { maxSquaredNorm = squaredNorm; offsetX = x; @@ -148,12 +148,12 @@ function processTestCase(key) { console.log("Positioned " + key + ": " + offsetX + ", " + offsetY); // Step 7: use these offsets to compute difference illustration - var bx = Math.max(offsetX, 0); // browser left padding - var by = Math.max(offsetY, 0); // browser top padding - var lx = Math.max(-offsetX, 0); // latex left padding - var ly = Math.max(-offsetY, 0); // latex top padding - var uw = Math.max(browser.width + bx, latex.width + lx); // union width - var uh = Math.max(browser.height + by, latex.height + ly); // u. height + const bx = Math.max(offsetX, 0); // browser left padding + const by = Math.max(offsetY, 0); // browser top padding + const lx = Math.max(-offsetX, 0); // latex left padding + const ly = Math.max(-offsetY, 0); // latex top padding + const uw = Math.max(browser.width + bx, latex.width + lx); // union w. + const uh = Math.max(browser.height + by, latex.height + ly); // u. h. return execFile("convert", [ // First image: latex rendering, converted to grayscale and padded "(", pngFile, "-grayscale", "Rec709Luminance", @@ -187,7 +187,7 @@ function ensureDir(dir) { // Execute a given command, and return a promise to its output. // Don't denodeify here, since fail branch needs access to stderr. function execFile(cmd, args, opts) { - var deferred = Q.defer(); + const deferred = Q.defer(); childProcess.execFile(cmd, args, opts, function(err, stdout, stderr) { if (err) { 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. function readPNG(file) { - var deferred = Q.defer(); - var onerror = deferred.reject.bind(deferred); - var stream = fs.createReadStream(file); + const deferred = Q.defer(); + const onerror = deferred.reject.bind(deferred); + const stream = fs.createReadStream(file); stream.on("error", onerror); pngparse.parseStream(stream, function(err, image) { if (err) { @@ -221,20 +221,19 @@ function readPNG(file) { // Take a parsed image data structure and apply FFT transformation to it function fftImage(image) { - var real = createMatrix(); - var imag = createMatrix(); - var idx = 0; - var nchan = image.channels; - var alphachan = 1 - (nchan % 2); - var colorchan = nchan - alphachan; - for (var y = 0; y < image.height; ++y) { - for (var x = 0; x < image.width; ++x) { - var c; - var v = 0; - for (c = 0; c < colorchan; ++c) { + const real = createMatrix(); + const imag = createMatrix(); + let idx = 0; + const nchan = image.channels; + const alphachan = 1 - (nchan % 2); + const colorchan = nchan - alphachan; + for (let y = 0; y < image.height; ++y) { + for (let x = 0; x < image.width; ++x) { + let v = 0; + for (let c = 0; c < colorchan; ++c) { v += 255 - image.data[idx++]; } - for (c = 0; c < alphachan; ++c) { + for (let c = 0; c < alphachan; ++c) { v += image.data[idx++]; } real.set(y, x, v); @@ -251,6 +250,6 @@ function fftImage(image) { // Create a new matrix of preconfigured dimensions, initialized to zero function createMatrix() { - var array = new Float64Array(alignWidth * alignHeight); + const array = new Float64Array(alignWidth * alignHeight); return new ndarray(array, [alignWidth, alignHeight]); } diff --git a/katex.js b/katex.js @@ -7,24 +7,24 @@ * errors in the expression, or errors in javascript handling. */ -var ParseError = require("./src/ParseError"); -var Settings = require("./src/Settings"); +const ParseError = require("./src/ParseError"); +const Settings = require("./src/Settings"); -var buildTree = require("./src/buildTree"); -var parseTree = require("./src/parseTree"); -var utils = require("./src/utils"); +const buildTree = require("./src/buildTree"); +const parseTree = require("./src/parseTree"); +const utils = require("./src/utils"); /** * Parse and build an expression, and place that expression in the DOM node * given. */ -var render = function(expression, baseNode, options) { +let render = function(expression, baseNode, options) { utils.clearNode(baseNode); - var settings = new Settings(options); + const settings = new Settings(options); - var tree = parseTree(expression, settings); - var node = buildTree(tree, expression, settings).toNode(); + const tree = parseTree(expression, settings); + const node = buildTree(tree, expression, settings).toNode(); baseNode.appendChild(node); }; @@ -46,18 +46,18 @@ if (typeof document !== "undefined") { /** * Parse and build an expression, and return the markup for that. */ -var renderToString = function(expression, options) { - var settings = new Settings(options); +const renderToString = function(expression, options) { + const settings = new Settings(options); - var tree = parseTree(expression, settings); + const tree = parseTree(expression, settings); return buildTree(tree, expression, settings).toMarkup(); }; /** * Parse an expression and return the parse tree. */ -var generateParseTree = function(expression, options) { - var settings = new Settings(options); +const generateParseTree = function(expression, options) { + const settings = new Settings(options); return parseTree(expression, settings); }; diff --git a/server.js b/server.js @@ -1,14 +1,14 @@ /* eslint no-console:0 */ -var fs = require("fs"); -var path = require("path"); +const fs = require("fs"); +const path = require("path"); -var babelify = require("babelify"); -var browserify = require("browserify"); -var express = require("express"); -var glob = require("glob"); -var less = require("less"); +const babelify = require("babelify"); +const browserify = require("browserify"); +const express = require("express"); +const glob = require("glob"); +const less = require("less"); -var app = express(); +const app = express(); if (require.main === module) { app.use(require("morgan")( @@ -17,7 +17,7 @@ if (require.main === module) { var serveBrowserified = function(file, standaloneName) { return function(req, res, next) { - var files; + let files; if (Array.isArray(file)) { files = file.map(function(f) { return path.join(__dirname, f); }); } else if (file.indexOf("*") !== -1) { @@ -26,16 +26,16 @@ var serveBrowserified = function(file, standaloneName) { files = [path.join(__dirname, file)]; } - var options = { + const options = { transform: [babelify] }; if (standaloneName) { options.standalone = standaloneName; } - var b = browserify(files, options); - var stream = b.bundle(); + const b = browserify(files, options); + const stream = b.bundle(); - var body = ""; + let body = ""; stream.on("data", function(s) { body += s; }); stream.on("error", function(e) { next(e); }); stream.on("end", function() { @@ -59,7 +59,7 @@ app.get("/contrib/auto-render/auto-render.js", "renderMathInElement")); 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) { if (err) { next(err); diff --git a/src/Lexer.js b/src/Lexer.js @@ -11,9 +11,9 @@ * kinds. */ -var matchAt = require("match-at"); +const matchAt = require("match-at"); -var ParseError = require("./ParseError"); +const ParseError = require("./ParseError"); // The main lexer class 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 * still reject the input. */ -var tokenRegex = new RegExp( +const tokenRegex = new RegExp( "([ \r\n\t]+)|" + // whitespace "([!-\\[\\]-\u2027\u202A-\uD7FF\uF900-\uFFFF]" + // single codepoint "|[\uD800-\uDBFF][\uDC00-\uDFFF]" + // surrogate pair @@ -88,21 +88,21 @@ var tokenRegex = new RegExp( * This function lexes a single token. */ Lexer.prototype.lex = function() { - var input = this.input; - var pos = this.pos; + const input = this.input; + const pos = this.pos; if (pos === input.length) { return new Token("EOF", pos, pos, this); } - var match = matchAt(tokenRegex, input, pos); + const match = matchAt(tokenRegex, input, pos); if (match === null) { throw new ParseError( "Unexpected character: '" + input[pos] + "'", new Token(input[pos], pos, pos + 1, this)); } - var text = match[2] || " "; - var start = this.pos; + const text = match[2] || " "; + const start = this.pos; this.pos += match[0].length; - var end = this.pos; + const end = this.pos; return new Token(text, start, end, this); }; diff --git a/src/MacroExpander.js b/src/MacroExpander.js @@ -3,7 +3,7 @@ * until only non-macro tokens remain. */ -var Lexer = require("./Lexer"); +const Lexer = require("./Lexer"); function MacroExpander(input, macros) { this.lexer = new Lexer(input); @@ -20,16 +20,16 @@ MacroExpander.prototype.nextToken = function() { if (this.stack.length === 0) { this.stack.push(this.lexer.lex()); } - var topToken = this.stack.pop(); - var name = topToken.text; + const topToken = this.stack.pop(); + const name = topToken.text; if (!(name.charAt(0) === "\\" && this.macros.hasOwnProperty(name))) { return topToken; } - var expansion = this.macros[name]; + let expansion = this.macros[name]; if (typeof expansion === "string") { - var bodyLexer = new Lexer(expansion); + const bodyLexer = new Lexer(expansion); expansion = []; - var tok = bodyLexer.lex(); + let tok = bodyLexer.lex(); while (tok.text !== "EOF") { expansion.push(tok); tok = bodyLexer.lex(); @@ -43,7 +43,7 @@ MacroExpander.prototype.nextToken = function() { MacroExpander.prototype.get = function(ignoreSpace) { this.discardedWhiteSpace = []; - var token = this.nextToken(); + let token = this.nextToken(); if (ignoreSpace) { while (token.text === " ") { this.discardedWhiteSpace.push(token); diff --git a/src/Options.js b/src/Options.js @@ -39,7 +39,7 @@ function Options(data) { * from "extension" will be copied to the new options object. */ Options.prototype.extend = function(extension) { - var data = { + const data = { style: this.style, size: this.size, color: this.color, @@ -49,7 +49,7 @@ Options.prototype.extend = function(extension) { font: this.font, }; - for (var key in extension) { + for (const key in extension) { if (extension.hasOwnProperty(key)) { data[key] = extension[key]; } @@ -115,7 +115,7 @@ Options.prototype.reset = function() { * A map of color names to CSS colors. * TODO(emily): Remove this when we have real macros */ -var colorMap = { +const colorMap = { "katex-blue": "#6495ed", "katex-orange": "#ffa500", "katex-pink": "#ff00af", diff --git a/src/ParseError.js b/src/ParseError.js @@ -10,15 +10,15 @@ * @param {(Token|ParseNode)=} token An object providing position information */ function ParseError(message, token) { - var error = "KaTeX parse error: " + message; - var start; - var end; + let error = "KaTeX parse error: " + message; + let start; + let end; if (token && token.lexer && token.start <= token.end) { // If we have the input and a position, make the error a bit fancier // Get the input - var input = token.lexer.input; + const input = token.lexer.input; // Prepend some information start = token.start; @@ -30,16 +30,16 @@ function ParseError(message, token) { } // 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 - var left; + let left; if (start > 15) { left = "…" + input.slice(start - 15, start); } else { left = input.slice(0, start); } - var right; + let right; if (end + 15 < input.length) { right = input.slice(end, end + 15) + "…"; } else { @@ -50,7 +50,7 @@ function ParseError(message, token) { // Some hackery to make ParseError a prototype of Error // See http://stackoverflow.com/a/8460753 - var self = new Error(error); + const self = new Error(error); self.name = "ParseError"; self.__proto__ = ParseError.prototype; diff --git a/src/Parser.js b/src/Parser.js @@ -1,13 +1,13 @@ /* eslint no-constant-condition:0 */ -var functions = require("./functions"); -var environments = require("./environments"); -var MacroExpander = require("./MacroExpander"); -var symbols = require("./symbols"); -var utils = require("./utils"); -var cjkRegex = require("./unicodeRegexes").cjkRegex; +const functions = require("./functions"); +const environments = require("./environments"); +const MacroExpander = require("./MacroExpander"); +const symbols = require("./symbols"); +const utils = require("./utils"); +const cjkRegex = require("./unicodeRegexes").cjkRegex; -var parseData = require("./parseData"); -var ParseError = require("./ParseError"); +const parseData = require("./parseData"); +const ParseError = require("./ParseError"); /** * 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; } -var ParseNode = parseData.ParseNode; +const ParseNode = parseData.ParseNode; /** * 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 this.mode = "math"; this.consume(); - var parse = this.parseInput(); + const parse = this.parseInput(); return parse; }; @@ -120,13 +120,13 @@ Parser.prototype.parse = function() { */ Parser.prototype.parseInput = function() { // 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 this.expect("EOF", false); return expression; }; -var endOfExpression = ["}", "\\end", "\\right", "&", "\\\\", "\\cr"]; +const endOfExpression = ["}", "\\end", "\\right", "&", "\\\\", "\\cr"]; /** * Parses an "expression", which is a list of atoms. @@ -142,11 +142,11 @@ var endOfExpression = ["}", "\\end", "\\right", "&", "\\\\", "\\cr"]; * @return {ParseNode} */ 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 // we reached the end, a }, or a \right) while (true) { - var lex = this.nextToken; + const lex = this.nextToken; if (endOfExpression.indexOf(lex.text) !== -1) { break; } @@ -156,10 +156,10 @@ Parser.prototype.parseExpression = function(breakOnInfix, breakOnTokenText) { if (breakOnInfix && functions[lex.text] && functions[lex.text].infix) { break; } - var atom = this.parseAtom(); + const atom = this.parseAtom(); if (!atom) { if (!this.settings.throwOnError && lex.text[0] === "\\") { - var errorNode = this.handleUnsupportedCmd(); + const errorNode = this.handleUnsupportedCmd(); body.push(errorNode); continue; } @@ -181,11 +181,11 @@ Parser.prototype.parseExpression = function(breakOnInfix, breakOnTokenText) { * @returns {Array} */ Parser.prototype.handleInfixNodes = function(body) { - var overIndex = -1; - var funcName; + let overIndex = -1; + let funcName; - for (var i = 0; i < body.length; i++) { - var node = body[i]; + for (let i = 0; i < body.length; i++) { + const node = body[i]; if (node.type === "infix") { if (overIndex !== -1) { throw new ParseError( @@ -198,11 +198,11 @@ Parser.prototype.handleInfixNodes = function(body) { } if (overIndex !== -1) { - var numerNode; - var denomNode; + let numerNode; + let denomNode; - var numerBody = body.slice(0, overIndex); - var denomBody = body.slice(overIndex + 1); + const numerBody = body.slice(0, overIndex); + const denomBody = body.slice(overIndex + 1); if (numerBody.length === 1 && numerBody[0].type === "ordgroup") { numerNode = numerBody[0]; @@ -216,7 +216,7 @@ Parser.prototype.handleInfixNodes = function(body) { denomNode = new ParseNode("ordgroup", denomBody, this.mode); } - var value = this.callFunction( + const value = this.callFunction( funcName, [numerNode, denomNode], null); return [new ParseNode(value.type, value, this.mode)]; } else { @@ -225,16 +225,16 @@ Parser.prototype.handleInfixNodes = function(body) { }; // The greediness of a superscript or subscript -var SUPSUB_GREEDINESS = 1; +const SUPSUB_GREEDINESS = 1; /** * Handle a subscript or superscript with nice errors. */ Parser.prototype.handleSupSubscript = function(name) { - var symbolToken = this.nextToken; - var symbol = symbolToken.text; + const symbolToken = this.nextToken; + const symbol = symbolToken.text; this.consume(); - var group = this.parseGroup(); + const group = this.parseGroup(); if (!group) { if (!this.settings.throwOnError && this.nextToken.text[0] === "\\") { @@ -248,7 +248,7 @@ Parser.prototype.handleSupSubscript = function(name) { } else if (group.isFunction) { // ^ and _ have a greediness, so handle interactions with functions' // greediness - var funcGreediness = functions[group.result].greediness; + const funcGreediness = functions[group.result].greediness; if (funcGreediness > SUPSUB_GREEDINESS) { return this.parseFunction(group); } else { @@ -266,14 +266,14 @@ Parser.prototype.handleSupSubscript = function(name) { * contained within a color node whose color is determined by errorColor */ Parser.prototype.handleUnsupportedCmd = function() { - var text = this.nextToken.text; - var textordArray = []; + const text = this.nextToken.text; + 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")); } - var textNode = new ParseNode( + const textNode = new ParseNode( "text", { body: textordArray, @@ -281,7 +281,7 @@ Parser.prototype.handleUnsupportedCmd = function() { }, this.mode); - var colorNode = new ParseNode( + const colorNode = new ParseNode( "color", { color: this.settings.errorColor, @@ -302,7 +302,7 @@ Parser.prototype.handleUnsupportedCmd = function() { Parser.prototype.parseAtom = function() { // The body of an atom is an implicit group, so that things like // \left(x\right)^2 work correctly. - var base = this.parseImplicitGroup(); + const base = this.parseImplicitGroup(); // In text mode, we don't have superscripts or subscripts if (this.mode === "text") { @@ -311,11 +311,11 @@ Parser.prototype.parseAtom = function() { // Note that base may be empty (i.e. null) at this point. - var superscript; - var subscript; + let superscript; + let subscript; while (true) { // Lex the first token - var lex = this.nextToken; + const lex = this.nextToken; if (lex.text === "\\limits" || lex.text === "\\nolimits") { // We got a limit control @@ -324,7 +324,7 @@ Parser.prototype.parseAtom = function() { "Limit controls must follow a math operator", lex); } else { - var limits = lex.text === "\\limits"; + const limits = lex.text === "\\limits"; base.value.limits = limits; base.value.alwaysHandleSupSub = true; } @@ -343,10 +343,10 @@ Parser.prototype.parseAtom = function() { subscript = this.handleSupSubscript("subscript"); } else if (lex.text === "'") { // 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 - var primes = [prime]; + const primes = [prime]; this.consume(); // Keep lexing tokens until we get something that's not a prime while (this.nextToken.text === "'") { @@ -376,13 +376,13 @@ Parser.prototype.parseAtom = function() { }; // A list of the size-changing functions, for use in parseImplicitGroup -var sizeFuncs = [ +const sizeFuncs = [ "\\tiny", "\\scriptsize", "\\footnotesize", "\\small", "\\normalsize", "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge", ]; // A list of the style-changing functions, for use in parseImplicitGroup -var styleFuncs = [ +const styleFuncs = [ "\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle", ]; @@ -398,27 +398,26 @@ var styleFuncs = [ * @return {?ParseNode} */ Parser.prototype.parseImplicitGroup = function() { - var start = this.parseSymbol(); + const start = this.parseSymbol(); if (start == null) { // If we didn't get anything we handle, fall back to parseFunction return this.parseFunction(); } - var func = start.result; - var body; + const func = start.result; if (func === "\\left") { // If we see a left: // Parse the entire left function (including the delimiter) - var left = this.parseFunction(start); + const left = this.parseFunction(start); // Parse out the implicit body ++this.leftrightDepth; - body = this.parseExpression(false); + const body = this.parseExpression(false); --this.leftrightDepth; // Check the next token this.expect("\\right", false); - var right = this.parseFunction(); + const right = this.parseFunction(); return new ParseNode("leftright", { body: body, left: left.value.value, @@ -426,26 +425,26 @@ Parser.prototype.parseImplicitGroup = function() { }, this.mode); } else if (func === "\\begin") { // begin...end is similar to left...right - var begin = this.parseFunction(start); - var envName = begin.value.name; + const begin = this.parseFunction(start); + const envName = begin.value.name; if (!environments.hasOwnProperty(envName)) { throw new ParseError( "No such environment: " + envName, begin.value.nameGroup); } // Build the environment object. Arguments and other information will // be made available to the begin and end methods using properties. - var env = environments[envName]; - var args = this.parseArguments("\\begin{" + envName + "}", env); - var context = { + const env = environments[envName]; + const args = this.parseArguments("\\begin{" + envName + "}", env); + const context = { mode: this.mode, envName: envName, parser: this, positions: args.pop(), }; - var result = env.handler(context, args); + const result = env.handler(context, args); this.expect("\\end", false); - var endNameToken = this.nextToken; - var end = this.parseFunction(); + const endNameToken = this.nextToken; + const end = this.parseFunction(); if (end.value.name !== envName) { throw new ParseError( "Mismatch: \\begin{" + envName + "} matched " + @@ -456,7 +455,7 @@ Parser.prototype.parseImplicitGroup = function() { return result; } else if (utils.contains(sizeFuncs, func)) { // If we see a sizing function, parse out the implict body - body = this.parseExpression(false); + const body = this.parseExpression(false); return new ParseNode("sizing", { // Figure out what size to use based on the list of functions above size: "size" + (utils.indexOf(sizeFuncs, func) + 1), @@ -464,7 +463,7 @@ Parser.prototype.parseImplicitGroup = function() { }, this.mode); } else if (utils.contains(styleFuncs, func)) { // If we see a styling function, parse out the implict body - body = this.parseExpression(true); + const body = this.parseExpression(true); return new ParseNode("styling", { // Figure out what style to use by pulling out the style from // the function name @@ -492,17 +491,17 @@ Parser.prototype.parseFunction = function(baseGroup) { if (baseGroup) { if (baseGroup.isFunction) { - var func = baseGroup.result; - var funcData = functions[func]; + const func = baseGroup.result; + const funcData = functions[func]; if (this.mode === "text" && !funcData.allowedInText) { throw new ParseError( "Can't use function '" + func + "' in text mode", baseGroup.token); } - var args = this.parseArguments(func, funcData); - var token = baseGroup.token; - var result = this.callFunction(func, args, args.pop(), token); + const args = this.parseArguments(func, funcData); + const token = baseGroup.token; + const result = this.callFunction(func, args, args.pop(), token); return new ParseNode(result.type, result, this.mode); } else { return baseGroup.result; @@ -516,7 +515,7 @@ Parser.prototype.parseFunction = function(baseGroup) { * Call a function handler with a suitable context and arguments. */ Parser.prototype.callFunction = function(name, args, positions, token) { - var context = { + const context = { funcName: name, parser: this, 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 */ Parser.prototype.parseArguments = function(func, funcData) { - var totalArgs = funcData.numArgs + funcData.numOptionalArgs; + const totalArgs = funcData.numArgs + funcData.numOptionalArgs; if (totalArgs === 0) { return [[this.pos]]; } - var baseGreediness = funcData.greediness; - var positions = [this.pos]; - var args = []; + const baseGreediness = funcData.greediness; + const positions = [this.pos]; + const args = []; - for (var i = 0; i < totalArgs; i++) { - var nextToken = this.nextToken; - var argType = funcData.argTypes && funcData.argTypes[i]; - var arg; + for (let i = 0; i < totalArgs; i++) { + const nextToken = this.nextToken; + const argType = funcData.argTypes && funcData.argTypes[i]; + let arg; if (i < funcData.numOptionalArgs) { if (argType) { arg = this.parseGroupOfType(argType, true); @@ -575,9 +574,9 @@ Parser.prototype.parseArguments = function(func, funcData) { } } } - var argNode; + let argNode; if (arg.isFunction) { - var argGreediness = + const argGreediness = functions[arg.result].greediness; if (argGreediness > baseGreediness) { argNode = this.parseFunction(arg); @@ -605,7 +604,7 @@ Parser.prototype.parseArguments = function(func, funcData) { * @return {?ParseFuncOrArgument} */ Parser.prototype.parseGroupOfType = function(innerMode, optional) { - var outerMode = this.mode; + const outerMode = this.mode; // Handle `original` argTypes if (innerMode === "original") { 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". // 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); return res; }; @@ -644,12 +643,12 @@ Parser.prototype.parseStringGroup = function(modeName, optional) { if (optional && this.nextToken.text !== "[") { return null; } - var outerMode = this.mode; + const outerMode = this.mode; this.mode = "text"; this.expect(optional ? "[" : "{"); - var str = ""; - var firstToken = this.nextToken; - var lastToken = firstToken; + let str = ""; + const firstToken = this.nextToken; + let lastToken = firstToken; while (this.nextToken.text !== (optional ? "]" : "}")) { if (this.nextToken.text === "EOF") { throw new ParseError( @@ -674,11 +673,11 @@ Parser.prototype.parseStringGroup = function(modeName, optional) { * @param {string} modeName Used to describe the mode in error messages */ Parser.prototype.parseRegexGroup = function(regex, modeName) { - var outerMode = this.mode; + const outerMode = this.mode; this.mode = "text"; - var firstToken = this.nextToken; - var lastToken = firstToken; - var str = ""; + const firstToken = this.nextToken; + let lastToken = firstToken; + let str = ""; while (this.nextToken.text !== "EOF" && regex.test(str + this.nextToken.text)) { lastToken = this.nextToken; @@ -698,11 +697,11 @@ Parser.prototype.parseRegexGroup = function(regex, modeName) { * Parses a color description. */ Parser.prototype.parseColorGroup = function(optional) { - var res = this.parseStringGroup("color", optional); + const res = this.parseStringGroup("color", optional); if (!res) { 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) { 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. */ Parser.prototype.parseSizeGroup = function(optional) { - var res; + let res; if (!optional && this.nextToken.text !== "{") { res = this.parseRegexGroup( /^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2}$/, "size"); @@ -725,11 +724,11 @@ Parser.prototype.parseSizeGroup = function(optional) { if (!res) { 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) { throw new ParseError("Invalid size: '" + res.text + "'", res); } - var data = { + const data = { number: +(match[1] + match[2]), // sign + magnitude, cast to number unit: match[3], }; @@ -753,13 +752,13 @@ Parser.prototype.parseSizeGroup = function(optional) { * @return {?ParseFuncOrArgument} */ Parser.prototype.parseGroup = function(optional) { - var firstToken = this.nextToken; + const firstToken = this.nextToken; // Try to parse an open brace if (this.nextToken.text === (optional ? "[" : "{")) { // If we get a brace, parse an expression this.consume(); - var expression = this.parseExpression(false, optional ? "]" : null); - var lastToken = this.nextToken; + const expression = this.parseExpression(false, optional ? "]" : null); + const lastToken = this.nextToken; // Make sure we get a close brace this.expect(optional ? "]" : "}"); if (this.mode === "text") { @@ -786,11 +785,10 @@ Parser.prototype.parseGroup = function(optional) { * list will be moified in place */ Parser.prototype.formLigatures = function(group) { - var i; - var n = group.length - 1; - for (i = 0; i < n; ++i) { - var a = group[i]; - var v = a.value; + let n = group.length - 1; + for (let i = 0; i < n; ++i) { + const a = group[i]; + const v = a.value; if (v === "-" && group[i + 1].value === "-") { if (i + 1 < n && group[i + 2].value === "-") { group.splice(i, 3, new ParseNode( @@ -817,7 +815,7 @@ Parser.prototype.formLigatures = function(group) { * @return {?ParseFuncOrArgument} */ Parser.prototype.parseSymbol = function() { - var nucleus = this.nextToken; + const nucleus = this.nextToken; if (functions[nucleus.text]) { this.consume(); diff --git a/src/Style.js b/src/Style.js @@ -6,18 +6,17 @@ * information about them. */ -var sigmas = require("./fontMetrics.js").sigmas; +const sigmas = require("./fontMetrics.js").sigmas; -var metrics = [{}, {}, {}]; -var i; -for (var key in sigmas) { +const metrics = [{}, {}, {}]; +for (const key in sigmas) { if (sigmas.hasOwnProperty(key)) { - for (i = 0; i < 3; i++) { + for (let i = 0; i < 3; 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]; } @@ -95,17 +94,17 @@ Style.prototype.isTight = function() { }; // IDs of the different styles -var D = 0; -var Dc = 1; -var T = 2; -var Tc = 3; -var S = 4; -var Sc = 5; -var SS = 6; -var SSc = 7; +const D = 0; +const Dc = 1; +const T = 2; +const Tc = 3; +const S = 4; +const Sc = 5; +const SS = 6; +const SSc = 7; // String names for the different sizes -var sizeNames = [ +const sizeNames = [ "displaystyle textstyle", "textstyle", "scriptstyle", @@ -113,7 +112,7 @@ var sizeNames = [ ]; // Reset names for the different sizes -var resetNames = [ +const resetNames = [ "reset-textstyle", "reset-textstyle", "reset-scriptstyle", @@ -121,7 +120,7 @@ var resetNames = [ ]; // Instances of the different styles -var styles = [ +const styles = [ new Style(D, 0, 1.0, false), new Style(Dc, 0, 1.0, true), new Style(T, 1, 1.0, false), @@ -133,11 +132,11 @@ var styles = [ ]; // Lookup tables for switching from one style to another -var sup = [S, Sc, S, Sc, SS, SSc, SS, SSc]; -var sub = [Sc, Sc, Sc, Sc, SSc, SSc, SSc, SSc]; -var fracNum = [T, Tc, S, Sc, SS, SSc, SS, SSc]; -var fracDen = [Tc, Tc, Sc, Sc, SSc, SSc, SSc, SSc]; -var cramp = [Dc, Dc, Tc, Tc, Sc, Sc, SSc, SSc]; +const sup = [S, Sc, S, Sc, SS, SSc, SS, SSc]; +const sub = [Sc, Sc, Sc, Sc, SSc, SSc, SSc, SSc]; +const fracNum = [T, Tc, S, Sc, SS, SSc, SS, SSc]; +const fracDen = [Tc, Tc, Sc, Sc, SSc, SSc, SSc, SSc]; +const cramp = [Dc, Dc, Tc, Tc, Sc, Sc, SSc, SSc]; // We only export some of the styles. Also, we don't export the `Style` class so // no more styles can be generated. diff --git a/src/buildCommon.js b/src/buildCommon.js @@ -4,12 +4,12 @@ * different kinds of domTree nodes in a consistent manner. */ -var domTree = require("./domTree"); -var fontMetrics = require("./fontMetrics"); -var symbols = require("./symbols"); -var utils = require("./utils"); +const domTree = require("./domTree"); +const fontMetrics = require("./fontMetrics"); +const symbols = require("./symbols"); +const utils = require("./utils"); -var greekCapitals = [ +const greekCapitals = [ "\\Gamma", "\\Delta", "\\Theta", @@ -24,7 +24,7 @@ var greekCapitals = [ ]; // The following have to be loaded from Main-Italic font, using class mainit -var mainitLetters = [ +const mainitLetters = [ "\u0131", // dotless i, \imath "\u0237", // dotless j, \jmath "\u00a3", // \pounds @@ -39,17 +39,17 @@ var mainitLetters = [ * TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which * 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 if (symbols[mode][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) { - var italic = metrics.italic; + let italic = metrics.italic; if (mode === "text") { italic = 0; } @@ -80,7 +80,7 @@ var makeSymbol = function(value, fontFamily, mode, options, classes) { * Makes a symbol in Main-Regular or AMS-Regular. * 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 // table. // 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. */ -var mathDefault = function(value, mode, options, classes, type) { +const mathDefault = function(value, mode, options, classes, type) { if (type === "mathord") { return mathit(value, mode, options, classes); } else if (type === "textord") { @@ -112,7 +112,7 @@ var mathDefault = function(value, mode, options, classes, type) { /** * 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)) || // glyphs for \imath and \jmath do not exist in Math-Italic so we // 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. */ -var makeOrd = function(group, options, type) { - var mode = group.mode; - var value = group.value; +const makeOrd = function(group, options, type) { + const mode = group.mode; + let value = group.value; if (symbols[mode][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 === "mathit" || utils.contains(mainitLetters, value)) { return mathit(value, mode, options, classes); } else { - var fontName = fontMap[font].fontName; + const fontName = fontMap[font].fontName; if (fontMetrics.getCharacterMetrics(value, fontName)) { return makeSymbol( 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 * children. */ -var sizeElementFromChildren = function(elem) { - var height = 0; - var depth = 0; - var maxFontSize = 0; +const sizeElementFromChildren = function(elem) { + let height = 0; + let depth = 0; + let maxFontSize = 0; 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) { 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 * should if present come first in `classes`. */ -var makeSpan = function(classes, children, options) { - var span = new domTree.span(classes, children, options); +const makeSpan = function(classes, children, options) { + const span = new domTree.span(classes, children, options); sizeElementFromChildren(span); @@ -204,7 +204,7 @@ var makeSpan = function(classes, children, options) { * Prepends the given children to the given span, updating height, depth, and * maxFontSize. */ -var prependChildren = function(span, children) { +const prependChildren = function(span, children) { span.children = children.concat(span.children); sizeElementFromChildren(span); @@ -213,8 +213,8 @@ var prependChildren = function(span, children) { /** * Makes a document fragment with the given list of children. */ -var makeFragment = function(children) { - var fragment = new domTree.documentFragment(children); +const makeFragment = function(children) { + const fragment = new domTree.documentFragment(children); 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 * with the correct font size. */ -var makeFontSizer = function(options, fontSize) { - var fontSizeInner = makeSpan([], [new domTree.symbolNode("\u200b")]); +const makeFontSizer = function(options, fontSize) { + const fontSizeInner = makeSpan([], [new domTree.symbolNode("\u200b")]); fontSizeInner.style.fontSize = (fontSize / options.style.sizeMultiplier) + "em"; - var fontSizer = makeSpan( + const fontSizer = makeSpan( ["fontsize-ensurer", "reset-" + options.size, "size5"], [fontSizeInner]); @@ -277,12 +277,12 @@ var makeFontSizer = function(options, fontSize) { * - options: An Options object * */ -var makeVList = function(children, positionType, positionData, options) { - var depth; - var currPos; - var i; +const makeVList = function(children, positionType, positionData, options) { + let depth; + let currPos; + let i; if (positionType === "individualShift") { - var oldChildren = children; + const oldChildren = children; children = [oldChildren[0]]; // 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; currPos = depth; for (i = 1; i < oldChildren.length; i++) { - var diff = -oldChildren[i].shift - currPos - + const diff = -oldChildren[i].shift - currPos - oldChildren[i].elem.depth; - var size = diff - + const size = diff - (oldChildren[i - 1].elem.height + oldChildren[i - 1].elem.depth); @@ -304,7 +304,7 @@ var makeVList = function(children, positionType, positionData, options) { } else if (positionType === "top") { // We always start at the bottom, so calculate the bottom by adding up // all the sizes - var bottom = positionData; + let bottom = positionData; for (i = 0; i < children.length; i++) { if (children[i].type === "kern") { bottom -= children[i].size; @@ -324,27 +324,27 @@ var makeVList = function(children, positionType, positionData, options) { } // Make the fontSizer - var maxFontSize = 0; + let maxFontSize = 0; for (i = 0; i < children.length; i++) { if (children[i].type === "elem") { 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 - var realChildren = []; + const realChildren = []; currPos = depth; for (i = 0; i < children.length; i++) { if (children[i].type === "kern") { currPos += children[i].size; } 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; - var childWrap = makeSpan([], [fontSizer, child]); + const childWrap = makeSpan([], [fontSizer, child]); childWrap.height -= shift; childWrap.depth += shift; 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 // baselines in some browsers (namely IE, sometimes safari) - var baselineFix = makeSpan( + const baselineFix = makeSpan( ["baseline-fix"], [fontSizer, new domTree.symbolNode("\u200b")]); 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 // since the makeSpan calculation won't take that in to account. 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 -var sizingMultiplier = { +const sizingMultiplier = { size1: 0.5, size2: 0.7, size3: 0.8, @@ -383,7 +383,7 @@ var sizingMultiplier = { // A map of spacing functions to their attributes, like size and corresponding // CSS class -var spacingFunctions = { +const spacingFunctions = { "\\qquad": { size: "2em", className: "qquad", @@ -420,7 +420,7 @@ var spacingFunctions = { * - fontName: the "style" parameter to fontMetrics.getCharacterMetrics */ // A map between tex font commands an MathML mathvariant attribute values -var fontMap = { +const fontMap = { // styles "mathbf": { variant: "bold", diff --git a/src/buildHTML.js b/src/buildHTML.js @@ -6,18 +6,18 @@ * called, to produce a final HTML tree. */ -var ParseError = require("./ParseError"); -var Style = require("./Style"); +const ParseError = require("./ParseError"); +const Style = require("./Style"); -var buildCommon = require("./buildCommon"); -var delimiter = require("./delimiter"); -var domTree = require("./domTree"); -var fontMetrics = require("./fontMetrics"); -var utils = require("./utils"); +const buildCommon = require("./buildCommon"); +const delimiter = require("./delimiter"); +const domTree = require("./domTree"); +const fontMetrics = require("./fontMetrics"); +const utils = require("./utils"); -var makeSpan = buildCommon.makeSpan; +const makeSpan = buildCommon.makeSpan; -var isSpace = function(node) { +const isSpace = function(node) { return node instanceof domTree.span && node.classes[0] === "mspace"; }; @@ -25,11 +25,11 @@ var isSpace = function(node) { // depending on their surroundings. See TeXbook pg. 442-446, Rules 5 and 6, // and the text before Rule 19. -var isBin = function(node) { +const isBin = function(node) { return node && node.classes[0] === "mbin"; }; -var isBinLeftCanceller = function(node, isRealGroup) { +const isBinLeftCanceller = function(node, isRealGroup) { // TODO: This code assumes that a node's math class is the first element // of its `classes` array. A later cleanup should ensure this, for // instance by changing the signature of `makeSpan`. @@ -41,7 +41,7 @@ var isBinLeftCanceller = function(node, isRealGroup) { } }; -var isBinRightCanceller = function(node, isRealGroup) { +const isBinRightCanceller = function(node, isRealGroup) { if (node) { return utils.contains(["mrel", "mclose", "mpunct"], node.classes[0]); } else { @@ -56,12 +56,12 @@ var isBinRightCanceller = function(node, isRealGroup) { * is a real group (no atoms will be added on either side), as opposed to * a partial group (e.g. one created by \color). */ -var buildExpression = function(expression, options, isRealGroup) { +const buildExpression = function(expression, options, isRealGroup) { // Parse expressions into `groups`. - var groups = []; - for (var i = 0; i < expression.length; i++) { - var group = expression[i]; - var output = buildGroup(group, options); + const groups = []; + for (let i = 0; i < expression.length; i++) { + const group = expression[i]; + const output = buildGroup(group, options); if (output instanceof domTree.documentFragment) { Array.prototype.push.apply(groups, output.children); } else { @@ -74,8 +74,8 @@ var buildExpression = function(expression, options, isRealGroup) { // spacing (e.g., "add thick space between mord and mrel"). Since CSS // adjacency rules implement atom spacing, spaces should be invisible to // CSS. So we splice them out of `groups` and into the atoms themselves. - var spaces = null; - for (i = 0; i < groups.length; i++) { + let spaces = null; + for (let i = 0; i < groups.length; i++) { if (isSpace(groups[i])) { spaces = spaces || []; spaces.push(groups[i]); @@ -94,7 +94,7 @@ var buildExpression = function(expression, options, isRealGroup) { } // Binary operators change to ordinary symbols in some contexts. - for (i = 0; i < groups.length; i++) { + for (let i = 0; i < groups.length; i++) { if (isBin(groups[i]) && (isBinLeftCanceller(groups[i - 1], isRealGroup) || isBinRightCanceller(groups[i + 1], isRealGroup))) { @@ -106,7 +106,7 @@ var buildExpression = function(expression, options, isRealGroup) { }; // Return math atom class (mclass) of a domTree. -var getTypeOfDomTree = function(node) { +const getTypeOfDomTree = function(node) { if (node instanceof domTree.documentFragment) { if (node.children.length) { return getTypeOfDomTree( @@ -129,7 +129,7 @@ var getTypeOfDomTree = function(node) { * its inner element should handle the superscripts and subscripts instead of * handling them itself. */ -var shouldHandleSupSub = function(group, options) { +const shouldHandleSupSub = function(group, options) { if (!group) { return false; } else if (group.type === "op") { @@ -150,7 +150,7 @@ var shouldHandleSupSub = function(group, options) { * cases, this will just be the group itself, but when ordgroups and colors have * a single element, we want to pull that out. */ -var getBaseElem = function(group) { +const getBaseElem = function(group) { if (!group) { return false; } else if (group.type === "ordgroup") { @@ -177,8 +177,8 @@ var getBaseElem = function(group) { * with a single character in them. To decide if something is a character box, * we find its innermost group, and see if it is a single character. */ -var isCharacterBox = function(group) { - var baseElem = getBaseElem(group); +const isCharacterBox = function(group) { + const baseElem = getBaseElem(group); // These are all they types of groups which hold single characters return baseElem.type === "mathord" || @@ -191,7 +191,7 @@ var isCharacterBox = function(group) { baseElem.type === "punct"; }; -var makeNullDelimiter = function(options, classes) { +const makeNullDelimiter = function(options, classes) { return makeSpan(classes.concat([ "sizing", "reset-" + options.size, "size5", options.style.reset(), Style.TEXT.cls(), @@ -202,7 +202,7 @@ var makeNullDelimiter = function(options, classes) { * This is a map of group types to the function used to handle that type. * Simpler types come at the beginning, while complicated types come afterwards. */ -var groupTypes = {}; +const groupTypes = {}; groupTypes.mathord = function(group, options) { return buildCommon.makeOrd(group, options, "mathord"); @@ -251,9 +251,9 @@ groupTypes.ordgroup = function(group, options) { }; groupTypes.text = function(group, options) { - var newOptions = options.withFont(group.value.style); - var inner = buildExpression(group.value.body, newOptions, true); - for (var i = 0; i < inner.length - 1; i++) { + const newOptions = options.withFont(group.value.style); + const inner = buildExpression(group.value.body, newOptions, true); + for (let i = 0; i < inner.length - 1; i++) { if (inner[i].tryCombine(inner[i + 1])) { inner.splice(i + 1, 1); i--; @@ -264,7 +264,7 @@ groupTypes.text = function(group, options) { }; groupTypes.color = function(group, options) { - var elements = buildExpression( + const elements = buildExpression( group.value.value, options.withColor(group.value.color), false @@ -287,14 +287,14 @@ groupTypes.supsub = function(group, options) { return groupTypes[group.value.base.type](group, options); } - var base = buildGroup(group.value.base, options.reset()); - var supmid; - var submid; - var sup; - var sub; + const base = buildGroup(group.value.base, options.reset()); + let supmid; + let submid; + let sup; + let sub; - var style = options.style; - var newOptions; + const style = options.style; + let newOptions; if (group.value.sup) { newOptions = options.withStyle(style.sup()); @@ -311,8 +311,8 @@ groupTypes.supsub = function(group, options) { } // Rule 18a - var supShift; - var subShift; + let supShift; + let subShift; if (isCharacterBox(group.value.base)) { supShift = 0; subShift = 0; @@ -322,7 +322,7 @@ groupTypes.supsub = function(group, options) { } // Rule 18c - var minSupShift; + let minSupShift; if (style === Style.DISPLAY) { minSupShift = style.metrics.sup1; } else if (style.cramped) { @@ -333,12 +333,12 @@ groupTypes.supsub = function(group, options) { // scriptspace is a font-size-independent size, so scale it // appropriately - var multiplier = Style.TEXT.sizeMultiplier * + const multiplier = Style.TEXT.sizeMultiplier * style.sizeMultiplier; - var scriptspace = + const scriptspace = (0.5 / fontMetrics.metrics.ptPerEm) / multiplier + "em"; - var supsub; + let supsub; if (!group.value.sup) { // Rule 18b subShift = Math.max( @@ -372,13 +372,13 @@ groupTypes.supsub = function(group, options) { supShift, minSupShift, sup.depth + 0.25 * style.metrics.xHeight); subShift = Math.max(subShift, style.metrics.sub2); - var ruleWidth = fontMetrics.metrics.defaultRuleThickness; + const ruleWidth = fontMetrics.metrics.defaultRuleThickness; // Rule 18e if ((supShift - sup.depth) - (sub.height - subShift) < 4 * ruleWidth) { subShift = 4 * ruleWidth - (supShift - sup.depth) + sub.height; - var psi = 0.8 * style.metrics.xHeight - (supShift - sup.depth); + const psi = 0.8 * style.metrics.xHeight - (supShift - sup.depth); if (psi > 0) { supShift += psi; subShift -= psi; @@ -400,7 +400,7 @@ groupTypes.supsub = function(group, options) { } // We ensure to wrap the supsub vlist in a span.msupsub to reset text-align - var mclass = getTypeOfDomTree(base) || "mord"; + const mclass = getTypeOfDomTree(base) || "mord"; return makeSpan([mclass], [base, makeSpan(["msupsub"], [supsub])], options); @@ -410,28 +410,28 @@ groupTypes.genfrac = function(group, options) { // Fractions are handled in the TeXbook on pages 444-445, rules 15(a-e). // Figure out what style this fraction should be in based on the // function used - var style = options.style; + let style = options.style; if (group.value.size === "display") { style = Style.DISPLAY; } else if (group.value.size === "text") { style = Style.TEXT; } - var nstyle = style.fracNum(); - var dstyle = style.fracDen(); - var newOptions; + const nstyle = style.fracNum(); + const dstyle = style.fracDen(); + let newOptions; newOptions = options.withStyle(nstyle); - var numer = buildGroup(group.value.numer, newOptions); - var numerreset = makeSpan([style.reset(), nstyle.cls()], + const numer = buildGroup(group.value.numer, newOptions); + const numerreset = makeSpan([style.reset(), nstyle.cls()], [numer], newOptions); newOptions = options.withStyle(dstyle); - var denom = buildGroup(group.value.denom, newOptions); - var denomreset = makeSpan([style.reset(), dstyle.cls()], + const denom = buildGroup(group.value.denom, newOptions); + const denomreset = makeSpan([style.reset(), dstyle.cls()], [denom], newOptions); - var ruleWidth; + let ruleWidth; if (group.value.hasBarLine) { ruleWidth = fontMetrics.metrics.defaultRuleThickness / options.style.sizeMultiplier; @@ -440,9 +440,9 @@ groupTypes.genfrac = function(group, options) { } // Rule 15b - var numShift; - var clearance; - var denomShift; + let numShift; + let clearance; + let denomShift; if (style.size === Style.DISPLAY.size) { numShift = style.metrics.num1; if (ruleWidth > 0) { @@ -462,10 +462,10 @@ groupTypes.genfrac = function(group, options) { denomShift = style.metrics.denom2; } - var frac; + let frac; if (ruleWidth === 0) { // Rule 15c - var candidateClearance = + const candidateClearance = (numShift - numer.depth) - (denom.height - denomShift); if (candidateClearance < clearance) { numShift += 0.5 * (clearance - candidateClearance); @@ -478,7 +478,7 @@ groupTypes.genfrac = function(group, options) { ], "individualShift", null, options); } else { // Rule 15d - var axisHeight = style.metrics.axisHeight; + const axisHeight = style.metrics.axisHeight; if ((numShift - numer.depth) - (axisHeight + 0.5 * ruleWidth) < clearance) { @@ -494,13 +494,13 @@ groupTypes.genfrac = function(group, options) { (denom.height - denomShift)); } - var mid = makeSpan( + const mid = makeSpan( [options.style.reset(), Style.TEXT.cls(), "frac-line"]); // Manually set the height of the line because its height is // created in CSS mid.height = ruleWidth; - var midShift = -(axisHeight - 0.5 * ruleWidth); + const midShift = -(axisHeight - 0.5 * ruleWidth); frac = buildCommon.makeVList([ {type: "elem", elem: denomreset, shift: denomShift}, @@ -515,15 +515,15 @@ groupTypes.genfrac = function(group, options) { frac.depth *= style.sizeMultiplier / options.style.sizeMultiplier; // Rule 15e - var delimSize; + let delimSize; if (style.size === Style.DISPLAY.size) { delimSize = style.metrics.delim1; } else { delimSize = style.metrics.delim2; } - var leftDelim; - var rightDelim; + let leftDelim; + let rightDelim; if (group.value.leftDelim == null) { leftDelim = makeNullDelimiter(options, ["mopen"]); } else { @@ -545,8 +545,8 @@ groupTypes.genfrac = function(group, options) { options); }; -var calculateSize = function(sizeValue, style) { - var x = sizeValue.number; +const calculateSize = function(sizeValue, style) { + let x = sizeValue.number; if (sizeValue.unit === "ex") { x *= style.metrics.emPerEx; } else if (sizeValue.unit === "mu") { @@ -556,40 +556,40 @@ var calculateSize = function(sizeValue, style) { }; groupTypes.array = function(group, options) { - var r; - var c; - var nr = group.value.body.length; - var nc = 0; - var body = new Array(nr); + let r; + let c; + const nr = group.value.body.length; + let nc = 0; + let body = new Array(nr); - var style = options.style; + const style = options.style; // Horizontal spacing - var pt = 1 / fontMetrics.metrics.ptPerEm; - var arraycolsep = 5 * pt; // \arraycolsep in article.cls + const pt = 1 / fontMetrics.metrics.ptPerEm; + const arraycolsep = 5 * pt; // \arraycolsep in article.cls // Vertical spacing - var baselineskip = 12 * pt; // see size10.clo + const baselineskip = 12 * pt; // see size10.clo // Default \arraystretch from lttab.dtx // TODO(gagern): may get redefined once we have user-defined macros - var arraystretch = utils.deflt(group.value.arraystretch, 1); - var arrayskip = arraystretch * baselineskip; - var arstrutHeight = 0.7 * arrayskip; // \strutbox in ltfsstrc.dtx and - var arstrutDepth = 0.3 * arrayskip; // \@arstrutbox in lttab.dtx + const arraystretch = utils.deflt(group.value.arraystretch, 1); + const arrayskip = arraystretch * baselineskip; + const arstrutHeight = 0.7 * arrayskip; // \strutbox in ltfsstrc.dtx and + const arstrutDepth = 0.3 * arrayskip; // \@arstrutbox in lttab.dtx - var totalHeight = 0; + let totalHeight = 0; for (r = 0; r < group.value.body.length; ++r) { - var inrow = group.value.body[r]; - var height = arstrutHeight; // \@array adds an \@arstrut - var depth = arstrutDepth; // to each tow (via the template) + const inrow = group.value.body[r]; + let height = arstrutHeight; // \@array adds an \@arstrut + let depth = arstrutDepth; // to each tow (via the template) if (nc < inrow.length) { nc = inrow.length; } - var outrow = new Array(inrow.length); + const outrow = new Array(inrow.length); for (c = 0; c < inrow.length; ++c) { - var elt = buildGroup(inrow[c], options); + const elt = buildGroup(inrow[c], options); if (depth < elt.depth) { depth = elt.depth; } @@ -599,7 +599,7 @@ groupTypes.array = function(group, options) { outrow[c] = elt; } - var gap = 0; + let gap = 0; if (group.value.rowGaps[r]) { gap = calculateSize(group.value.rowGaps[r].value, style); if (gap > 0) { // \@argarraycr @@ -619,20 +619,20 @@ groupTypes.array = function(group, options) { body[r] = outrow; } - var offset = totalHeight / 2 + style.metrics.axisHeight; - var colDescriptions = group.value.cols || []; - var cols = []; - var colSep; - var colDescrNum; + const offset = totalHeight / 2 + style.metrics.axisHeight; + const colDescriptions = group.value.cols || []; + const cols = []; + let colSep; + let colDescrNum; for (c = 0, colDescrNum = 0; // Continue while either there are more columns or more column // descriptions, so trailing separators don't get lost. c < nc || colDescrNum < colDescriptions.length; ++c, ++colDescrNum) { - var colDescr = colDescriptions[colDescrNum] || {}; + let colDescr = colDescriptions[colDescrNum] || {}; - var firstSeparator = true; + let firstSeparator = true; while (colDescr.type === "separator") { // If there is more than one separator in a row, add a space // between them. @@ -644,7 +644,7 @@ groupTypes.array = function(group, options) { } if (colDescr.separator === "|") { - var separator = makeSpan( + const separator = makeSpan( ["vertical-separator"], []); separator.style.height = totalHeight + "em"; @@ -666,7 +666,7 @@ groupTypes.array = function(group, options) { continue; } - var sepwidth; + let sepwidth; if (c > 0 || group.value.hskipBeforeAndAfter) { sepwidth = utils.deflt(colDescr.pregap, arraycolsep); if (sepwidth !== 0) { @@ -676,14 +676,14 @@ groupTypes.array = function(group, options) { } } - var col = []; + let col = []; for (r = 0; r < nr; ++r) { - var row = body[r]; - var elem = row[c]; + const row = body[r]; + const elem = row[c]; if (!elem) { continue; } - var shift = row.pos - offset; + const shift = row.pos - offset; elem.depth = row.depth; elem.height = row.height; col.push({type: "elem", elem: elem, shift: shift}); @@ -731,26 +731,26 @@ groupTypes.spacing = function(group, options) { }; groupTypes.llap = function(group, options) { - var inner = makeSpan( + const inner = makeSpan( ["inner"], [buildGroup(group.value.body, options.reset())]); - var fix = makeSpan(["fix"], []); + const fix = makeSpan(["fix"], []); return makeSpan( ["mord", "llap", options.style.cls()], [inner, fix], options); }; groupTypes.rlap = function(group, options) { - var inner = makeSpan( + const inner = makeSpan( ["inner"], [buildGroup(group.value.body, options.reset())]); - var fix = makeSpan(["fix"], []); + const fix = makeSpan(["fix"], []); return makeSpan( ["mord", "rlap", options.style.cls()], [inner, fix], options); }; groupTypes.op = function(group, options) { // Operators are handled in the TeXbook pg. 443-444, rule 13(a). - var supGroup; - var subGroup; - var hasLimits = false; + let supGroup; + let subGroup; + let hasLimits = false; if (group.type === "supsub") { // If we have limits, supsub will pass us its group to handle. Pull // out the superscript and subscript and set the group to the op in @@ -761,14 +761,14 @@ groupTypes.op = function(group, options) { hasLimits = true; } - var style = options.style; + const style = options.style; // Most operators have a large successor symbol, but these don't. - var noSuccessor = [ + const noSuccessor = [ "\\smallint", ]; - var large = false; + let large = false; if (style.size === Style.DISPLAY.size && group.value.symbol && !utils.contains(noSuccessor, group.value.body)) { @@ -777,12 +777,12 @@ groupTypes.op = function(group, options) { large = true; } - var base; - var baseShift = 0; - var slant = 0; + let base; + let baseShift = 0; + let slant = 0; if (group.value.symbol) { // If this is a symbol, create the symbol. - var fontName = large ? "Size2-Regular" : "Size1-Regular"; + const fontName = large ? "Size2-Regular" : "Size1-Regular"; base = buildCommon.makeSymbol( group.value.body, fontName, "math", options, ["mop", "op-symbol", large ? "large-op" : "small-op"]); @@ -799,7 +799,7 @@ groupTypes.op = function(group, options) { slant = base.italic; } else if (group.value.value) { // If this is a list, compose that list. - var inner = buildExpression(group.value.value, options, true); + const inner = buildExpression(group.value.value, options, true); base = makeSpan(["mop"], inner, options); } else { @@ -807,8 +807,8 @@ groupTypes.op = function(group, options) { // operator's name. // TODO(emily): Add a space in the middle of some of these // operators, like \limsup - var output = []; - for (var i = 1; i < group.value.body.length; i++) { + const output = []; + for (let i = 1; i < group.value.body.length; i++) { output.push(buildCommon.mathsym(group.value.body[i], group.mode)); } base = makeSpan(["mop"], output, options); @@ -819,16 +819,16 @@ groupTypes.op = function(group, options) { // in a new span so it is an inline, and works. base = makeSpan([], [base]); - var supmid; - var supKern; - var submid; - var subKern; - var newOptions; + let supmid; + let supKern; + let submid; + let subKern; + let newOptions; // We manually have to handle the superscripts and subscripts. This, // aside from the kern calculations, is copied from supsub. if (supGroup) { newOptions = options.withStyle(style.sup()); - var sup = buildGroup(supGroup, newOptions); + const sup = buildGroup(supGroup, newOptions); supmid = makeSpan([style.reset(), style.sup().cls()], [sup], newOptions); @@ -839,7 +839,7 @@ groupTypes.op = function(group, options) { if (subGroup) { newOptions = options.withStyle(style.sub()); - var sub = buildGroup(subGroup, newOptions); + const sub = buildGroup(subGroup, newOptions); submid = makeSpan([style.reset(), style.sub().cls()], [sub], newOptions); @@ -850,9 +850,9 @@ groupTypes.op = function(group, options) { // Build the final group as a vlist of the possible subscript, base, // and possible superscript. - var finalGroup; - var top; - var bottom; + let finalGroup; + let top; + let bottom; if (!supGroup) { top = base.height - baseShift; @@ -917,7 +917,7 @@ groupTypes.op = function(group, options) { }; groupTypes.mod = function(group, options) { - var inner = []; + const inner = []; if (group.value.modType === "bmod") { // “\nonscript\mskip-\medmuskip\mkern5mu” @@ -939,7 +939,7 @@ groupTypes.mod = function(group, options) { } if (group.value.modType !== "pod") { - var modInner = [ + const modInner = [ buildCommon.mathsym("m", group.mode), buildCommon.mathsym("o", group.mode), buildCommon.mathsym("d", group.mode)]; @@ -973,23 +973,23 @@ groupTypes.katex = function(group, options) { // The KaTeX logo. The offsets for the K and a were chosen to look // good, but the offsets for the T, E, and X were taken from the // definition of \TeX in TeX (see TeXbook pg. 356) - var k = makeSpan( + const k = makeSpan( ["k"], [buildCommon.mathsym("K", group.mode)], options); - var a = makeSpan( + const a = makeSpan( ["a"], [buildCommon.mathsym("A", group.mode)], options); a.height = (a.height + 0.2) * 0.75; a.depth = (a.height - 0.2) * 0.75; - var t = makeSpan( + const t = makeSpan( ["t"], [buildCommon.mathsym("T", group.mode)], options); - var e = makeSpan( + const e = makeSpan( ["e"], [buildCommon.mathsym("E", group.mode)], options); e.height = (e.height - 0.2155); e.depth = (e.depth + 0.2155); - var x = makeSpan( + const x = makeSpan( ["x"], [buildCommon.mathsym("X", group.mode)], options); return makeSpan( @@ -998,23 +998,23 @@ groupTypes.katex = function(group, options) { groupTypes.overline = function(group, options) { // Overlines are handled in the TeXbook pg 443, Rule 9. - var style = options.style; + const style = options.style; // Build the inner group in the cramped style. - var innerGroup = buildGroup(group.value.body, + const innerGroup = buildGroup(group.value.body, options.withStyle(style.cramp())); - var ruleWidth = fontMetrics.metrics.defaultRuleThickness / + const ruleWidth = fontMetrics.metrics.defaultRuleThickness / style.sizeMultiplier; // Create the line above the body - var line = makeSpan( + const line = makeSpan( [style.reset(), Style.TEXT.cls(), "overline-line"]); line.height = ruleWidth; line.maxFontSize = 1.0; // Generate the vlist, with the appropriate kerns - var vlist = buildCommon.makeVList([ + const vlist = buildCommon.makeVList([ {type: "elem", elem: innerGroup}, {type: "kern", size: 3 * ruleWidth}, {type: "elem", elem: line}, @@ -1026,21 +1026,21 @@ groupTypes.overline = function(group, options) { groupTypes.underline = function(group, options) { // Underlines are handled in the TeXbook pg 443, Rule 10. - var style = options.style; + const style = options.style; // Build the inner group. - var innerGroup = buildGroup(group.value.body, options); + const innerGroup = buildGroup(group.value.body, options); - var ruleWidth = fontMetrics.metrics.defaultRuleThickness / + const ruleWidth = fontMetrics.metrics.defaultRuleThickness / style.sizeMultiplier; // Create the line above the body - var line = makeSpan([style.reset(), Style.TEXT.cls(), "underline-line"]); + const line = makeSpan([style.reset(), Style.TEXT.cls(), "underline-line"]); line.height = ruleWidth; line.maxFontSize = 1.0; // Generate the vlist, with the appropriate kerns - var vlist = buildCommon.makeVList([ + const vlist = buildCommon.makeVList([ {type: "kern", size: ruleWidth}, {type: "elem", elem: line}, {type: "kern", size: 3 * ruleWidth}, @@ -1052,39 +1052,40 @@ groupTypes.underline = function(group, options) { groupTypes.sqrt = function(group, options) { // Square roots are handled in the TeXbook pg. 443, Rule 11. - var style = options.style; + const style = options.style; // First, we do the same steps as in overline to build the inner group // and line - var inner = buildGroup(group.value.body, options.withStyle(style.cramp())); + const inner = buildGroup( + group.value.body, options.withStyle(style.cramp())); - var ruleWidth = fontMetrics.metrics.defaultRuleThickness / + const ruleWidth = fontMetrics.metrics.defaultRuleThickness / style.sizeMultiplier; - var line = makeSpan( + const line = makeSpan( [style.reset(), Style.TEXT.cls(), "sqrt-line"], [], options); line.height = ruleWidth; line.maxFontSize = 1.0; - var phi = ruleWidth; + let phi = ruleWidth; if (style.id < Style.TEXT.id) { phi = style.metrics.xHeight; } // Calculate the clearance between the body and line - var lineClearance = ruleWidth + phi / 4; + let lineClearance = ruleWidth + phi / 4; - var innerHeight = (inner.height + inner.depth) * style.sizeMultiplier; - var minDelimiterHeight = innerHeight + lineClearance + ruleWidth; + const innerHeight = (inner.height + inner.depth) * style.sizeMultiplier; + const minDelimiterHeight = innerHeight + lineClearance + ruleWidth; // Create a \surd delimiter of the required minimum size - var delim = makeSpan(["sqrt-sign"], [ + const delim = makeSpan(["sqrt-sign"], [ delimiter.customSizedDelim("\\surd", minDelimiterHeight, false, options, group.mode)], options); - var delimDepth = (delim.height + delim.depth) - ruleWidth; + const delimDepth = (delim.height + delim.depth) - ruleWidth; // Adjust the clearance based on the delimiter size if (delimDepth > inner.height + inner.depth + lineClearance) { @@ -1093,7 +1094,8 @@ groupTypes.sqrt = function(group, options) { } // Shift the delimiter so that its top lines up with the top of the line - var delimShift = -(inner.height + lineClearance + ruleWidth) + delim.height; + const delimShift = -(inner.height + lineClearance + ruleWidth) + + delim.height; delim.style.top = delimShift + "em"; delim.height -= delimShift; delim.depth += delimShift; @@ -1103,7 +1105,7 @@ groupTypes.sqrt = function(group, options) { // should omit the body entirely. (note this doesn't work for something // like `\sqrt{\rlap{x}}`, but if someone is doing that they deserve for // it not to work. - var body; + let body; if (inner.height === 0 && inner.depth === 0) { body = makeSpan(); } else { @@ -1121,28 +1123,28 @@ groupTypes.sqrt = function(group, options) { // Handle the optional root index // The index is always in scriptscript style - var newOptions = options.withStyle(Style.SCRIPTSCRIPT); - var root = buildGroup(group.value.index, newOptions); - var rootWrap = makeSpan( + const newOptions = options.withStyle(Style.SCRIPTSCRIPT); + const root = buildGroup(group.value.index, newOptions); + const rootWrap = makeSpan( [style.reset(), Style.SCRIPTSCRIPT.cls()], [root], newOptions); // Figure out the height and depth of the inner part - var innerRootHeight = Math.max(delim.height, body.height); - var innerRootDepth = Math.max(delim.depth, body.depth); + const innerRootHeight = Math.max(delim.height, body.height); + const innerRootDepth = Math.max(delim.depth, body.depth); // The amount the index is shifted by. This is taken from the TeX // source, in the definition of `\r@@t`. - var toShift = 0.6 * (innerRootHeight - innerRootDepth); + const toShift = 0.6 * (innerRootHeight - innerRootDepth); // Build a VList with the superscript shifted up correctly - var rootVList = buildCommon.makeVList( + const rootVList = buildCommon.makeVList( [{type: "elem", elem: rootWrap}], "shift", -toShift, options); // Add a class surrounding it so we can add on the appropriate // kerning - var rootVListWrap = makeSpan(["root"], [rootVList]); + const rootVListWrap = makeSpan(["root"], [rootVList]); return makeSpan(["mord", "sqrt"], [rootVListWrap, delim, body], options); @@ -1153,18 +1155,18 @@ groupTypes.sizing = function(group, options) { // Handle sizing operators like \Huge. Real TeX doesn't actually allow // these functions inside of math expressions, so we do some special // handling. - var inner = buildExpression(group.value.value, + const inner = buildExpression(group.value.value, options.withSize(group.value.size), false); // Compute the correct maxFontSize. - var style = options.style; - var fontSize = buildCommon.sizingMultiplier[group.value.size]; - fontSize = fontSize * style.sizeMultiplier; + const style = options.style; + const fontSize = buildCommon.sizingMultiplier[group.value.size] * + style.sizeMultiplier; // Add size-resetting classes to the inner list and set maxFontSize // manually. Handle nested size changes. - for (var i = 0; i < inner.length; i++) { - var pos = utils.indexOf(inner[i].classes, "sizing"); + for (let i = 0; i < inner.length; i++) { + const pos = utils.indexOf(inner[i].classes, "sizing"); if (pos < 0) { inner[i].classes.push("sizing", "reset-" + options.size, group.value.size, style.cls()); @@ -1184,23 +1186,23 @@ groupTypes.styling = function(group, options) { // Style changes are handled in the TeXbook on pg. 442, Rule 3. // Figure out what style we're changing to. - var styleMap = { + const styleMap = { "display": Style.DISPLAY, "text": Style.TEXT, "script": Style.SCRIPT, "scriptscript": Style.SCRIPTSCRIPT, }; - var newStyle = styleMap[group.value.style]; - var newOptions = options.withStyle(newStyle); + const newStyle = styleMap[group.value.style]; + const newOptions = options.withStyle(newStyle); // Build the inner expression in the new style. - var inner = buildExpression( + const inner = buildExpression( group.value.value, newOptions, false); // Add style-resetting classes to the inner list. Handle nested changes. - for (var i = 0; i < inner.length; i++) { - var pos = utils.indexOf(inner[i].classes, newStyle.reset()); + for (let i = 0; i < inner.length; i++) { + const pos = utils.indexOf(inner[i].classes, newStyle.reset()); if (pos < 0) { inner[i].classes.push(options.style.reset(), newStyle.cls()); } else { @@ -1214,12 +1216,12 @@ groupTypes.styling = 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)); }; groupTypes.delimsizing = function(group, options) { - var delim = group.value.value; + const delim = group.value.value; if (delim === ".") { // Empty delimiters still count as elements, even though they don't @@ -1235,14 +1237,14 @@ groupTypes.delimsizing = function(group, options) { groupTypes.leftright = function(group, options) { // Build the inner expression - var inner = buildExpression(group.value.body, options.reset(), true); + const inner = buildExpression(group.value.body, options.reset(), true); - var innerHeight = 0; - var innerDepth = 0; - var hadMiddle = false; + let innerHeight = 0; + let innerDepth = 0; + let hadMiddle = false; // Calculate its height and depth - for (var i = 0; i < inner.length; i++) { + for (let i = 0; i < inner.length; i++) { if (inner[i].isMiddle) { hadMiddle = true; } else { @@ -1251,7 +1253,7 @@ groupTypes.leftright = function(group, options) { } } - var style = options.style; + const style = options.style; // The size of delimiters is the same, regardless of what style we are // in. Thus, to correctly calculate the size of delimiter we need around @@ -1259,7 +1261,7 @@ groupTypes.leftright = function(group, options) { innerHeight *= style.sizeMultiplier; innerDepth *= style.sizeMultiplier; - var leftDelim; + let leftDelim; if (group.value.left === ".") { // Empty delimiters in \left and \right make null delimiter spaces. leftDelim = makeNullDelimiter(options, ["mopen"]); @@ -1275,7 +1277,7 @@ groupTypes.leftright = function(group, options) { // Handle middle delimiters if (hadMiddle) { - for (i = 1; i < inner.length; i++) { + for (let i = 1; i < inner.length; i++) { if (inner[i].isMiddle) { // Apply the options that were active when \middle was called inner[i] = delimiter.leftRightDelim( @@ -1285,7 +1287,7 @@ groupTypes.leftright = function(group, options) { } } - var rightDelim; + let rightDelim; // Same for the right delimiter if (group.value.right === ".") { rightDelim = makeNullDelimiter(options, ["mclose"]); @@ -1302,7 +1304,7 @@ groupTypes.leftright = function(group, options) { }; groupTypes.middle = function(group, options) { - var middleDelim; + let middleDelim; if (group.value.value === ".") { middleDelim = makeNullDelimiter(options, []); } else { @@ -1316,17 +1318,17 @@ groupTypes.middle = function(group, options) { groupTypes.rule = function(group, options) { // Make an empty span for the rule - var rule = makeSpan(["mord", "rule"], [], options); - var style = options.style; + const rule = makeSpan(["mord", "rule"], [], options); + const style = options.style; // Calculate the shift, width, and height of the rule, and account for units - var shift = 0; + let shift = 0; if (group.value.shift) { shift = calculateSize(group.value.shift, style); } - var width = calculateSize(group.value.width, style); - var height = calculateSize(group.value.height, style); + let width = calculateSize(group.value.width, style); + let height = calculateSize(group.value.height, style); // The sizes of rules are absolute, so make it larger if we are in a // smaller style. @@ -1349,10 +1351,10 @@ groupTypes.rule = function(group, options) { groupTypes.kern = function(group, options) { // Make an empty span for the rule - var rule = makeSpan(["mord", "rule"], [], options); - var style = options.style; + const rule = makeSpan(["mord", "rule"], [], options); + const style = options.style; - var dimension = 0; + let dimension = 0; if (group.value.dimension) { dimension = calculateSize(group.value.dimension, style); } @@ -1366,10 +1368,10 @@ groupTypes.kern = function(group, options) { groupTypes.accent = function(group, options) { // Accents are handled in the TeXbook pg. 443, rule 12. - var base = group.value.base; - var style = options.style; + let base = group.value.base; + const style = options.style; - var supsubGroup; + let supsubGroup; if (group.type === "supsub") { // If our base is a character box, and we have superscripts and // subscripts, the supsub will defer to us. In particular, we want @@ -1380,7 +1382,7 @@ groupTypes.accent = function(group, options) { // rendering that, while keeping track of where the accent is. // The supsub group is the group that was passed in - var supsub = group; + const supsub = group; // The real accent group is the base of the supsub group group = supsub.value.base; // The character box is the base of the accent group @@ -1395,7 +1397,7 @@ groupTypes.accent = function(group, options) { } // Build the base group - var body = buildGroup( + const body = buildGroup( base, options.withStyle(style.cramp())); // Calculate the skew of the accent. This is based on the line "If the @@ -1403,13 +1405,13 @@ groupTypes.accent = function(group, options) { // kern amount for the nucleus followed by the \skewchar of its font." // Note that our skew metrics are just the kern between each character // and the skewchar. - var skew; + let skew = 0; if (isCharacterBox(base)) { // If the base is a character box, then we want the skew of the // innermost character. To do that, we find the innermost character: - var baseChar = getBaseElem(base); + const baseChar = getBaseElem(base); // Then, we render its group to get the symbol inside it - var baseGroup = buildGroup( + const baseGroup = buildGroup( baseChar, options.withStyle(style.cramp())); // Finally, we pull the skew off of the symbol. skew = baseGroup.skew; @@ -1417,17 +1419,15 @@ groupTypes.accent = function(group, options) { // removed with getBaseElem might contain things like \color which // we can't get rid of. // TODO(emily): Find a better way to get the skew - } else { - skew = 0; } // calculate the amount of space between the body and the accent - var clearance = Math.min( + const clearance = Math.min( body.height, style.metrics.xHeight); // Build the accent - var accent = buildCommon.makeSymbol( + const accent = buildCommon.makeSymbol( group.value.accent, "Main-Regular", "math", options); // Remove the italic correction of the accent, because it only serves to // shift the accent over to a place we don't want. @@ -1437,9 +1437,9 @@ groupTypes.accent = function(group, options) { // thus shows up much too far to the left. To account for this, we add a // specific class which shifts the accent over to where we want it. // TODO(emily): Fix this in a better way, like by changing the font - var vecClass = group.value.accent === "\\vec" ? "accent-vec" : null; + const vecClass = group.value.accent === "\\vec" ? "accent-vec" : null; - var accentBody = makeSpan(["accent-body", vecClass], [ + let accentBody = makeSpan(["accent-body", vecClass], [ makeSpan([], [accent])]); accentBody = buildCommon.makeVList([ @@ -1453,7 +1453,7 @@ groupTypes.accent = function(group, options) { // we shift it to the right by 1*skew. accentBody.children[1].style.marginLeft = 2 * skew + "em"; - var accentWrap = makeSpan(["mord", "accent"], [accentBody], options); + const accentWrap = makeSpan(["mord", "accent"], [accentBody], options); if (supsubGroup) { // Here, we replace the "base" child of the supsub with our newly @@ -1474,7 +1474,7 @@ groupTypes.accent = function(group, options) { }; groupTypes.phantom = function(group, options) { - var elements = buildExpression( + const elements = buildExpression( group.value.value, options.withPhantom(), false @@ -1486,7 +1486,7 @@ groupTypes.phantom = function(group, options) { }; groupTypes.mclass = function(group, options) { - var elements = buildExpression(group.value.value, options, true); + const elements = buildExpression(group.value.value, options, true); return makeSpan([group.value.mclass], elements, options); }; @@ -1496,15 +1496,15 @@ groupTypes.mclass = function(group, options) { * function for it. It also handles the interaction of size and style changes * between parents and children. */ -var buildGroup = function(group, options) { +const buildGroup = function(group, options) { if (!group) { return makeSpan(); } if (groupTypes[group.type]) { // Call the groupTypes function - var groupNode = groupTypes[group.type](group, options); - var multiplier; + const groupNode = groupTypes[group.type](group, options); + let multiplier; // If the style changed between the parent and the current group, // account for the size difference @@ -1537,20 +1537,20 @@ var buildGroup = function(group, options) { * Take an entire parse tree, and build it into an appropriate set of HTML * nodes. */ -var buildHTML = function(tree, options) { +const buildHTML = function(tree, options) { // buildExpression is destructive, so we need to make a clone // of the incoming tree so that it isn't accidentally changed tree = JSON.parse(JSON.stringify(tree)); // Build the expression contained in the tree - var expression = buildExpression(tree, options, true); - var body = makeSpan(["base", options.style.cls()], expression, options); + const expression = buildExpression(tree, options, true); + const body = makeSpan(["base", options.style.cls()], expression, options); // Add struts, which ensure that the top of the HTML element falls at the // height of the expression, and the bottom of the HTML element falls at the // depth of the expression. - var topStrut = makeSpan(["strut"]); - var bottomStrut = makeSpan(["strut", "bottom"]); + const topStrut = makeSpan(["strut"]); + const bottomStrut = makeSpan(["strut", "bottom"]); topStrut.style.height = body.height + "em"; bottomStrut.style.height = (body.height + body.depth) + "em"; @@ -1560,7 +1560,7 @@ var buildHTML = function(tree, options) { bottomStrut.style.verticalAlign = -body.depth + "em"; // Wrap the struts and body together - var htmlNode = makeSpan(["katex-html"], [topStrut, bottomStrut, body]); + const htmlNode = makeSpan(["katex-html"], [topStrut, bottomStrut, body]); htmlNode.setAttribute("aria-hidden", "true"); diff --git a/src/buildMathML.js b/src/buildMathML.js @@ -4,21 +4,21 @@ * parser. */ -var buildCommon = require("./buildCommon"); -var fontMetrics = require("./fontMetrics"); -var mathMLTree = require("./mathMLTree"); -var ParseError = require("./ParseError"); -var symbols = require("./symbols"); -var utils = require("./utils"); +const buildCommon = require("./buildCommon"); +const fontMetrics = require("./fontMetrics"); +const mathMLTree = require("./mathMLTree"); +const ParseError = require("./ParseError"); +const symbols = require("./symbols"); +const utils = require("./utils"); -var makeSpan = buildCommon.makeSpan; -var fontMap = buildCommon.fontMap; +const makeSpan = buildCommon.makeSpan; +const fontMap = buildCommon.fontMap; /** * Takes a symbol and converts it into a MathML text node after performing * optional replacement from symbols.js. */ -var makeText = function(text, mode) { +const makeText = function(text, mode) { if (symbols[mode][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. */ -var getVariant = function(group, options) { - var font = options.font; +const getVariant = function(group, options) { + const font = options.font; if (!font) { return null; } - var mode = group.mode; + const mode = group.mode; if (font === "mathit") { return "italic"; } - var value = group.value; + let value = group.value; if (utils.contains(["\\imath", "\\jmath"], value)) { return null; } @@ -49,7 +49,7 @@ var getVariant = function(group, options) { value = symbols[mode][value].replace; } - var fontName = fontMap[font].fontName; + const fontName = fontMap[font].fontName; if (fontMetrics.getCharacterMetrics(value, fontName)) { 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 * tree. Each function should take a parse group and return a MathML node. */ -var groupTypes = {}; +const groupTypes = {}; groupTypes.mathord = function(group, options) { - var node = new mathMLTree.MathNode( + const node = new mathMLTree.MathNode( "mi", [makeText(group.value, group.mode)]); - var variant = getVariant(group, options); + const variant = getVariant(group, options); if (variant) { node.setAttribute("mathvariant", variant); } @@ -76,11 +76,11 @@ groupTypes.mathord = 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)) { // TODO(kevinb) merge adjacent <mn> nodes // do it as a post processing step @@ -97,42 +97,42 @@ groupTypes.textord = function(group, options) { }; groupTypes.bin = function(group) { - var node = new mathMLTree.MathNode( + const node = new mathMLTree.MathNode( "mo", [makeText(group.value, group.mode)]); return node; }; groupTypes.rel = function(group) { - var node = new mathMLTree.MathNode( + const node = new mathMLTree.MathNode( "mo", [makeText(group.value, group.mode)]); return node; }; groupTypes.open = function(group) { - var node = new mathMLTree.MathNode( + const node = new mathMLTree.MathNode( "mo", [makeText(group.value, group.mode)]); return node; }; groupTypes.close = function(group) { - var node = new mathMLTree.MathNode( + const node = new mathMLTree.MathNode( "mo", [makeText(group.value, group.mode)]); return node; }; groupTypes.inner = function(group) { - var node = new mathMLTree.MathNode( + const node = new mathMLTree.MathNode( "mo", [makeText(group.value, group.mode)]); return node; }; groupTypes.punct = function(group) { - var node = new mathMLTree.MathNode( + const node = new mathMLTree.MathNode( "mo", [makeText(group.value, group.mode)]); node.setAttribute("separator", "true"); @@ -141,25 +141,25 @@ groupTypes.punct = function(group) { }; 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; }; 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; }; 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); @@ -167,7 +167,7 @@ groupTypes.color = 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) { children.push(buildGroup(group.value.sub, options)); @@ -177,7 +177,7 @@ groupTypes.supsub = function(group, options) { children.push(buildGroup(group.value.sup, options)); } - var nodeType; + let nodeType; if (!group.value.sub) { nodeType = "msup"; } else if (!group.value.sup) { @@ -186,13 +186,13 @@ groupTypes.supsub = function(group, options) { nodeType = "msubsup"; } - var node = new mathMLTree.MathNode(nodeType, children); + const node = new mathMLTree.MathNode(nodeType, children); return node; }; groupTypes.genfrac = function(group, options) { - var node = new mathMLTree.MathNode( + const node = new mathMLTree.MathNode( "mfrac", [ buildGroup(group.value.numer, options), @@ -204,10 +204,10 @@ groupTypes.genfrac = function(group, options) { } if (group.value.leftDelim != null || group.value.rightDelim != null) { - var withDelims = []; + const withDelims = []; if (group.value.leftDelim != null) { - var leftOp = new mathMLTree.MathNode( + const leftOp = new mathMLTree.MathNode( "mo", [new mathMLTree.TextNode(group.value.leftDelim)]); leftOp.setAttribute("fence", "true"); @@ -218,7 +218,7 @@ groupTypes.genfrac = function(group, options) { withDelims.push(node); if (group.value.rightDelim != null) { - var rightOp = new mathMLTree.MathNode( + const rightOp = new mathMLTree.MathNode( "mo", [new mathMLTree.TextNode(group.value.rightDelim)]); rightOp.setAttribute("fence", "true"); @@ -226,7 +226,7 @@ groupTypes.genfrac = function(group, options) { withDelims.push(rightOp); } - var outerNode = new mathMLTree.MathNode("mrow", withDelims); + const outerNode = new mathMLTree.MathNode("mrow", withDelims); return outerNode; } @@ -246,7 +246,7 @@ groupTypes.array = function(group, options) { }; groupTypes.sqrt = function(group, options) { - var node; + let node; if (group.value.index) { node = new mathMLTree.MathNode( "mroot", [ @@ -262,10 +262,10 @@ groupTypes.sqrt = 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 !== ".") { - var leftNode = new mathMLTree.MathNode( + const leftNode = new mathMLTree.MathNode( "mo", [makeText(group.value.left, group.mode)]); leftNode.setAttribute("fence", "true"); @@ -274,7 +274,7 @@ groupTypes.leftright = function(group, options) { } if (group.value.right !== ".") { - var rightNode = new mathMLTree.MathNode( + const rightNode = new mathMLTree.MathNode( "mo", [makeText(group.value.right, group.mode)]); rightNode.setAttribute("fence", "true"); @@ -282,23 +282,23 @@ groupTypes.leftright = function(group, options) { inner.push(rightNode); } - var outerNode = new mathMLTree.MathNode("mrow", inner); + const outerNode = new mathMLTree.MathNode("mrow", inner); return outerNode; }; groupTypes.middle = function(group, options) { - var middleNode = new mathMLTree.MathNode( + const middleNode = new mathMLTree.MathNode( "mo", [makeText(group.value.middle, group.mode)]); middleNode.setAttribute("fence", "true"); return middleNode; }; groupTypes.accent = function(group, options) { - var accentNode = new mathMLTree.MathNode( + const accentNode = new mathMLTree.MathNode( "mo", [makeText(group.value.accent, group.mode)]); - var node = new mathMLTree.MathNode( + const node = new mathMLTree.MathNode( "mover", [buildGroup(group.value.base, options), accentNode]); @@ -308,7 +308,7 @@ groupTypes.accent = function(group, options) { }; groupTypes.spacing = function(group) { - var node; + let node; if (group.value === "\\ " || group.value === "\\space" || group.value === " " || group.value === "~") { @@ -325,7 +325,7 @@ groupTypes.spacing = function(group) { }; groupTypes.op = function(group, options) { - var node; + let node; // TODO(emily): handle big operators using the `largeop` attribute @@ -350,7 +350,7 @@ groupTypes.op = function(group, options) { }; groupTypes.mod = function(group, options) { - var inner = []; + let inner = []; if (group.value.modType === "pod" || group.value.modType === "pmod") { inner.push(new mathMLTree.MathNode( @@ -361,7 +361,7 @@ groupTypes.mod = function(group, options) { "mo", [makeText("mod", group.mode)])); } if (group.value.value) { - var space = new mathMLTree.MathNode("mspace"); + const space = new mathMLTree.MathNode("mspace"); space.setAttribute("width", "0.333333em"); inner.push(space); inner = inner.concat(buildExpression(group.value.value, options)); @@ -375,25 +375,25 @@ groupTypes.mod = function(group, options) { }; groupTypes.katex = function(group) { - var node = new mathMLTree.MathNode( + const node = new mathMLTree.MathNode( "mtext", [new mathMLTree.TextNode("KaTeX")]); return node; }; groupTypes.font = function(group, options) { - var font = group.value.font; + const font = group.value.font; return buildGroup(group.value.body, options.withFont(font)); }; groupTypes.delimsizing = function(group) { - var children = []; + const children = []; if (group.value.value !== ".") { 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" || group.value.mclass === "mclose") { @@ -410,18 +410,18 @@ groupTypes.delimsizing = function(group) { }; 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"], "text": ["0", "false"], "script": ["1", "false"], "scriptscript": ["2", "false"], }; - var attr = styleAttributes[group.value.style]; + const attr = styleAttributes[group.value.style]; node.setAttribute("scriptlevel", attr[0]); node.setAttribute("displaystyle", attr[1]); @@ -430,9 +430,9 @@ groupTypes.styling = 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 // 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) { - var operator = new mathMLTree.MathNode( + const operator = new mathMLTree.MathNode( "mo", [new mathMLTree.TextNode("\u203e")]); operator.setAttribute("stretchy", "true"); - var node = new mathMLTree.MathNode( + const node = new mathMLTree.MathNode( "mover", [buildGroup(group.value.body, options), operator]); node.setAttribute("accent", "true"); @@ -459,11 +459,11 @@ groupTypes.overline = function(group, options) { }; groupTypes.underline = function(group, options) { - var operator = new mathMLTree.MathNode( + const operator = new mathMLTree.MathNode( "mo", [new mathMLTree.TextNode("\u203e")]); operator.setAttribute("stretchy", "true"); - var node = new mathMLTree.MathNode( + const node = new mathMLTree.MathNode( "munder", [buildGroup(group.value.body, options), operator]); node.setAttribute("accentunder", "true"); @@ -474,20 +474,20 @@ groupTypes.underline = function(group, options) { groupTypes.rule = function(group) { // TODO(emily): Figure out if there's an actual way to draw black boxes // in MathML. - var node = new mathMLTree.MathNode("mrow"); + const node = new mathMLTree.MathNode("mrow"); return node; }; groupTypes.kern = function(group) { // 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; }; groupTypes.llap = function(group, options) { - var node = new mathMLTree.MathNode( + const node = new mathMLTree.MathNode( "mpadded", [buildGroup(group.value.body, options)]); node.setAttribute("lspace", "-1width"); @@ -497,7 +497,7 @@ groupTypes.llap = function(group, options) { }; groupTypes.rlap = function(group, options) { - var node = new mathMLTree.MathNode( + const node = new mathMLTree.MathNode( "mpadded", [buildGroup(group.value.body, options)]); node.setAttribute("width", "0px"); @@ -506,12 +506,12 @@ groupTypes.rlap = 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); }; 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); }; @@ -520,10 +520,10 @@ groupTypes.mclass = function(group, options) { * MathML nodes. A little simpler than the HTML version because we don't do any * previous-node handling. */ -var buildExpression = function(expression, options) { - var groups = []; - for (var i = 0; i < expression.length; i++) { - var group = expression[i]; +const buildExpression = function(expression, options) { + const groups = []; + for (let i = 0; i < expression.length; i++) { + const group = expression[i]; groups.push(buildGroup(group, options)); } return groups; @@ -533,7 +533,7 @@ var buildExpression = function(expression, options) { * Takes a group from the parser and calls the appropriate groupTypes function * on it to produce a MathML node. */ -var buildGroup = function(group, options) { +const buildGroup = function(group, options) { if (!group) { 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 * we can do appropriate styling. */ -var buildMathML = function(tree, texExpression, options) { - var expression = buildExpression(tree, options); +const buildMathML = function(tree, texExpression, options) { + const expression = buildExpression(tree, options); // Wrap up the expression in an mrow so it is presented in the semantics // tag correctly. - var wrapper = new mathMLTree.MathNode("mrow", expression); + const wrapper = new mathMLTree.MathNode("mrow", expression); // Build a TeX annotation of the source - var annotation = new mathMLTree.MathNode( + const annotation = new mathMLTree.MathNode( "annotation", [new mathMLTree.TextNode(texExpression)]); annotation.setAttribute("encoding", "application/x-tex"); - var semantics = new mathMLTree.MathNode( + const semantics = new mathMLTree.MathNode( "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. return makeSpan(["katex-mathml"], [math]); diff --git a/src/buildTree.js b/src/buildTree.js @@ -1,32 +1,32 @@ -var buildHTML = require("./buildHTML"); -var buildMathML = require("./buildMathML"); -var buildCommon = require("./buildCommon"); -var Options = require("./Options"); -var Settings = require("./Settings"); -var Style = require("./Style"); +const buildHTML = require("./buildHTML"); +const buildMathML = require("./buildMathML"); +const buildCommon = require("./buildCommon"); +const Options = require("./Options"); +const Settings = require("./Settings"); +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({}); - var startStyle = Style.TEXT; + let startStyle = Style.TEXT; if (settings.displayMode) { startStyle = Style.DISPLAY; } // Setup the default options - var options = new Options({ + const options = new Options({ style: startStyle, size: "size5", }); // `buildHTML` sometimes messes with the parse tree (like turning bins -> // ords), so we build the MathML version first. - var mathMLNode = buildMathML(tree, expression, options); - var htmlNode = buildHTML(tree, options); + const mathMLNode = buildMathML(tree, expression, options); + const htmlNode = buildHTML(tree, options); - var katexNode = makeSpan(["katex"], [ + const katexNode = makeSpan(["katex"], [ mathMLNode, htmlNode, ]); diff --git a/src/delimiter.js b/src/delimiter.js @@ -20,21 +20,21 @@ * used in `\left` and `\right`. */ -var ParseError = require("./ParseError"); -var Style = require("./Style"); +const ParseError = require("./ParseError"); +const Style = require("./Style"); -var buildCommon = require("./buildCommon"); -var fontMetrics = require("./fontMetrics"); -var symbols = require("./symbols"); -var utils = require("./utils"); +const buildCommon = require("./buildCommon"); +const fontMetrics = require("./fontMetrics"); +const symbols = require("./symbols"); +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. * after following replacement from symbols.js) */ -var getMetrics = function(symbol, font) { +const getMetrics = function(symbol, font) { if (symbols.math[symbol] && symbols.math[symbol].replace) { return fontMetrics.getCharacterMetrics( 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) */ -var mathrmSize = function(value, size, mode, options) { +const mathrmSize = function(value, size, mode, options) { return buildCommon.makeSymbol(value, "Size" + size + "-Regular", 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, * and maxFontSizes. */ -var styleWrap = function(delim, toStyle, options, classes) { +const styleWrap = function(delim, toStyle, options, classes) { classes = classes || []; - var span = makeSpan( + const span = makeSpan( classes.concat(["style-wrap", options.style.reset(), toStyle.cls()]), [delim], options); - var multiplier = toStyle.sizeMultiplier / options.style.sizeMultiplier; + const multiplier = toStyle.sizeMultiplier / options.style.sizeMultiplier; span.height *= 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 * scriptscriptstyle. */ -var makeSmallDelim = function(delim, style, center, options, mode, classes) { - var text = buildCommon.makeSymbol(delim, "Main-Regular", mode, options); +const makeSmallDelim = function(delim, style, center, options, mode, classes) { + 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) { - var shift = + const shift = (1 - options.style.sizeMultiplier / style.sizeMultiplier) * 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, * Size3, or Size4 fonts. It is always rendered in textstyle. */ -var makeLargeDelim = function(delim, size, center, options, mode, classes) { - var inner = mathrmSize(delim, size, mode, options); +const makeLargeDelim = function(delim, size, center, options, mode, classes) { + const inner = mathrmSize(delim, size, mode, options); - var span = styleWrap( + const span = styleWrap( makeSpan(["delimsizing", "size" + size], [inner], options), Style.TEXT, options, classes); if (center) { - var shift = (1 - options.style.sizeMultiplier) * + const shift = (1 - options.style.sizeMultiplier) * options.style.metrics.axisHeight; 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 * in `makeStackedDelim` to make the stacking pieces for the delimiter. */ -var makeInner = function(symbol, font, mode) { - var sizeClass; +const makeInner = function(symbol, font, mode) { + let sizeClass; // Apply the correct CSS class to choose the right font. if (font === "Size1-Regular") { sizeClass = "delim-size1"; @@ -130,7 +130,7 @@ var makeInner = function(symbol, font, mode) { sizeClass = "delim-size4"; } - var inner = makeSpan( + const inner = makeSpan( ["delimsizinginner", sizeClass], [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 * 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) { // There are four parts, the top, an optional middle, a repeated part, and a // bottom. - var top; - var middle; - var repeat; - var bottom; + let top; + let middle; + let repeat; + let bottom; top = repeat = bottom = delim; middle = null; // 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 // '\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 - var topMetrics = getMetrics(top, font); - var topHeightTotal = topMetrics.height + topMetrics.depth; - var repeatMetrics = getMetrics(repeat, font); - var repeatHeightTotal = repeatMetrics.height + repeatMetrics.depth; - var bottomMetrics = getMetrics(bottom, font); - var bottomHeightTotal = bottomMetrics.height + bottomMetrics.depth; - var middleHeightTotal = 0; - var middleFactor = 1; + const topMetrics = getMetrics(top, font); + const topHeightTotal = topMetrics.height + topMetrics.depth; + const repeatMetrics = getMetrics(repeat, font); + const repeatHeightTotal = repeatMetrics.height + repeatMetrics.depth; + const bottomMetrics = getMetrics(bottom, font); + const bottomHeightTotal = bottomMetrics.height + bottomMetrics.depth; + let middleHeightTotal = 0; + let middleFactor = 1; if (middle !== null) { - var middleMetrics = getMetrics(middle, font); + const middleMetrics = getMetrics(middle, font); middleHeightTotal = middleMetrics.height + middleMetrics.depth; middleFactor = 2; // repeat symmetrically above and below middle } // Calcuate the minimal height that the delimiter can have. // 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 - var repeatCount = Math.ceil( + const repeatCount = Math.ceil( (heightTotal - minHeight) / (middleFactor * repeatHeightTotal)); // Compute the total height of the delimiter including all the symbols - var realHeightTotal = + const realHeightTotal = minHeight + repeatCount * middleFactor * repeatHeightTotal; // 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 // centered around the axis in the current style, while normally it is // centered around the axis in textstyle. - var axisHeight = options.style.metrics.axisHeight; + let axisHeight = options.style.metrics.axisHeight; if (center) { axisHeight *= options.style.sizeMultiplier; } // 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 // Keep a list of the inner pieces - var inners = []; + const inners = []; // Add the bottom symbol inners.push(makeInner(bottom, font, mode)); - var i; if (middle === null) { // Add that many symbols - for (i = 0; i < repeatCount; i++) { + for (let i = 0; i < repeatCount; i++) { inners.push(makeInner(repeat, font, mode)); } } else { // When there is a middle bit, we need the middle part and two repeated // sections - for (i = 0; i < repeatCount; i++) { + for (let i = 0; i < repeatCount; i++) { inners.push(makeInner(repeat, 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)); } } @@ -318,7 +317,7 @@ var makeStackedDelim = function(delim, heightTotal, center, options, mode, inners.push(makeInner(top, font, mode)); // Finally, build the vlist - var inner = buildCommon.makeVList(inners, "bottom", depth, options); + const inner = buildCommon.makeVList(inners, "bottom", depth, options); return styleWrap( 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 // too large -var stackLargeDelimiters = [ +const stackLargeDelimiters = [ "(", ")", "[", "\\lbrack", "]", "\\rbrack", "\\{", "\\lbrace", "\\}", "\\rbrace", "\\lfloor", "\\rfloor", "\\lceil", "\\rceil", @@ -335,7 +334,7 @@ var stackLargeDelimiters = [ ]; // delimiters that always stack -var stackAlwaysDelimiters = [ +const stackAlwaysDelimiters = [ "\\uparrow", "\\downarrow", "\\updownarrow", "\\Uparrow", "\\Downarrow", "\\Updownarrow", "|", "\\|", "\\vert", "\\Vert", @@ -344,19 +343,19 @@ var stackAlwaysDelimiters = [ ]; // and delimiters that never stack -var stackNeverDelimiters = [ +const stackNeverDelimiters = [ "<", ">", "\\langle", "\\rangle", "/", "\\backslash", "\\lt", "\\gt", ]; // Metrics of the different sizes. Found by looking at TeX's output of // $\bigl| // \Bigl| \biggl| \Biggl| \showlists$ // 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. */ -var makeSizedDelim = function(delim, size, options, mode, classes) { +const makeSizedDelim = function(delim, size, options, mode, classes) { // < and > turn into \langle and \rangle in delimiters if (delim === "<" || delim === "\\lt") { 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 -var stackNeverDelimiterSequence = [ +const stackNeverDelimiterSequence = [ {type: "small", style: Style.SCRIPTSCRIPT}, {type: "small", style: Style.SCRIPT}, {type: "small", style: Style.TEXT}, @@ -400,7 +399,7 @@ var stackNeverDelimiterSequence = [ ]; // Delimiters that always stack try the small delimiters first, then stack -var stackAlwaysDelimiterSequence = [ +const stackAlwaysDelimiterSequence = [ {type: "small", style: Style.SCRIPTSCRIPT}, {type: "small", style: Style.SCRIPT}, {type: "small", style: Style.TEXT}, @@ -409,7 +408,7 @@ var stackAlwaysDelimiterSequence = [ // Delimiters that stack when large try the small and then large delimiters, and // stack afterwards -var stackLargeDelimiterSequence = [ +const stackLargeDelimiterSequence = [ {type: "small", style: Style.SCRIPTSCRIPT}, {type: "small", style: Style.SCRIPT}, {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. */ -var delimTypeToFont = function(type) { +const delimTypeToFont = function(type) { if (type.type === "small") { return "Main-Regular"; } 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 * 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 // 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 // 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); - for (var i = start; i < sequence.length; i++) { + const start = Math.min(2, 3 - options.style.size); + for (let i = start; i < sequence.length; i++) { if (sequence[i].type === "stack") { // This is always the last delimiter, so we just break the loop now. break; } - var metrics = getMetrics(delim, delimTypeToFont(sequence[i])); - var heightDepth = metrics.height + metrics.depth; + const metrics = getMetrics(delim, delimTypeToFont(sequence[i])); + let heightDepth = metrics.height + metrics.depth; // Small delimiters are scaled down versions of the same font, so we // 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 * 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) { if (delim === "<" || delim === "\\lt") { delim = "\\langle"; @@ -482,7 +481,7 @@ var makeCustomSizedDelim = function(delim, height, center, options, mode, } // Decide what sequence to use - var sequence; + let sequence; if (utils.contains(stackNeverDelimiters, delim)) { sequence = stackNeverDelimiterSequence; } else if (utils.contains(stackLargeDelimiters, delim)) { @@ -492,7 +491,7 @@ var makeCustomSizedDelim = function(delim, height, center, options, mode, } // 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 // 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 * of an expression that the delimiters surround. */ -var makeLeftRightDelim = function(delim, height, depth, options, mode, +const makeLeftRightDelim = function(delim, height, depth, options, mode, classes) { // We always center \left/\right delimiters, so the axis is always shifted - var axisHeight = + const axisHeight = options.style.metrics.axisHeight * options.style.sizeMultiplier; // Taken from TeX source, tex.web, function make_left_right - var delimiterFactor = 901; - var delimiterExtend = 5.0 / fontMetrics.metrics.ptPerEm; + const delimiterFactor = 901; + const delimiterExtend = 5.0 / fontMetrics.metrics.ptPerEm; - var maxDistFromAxis = Math.max( + const maxDistFromAxis = Math.max( height - axisHeight, depth + axisHeight); - var totalHeight = Math.max( + const totalHeight = Math.max( // In real TeX, calculations are done using integral values which are // 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 diff --git a/src/domTree.js b/src/domTree.js @@ -7,16 +7,16 @@ * * Similar functions for working with MathML nodes exist in mathMLTree.js. */ -var unicodeRegexes = require("./unicodeRegexes"); -var utils = require("./utils"); +const unicodeRegexes = require("./unicodeRegexes"); +const utils = require("./utils"); /** * Create an HTML className based on a list of classes. In addition to joining * with spaces, we also remove null or empty classes. */ -var createClass = function(classes) { +const createClass = function(classes) { classes = classes.slice(); - for (var i = classes.length - 1; i >= 0; i--) { + for (let i = classes.length - 1; i >= 0; i--) { if (!classes[i]) { classes.splice(i, 1); } @@ -65,27 +65,27 @@ span.prototype.tryCombine = function(sibling) { * Convert the span into an HTML node */ span.prototype.toNode = function() { - var span = document.createElement("span"); + const span = document.createElement("span"); // Apply the class span.className = createClass(this.classes); // Apply inline styles - for (var style in this.style) { + for (const style in this.style) { if (Object.prototype.hasOwnProperty.call(this.style, style)) { span.style[style] = this.style[style]; } } // Apply attributes - for (var attr in this.attributes) { + for (const attr in this.attributes) { if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { span.setAttribute(attr, this.attributes[attr]); } } // Append the children, also as HTML nodes - for (var i = 0; i < this.children.length; i++) { + for (let i = 0; i < this.children.length; i++) { span.appendChild(this.children[i].toNode()); } @@ -96,7 +96,7 @@ span.prototype.toNode = function() { * Convert the span into an HTML markup string */ span.prototype.toMarkup = function() { - var markup = "<span"; + let markup = "<span"; // Add the class if (this.classes.length) { @@ -105,10 +105,10 @@ span.prototype.toMarkup = function() { markup += "\""; } - var styles = ""; + let styles = ""; // Add the styles, after hyphenation - for (var style in this.style) { + for (const style in this.style) { if (this.style.hasOwnProperty(style)) { styles += utils.hyphenate(style) + ":" + this.style[style] + ";"; } @@ -119,7 +119,7 @@ span.prototype.toMarkup = function() { } // Add the attributes - for (var attr in this.attributes) { + for (const attr in this.attributes) { if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { markup += " " + attr + "=\""; markup += utils.escape(this.attributes[attr]); @@ -130,7 +130,7 @@ span.prototype.toMarkup = function() { 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(); } @@ -157,10 +157,10 @@ function documentFragment(children) { */ documentFragment.prototype.toNode = function() { // Create a fragment - var frag = document.createDocumentFragment(); + const frag = document.createDocumentFragment(); // 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()); } @@ -171,17 +171,17 @@ documentFragment.prototype.toNode = function() { * Convert the fragment into HTML markup */ documentFragment.prototype.toMarkup = function() { - var markup = ""; + let markup = ""; // 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(); } return markup; }; -var iCombinations = { +const iCombinations = { 'î': '\u0131\u0302', 'ï': '\u0131\u0308', 'í': '\u0131\u0301', @@ -233,13 +233,13 @@ symbolNode.prototype.tryCombine = function(sibling) { || this.maxFontSize !== sibling.maxFontSize) { return false; } - for (var style in this.style) { + for (const style in this.style) { if (this.style.hasOwnProperty(style) && this.style[style] !== sibling.style[style]) { return false; } } - for (style in sibling.style) { + for (const style in sibling.style) { if (sibling.style.hasOwnProperty(style) && this.style[style] !== sibling.style[style]) { return false; @@ -257,8 +257,8 @@ symbolNode.prototype.tryCombine = function(sibling) { * created if it is needed. */ symbolNode.prototype.toNode = function() { - var node = document.createTextNode(this.value); - var span = null; + const node = document.createTextNode(this.value); + let span = null; if (this.italic > 0) { span = document.createElement("span"); @@ -270,7 +270,7 @@ symbolNode.prototype.toNode = function() { span.className = createClass(this.classes); } - for (var style in this.style) { + for (const style in this.style) { if (this.style.hasOwnProperty(style)) { span = span || document.createElement("span"); span.style[style] = this.style[style]; @@ -291,9 +291,9 @@ symbolNode.prototype.toNode = function() { symbolNode.prototype.toMarkup = function() { // TODO(alpert): More duplication than I'd like from // span.prototype.toMarkup and symbolNode.prototype.toNode... - var needsSpan = false; + let needsSpan = false; - var markup = "<span"; + let markup = "<span"; if (this.classes.length) { needsSpan = true; @@ -302,12 +302,12 @@ symbolNode.prototype.toMarkup = function() { markup += "\""; } - var styles = ""; + let styles = ""; if (this.italic > 0) { styles += "margin-right:" + this.italic + "em;"; } - for (var style in this.style) { + for (const style in this.style) { if (this.style.hasOwnProperty(style)) { styles += utils.hyphenate(style) + ":" + this.style[style] + ";"; } @@ -318,7 +318,7 @@ symbolNode.prototype.toMarkup = function() { markup += " style=\"" + utils.escape(styles) + "\""; } - var escaped = utils.escape(this.value); + const escaped = utils.escape(this.value); if (needsSpan) { markup += ">"; markup += escaped; diff --git a/src/environments.js b/src/environments.js @@ -1,9 +1,9 @@ /* eslint no-constant-condition:0 */ -var parseData = require("./parseData"); -var ParseError = require("./ParseError"); -var Style = require("./Style"); +const parseData = require("./parseData"); +const ParseError = require("./ParseError"); +const Style = require("./Style"); -var ParseNode = parseData.ParseNode; +const ParseNode = parseData.ParseNode; /** * Parse the body of the environment, with rows delimited by \\ and @@ -11,19 +11,19 @@ var ParseNode = parseData.ParseNode; * with one group per cell. */ function parseArray(parser, result) { - var row = []; - var body = [row]; - var rowGaps = []; + let row = []; + const body = [row]; + const rowGaps = []; while (true) { - var cell = parser.parseExpression(false, null); + const cell = parser.parseExpression(false, null); row.push(new ParseNode("ordgroup", cell, parser.mode)); - var next = parser.nextToken.text; + const next = parser.nextToken.text; if (next === "&") { parser.consume(); } else if (next === "\\end") { break; } else if (next === "\\\\" || next === "\\cr") { - var cr = parser.parseFunction(); + const cr = parser.parseFunction(); rowGaps.push(cr.value.size); row = []; body.push(row); @@ -69,7 +69,7 @@ function defineEnvironment(names, props, handler) { props = { numArgs: props }; } // Set default values of environments - var data = { + const data = { numArgs: props.numArgs || 0, argTypes: props.argTypes, greediness: 1, @@ -77,7 +77,7 @@ function defineEnvironment(names, props, handler) { numOptionalArgs: props.numOptionalArgs || 0, handler: handler, }; - for (var i = 0; i < names.length; ++i) { + for (let i = 0; i < names.length; ++i) { module.exports[names[i]] = data; } } @@ -87,10 +87,10 @@ function defineEnvironment(names, props, handler) { defineEnvironment("array", { numArgs: 1, }, function(context, args) { - var colalign = args[0]; + let colalign = args[0]; colalign = colalign.value.map ? colalign.value : [colalign]; - var cols = colalign.map(function(node) { - var ca = node.value; + const cols = colalign.map(function(node) { + const ca = node.value; if ("lcr".indexOf(ca) !== -1) { return { type: "align", @@ -106,7 +106,7 @@ defineEnvironment("array", { "Unknown column alignment: " + node.value, node); }); - var res = { + let res = { type: "array", cols: cols, hskipBeforeAndAfter: true, // \@preamble in lttab.dtx @@ -126,7 +126,7 @@ defineEnvironment([ "Vmatrix", ], { }, function(context) { - var delimiters = { + const delimiters = { "matrix": null, "pmatrix": ["(", ")"], "bmatrix": ["[", "]"], @@ -134,7 +134,7 @@ defineEnvironment([ "vmatrix": ["|", "|"], "Vmatrix": ["\\Vert", "\\Vert"], }[context.envName]; - var res = { + let res = { type: "array", hskipBeforeAndAfter: false, // \hskip -\arraycolsep in amsmath }; @@ -154,7 +154,7 @@ defineEnvironment([ // \left\{\begin{array}{@{}l@{\quad}l@{}} … \end{array}\right. defineEnvironment("cases", { }, function(context) { - var res = { + let res = { type: "array", arraystretch: 1.2, cols: [{ @@ -188,25 +188,24 @@ defineEnvironment("cases", { // so that \strut@ is the same as \strut. defineEnvironment("aligned", { }, function(context) { - var res = { + let res = { type: "array", cols: [], }; res = parseArray(context.parser, res); - var emptyGroup = new ParseNode("ordgroup", [], context.mode); - var numCols = 0; + const emptyGroup = new ParseNode("ordgroup", [], context.mode); + let numCols = 0; res.value.body.forEach(function(row) { - var i; - for (i = 1; i < row.length; i += 2) { + for (let i = 1; i < row.length; i += 2) { row[i].value.unshift(emptyGroup); } if (numCols < row.length) { numCols = row.length; } }); - for (var i = 0; i < numCols; ++i) { - var align = "r"; - var pregap = 0; + for (let i = 0; i < numCols; ++i) { + let align = "r"; + let pregap = 0; if (i % 2 === 1) { align = "l"; } else if (i > 0) { diff --git a/src/fontMetrics.js b/src/fontMetrics.js @@ -1,7 +1,7 @@ /* eslint no-unused-vars:0 */ -var Style = require("./Style"); -var cjkRegex = require("./unicodeRegexes").cjkRegex; +const Style = require("./Style"); +const cjkRegex = require("./unicodeRegexes").cjkRegex; /** * 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 // care about is the FONTDIMEN section. Each value is measured in EMs. -var sigmas = { +const sigmas = { slant: [0.250, 0.250, 0.250], // sigma1 space: [0.000, 0.000, 0.000], // sigma2 stretch: [0.000, 0.000, 0.000], // sigma3 @@ -62,34 +62,34 @@ var sigmas = { // \showthe\fontdimenX\a // where X is the corresponding variable number. These correspond to the font // parameters of the extension fonts (family 3). See the TeXbook, page 441. -var xi1 = 0; -var xi2 = 0; -var xi3 = 0; -var xi4 = 0; -var xi5 = 0.431; -var xi6 = 1; -var xi7 = 0; -var xi8 = 0.04; -var xi9 = 0.111; -var xi10 = 0.166; -var xi11 = 0.2; -var xi12 = 0.6; -var xi13 = 0.1; +const xi1 = 0; +const xi2 = 0; +const xi3 = 0; +const xi4 = 0; +const xi5 = 0.431; +const xi6 = 1; +const xi7 = 0; +const xi8 = 0.04; +const xi9 = 0.111; +const xi10 = 0.166; +const xi11 = 0.2; +const xi12 = 0.6; +const xi13 = 0.1; // This value determines how large a pt is, for metrics which are defined in // terms of pts. // This value is also used in katex.less; if you change it make sure the values // match. -var ptPerEm = 10.0; +const ptPerEm = 10.0; // The space between adjacent `|` columns in an array definition. From // `\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 */ -var metrics = { +const metrics = { defaultRuleThickness: xi8, bigOpSpacing1: xi9, bigOpSpacing2: xi10, @@ -104,7 +104,7 @@ var metrics = { // metrics, including height, depth, italic correction, and skew (kern from the // character to the corresponding \skewchar) // 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 // 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 // the fraction bar or root line from intersecting the glyph. // TODO(kevinb) allow union of multiple glyph metrics for better accuracy. -var extraCharacterMap = { +const extraCharacterMap = { // Latin-1 'À': 'A', 'Á': 'A', @@ -252,14 +252,14 @@ var extraCharacterMap = { * Note: the `width` property may be undefined if fontMetricsData.js wasn't * built using `Make extended_metrics`. */ -var getCharacterMetrics = function(character, style) { - var ch = character.charCodeAt(0); +const getCharacterMetrics = function(character, style) { + let ch = character.charCodeAt(0); if (character[0] in extraCharacterMap) { ch = extraCharacterMap[character[0]].charCodeAt(0); } else if (cjkRegex.test(character[0])) { ch = 'M'.charCodeAt(0); } - var metrics = metricMap[style][ch]; + const metrics = metricMap[style][ch]; if (metrics) { return { depth: metrics[0], diff --git a/src/functions.js b/src/functions.js @@ -1,7 +1,7 @@ -var utils = require("./utils"); -var ParseError = require("./ParseError"); -var parseData = require("./parseData"); -var ParseNode = parseData.ParseNode; +const utils = require("./utils"); +const ParseError = require("./ParseError"); +const parseData = require("./parseData"); +const ParseNode = parseData.ParseNode; /* This file contains a list of functions that we parse, identified by * the calls to defineFunction. @@ -88,7 +88,7 @@ function defineFunction(names, props, handler) { props = { numArgs: props }; } // Set default values of functions - var data = { + const data = { numArgs: props.numArgs, argTypes: props.argTypes, greediness: (props.greediness === undefined) ? 1 : props.greediness, @@ -97,14 +97,14 @@ function defineFunction(names, props, handler) { infix: !!props.infix, handler: handler, }; - for (var i = 0; i < names.length; ++i) { + for (let i = 0; i < names.length; ++i) { module.exports[names[i]] = data; } } // Since the corresponding buildHTML/buildMathML function expects a // list of elements, we normalize for different kinds of arguments -var ordargument = function(arg) { +const ordargument = function(arg) { if (arg.type === "ordgroup") { return arg.value; } else { @@ -117,8 +117,8 @@ defineFunction("\\sqrt", { numArgs: 1, numOptionalArgs: 1, }, function(context, args) { - var index = args[0]; - var body = args[1]; + const index = args[0]; + const body = args[1]; return { type: "sqrt", body: body, @@ -127,7 +127,7 @@ defineFunction("\\sqrt", { }); // Non-mathy text, possibly in a font -var textFunctionStyles = { +const textFunctionStyles = { "\\text": undefined, "\\textrm": "mathrm", "\\textsf": "mathsf", "\\texttt": "mathtt", "\\textnormal": "mathrm", "\\textbf": "mathbf", "\\textit": "textit", @@ -142,7 +142,7 @@ defineFunction([ greediness: 2, allowedInText: true, }, function(context, args) { - var body = args[0]; + const body = args[0]; return { type: "text", body: ordargument(body), @@ -157,8 +157,8 @@ defineFunction("\\color", { greediness: 3, argTypes: ["color", "original"], }, function(context, args) { - var color = args[0]; - var body = args[1]; + const color = args[0]; + const body = args[1]; return { type: "color", color: color.value, @@ -170,7 +170,7 @@ defineFunction("\\color", { defineFunction("\\overline", { numArgs: 1, }, function(context, args) { - var body = args[0]; + const body = args[0]; return { type: "overline", body: body, @@ -181,7 +181,7 @@ defineFunction("\\overline", { defineFunction("\\underline", { numArgs: 1, }, function(context, args) { - var body = args[0]; + const body = args[0]; return { type: "underline", body: body, @@ -194,9 +194,9 @@ defineFunction("\\rule", { numOptionalArgs: 1, argTypes: ["size", "size", "size"], }, function(context, args) { - var shift = args[0]; - var width = args[1]; - var height = args[2]; + const shift = args[0]; + const width = args[1]; + const height = args[2]; return { type: "rule", shift: shift && shift.value, @@ -229,7 +229,7 @@ defineFunction("\\KaTeX", { defineFunction("\\phantom", { numArgs: 1, }, function(context, args) { - var body = args[0]; + const body = args[0]; return { type: "phantom", value: ordargument(body), @@ -243,7 +243,7 @@ defineFunction([ ], { numArgs: 1, }, function(context, args) { - var body = args[0]; + const body = args[0]; return { type: "mclass", mclass: "m" + context.funcName.substr(5), @@ -255,10 +255,10 @@ defineFunction([ defineFunction("\\stackrel", { numArgs: 2, }, function(context, args) { - var top = args[0]; - var bottom = args[1]; + const top = args[0]; + const bottom = args[1]; - var bottomop = new ParseNode("op", { + const bottomop = new ParseNode("op", { type: "op", limits: true, alwaysHandleSupSub: true, @@ -266,7 +266,7 @@ defineFunction("\\stackrel", { value: ordargument(bottom), }, bottom.mode); - var supsub = new ParseNode("supsub", { + const supsub = new ParseNode("supsub", { base: bottomop, sup: top, sub: null, @@ -293,7 +293,7 @@ defineFunction("\\bmod", { defineFunction(["\\pod", "\\pmod", "\\mod"], { numArgs: 1, }, function(context, args) { - var body = args[0]; + const body = args[0]; return { type: "mod", modType: context.funcName.substr(1), @@ -302,7 +302,7 @@ defineFunction(["\\pod", "\\pmod", "\\mod"], { }); // Extra data needed for the delimiter handler down below -var delimiterSizes = { +const delimiterSizes = { "\\bigl" : {mclass: "mopen", size: 1}, "\\Bigl" : {mclass: "mopen", size: 2}, "\\biggl": {mclass: "mopen", size: 3}, @@ -321,7 +321,7 @@ var delimiterSizes = { "\\Bigg" : {mclass: "mord", size: 4}, }; -var delimiters = [ +const delimiters = [ "(", ")", "[", "\\lbrack", "]", "\\rbrack", "\\{", "\\lbrace", "\\}", "\\rbrace", "\\lfloor", "\\rfloor", "\\lceil", "\\rceil", @@ -336,7 +336,7 @@ var delimiters = [ ".", ]; -var fontAliases = { +const fontAliases = { "\\Bbb": "\\mathbb", "\\bold": "\\mathbf", "\\frak": "\\mathfrak", @@ -362,7 +362,7 @@ defineFunction([ allowedInText: true, greediness: 3, }, function(context, args) { - var body = args[0]; + const body = args[0]; return { type: "color", color: "katex-" + context.funcName.slice(1), @@ -440,7 +440,7 @@ defineFunction([ defineFunction("\\mathop", { numArgs: 1, }, function(context, args) { - var body = args[0]; + const body = args[0]; return { type: "op", limits: false, @@ -458,12 +458,12 @@ defineFunction([ numArgs: 2, greediness: 2, }, function(context, args) { - var numer = args[0]; - var denom = args[1]; - var hasBarLine; - var leftDelim = null; - var rightDelim = null; - var size = "auto"; + const numer = args[0]; + const denom = args[1]; + let hasBarLine; + let leftDelim = null; + let rightDelim = null; + let size = "auto"; switch (context.funcName) { case "\\dfrac": @@ -512,7 +512,7 @@ defineFunction(["\\llap", "\\rlap"], { numArgs: 1, allowedInText: true, }, function(context, args) { - var body = args[0]; + const body = args[0]; return { type: context.funcName.slice(1), body: body, @@ -520,7 +520,7 @@ defineFunction(["\\llap", "\\rlap"], { }); // Delimiter functions -var checkDelimiter = function(delim, context) { +const checkDelimiter = function(delim, context) { if (utils.contains(delimiters, delim.value)) { return delim; } else { @@ -538,7 +538,7 @@ defineFunction([ ], { numArgs: 1, }, function(context, args) { - var delim = checkDelimiter(args[0], context); + const delim = checkDelimiter(args[0], context); return { type: "delimsizing", @@ -553,7 +553,7 @@ defineFunction([ ], { numArgs: 1, }, 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 // why this data doesn't match what is in buildHTML. @@ -566,7 +566,7 @@ defineFunction([ defineFunction("\\middle", { numArgs: 1, }, function(context, args) { - var delim = checkDelimiter(args[0], context); + const delim = checkDelimiter(args[0], context); if (!context.parser.leftrightDepth) { throw new ParseError("\\middle without preceding \\left", delim); } @@ -604,8 +604,8 @@ defineFunction([ numArgs: 1, greediness: 2, }, function(context, args) { - var body = args[0]; - var func = context.funcName; + const body = args[0]; + let func = context.funcName; if (func in fontAliases) { func = fontAliases[func]; } @@ -625,7 +625,7 @@ defineFunction([ ], { numArgs: 1, }, function(context, args) { - var base = args[0]; + const base = args[0]; return { type: "accent", accent: context.funcName, @@ -638,7 +638,7 @@ defineFunction(["\\over", "\\choose", "\\atop"], { numArgs: 0, infix: true, }, function(context) { - var replaceWith; + let replaceWith; switch (context.funcName) { case "\\over": replaceWith = "\\frac"; @@ -665,7 +665,7 @@ defineFunction(["\\\\", "\\cr"], { numOptionalArgs: 1, argTypes: ["size"], }, function(context, args) { - var size = args[0]; + const size = args[0]; return { type: "cr", size: size, @@ -677,12 +677,12 @@ defineFunction(["\\begin", "\\end"], { numArgs: 1, argTypes: ["text"], }, function(context, args) { - var nameGroup = args[0]; + const nameGroup = args[0]; if (nameGroup.type !== "ordgroup") { throw new ParseError("Invalid environment name", nameGroup); } - var name = ""; - for (var i = 0; i < nameGroup.value.length; ++i) { + let name = ""; + for (let i = 0; i < nameGroup.value.length; ++i) { name += nameGroup.value[i].value; } return { diff --git a/src/mathMLTree.js b/src/mathMLTree.js @@ -8,7 +8,7 @@ * 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 @@ -33,16 +33,16 @@ MathNode.prototype.setAttribute = function(name, value) { * Converts the math node into a MathML-namespaced DOM element. */ MathNode.prototype.toNode = function() { - var node = document.createElementNS( + const node = document.createElementNS( "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)) { 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()); } @@ -53,10 +53,10 @@ MathNode.prototype.toNode = function() { * Converts the math node into an HTML markup string. */ MathNode.prototype.toMarkup = function() { - var markup = "<" + this.type; + let markup = "<" + this.type; // Add the attributes - for (var attr in this.attributes) { + for (const attr in this.attributes) { if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { markup += " " + attr + "=\""; markup += utils.escape(this.attributes[attr]); @@ -66,7 +66,7 @@ MathNode.prototype.toMarkup = function() { markup += ">"; - for (var i = 0; i < this.children.length; i++) { + for (let i = 0; i < this.children.length; i++) { markup += this.children[i].toMarkup(); } diff --git a/src/parseTree.js b/src/parseTree.js @@ -3,16 +3,16 @@ * TODO(emily): Remove this */ -var Parser = require("./Parser"); +const Parser = require("./Parser"); /** * 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)) { 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(); }; diff --git a/src/symbols.js b/src/symbols.js @@ -33,25 +33,25 @@ function defineSymbol(mode, font, group, replace, name) { // This helps minify the code, and also spotting typos using jshint. // modes: -var math = "math"; -var text = "text"; +const math = "math"; +const text = "text"; // fonts: -var main = "main"; -var ams = "ams"; +const main = "main"; +const ams = "ams"; // groups: -var accent = "accent"; -var bin = "bin"; -var close = "close"; -var inner = "inner"; -var mathord = "mathord"; -var op = "op"; -var open = "open"; -var punct = "punct"; -var rel = "rel"; -var spacing = "spacing"; -var textord = "textord"; +const accent = "accent"; +const bin = "bin"; +const close = "close"; +const inner = "inner"; +const mathord = "mathord"; +const op = "op"; +const open = "open"; +const punct = "punct"; +const rel = "rel"; +const spacing = "spacing"; +const textord = "textord"; // Now comes the symbol table @@ -616,50 +616,48 @@ 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. -var i; -var ch; // All of these are textords in math mode -var mathTextSymbols = "0123456789/@.\""; -for (i = 0; i < mathTextSymbols.length; i++) { - ch = mathTextSymbols.charAt(i); +const mathTextSymbols = "0123456789/@.\""; +for (let i = 0; i < mathTextSymbols.length; i++) { + const ch = mathTextSymbols.charAt(i); defineSymbol(math, main, textord, ch, ch); } // All of these are textords in text mode -var textSymbols = "0123456789!@*()-=+[]\";:?/.,"; -for (i = 0; i < textSymbols.length; i++) { - ch = textSymbols.charAt(i); +const textSymbols = "0123456789!@*()-=+[]\";:?/.,"; +for (let i = 0; i < textSymbols.length; i++) { + const ch = textSymbols.charAt(i); defineSymbol(text, main, textord, ch, ch); } // All of these are textords in text mode, and mathords in math mode -var letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; -for (i = 0; i < letters.length; i++) { - ch = letters.charAt(i); +const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; +for (let i = 0; i < letters.length; i++) { + const ch = letters.charAt(i); defineSymbol(math, main, mathord, ch, ch); defineSymbol(text, main, textord, ch, ch); } // Latin-1 letters -for (i = 0x00C0; i <= 0x00D6; i++) { - ch = String.fromCharCode(i); +for (let i = 0x00C0; i <= 0x00D6; i++) { + const ch = String.fromCharCode(i); defineSymbol(text, main, textord, ch, ch); } -for (i = 0x00D8; i <= 0x00F6; i++) { - ch = String.fromCharCode(i); +for (let i = 0x00D8; i <= 0x00F6; i++) { + const ch = String.fromCharCode(i); defineSymbol(text, main, textord, ch, ch); } -for (i = 0x00F8; i <= 0x00FF; i++) { - ch = String.fromCharCode(i); +for (let i = 0x00F8; i <= 0x00FF; i++) { + const ch = String.fromCharCode(i); defineSymbol(text, main, textord, ch, ch); } // Cyrillic -for (i = 0x0410; i <= 0x044F; i++) { - ch = String.fromCharCode(i); +for (let i = 0x0410; i <= 0x044F; i++) { + const ch = String.fromCharCode(i); defineSymbol(text, main, textord, ch, ch); } diff --git a/src/unicodeRegexes.js b/src/unicodeRegexes.js @@ -1,4 +1,4 @@ -var hangulRegex = /[\uAC00-\uD7AF]/; +const hangulRegex = /[\uAC00-\uD7AF]/; // This regex combines // - Hiragana: [\u3040-\u309F] @@ -6,7 +6,7 @@ var hangulRegex = /[\uAC00-\uD7AF]/; // - CJK ideograms: [\u4E00-\u9FAF] // - Hangul syllables: [\uAC00-\uD7AF] // Notably missing are halfwidth Katakana and Romanji glyphs. -var cjkRegex = +const cjkRegex = /[\u3040-\u309F]|[\u30A0-\u30FF]|[\u4E00-\u9FAF]|[\uAC00-\uD7AF]/; module.exports = { diff --git a/src/utils.js b/src/utils.js @@ -7,17 +7,16 @@ * Provide an `indexOf` function which works in IE8, but defers to native if * possible. */ -var nativeIndexOf = Array.prototype.indexOf; -var indexOf = function(list, elem) { +const nativeIndexOf = Array.prototype.indexOf; +const indexOf = function(list, elem) { if (list == null) { return -1; } if (nativeIndexOf && list.indexOf === nativeIndexOf) { return list.indexOf(elem); } - var i = 0; - var l = list.length; - for (; i < l; i++) { + const l = list.length; + for (let i = 0; i < l; i++) { if (list[i] === elem) { return i; } @@ -28,25 +27,25 @@ var indexOf = function(list, elem) { /** * Return whether an element is contained in a list */ -var contains = function(list, elem) { +const contains = function(list, elem) { return indexOf(list, elem) !== -1; }; /** * Provide a default value if a setting is undefined */ -var deflt = function(setting, defaultIfUndefined) { +const deflt = function(setting, defaultIfUndefined) { return setting === undefined ? defaultIfUndefined : setting; }; // hyphenate and escape adapted from Facebook's React under Apache 2 license -var uppercase = /([A-Z])/g; -var hyphenate = function(str) { +const uppercase = /([A-Z])/g; +const hyphenate = function(str) { return str.replace(uppercase, "-$1").toLowerCase(); }; -var ESCAPE_LOOKUP = { +const ESCAPE_LOOKUP = { "&": "&amp;", ">": "&gt;", "<": "&lt;", @@ -54,7 +53,7 @@ var ESCAPE_LOOKUP = { "'": "&#x27;", }; -var ESCAPE_REGEX = /[&><"']/g; +const ESCAPE_REGEX = /[&><"']/g; function escaper(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 * browsers. Note that we don't define this if there is no document. */ -var setTextContent; +let setTextContent; if (typeof document !== "undefined") { - var testNode = document.createElement("span"); + const testNode = document.createElement("span"); if ("textContent" in testNode) { setTextContent = function(node, text) { node.textContent = text; diff --git a/test/errors-spec.js b/test/errors-spec.js @@ -4,15 +4,15 @@ /* global it: false */ /* global describe: false */ -var parseTree = require("../src/parseTree"); -var Settings = require("../src/Settings"); +const parseTree = require("../src/parseTree"); +const Settings = require("../src/Settings"); -var defaultSettings = new Settings({}); +const defaultSettings = new Settings({}); beforeEach(function() { jasmine.addMatchers({ toFailWithParseError: function(util, customEqualityTesters) { - var prefix = "KaTeX parse error: "; + const prefix = "KaTeX parse error: "; return { compare: function(actual, expected) { try { @@ -28,8 +28,8 @@ beforeEach(function() { message: "'" + actual + "' parsed with error", }; } - var msg = e.message; - var exp = prefix + expected; + const msg = e.message; + const exp = prefix + expected; if (msg === exp) { return { pass: true, diff --git a/test/katex-spec.js b/test/katex-spec.js @@ -5,28 +5,28 @@ /* global it: false */ /* global describe: false */ -var buildMathML = require("../src/buildMathML"); -var buildTree = require("../src/buildTree"); -var katex = require("../katex"); -var ParseError = require("../src/ParseError"); -var parseTree = require("../src/parseTree"); -var Options = require("../src/Options"); -var Settings = require("../src/Settings"); -var Style = require("../src/Style"); - -var defaultSettings = new Settings({}); -var defaultOptions = new Options({ +const buildMathML = require("../src/buildMathML"); +const buildTree = require("../src/buildTree"); +const katex = require("../katex"); +const ParseError = require("../src/ParseError"); +const parseTree = require("../src/parseTree"); +const Options = require("../src/Options"); +const Settings = require("../src/Settings"); +const Style = require("../src/Style"); + +const defaultSettings = new Settings({}); +const defaultOptions = new Options({ style: Style.TEXT, size: "size5", }); -var _getBuilt = function(expr, settings) { - var usedSettings = settings ? settings : defaultSettings; - var parsedTree = parseTree(expr, usedSettings); - var rootNode = buildTree(parsedTree, expr, usedSettings); +const _getBuilt = function(expr, settings) { + const usedSettings = settings ? settings : defaultSettings; + const parsedTree = parseTree(expr, usedSettings); + const rootNode = buildTree(parsedTree, expr, usedSettings); // grab the root node of the HTML rendering - var builtHTML = rootNode.children[1]; + const builtHTML = rootNode.children[1]; // Remove the outer .katex and .katex-inner layers return builtHTML.children[2].children; @@ -38,8 +38,8 @@ var _getBuilt = function(expr, settings) { * @param settings * @returns {Object} */ -var getBuilt = function(expr, settings) { - var usedSettings = settings ? settings : defaultSettings; +const getBuilt = function(expr, settings) { + const usedSettings = settings ? settings : defaultSettings; expect(expr).toBuild(usedSettings); return _getBuilt(expr, settings); }; @@ -50,14 +50,14 @@ var getBuilt = function(expr, settings) { * @param settings * @returns {Object} */ -var getParsed = function(expr, settings) { - var usedSettings = settings ? settings : defaultSettings; +const getParsed = function(expr, settings) { + const usedSettings = settings ? settings : defaultSettings; expect(expr).toParse(usedSettings); return parseTree(expr, usedSettings); }; -var stripPositions = function(expr) { +const stripPositions = function(expr) { if (typeof expr !== "object" || expr === null) { return expr; } @@ -72,7 +72,7 @@ var stripPositions = function(expr) { return expr; }; -var parseAndSetResult = function(expr, result, settings) { +const parseAndSetResult = function(expr, result, settings) { try { return parseTree(expr, settings || defaultSettings); } catch (e) { @@ -93,9 +93,9 @@ beforeEach(function() { toParse: function() { return { compare: function(actual, settings) { - var usedSettings = settings ? settings : defaultSettings; + const usedSettings = settings ? settings : defaultSettings; - var result = { + const result = { pass: true, message: "'" + actual + "' succeeded parsing", }; @@ -108,9 +108,9 @@ beforeEach(function() { toNotParse: function() { return { compare: function(actual, settings) { - var usedSettings = settings ? settings : defaultSettings; + const usedSettings = settings ? settings : defaultSettings; - var result = { + const result = { pass: false, message: "Expected '" + actual + "' to fail " + "parsing, but it succeeded", @@ -137,9 +137,9 @@ beforeEach(function() { toBuild: function() { return { compare: function(actual, settings) { - var usedSettings = settings ? settings : defaultSettings; + const usedSettings = settings ? settings : defaultSettings; - var result = { + const result = { pass: true, message: "'" + actual + "' succeeded in building", }; @@ -167,17 +167,17 @@ beforeEach(function() { toParseLike: function(util, baton) { return { compare: function(actual, expected) { - var result = { + const result = { pass: true, message: "Parse trees of '" + actual + "' and '" + expected + "' are equivalent", }; - var actualTree = parseAndSetResult(actual, result); + const actualTree = parseAndSetResult(actual, result); if (!actualTree) { return result; } - var expectedTree = parseAndSetResult(expected, result); + const expectedTree = parseAndSetResult(expected, result); if (!expectedTree) { return result; } @@ -202,122 +202,122 @@ describe("A parser", function() { }); it("should ignore whitespace", function() { - var parseA = stripPositions(getParsed(" x y ")); - var parseB = stripPositions(getParsed("xy")); + const parseA = stripPositions(getParsed(" x y ")); + const parseB = stripPositions(getParsed("xy")); expect(parseA).toEqual(parseB); }); }); describe("An ord parser", function() { - var expression = "1234|/@.\"`abcdefgzABCDEFGZ"; + const expression = "1234|/@.\"`abcdefgzABCDEFGZ"; it("should not fail", function() { expect(expression).toParse(); }); it("should build a list of ords", function() { - var parse = getParsed(expression); + const parse = getParsed(expression); expect(parse).toBeTruthy(); - for (var i = 0; i < parse.length; i++) { - var group = parse[i]; + for (let i = 0; i < parse.length; i++) { + const group = parse[i]; expect(group.type).toMatch("ord"); } }); it("should parse the right number of ords", function() { - var parse = getParsed(expression); + const parse = getParsed(expression); expect(parse.length).toBe(expression.length); }); }); describe("A bin parser", function() { - var expression = "+-*\\cdot\\pm\\div"; + const expression = "+-*\\cdot\\pm\\div"; it("should not fail", function() { expect(expression).toParse(); }); it("should build a list of bins", function() { - var parse = getParsed(expression); + const parse = getParsed(expression); expect(parse).toBeTruthy(); - for (var i = 0; i < parse.length; i++) { - var group = parse[i]; + for (let i = 0; i < parse.length; i++) { + const group = parse[i]; expect(group.type).toEqual("bin"); } }); }); describe("A rel parser", function() { - var expression = "=<>\\leq\\geq\\neq\\nleq\\ngeq\\cong"; + const expression = "=<>\\leq\\geq\\neq\\nleq\\ngeq\\cong"; it("should not fail", function() { expect(expression).toParse(); }); it("should build a list of rels", function() { - var parse = getParsed(expression); + const parse = getParsed(expression); expect(parse).toBeTruthy(); - for (var i = 0; i < parse.length; i++) { - var group = parse[i]; + for (let i = 0; i < parse.length; i++) { + const group = parse[i]; expect(group.type).toEqual("rel"); } }); }); describe("A punct parser", function() { - var expression = ",;\\colon"; + const expression = ",;\\colon"; it("should not fail", function() { expect(expression).toParse(); }); it("should build a list of puncts", function() { - var parse = getParsed(expression); + const parse = getParsed(expression); expect(parse).toBeTruthy(); - for (var i = 0; i < parse.length; i++) { - var group = parse[i]; + for (let i = 0; i < parse.length; i++) { + const group = parse[i]; expect(group.type).toEqual("punct"); } }); }); describe("An open parser", function() { - var expression = "(["; + const expression = "(["; it("should not fail", function() { expect(expression).toParse(); }); it("should build a list of opens", function() { - var parse = getParsed(expression); + const parse = getParsed(expression); expect(parse).toBeTruthy(); - for (var i = 0; i < parse.length; i++) { - var group = parse[i]; + for (let i = 0; i < parse.length; i++) { + const group = parse[i]; expect(group.type).toEqual("open"); } }); }); describe("A close parser", function() { - var expression = ")]?!"; + const expression = ")]?!"; it("should not fail", function() { expect(expression).toParse(); }); it("should build a list of closes", function() { - var parse = getParsed(expression); + const parse = getParsed(expression); expect(parse).toBeTruthy(); - for (var i = 0; i < parse.length; i++) { - var group = parse[i]; + for (let i = 0; i < parse.length; i++) { + const group = parse[i]; expect(group.type).toEqual("close"); } }); @@ -352,7 +352,7 @@ describe("A subscript and superscript parser", function() { }); it("should produce supsubs for superscript", function() { - var parse = getParsed("x^2")[0]; + const parse = getParsed("x^2")[0]; expect(parse.type).toBe("supsub"); expect(parse.value.base).toBeDefined(); @@ -361,7 +361,7 @@ describe("A subscript and superscript parser", function() { }); it("should produce supsubs for subscript", function() { - var parse = getParsed("x_3")[0]; + const parse = getParsed("x_3")[0]; expect(parse.type).toBe("supsub"); expect(parse.value.base).toBeDefined(); @@ -370,7 +370,7 @@ describe("A subscript and superscript parser", function() { }); it("should produce supsubs for ^_", function() { - var parse = getParsed("x^2_3")[0]; + const parse = getParsed("x^2_3")[0]; expect(parse.type).toBe("supsub"); expect(parse.value.base).toBeDefined(); @@ -379,7 +379,7 @@ describe("A subscript and superscript parser", function() { }); it("should produce supsubs for _^", function() { - var parse = getParsed("x_3^2")[0]; + const parse = getParsed("x_3^2")[0]; expect(parse.type).toBe("supsub"); expect(parse.value.base).toBeDefined(); @@ -388,8 +388,8 @@ describe("A subscript and superscript parser", function() { }); it("should produce the same thing regardless of order", function() { - var parseA = stripPositions(getParsed("x^2_3")); - var parseB = stripPositions(getParsed("x_3^2")); + const parseA = stripPositions(getParsed("x^2_3")); + const parseB = stripPositions(getParsed("x_3^2")); expect(parseA).toEqual(parseB); }); @@ -470,7 +470,7 @@ describe("A parser with limit controls", function() { it("should have the rightmost limit control determine the limits property " + "of the preceding op node", function() { - var parsedInput = getParsed("\\int\\nolimits\\limits_2^2"); + let parsedInput = getParsed("\\int\\nolimits\\limits_2^2"); expect(parsedInput[0].value.base.value.limits).toBe(true); parsedInput = getParsed("\\int\\limits_2\\nolimits^2"); @@ -484,11 +484,11 @@ describe("A group parser", function() { }); it("should produce a single ord", function() { - var parse = getParsed("{xy}"); + const parse = getParsed("{xy}"); expect(parse.length).toBe(1); - var ord = parse[0]; + const ord = parse[0]; expect(ord.type).toMatch("ord"); expect(ord.value).toBeTruthy(); @@ -502,32 +502,32 @@ describe("An implicit group parser", function() { }); it("should produce a single object", function() { - var parse = getParsed("\\Large abc"); + const parse = getParsed("\\Large abc"); expect(parse.length).toBe(1); - var sizing = parse[0]; + const sizing = parse[0]; expect(sizing.type).toEqual("sizing"); expect(sizing.value).toBeTruthy(); }); it("should apply only after the function", function() { - var parse = getParsed("a \\Large abc"); + const parse = getParsed("a \\Large abc"); expect(parse.length).toBe(2); - var sizing = parse[1]; + const sizing = parse[1]; expect(sizing.type).toEqual("sizing"); expect(sizing.value.value.length).toBe(3); }); it("should stop at the ends of groups", function() { - var parse = getParsed("a { b \\Large c } d"); + const parse = getParsed("a { b \\Large c } d"); - var group = parse[1]; - var sizing = group.value[1]; + const group = parse[1]; + const sizing = group.value[1]; expect(sizing.type).toEqual("sizing"); expect(sizing.value.value.length).toBe(1); @@ -571,16 +571,16 @@ describe("A function parser", function() { }); describe("A frac parser", function() { - var expression = "\\frac{x}{y}"; - var dfracExpression = "\\dfrac{x}{y}"; - var tfracExpression = "\\tfrac{x}{y}"; + const expression = "\\frac{x}{y}"; + const dfracExpression = "\\dfrac{x}{y}"; + const tfracExpression = "\\tfrac{x}{y}"; it("should not fail", function() { expect(expression).toParse(); }); it("should produce a frac", function() { - var parse = getParsed(expression)[0]; + const parse = getParsed(expression)[0]; expect(parse.type).toEqual("genfrac"); expect(parse.value.numer).toBeDefined(); @@ -594,13 +594,13 @@ describe("A frac parser", function() { }); it("should parse dfrac and tfrac as fracs", function() { - var dfracParse = getParsed(dfracExpression)[0]; + const dfracParse = getParsed(dfracExpression)[0]; expect(dfracParse.type).toEqual("genfrac"); expect(dfracParse.value.numer).toBeDefined(); expect(dfracParse.value.denom).toBeDefined(); - var tfracParse = getParsed(tfracExpression)[0]; + const tfracParse = getParsed(tfracExpression)[0]; expect(tfracParse.type).toEqual("genfrac"); expect(tfracParse.value.numer).toBeDefined(); @@ -608,7 +608,7 @@ describe("A frac parser", function() { }); it("should parse atop", function() { - var parse = getParsed("x \\atop y")[0]; + const parse = getParsed("x \\atop y")[0]; expect(parse.type).toEqual("genfrac"); expect(parse.value.numer).toBeDefined(); @@ -618,8 +618,8 @@ describe("A frac parser", function() { }); describe("An over parser", function() { - var simpleOver = "1 \\over x"; - var complexOver = "1+2i \\over 3+4i"; + const simpleOver = "1 \\over x"; + const complexOver = "1+2i \\over 3+4i"; it("should not fail", function() { expect(simpleOver).toParse(); @@ -627,7 +627,7 @@ describe("An over parser", function() { }); it("should produce a frac", function() { - var parse; + let parse; parse = getParsed(simpleOver)[0]; @@ -643,38 +643,38 @@ describe("An over parser", function() { }); it("should create a numerator from the atoms before \\over", function() { - var parse = getParsed(complexOver)[0]; + const parse = getParsed(complexOver)[0]; - var numer = parse.value.numer; + const numer = parse.value.numer; expect(numer.value.length).toEqual(4); }); it("should create a demonimator from the atoms after \\over", function() { - var parse = getParsed(complexOver)[0]; + const parse = getParsed(complexOver)[0]; - var denom = parse.value.numer; + const denom = parse.value.numer; expect(denom.value.length).toEqual(4); }); it("should handle empty numerators", function() { - var emptyNumerator = "\\over x"; - var parse = getParsed(emptyNumerator)[0]; + const emptyNumerator = "\\over x"; + const parse = getParsed(emptyNumerator)[0]; expect(parse.type).toEqual("genfrac"); expect(parse.value.numer).toBeDefined(); expect(parse.value.denom).toBeDefined(); }); it("should handle empty denominators", function() { - var emptyDenominator = "1 \\over"; - var parse = getParsed(emptyDenominator)[0]; + const emptyDenominator = "1 \\over"; + const parse = getParsed(emptyDenominator)[0]; expect(parse.type).toEqual("genfrac"); expect(parse.value.numer).toBeDefined(); expect(parse.value.denom).toBeDefined(); }); it("should handle \\displaystyle correctly", function() { - var displaystyleExpression = "\\displaystyle 1 \\over 2"; - var parse = getParsed(displaystyleExpression)[0]; + const displaystyleExpression = "\\displaystyle 1 \\over 2"; + const parse = getParsed(displaystyleExpression)[0]; expect(parse.type).toEqual("genfrac"); expect(parse.value.numer.value[0].type).toEqual("styling"); expect(parse.value.denom).toBeDefined(); @@ -688,8 +688,8 @@ describe("An over parser", function() { }); it("should handle nested factions", function() { - var nestedOverExpression = "{1 \\over 2} \\over 3"; - var parse = getParsed(nestedOverExpression)[0]; + const nestedOverExpression = "{1 \\over 2} \\over 3"; + const parse = getParsed(nestedOverExpression)[0]; expect(parse.type).toEqual("genfrac"); expect(parse.value.numer.value[0].type).toEqual("genfrac"); expect(parse.value.numer.value[0].value.numer.value[0].value).toEqual("1"); @@ -699,23 +699,23 @@ describe("An over parser", function() { }); it("should fail with multiple overs in the same group", function() { - var badMultipleOvers = "1 \\over 2 + 3 \\over 4"; + const badMultipleOvers = "1 \\over 2 + 3 \\over 4"; expect(badMultipleOvers).toNotParse(); - var badOverChoose = "1 \\over 2 \\choose 3"; + const badOverChoose = "1 \\over 2 \\choose 3"; expect(badOverChoose).toNotParse(); }); }); describe("A sizing parser", function() { - var sizeExpression = "\\Huge{x}\\small{x}"; + const sizeExpression = "\\Huge{x}\\small{x}"; it("should not fail", function() { expect(sizeExpression).toParse(); }); it("should produce a sizing node", function() { - var parse = getParsed(sizeExpression)[0]; + const parse = getParsed(sizeExpression)[0]; expect(parse.type).toEqual("sizing"); expect(parse.value).toBeDefined(); @@ -723,30 +723,30 @@ describe("A sizing parser", function() { }); describe("A text parser", function() { - var textExpression = "\\text{a b}"; - var noBraceTextExpression = "\\text x"; - var nestedTextExpression = + const textExpression = "\\text{a b}"; + const noBraceTextExpression = "\\text x"; + const nestedTextExpression = "\\text{a {b} \\blue{c} \\color{#fff}{x} \\llap{x}}"; - var spaceTextExpression = "\\text{ a \\ }"; - var leadingSpaceTextExpression = "\\text {moo}"; - var badTextExpression = "\\text{a b%}"; - var badFunctionExpression = "\\text{\\sqrt{x}}"; - var mathTokenAfterText = "\\text{sin}^2"; + const spaceTextExpression = "\\text{ a \\ }"; + const leadingSpaceTextExpression = "\\text {moo}"; + const badTextExpression = "\\text{a b%}"; + const badFunctionExpression = "\\text{\\sqrt{x}}"; + const mathTokenAfterText = "\\text{sin}^2"; it("should not fail", function() { expect(textExpression).toParse(); }); it("should produce a text", function() { - var parse = getParsed(textExpression)[0]; + const parse = getParsed(textExpression)[0]; expect(parse.type).toEqual("text"); expect(parse.value).toBeDefined(); }); it("should produce textords instead of mathords", function() { - var parse = getParsed(textExpression)[0]; - var group = parse.value.body; + const parse = getParsed(textExpression)[0]; + const group = parse.value.body; expect(group[0].type).toEqual("textord"); }); @@ -768,8 +768,8 @@ describe("A text parser", function() { }); it("should contract spaces", function() { - var parse = getParsed(spaceTextExpression)[0]; - var group = parse.value.body; + const parse = getParsed(spaceTextExpression)[0]; + const group = parse.value.body; expect(group[0].type).toEqual("spacing"); expect(group[1].type).toEqual("textord"); @@ -782,7 +782,7 @@ describe("A text parser", function() { }); it("should ignore a space before the text group", function() { - var parse = getParsed(leadingSpaceTextExpression)[0]; + const parse = getParsed(leadingSpaceTextExpression)[0]; // [m, o, o] expect(parse.value.body.length).toBe(3); expect( @@ -792,17 +792,17 @@ describe("A text parser", function() { }); describe("A color parser", function() { - var colorExpression = "\\blue{x}"; - var newColorExpression = "\\redA{x}"; - var customColorExpression = "\\color{#fA6}{x}"; - var badCustomColorExpression = "\\color{bad-color}{x}"; + const colorExpression = "\\blue{x}"; + const newColorExpression = "\\redA{x}"; + const customColorExpression = "\\color{#fA6}{x}"; + const badCustomColorExpression = "\\color{bad-color}{x}"; it("should not fail", function() { expect(colorExpression).toParse(); }); it("should build a color node", function() { - var parse = getParsed(colorExpression)[0]; + const parse = getParsed(colorExpression)[0]; expect(parse.type).toEqual("color"); expect(parse.value.color).toBeDefined(); @@ -814,7 +814,7 @@ describe("A color parser", function() { }); it("should correctly extract the custom color", function() { - var parse = getParsed(customColorExpression)[0]; + const parse = getParsed(customColorExpression)[0]; expect(parse.value.color).toEqual("#fA6"); }); @@ -836,8 +836,8 @@ describe("A color parser", function() { }); describe("A tie parser", function() { - var mathTie = "a~b"; - var textTie = "\\text{a~ b}"; + const mathTie = "a~b"; + const textTie = "\\text{a~ b}"; it("should parse ties in math mode", function() { expect(mathTie).toParse(); @@ -848,30 +848,30 @@ describe("A tie parser", function() { }); it("should produce spacing in math mode", function() { - var parse = getParsed(mathTie); + const parse = getParsed(mathTie); expect(parse[1].type).toEqual("spacing"); }); it("should produce spacing in text mode", function() { - var text = getParsed(textTie)[0]; - var parse = text.value.body; + const text = getParsed(textTie)[0]; + const parse = text.value.body; expect(parse[1].type).toEqual("spacing"); }); it("should not contract with spaces in text mode", function() { - var text = getParsed(textTie)[0]; - var parse = text.value.body; + const text = getParsed(textTie)[0]; + const parse = text.value.body; expect(parse[2].type).toEqual("spacing"); }); }); describe("A delimiter sizing parser", function() { - var normalDelim = "\\bigl |"; - var notDelim = "\\bigl x"; - var bigDelim = "\\Biggr \\langle"; + const normalDelim = "\\bigl |"; + const notDelim = "\\bigl x"; + const bigDelim = "\\Biggr \\langle"; it("should parse normal delimiters", function() { expect(normalDelim).toParse(); @@ -883,22 +883,22 @@ describe("A delimiter sizing parser", function() { }); it("should produce a delimsizing", function() { - var parse = getParsed(normalDelim)[0]; + const parse = getParsed(normalDelim)[0]; expect(parse.type).toEqual("delimsizing"); }); it("should produce the correct direction delimiter", function() { - var leftParse = getParsed(normalDelim)[0]; - var rightParse = getParsed(bigDelim)[0]; + const leftParse = getParsed(normalDelim)[0]; + const rightParse = getParsed(bigDelim)[0]; expect(leftParse.value.mclass).toEqual("mopen"); expect(rightParse.value.mclass).toEqual("mclose"); }); it("should parse the correct size delimiter", function() { - var smallParse = getParsed(normalDelim)[0]; - var bigParse = getParsed(bigDelim)[0]; + const smallParse = getParsed(normalDelim)[0]; + const bigParse = getParsed(bigDelim)[0]; expect(smallParse.value.size).toEqual(1); expect(bigParse.value.size).toEqual(4); @@ -906,26 +906,26 @@ describe("A delimiter sizing parser", function() { }); describe("An overline parser", function() { - var overline = "\\overline{x}"; + const overline = "\\overline{x}"; it("should not fail", function() { expect(overline).toParse(); }); it("should produce an overline", function() { - var parse = getParsed(overline)[0]; + const parse = getParsed(overline)[0]; expect(parse.type).toEqual("overline"); }); }); describe("A rule parser", function() { - var emRule = "\\rule{1em}{2em}"; - var exRule = "\\rule{1ex}{2em}"; - var badUnitRule = "\\rule{1px}{2em}"; - var noNumberRule = "\\rule{1em}{em}"; - var incompleteRule = "\\rule{1em}"; - var hardNumberRule = "\\rule{ 01.24ex}{2.450 em }"; + const emRule = "\\rule{1em}{2em}"; + const exRule = "\\rule{1ex}{2em}"; + const badUnitRule = "\\rule{1px}{2em}"; + const noNumberRule = "\\rule{1em}{em}"; + const incompleteRule = "\\rule{1em}"; + const hardNumberRule = "\\rule{ 01.24ex}{2.450 em }"; it("should not fail", function() { expect(emRule).toParse(); @@ -943,14 +943,14 @@ describe("A rule parser", function() { }); it("should produce a rule", function() { - var parse = getParsed(emRule)[0]; + const parse = getParsed(emRule)[0]; expect(parse.type).toEqual("rule"); }); it("should list the correct units", function() { - var emParse = getParsed(emRule)[0]; - var exParse = getParsed(exRule)[0]; + const emParse = getParsed(emRule)[0]; + const exParse = getParsed(exRule)[0]; expect(emParse.value.width.unit).toEqual("em"); expect(emParse.value.height.unit).toEqual("em"); @@ -960,14 +960,14 @@ describe("A rule parser", function() { }); it("should parse the number correctly", function() { - var hardNumberParse = getParsed(hardNumberRule)[0]; + const hardNumberParse = getParsed(hardNumberRule)[0]; expect(hardNumberParse.value.width.number).toBeCloseTo(1.24); expect(hardNumberParse.value.height.number).toBeCloseTo(2.45); }); it("should parse negative sizes", function() { - var parse = getParsed("\\rule{-1em}{- 0.2em}")[0]; + const parse = getParsed("\\rule{-1em}{- 0.2em}")[0]; expect(parse.value.width.number).toBeCloseTo(-1); expect(parse.value.height.number).toBeCloseTo(-0.2); @@ -975,16 +975,16 @@ describe("A rule parser", function() { }); describe("A kern parser", function() { - var emKern = "\\kern{1em}"; - var exKern = "\\kern{1ex}"; - var muKern = "\\kern{1mu}"; - var badUnitRule = "\\kern{1px}"; - var noNumberRule = "\\kern{em}"; + const emKern = "\\kern{1em}"; + const exKern = "\\kern{1ex}"; + const muKern = "\\kern{1mu}"; + const badUnitRule = "\\kern{1px}"; + const noNumberRule = "\\kern{em}"; it("should list the correct units", function() { - var emParse = getParsed(emKern)[0]; - var exParse = getParsed(exKern)[0]; - var muParse = getParsed(muKern)[0]; + const emParse = getParsed(emKern)[0]; + const exParse = getParsed(exKern)[0]; + const muParse = getParsed(muKern)[0]; expect(emParse.value.dimension.unit).toEqual("em"); expect(exParse.value.dimension.unit).toEqual("ex"); @@ -997,27 +997,27 @@ describe("A kern parser", function() { }); it("should parse negative sizes", function() { - var parse = getParsed("\\kern{-1em}")[0]; + const parse = getParsed("\\kern{-1em}")[0]; expect(parse.value.dimension.number).toBeCloseTo(-1); }); it("should parse positive sizes", function() { - var parse = getParsed("\\kern{+1em}")[0]; + const parse = getParsed("\\kern{+1em}")[0]; expect(parse.value.dimension.number).toBeCloseTo(1); }); }); describe("A non-braced kern parser", function() { - var emKern = "\\kern1em"; - var exKern = "\\kern 1 ex"; - var muKern = "\\kern 1mu"; - var badUnitRule = "\\kern1px"; - var noNumberRule = "\\kern em"; + const emKern = "\\kern1em"; + const exKern = "\\kern 1 ex"; + const muKern = "\\kern 1mu"; + const badUnitRule = "\\kern1px"; + const noNumberRule = "\\kern em"; it("should list the correct units", function() { - var emParse = getParsed(emKern)[0]; - var exParse = getParsed(exKern)[0]; - var muParse = getParsed(muKern)[0]; + const emParse = getParsed(emKern)[0]; + const exParse = getParsed(exKern)[0]; + const muParse = getParsed(muKern)[0]; expect(emParse.value.dimension.unit).toEqual("em"); expect(exParse.value.dimension.unit).toEqual("ex"); @@ -1030,26 +1030,26 @@ describe("A non-braced kern parser", function() { }); it("should parse negative sizes", function() { - var parse = getParsed("\\kern-1em")[0]; + const parse = getParsed("\\kern-1em")[0]; expect(parse.value.dimension.number).toBeCloseTo(-1); }); it("should parse positive sizes", function() { - var parse = getParsed("\\kern+1em")[0]; + const parse = getParsed("\\kern+1em")[0]; expect(parse.value.dimension.number).toBeCloseTo(1); }); }); describe("A left/right parser", function() { - var normalLeftRight = "\\left( \\dfrac{x}{y} \\right)"; - var emptyRight = "\\left( \\dfrac{x}{y} \\right."; + const normalLeftRight = "\\left( \\dfrac{x}{y} \\right)"; + const emptyRight = "\\left( \\dfrac{x}{y} \\right."; it("should not fail", function() { expect(normalLeftRight).toParse(); }); it("should produce a leftright", function() { - var parse = getParsed(normalLeftRight)[0]; + const parse = getParsed(normalLeftRight)[0]; expect(parse.type).toEqual("leftright"); expect(parse.value.left).toEqual("("); @@ -1057,8 +1057,8 @@ describe("A left/right parser", function() { }); it("should error when it is mismatched", function() { - var unmatchedLeft = "\\left( \\dfrac{x}{y}"; - var unmatchedRight = "\\dfrac{x}{y} \\right)"; + const unmatchedLeft = "\\left( \\dfrac{x}{y}"; + const unmatchedRight = "\\dfrac{x}{y} \\right)"; expect(unmatchedLeft).toNotParse(); @@ -1066,12 +1066,12 @@ describe("A left/right parser", function() { }); it("should error when braces are mismatched", function() { - var unmatched = "{ \\left( \\dfrac{x}{y} } \\right)"; + const unmatched = "{ \\left( \\dfrac{x}{y} } \\right)"; expect(unmatched).toNotParse(); }); it("should error when non-delimiters are provided", function() { - var nonDelimiter = "\\left$ \\dfrac{x}{y} \\right)"; + const nonDelimiter = "\\left$ \\dfrac{x}{y} \\right)"; expect(nonDelimiter).toNotParse(); }); @@ -1080,27 +1080,27 @@ describe("A left/right parser", function() { }); it("should parse the '.' delimiter with normal sizes", function() { - var normalEmpty = "\\Bigl ."; + const normalEmpty = "\\Bigl ."; expect(normalEmpty).toParse(); }); it("should handle \\middle", function() { - var normalMiddle = "\\left( \\dfrac{x}{y} \\middle| \\dfrac{y}{z} \\right)"; + const normalMiddle = "\\left( \\dfrac{x}{y} \\middle| \\dfrac{y}{z} \\right)"; expect(normalMiddle).toParse(); }); it("should handle multiple \\middles", function() { - var multiMiddle = "\\left( \\dfrac{x}{y} \\middle| \\dfrac{y}{z} \\middle/ \\dfrac{z}{q} \\right)"; + const multiMiddle = "\\left( \\dfrac{x}{y} \\middle| \\dfrac{y}{z} \\middle/ \\dfrac{z}{q} \\right)"; expect(multiMiddle).toParse(); }); it("should handle nested \\middles", function() { - var nestedMiddle = "\\left( a^2 \\middle| \\left( b \\middle/ c \\right) \\right)"; + const nestedMiddle = "\\left( a^2 \\middle| \\left( b \\middle/ c \\right) \\right)"; expect(nestedMiddle).toParse(); }); it("should error when \\middle is not in \\left...\\right", function() { - var unmatchedMiddle = "(\\middle|\\dfrac{x}{y})"; + const unmatchedMiddle = "(\\middle|\\dfrac{x}{y})"; expect(unmatchedMiddle).toNotParse(); }); }); @@ -1136,8 +1136,8 @@ describe("A begin/end parser", function() { }); it("should nest", function() { - var m1 = "\\begin{pmatrix}1&2\\\\3&4\\end{pmatrix}"; - var m2 = "\\begin{array}{rl}" + m1 + "&0\\\\0&" + m1 + "\\end{array}"; + const m1 = "\\begin{pmatrix}1&2\\\\3&4\\end{pmatrix}"; + const m2 = "\\begin{array}{rl}" + m1 + "&0\\\\0&" + m1 + "\\end{array}"; expect(m2).toParse(); }); @@ -1147,8 +1147,8 @@ describe("A begin/end parser", function() { }); describe("A sqrt parser", function() { - var sqrt = "\\sqrt{x}"; - var missingGroup = "\\sqrt"; + const sqrt = "\\sqrt{x}"; + const missingGroup = "\\sqrt"; it("should parse square roots", function() { expect(sqrt).toParse(); @@ -1159,7 +1159,7 @@ describe("A sqrt parser", function() { }); it("should produce sqrts", function() { - var parse = getParsed(sqrt)[0]; + const parse = getParsed(sqrt)[0]; expect(parse.type).toEqual("sqrt"); }); @@ -1171,7 +1171,7 @@ describe("A TeX-compliant parser", function() { }); it("should fail if there are not enough arguments", function() { - var missingGroups = [ + const missingGroups = [ "\\frac{x}", "\\color{#fff}", "\\rule{1em}", @@ -1180,7 +1180,7 @@ describe("A TeX-compliant parser", function() { "\\text", ]; - for (var i = 0; i < missingGroups.length; i++) { + for (let i = 0; i < missingGroups.length; i++) { expect(missingGroups[i]).toNotParse(); } }); @@ -1191,7 +1191,7 @@ describe("A TeX-compliant parser", function() { }); it("should fail when arguments require arguments", function() { - var badArguments = [ + const badArguments = [ "\\frac \\frac x y z", "\\frac x \\frac y z", "\\frac \\sqrt x y", @@ -1207,13 +1207,13 @@ describe("A TeX-compliant parser", function() { "\\sqrt \\llap x", ]; - for (var i = 0; i < badArguments.length; i++) { + for (let i = 0; i < badArguments.length; i++) { expect(badArguments[i]).toNotParse(); } }); it("should work when the arguments have braces", function() { - var goodArguments = [ + const goodArguments = [ "\\frac {\\frac x y} z", "\\frac x {\\frac y z}", "\\frac {\\sqrt x} y", @@ -1225,33 +1225,33 @@ describe("A TeX-compliant parser", function() { "\\sqrt {\\llap x}", ]; - for (var i = 0; i < goodArguments.length; i++) { + for (let i = 0; i < goodArguments.length; i++) { expect(goodArguments[i]).toParse(); } }); it("should fail when sup/subscripts require arguments", function() { - var badSupSubscripts = [ + const badSupSubscripts = [ "x^\\sqrt x", "x^\\llap x", "x_\\sqrt x", "x_\\llap x", ]; - for (var i = 0; i < badSupSubscripts.length; i++) { + for (let i = 0; i < badSupSubscripts.length; i++) { expect(badSupSubscripts[i]).toNotParse(); } }); it("should work when sup/subscripts arguments have braces", function() { - var goodSupSubscripts = [ + const goodSupSubscripts = [ "x^{\\sqrt x}", "x^{\\llap x}", "x_{\\sqrt x}", "x_{\\llap x}", ]; - for (var i = 0; i < goodSupSubscripts.length; i++) { + for (let i = 0; i < goodSupSubscripts.length; i++) { expect(goodSupSubscripts[i]).toParse(); } }); @@ -1282,7 +1282,7 @@ describe("A TeX-compliant parser", function() { }); it("should fail when arguments are \\left", function() { - var badLeftArguments = [ + const badLeftArguments = [ "\\frac \\left( x \\right) y", "\\frac x \\left( y \\right)", "\\llap \\left( x \\right)", @@ -1290,13 +1290,13 @@ describe("A TeX-compliant parser", function() { "x^\\left( x \\right)", ]; - for (var i = 0; i < badLeftArguments.length; i++) { + for (let i = 0; i < badLeftArguments.length; i++) { expect(badLeftArguments[i]).toNotParse(); } }); it("should succeed when there are braces around the \\left/\\right", function() { - var goodLeftArguments = [ + const goodLeftArguments = [ "\\frac {\\left( x \\right)} y", "\\frac x {\\left( y \\right)}", "\\llap {\\left( x \\right)}", @@ -1304,7 +1304,7 @@ describe("A TeX-compliant parser", function() { "x^{\\left( x \\right)}", ]; - for (var i = 0; i < goodLeftArguments.length; i++) { + for (let i = 0; i < goodLeftArguments.length; i++) { expect(goodLeftArguments[i]).toParse(); } }); @@ -1319,22 +1319,22 @@ describe("A style change parser", function() { }); it("should produce the correct style", function() { - var displayParse = getParsed("\\displaystyle x")[0]; + const displayParse = getParsed("\\displaystyle x")[0]; expect(displayParse.value.style).toEqual("display"); - var scriptscriptParse = getParsed("\\scriptscriptstyle x")[0]; + const scriptscriptParse = getParsed("\\scriptscriptstyle x")[0]; expect(scriptscriptParse.value.style).toEqual("scriptscript"); }); it("should only change the style within its group", function() { - var text = "a b { c d \\displaystyle e f } g h"; - var parse = getParsed(text); + const text = "a b { c d \\displaystyle e f } g h"; + const parse = getParsed(text); - var displayNode = parse[2].value[2]; + const displayNode = parse[2].value[2]; expect(displayNode.type).toEqual("styling"); - var displayBody = displayNode.value.value; + const displayBody = displayNode.value.value; expect(displayBody.length).toEqual(2); expect(displayBody[0].value).toEqual("e"); @@ -1357,34 +1357,34 @@ describe("A font parser", function() { }); it("should produce the correct fonts", function() { - var mathbbParse = getParsed("\\mathbb x")[0]; + const mathbbParse = getParsed("\\mathbb x")[0]; expect(mathbbParse.value.font).toEqual("mathbb"); expect(mathbbParse.value.type).toEqual("font"); - var mathrmParse = getParsed("\\mathrm x")[0]; + const mathrmParse = getParsed("\\mathrm x")[0]; expect(mathrmParse.value.font).toEqual("mathrm"); expect(mathrmParse.value.type).toEqual("font"); - var mathitParse = getParsed("\\mathit x")[0]; + const mathitParse = getParsed("\\mathit x")[0]; expect(mathitParse.value.font).toEqual("mathit"); expect(mathitParse.value.type).toEqual("font"); - var mathcalParse = getParsed("\\mathcal C")[0]; + const mathcalParse = getParsed("\\mathcal C")[0]; expect(mathcalParse.value.font).toEqual("mathcal"); expect(mathcalParse.value.type).toEqual("font"); - var mathfrakParse = getParsed("\\mathfrak C")[0]; + const mathfrakParse = getParsed("\\mathfrak C")[0]; expect(mathfrakParse.value.font).toEqual("mathfrak"); expect(mathfrakParse.value.type).toEqual("font"); }); it("should parse nested font commands", function() { - var nestedParse = getParsed("\\mathbb{R \\neq \\mathrm{R}}")[0]; + const nestedParse = getParsed("\\mathbb{R \\neq \\mathrm{R}}")[0]; expect(nestedParse.value.font).toEqual("mathbb"); expect(nestedParse.value.type).toEqual("font"); expect(nestedParse.value.body.value.length).toEqual(3); - var bbBody = nestedParse.value.body.value; + const bbBody = nestedParse.value.body.value; expect(bbBody[0].type).toEqual("mathord"); expect(bbBody[1].type).toEqual("rel"); expect(bbBody[2].type).toEqual("font"); @@ -1393,10 +1393,10 @@ describe("A font parser", function() { }); it("should work with \\color", function() { - var colorMathbbParse = getParsed("\\color{blue}{\\mathbb R}")[0]; + const colorMathbbParse = getParsed("\\color{blue}{\\mathbb R}")[0]; expect(colorMathbbParse.value.type).toEqual("color"); expect(colorMathbbParse.value.color).toEqual("blue"); - var body = colorMathbbParse.value.value; + const body = colorMathbbParse.value.value; expect(body.length).toEqual(1); expect(body[0].value.type).toEqual("font"); expect(body[0].value.font).toEqual("mathbb"); @@ -1407,7 +1407,7 @@ describe("A font parser", function() { }); it("should nest fonts correctly", function() { - var bf = getParsed("\\mathbf{a\\mathrm{b}c}")[0]; + const bf = getParsed("\\mathbf{a\\mathrm{b}c}")[0]; expect(bf.value.type).toEqual("font"); expect(bf.value.font).toEqual("mathbf"); expect(bf.value.body.value.length).toEqual(3); @@ -1424,65 +1424,65 @@ describe("A font parser", function() { describe("An HTML font tree-builder", function() { it("should render \\mathbb{R} with the correct font", function() { - var markup = katex.renderToString("\\mathbb{R}"); + const markup = katex.renderToString("\\mathbb{R}"); expect(markup).toContain("<span class=\"mord mathbb\">R</span>"); }); it("should render \\mathrm{R} with the correct font", function() { - var markup = katex.renderToString("\\mathrm{R}"); + const markup = katex.renderToString("\\mathrm{R}"); expect(markup).toContain("<span class=\"mord mathrm\">R</span>"); }); it("should render \\mathcal{R} with the correct font", function() { - var markup = katex.renderToString("\\mathcal{R}"); + const markup = katex.renderToString("\\mathcal{R}"); expect(markup).toContain("<span class=\"mord mathcal\">R</span>"); }); it("should render \\mathfrak{R} with the correct font", function() { - var markup = katex.renderToString("\\mathfrak{R}"); + const markup = katex.renderToString("\\mathfrak{R}"); expect(markup).toContain("<span class=\"mord mathfrak\">R</span>"); }); it("should render \\text{R} with the correct font", function() { - var markup = katex.renderToString("\\text{R}"); + const markup = katex.renderToString("\\text{R}"); expect(markup).toContain("<span class=\"mord mathrm\">R</span>"); }); it("should render \\textit{R} with the correct font", function() { - var markup = katex.renderToString("\\textit{R}"); + const markup = katex.renderToString("\\textit{R}"); expect(markup).toContain("<span class=\"mord textit\">R</span>"); }); it("should render \\text{\\textit{R}} with the correct font", function() { - var markup = katex.renderToString("\\text{\\textit{R}}"); + const markup = katex.renderToString("\\text{\\textit{R}}"); expect(markup).toContain("<span class=\"mord textit\">R</span>"); }); it("should render \\text{R\\textit{S}T} with the correct fonts", function() { - var markup = katex.renderToString("\\text{R\\textit{S}T}"); + const markup = katex.renderToString("\\text{R\\textit{S}T}"); expect(markup).toContain("<span class=\"mord mathrm\">R</span>"); expect(markup).toContain("<span class=\"mord textit\">S</span>"); expect(markup).toContain("<span class=\"mord mathrm\">T</span>"); }); it("should render \\textbf{R} with the correct font", function() { - var markup = katex.renderToString("\\textbf{R}"); + const markup = katex.renderToString("\\textbf{R}"); expect(markup).toContain("<span class=\"mord mathbf\">R</span>"); }); it("should render \\textsf{R} with the correct font", function() { - var markup = katex.renderToString("\\textsf{R}"); + const markup = katex.renderToString("\\textsf{R}"); expect(markup).toContain("<span class=\"mord mathsf\">R</span>"); }); it("should render \\texttt{R} with the correct font", function() { - var markup = katex.renderToString("\\texttt{R}"); + const markup = katex.renderToString("\\texttt{R}"); expect(markup).toContain("<span class=\"mord mathtt\">R</span>"); }); it("should render a combination of font and color changes", function() { - var markup = katex.renderToString("\\color{blue}{\\mathbb R}"); - var span = "<span class=\"mord mathbb\" style=\"color:blue;\">R</span>"; + let markup = katex.renderToString("\\color{blue}{\\mathbb R}"); + let span = "<span class=\"mord mathbb\" style=\"color:blue;\">R</span>"; expect(markup).toContain(span); markup = katex.renderToString("\\mathbb{\\color{blue}{R}}"); @@ -1520,11 +1520,11 @@ describe("An HTML font tree-builder", function() { describe("A MathML font tree-builder", function() { - var contents = "Ax2k\\omega\\Omega\\imath+"; + const contents = "Ax2k\\omega\\Omega\\imath+"; it("should render " + contents + " with the correct mathvariants", function() { - var tree = getParsed(contents); - var markup = buildMathML(tree, contents, defaultOptions).toMarkup(); + const tree = getParsed(contents); + const markup = buildMathML(tree, contents, defaultOptions).toMarkup(); expect(markup).toContain("<mi>A</mi>"); expect(markup).toContain("<mi>x</mi>"); expect(markup).toContain("<mn>2</mn>"); @@ -1535,9 +1535,9 @@ describe("A MathML font tree-builder", function() { }); it("should render \\mathbb{" + contents + "} with the correct mathvariants", function() { - var tex = "\\mathbb{" + contents + "}"; - var tree = getParsed(tex); - var markup = buildMathML(tree, tex, defaultOptions).toMarkup(); + const tex = "\\mathbb{" + contents + "}"; + const tree = getParsed(tex); + const markup = buildMathML(tree, tex, defaultOptions).toMarkup(); expect(markup).toContain("<mi mathvariant=\"double-struck\">A</mi>"); expect(markup).toContain("<mi>x</mi>"); expect(markup).toContain("<mn mathvariant=\"normal\">2</mn>"); @@ -1548,9 +1548,9 @@ describe("A MathML font tree-builder", function() { }); it("should render \\mathrm{" + contents + "} with the correct mathvariants", function() { - var tex = "\\mathrm{" + contents + "}"; - var tree = getParsed(tex); - var markup = buildMathML(tree, tex, defaultOptions).toMarkup(); + const tex = "\\mathrm{" + contents + "}"; + const tree = getParsed(tex); + const markup = buildMathML(tree, tex, defaultOptions).toMarkup(); expect(markup).toContain("<mi mathvariant=\"normal\">A</mi>"); expect(markup).toContain("<mi mathvariant=\"normal\">x</mi>"); expect(markup).toContain("<mn mathvariant=\"normal\">2</mn>"); @@ -1561,9 +1561,9 @@ describe("A MathML font tree-builder", function() { }); it("should render \\mathit{" + contents + "} with the correct mathvariants", function() { - var tex = "\\mathit{" + contents + "}"; - var tree = getParsed(tex); - var markup = buildMathML(tree, tex, defaultOptions).toMarkup(); + const tex = "\\mathit{" + contents + "}"; + const tree = getParsed(tex); + const markup = buildMathML(tree, tex, defaultOptions).toMarkup(); expect(markup).toContain("<mi mathvariant=\"italic\">A</mi>"); expect(markup).toContain("<mi mathvariant=\"italic\">x</mi>"); expect(markup).toContain("<mn mathvariant=\"italic\">2</mn>"); @@ -1574,9 +1574,9 @@ describe("A MathML font tree-builder", function() { }); it("should render \\mathbf{" + contents + "} with the correct mathvariants", function() { - var tex = "\\mathbf{" + contents + "}"; - var tree = getParsed(tex); - var markup = buildMathML(tree, tex, defaultOptions).toMarkup(); + const tex = "\\mathbf{" + contents + "}"; + const tree = getParsed(tex); + const markup = buildMathML(tree, tex, defaultOptions).toMarkup(); expect(markup).toContain("<mi mathvariant=\"bold\">A</mi>"); expect(markup).toContain("<mi mathvariant=\"bold\">x</mi>"); expect(markup).toContain("<mn mathvariant=\"bold\">2</mn>"); @@ -1587,9 +1587,9 @@ describe("A MathML font tree-builder", function() { }); it("should render \\mathcal{" + contents + "} with the correct mathvariants", function() { - var tex = "\\mathcal{" + contents + "}"; - var tree = getParsed(tex); - var markup = buildMathML(tree, tex, defaultOptions).toMarkup(); + const tex = "\\mathcal{" + contents + "}"; + const tree = getParsed(tex); + const markup = buildMathML(tree, tex, defaultOptions).toMarkup(); expect(markup).toContain("<mi mathvariant=\"script\">A</mi>"); expect(markup).toContain("<mi>x</mi>"); // script is caps only expect(markup).toContain("<mn mathvariant=\"script\">2</mn>"); @@ -1602,9 +1602,9 @@ describe("A MathML font tree-builder", function() { }); it("should render \\mathfrak{" + contents + "} with the correct mathvariants", function() { - var tex = "\\mathfrak{" + contents + "}"; - var tree = getParsed(tex); - var markup = buildMathML(tree, tex, defaultOptions).toMarkup(); + const tex = "\\mathfrak{" + contents + "}"; + const tree = getParsed(tex); + const markup = buildMathML(tree, tex, defaultOptions).toMarkup(); expect(markup).toContain("<mi mathvariant=\"fraktur\">A</mi>"); expect(markup).toContain("<mi mathvariant=\"fraktur\">x</mi>"); expect(markup).toContain("<mn mathvariant=\"fraktur\">2</mn>"); @@ -1617,9 +1617,9 @@ describe("A MathML font tree-builder", function() { }); it("should render \\mathscr{" + contents + "} with the correct mathvariants", function() { - var tex = "\\mathscr{" + contents + "}"; - var tree = getParsed(tex); - var markup = buildMathML(tree, tex, defaultOptions).toMarkup(); + const tex = "\\mathscr{" + contents + "}"; + const tree = getParsed(tex); + const markup = buildMathML(tree, tex, defaultOptions).toMarkup(); expect(markup).toContain("<mi mathvariant=\"script\">A</mi>"); // MathJax marks everything below as "script" except \omega // We don't have these glyphs in "script" and neither does MathJax @@ -1632,9 +1632,9 @@ describe("A MathML font tree-builder", function() { }); it("should render \\mathsf{" + contents + "} with the correct mathvariants", function() { - var tex = "\\mathsf{" + contents + "}"; - var tree = getParsed(tex); - var markup = buildMathML(tree, tex, defaultOptions).toMarkup(); + const tex = "\\mathsf{" + contents + "}"; + const tree = getParsed(tex); + const markup = buildMathML(tree, tex, defaultOptions).toMarkup(); expect(markup).toContain("<mi mathvariant=\"sans-serif\">A</mi>"); expect(markup).toContain("<mi mathvariant=\"sans-serif\">x</mi>"); expect(markup).toContain("<mn mathvariant=\"sans-serif\">2</mn>"); @@ -1645,10 +1645,10 @@ describe("A MathML font tree-builder", function() { }); it("should render a combination of font and color changes", function() { - var tex = "\\color{blue}{\\mathbb R}"; - var tree = getParsed(tex); - var markup = buildMathML(tree, tex, defaultOptions).toMarkup(); - var node = "<mstyle mathcolor=\"blue\">" + + let tex = "\\color{blue}{\\mathbb R}"; + let tree = getParsed(tex); + let markup = buildMathML(tree, tex, defaultOptions).toMarkup(); + let node = "<mstyle mathcolor=\"blue\">" + "<mi mathvariant=\"double-struck\">R</mi>" + "</mstyle>"; expect(markup).toContain(node); @@ -1666,13 +1666,13 @@ describe("A MathML font tree-builder", function() { describe("A bin builder", function() { it("should create mbins normally", function() { - var built = getBuilt("x + y"); + const built = getBuilt("x + y"); expect(built[1].classes).toContain("mbin"); }); it("should create ords when at the beginning of lists", function() { - var built = getBuilt("+ x"); + const built = getBuilt("+ x"); expect(built[0].classes).toContain("mord"); expect(built[0].classes).not.toContain("mbin"); @@ -1696,7 +1696,7 @@ describe("A bin builder", function() { describe("A markup generator", function() { it("marks trees up", function() { // Just a few quick sanity checks here... - var markup = katex.renderToString("\\sigma^2"); + const markup = katex.renderToString("\\sigma^2"); expect(markup.indexOf("<span")).toBe(0); expect(markup).toContain("\u03c3"); // sigma expect(markup).toContain("margin-right"); @@ -1704,7 +1704,7 @@ describe("A markup generator", function() { }); it("generates both MathML and HTML", function() { - var markup = katex.renderToString("a"); + const markup = katex.renderToString("a"); expect(markup).toContain("<span"); expect(markup).toContain("<math"); @@ -1713,7 +1713,7 @@ describe("A markup generator", function() { describe("A parse tree generator", function() { it("generates a tree", function() { - var tree = stripPositions(katex.__parse("\\sigma^2")); + const tree = stripPositions(katex.__parse("\\sigma^2")); expect(JSON.stringify(tree)).toEqual(JSON.stringify([ { "type": "supsub", @@ -1745,13 +1745,13 @@ describe("An accent parser", function() { }); it("should produce accents", function() { - var parse = getParsed("\\vec x")[0]; + const parse = getParsed("\\vec x")[0]; expect(parse.type).toEqual("accent"); }); it("should be grouped more tightly than supsubs", function() { - var parse = getParsed("\\vec x^2")[0]; + const parse = getParsed("\\vec x^2")[0]; expect(parse.type).toEqual("supsub"); }); @@ -1787,7 +1787,7 @@ describe("A phantom parser", function() { }); it("should build a phantom node", function() { - var parse = getParsed("\\phantom{x}")[0]; + const parse = getParsed("\\phantom{x}")[0]; expect(parse.type).toEqual("phantom"); expect(parse.value.value).toBeDefined(); @@ -1803,14 +1803,14 @@ describe("A phantom builder", function() { }); it("should make the children transparent", function() { - var children = getBuilt("\\phantom{x+1}"); + const children = getBuilt("\\phantom{x+1}"); expect(children[0].style.color).toBe("transparent"); expect(children[1].style.color).toBe("transparent"); expect(children[2].style.color).toBe("transparent"); }); it("should make all descendants transparent", function() { - var children = getBuilt("\\phantom{x+\\blue{1}}"); + const children = getBuilt("\\phantom{x+\\blue{1}}"); expect(children[0].style.color).toBe("transparent"); expect(children[1].style.color).toBe("transparent"); expect(children[2].style.color).toBe("transparent"); @@ -1857,7 +1857,7 @@ describe("An optional argument parser", function() { describe("An array environment", function() { it("should accept a single alignment character", function() { - var parse = getParsed("\\begin{array}r1\\\\20\\end{array}"); + const parse = getParsed("\\begin{array}r1\\\\20\\end{array}"); expect(parse[0].type).toBe("array"); expect(parse[0].value.cols).toEqual([ { type: "align", align: "r" }, @@ -1865,7 +1865,7 @@ describe("An array environment", function() { }); it("should accept vertical separators", function() { - var parse = getParsed("\\begin{array}{|l||c|}\\end{array}"); + const parse = getParsed("\\begin{array}{|l||c|}\\end{array}"); expect(parse[0].type).toBe("array"); expect(parse[0].value.cols).toEqual([ { type: "separator", separator: "|" }, @@ -1898,12 +1898,12 @@ describe("An aligned environment", function() { }); -var getMathML = function(expr, settings) { - var usedSettings = settings ? settings : defaultSettings; +const getMathML = function(expr, settings) { + const usedSettings = settings ? settings : defaultSettings; expect(expr).toParse(usedSettings); - var built = buildMathML(parseTree(expr, usedSettings), expr, usedSettings); + const built = buildMathML(parseTree(expr, usedSettings), expr, usedSettings); // Strip off the surrounding <span> return built.children[0]; @@ -1911,33 +1911,33 @@ var getMathML = function(expr, settings) { describe("A MathML builder", function() { it("should generate math nodes", function() { - var node = getMathML("x^2"); + const node = getMathML("x^2"); expect(node.type).toEqual("math"); }); it("should generate appropriate MathML types", function() { - var identifier = getMathML("x").children[0].children[0]; + const identifier = getMathML("x").children[0].children[0]; expect(identifier.children[0].type).toEqual("mi"); - var number = getMathML("1").children[0].children[0]; + const number = getMathML("1").children[0].children[0]; expect(number.children[0].type).toEqual("mn"); - var operator = getMathML("+").children[0].children[0]; + const operator = getMathML("+").children[0].children[0]; expect(operator.children[0].type).toEqual("mo"); - var space = getMathML("\\;").children[0].children[0]; + const space = getMathML("\\;").children[0].children[0]; expect(space.children[0].type).toEqual("mspace"); - var text = getMathML("\\text{a}").children[0].children[0]; + const text = getMathML("\\text{a}").children[0].children[0]; expect(text.children[0].type).toEqual("mtext"); - var textop = getMathML("\\sin").children[0].children[0]; + const textop = getMathML("\\sin").children[0].children[0]; expect(textop.children[0].type).toEqual("mi"); }); it("should generate a <mphantom> node for \\phantom", function() { - var phantom = getMathML("\\phantom{x}").children[0].children[0]; + const phantom = getMathML("\\phantom{x}").children[0].children[0]; expect(phantom.children[0].type).toEqual("mphantom"); }); }); @@ -1945,8 +1945,8 @@ describe("A MathML builder", function() { describe("A parser that does not throw on unsupported commands", function() { // The parser breaks on unsupported commands unless it is explicitly // told not to - var errorColor = "#933"; - var noThrowSettings = new Settings({ + const errorColor = "#933"; + const noThrowSettings = new Settings({ throwOnError: false, errorColor: errorColor, }); @@ -1978,7 +1978,7 @@ describe("A parser that does not throw on unsupported commands", function() { }); it("should produce color nodes with a color value given by errorColor", function() { - var parsedInput = getParsed("\\error", noThrowSettings); + const parsedInput = getParsed("\\error", noThrowSettings); expect(parsedInput[0].type).toBe("color"); expect(parsedInput[0].value.color).toBe(errorColor); }); @@ -1995,8 +1995,8 @@ describe("The symbol table integraty", function() { describe("A macro expander", function() { - var compareParseTree = function(actual, expected, macros) { - var settings = new Settings({macros: macros}); + const compareParseTree = function(actual, expected, macros) { + const settings = new Settings({macros: macros}); actual = stripPositions(parseTree(actual, settings)); expected = stripPositions(parseTree(expected, defaultSettings)); expect(actual).toEqual(expected); diff --git a/test/symgroups.js b/test/symgroups.js @@ -1,20 +1,20 @@ /* eslint no-console:0 */ "use strict"; -var fs = require("fs"); -var childProcess = require("child_process"); +const fs = require("fs"); +const childProcess = require("child_process"); -var opts = require("nomnom") +const opts = require("nomnom") .option("spacing", { flag: true, help: "Print mismatches involving spacing commands", }) .parse(); -var symbols = require("../src/symbols"); -var keys = Object.keys(symbols.math); +const symbols = require("../src/symbols"); +const keys = Object.keys(symbols.math); keys.sort(); -var types = [ +const types = [ "mathord", "op", "bin", "rel", "open", "close", "punct", "inner", "spacing", "accent", "textord", ]; @@ -22,22 +22,22 @@ var types = [ process.nextTick(writeTexFile); function writeTexFile() { - var tex = fs.createWriteStream("symgroups.tex"); + const tex = fs.createWriteStream("symgroups.tex"); tex.on("finish", typeset); tex.write("\\documentclass{article}\n" + "\\usepackage{textcomp,amsmath,amssymb,gensymb}\n" + "\\begin{document}\n" + "\\showboxbreadth=\\maxdimen\\showboxdepth=\\maxdimen\n\n"); keys.forEach(function(key, idx) { - var sym = symbols.math[key]; - var type = types.indexOf(sym.group) + 1; + const sym = symbols.math[key]; + const type = types.indexOf(sym.group) + 1; tex.write("$" + idx + "+" + key + "+" + type + "\\showlists$\n\n"); }); tex.end("\\end{document}\n"); } function typeset() { - var proc = childProcess.spawn( + const proc = childProcess.spawn( "pdflatex", ["--interaction=nonstopmode", "symgroups"], {stdio: "ignore"}); proc.on("exit", function(code, signal) { @@ -76,29 +76,29 @@ function typeset() { */ // 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 -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 -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 -var reDigit = /^\.\\fam0 ([0-9])/mg; +const reDigit = /^\.\\fam0 ([0-9])/mg; // Match the atom type, i.e. "\mathrel" in the above example -var reAtom = /\\([a-z]+)/; +const reAtom = /\\([a-z]+)/; function evaluate(err, log) { if (err) { throw err; } - var match; - var nextIndex = 0; + let match; + let nextIndex = 0; while ((match = reMM.exec(log)) !== null) { - var list = match[1]; + const list = match[1]; match = reParts.exec(list); if (!match) { match = reEmpty.exec(list); @@ -113,9 +113,9 @@ function evaluate(err, log) { console.error(list); process.exit(2); } - var idx = extractDigits(match[1]); - var atom = match[2]; - var katexType = types[extractDigits(match[3]) - 1] || "???"; + const idx = extractDigits(match[1]); + const atom = match[2]; + const katexType = types[extractDigits(match[3]) - 1] || "???"; match = reAtom.exec(atom); if (!match) { console.error("Failed to find atom type"); @@ -123,7 +123,7 @@ function evaluate(err, log) { console.error(list); process.exit(3); } - var latexType = match[1]; + const latexType = match[1]; if (katexType !== latexType && "math" + katexType !== latexType && (katexType !== "textord" || latexType !== "mathord") && (katexType !== "spacing" || opts.spacing)) { @@ -145,8 +145,8 @@ function evaluate(err, log) { } function extractDigits(str) { - var match; - var res = ""; + let match; + let res = ""; while ((match = reDigit.exec(str)) !== null) { res += match[1]; } diff --git a/test/unicode-spec.js b/test/unicode-spec.js @@ -4,13 +4,13 @@ /* global expect: false */ /* global it: false */ /* global describe: false */ -var ParseError = require("../src/ParseError"); -var parseTree = require("../src/parseTree"); -var Settings = require("../src/Settings"); +const ParseError = require("../src/ParseError"); +const parseTree = require("../src/parseTree"); +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 { return parseTree(expr, settings || defaultSettings); } catch (e) { @@ -32,9 +32,9 @@ describe("unicode", function() { toParse: function() { return { compare: function(actual, settings) { - var usedSettings = settings ? settings : defaultSettings; + const usedSettings = settings ? settings : defaultSettings; - var result = { + const result = { pass: true, message: "'" + actual + "' succeeded parsing", }; @@ -47,9 +47,9 @@ describe("unicode", function() { toNotParse: function() { return { compare: function(actual, settings) { - var usedSettings = settings ? settings : defaultSettings; + const usedSettings = settings ? settings : defaultSettings; - var result = { + const result = { pass: false, message: "Expected '" + actual + "' to fail " + "parsing, but it succeeded",