commit
9ad50178f1
86
.eslintrc
Normal file
86
.eslintrc
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
{
|
||||||
|
"rules": {
|
||||||
|
"arrow-spacing": 2,
|
||||||
|
"brace-style": [2, "1tbs", { "allowSingleLine": true }],
|
||||||
|
// We'd possibly like to remove the 'properties': 'never' one day.
|
||||||
|
"camelcase": [2, { "properties": "never" }],
|
||||||
|
"comma-dangle": [2, "always-multiline"],
|
||||||
|
"comma-spacing": [2, { "before": false, "after": true }],
|
||||||
|
"constructor-super": 2,
|
||||||
|
"curly": 2,
|
||||||
|
"eol-last": 2,
|
||||||
|
"eqeqeq": [2, "allow-null"],
|
||||||
|
"guard-for-in": 2,
|
||||||
|
"indent": [2, 4, {"SwitchCase": 1}],
|
||||||
|
"linebreak-style": [2, "unix"],
|
||||||
|
"max-len": [2, 80, 4, { "ignoreUrls": true, "ignorePattern": "\\brequire\\([\"']|eslint-disable" }],
|
||||||
|
"no-alert": 2,
|
||||||
|
"no-array-constructor": 2,
|
||||||
|
"no-console": 2,
|
||||||
|
"no-const-assign": 2,
|
||||||
|
"no-debugger": 2,
|
||||||
|
"no-dupe-class-members": 2,
|
||||||
|
"no-dupe-keys": 2,
|
||||||
|
"no-extra-bind": 2,
|
||||||
|
"no-new": 2,
|
||||||
|
"no-new-func": 2,
|
||||||
|
"no-new-object": 2,
|
||||||
|
"no-spaced-func": 2,
|
||||||
|
"no-this-before-super": 2,
|
||||||
|
"no-throw-literal": 2,
|
||||||
|
"no-trailing-spaces": 2,
|
||||||
|
"no-undef": 2,
|
||||||
|
"no-unexpected-multiline": 2,
|
||||||
|
"no-unreachable": 2,
|
||||||
|
"no-unused-vars": [2, {"args": "none", "varsIgnorePattern": "^_*$"}],
|
||||||
|
"no-useless-call": 2,
|
||||||
|
"no-with": 2,
|
||||||
|
"one-var": [2, "never"],
|
||||||
|
"prefer-const": 2,
|
||||||
|
"prefer-spread": 2,
|
||||||
|
"semi": [2, "always"],
|
||||||
|
"space-after-keywords": 2,
|
||||||
|
"space-before-blocks": 2,
|
||||||
|
"space-before-function-paren": [2, "never"],
|
||||||
|
"space-before-keywords": 2,
|
||||||
|
"space-infix-ops": 2,
|
||||||
|
"space-return-throw-case": 2,
|
||||||
|
"space-unary-ops": 2,
|
||||||
|
// ---------------------------------------
|
||||||
|
// Stuff we explicitly disable.
|
||||||
|
// We turned this off because it complains when you have a
|
||||||
|
// multi-line string, which I think is going too far.
|
||||||
|
"prefer-template": 0,
|
||||||
|
// 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"],
|
||||||
|
// Might be nice to turn this on one day, but since we don't
|
||||||
|
// use jsdoc anywhere it seems silly to require it yet.
|
||||||
|
"valid-jsdoc": 0,
|
||||||
|
"require-jsdoc": 0
|
||||||
|
},
|
||||||
|
"ecmaFeatures": {
|
||||||
|
"arrowFunctions": true,
|
||||||
|
"blockBindings": true,
|
||||||
|
"classes": true,
|
||||||
|
"destructuring": true,
|
||||||
|
"experimentalObjectRestSpread": true,
|
||||||
|
"forOf": true,
|
||||||
|
"jsx": true,
|
||||||
|
"restParams": true,
|
||||||
|
"spread": true,
|
||||||
|
"templateStrings": true
|
||||||
|
},
|
||||||
|
"env": {
|
||||||
|
// "es6": true,
|
||||||
|
"node": true,
|
||||||
|
"browser": true
|
||||||
|
},
|
||||||
|
"extends": "eslint:recommended"
|
||||||
|
}
|
68
.jshintrc
68
.jshintrc
|
@ -1,68 +0,0 @@
|
||||||
{
|
|
||||||
"bitwise" : true,
|
|
||||||
"camelcase" : true,
|
|
||||||
"curly" : true,
|
|
||||||
"eqeqeq" : false,
|
|
||||||
"es3" : true,
|
|
||||||
"forin" : false,
|
|
||||||
"immed" : true,
|
|
||||||
"indent" : 4,
|
|
||||||
"latedef" : false,
|
|
||||||
"newcap" : true,
|
|
||||||
"noarg" : true,
|
|
||||||
"noempty" : true,
|
|
||||||
"nonbsp" : true,
|
|
||||||
"nonew" : true,
|
|
||||||
"plusplus" : false,
|
|
||||||
"quotmark" : "double",
|
|
||||||
"undef" : true,
|
|
||||||
"unused" : "vars",
|
|
||||||
"strict" : false,
|
|
||||||
"trailing" : true,
|
|
||||||
"maxparams" : 7,
|
|
||||||
"maxdepth" : 6,
|
|
||||||
|
|
||||||
"asi" : false,
|
|
||||||
"boss" : false,
|
|
||||||
"debug" : false,
|
|
||||||
"eqnull" : true,
|
|
||||||
"esnext" : false,
|
|
||||||
"evil" : false,
|
|
||||||
"expr" : true,
|
|
||||||
"funcscope" : false,
|
|
||||||
"globalstrict" : false,
|
|
||||||
"iterator" : false,
|
|
||||||
"lastsemic" : false,
|
|
||||||
"laxbreak" : true,
|
|
||||||
"laxcomma" : false,
|
|
||||||
"loopfunc" : false,
|
|
||||||
"maxerr" : 50,
|
|
||||||
"multistr" : false,
|
|
||||||
"notypeof" : false,
|
|
||||||
"proto" : true,
|
|
||||||
"scripturl" : false,
|
|
||||||
"smarttabs" : false,
|
|
||||||
"shadow" : false,
|
|
||||||
"sub" : false,
|
|
||||||
"supernew" : false,
|
|
||||||
"validthis" : false,
|
|
||||||
"noyield" : false,
|
|
||||||
|
|
||||||
"browser" : true,
|
|
||||||
"couch" : false,
|
|
||||||
"devel" : false,
|
|
||||||
"dojo" : false,
|
|
||||||
"jquery" : false,
|
|
||||||
"mootools" : false,
|
|
||||||
"node" : true,
|
|
||||||
"nonstandard" : false,
|
|
||||||
"prototypejs" : false,
|
|
||||||
"rhino" : false,
|
|
||||||
"worker" : false,
|
|
||||||
"wsh" : false,
|
|
||||||
"yui" : false,
|
|
||||||
"globals": {
|
|
||||||
"JSON": false,
|
|
||||||
"console": true
|
|
||||||
}
|
|
||||||
}
|
|
2
Makefile
2
Makefile
|
@ -17,7 +17,7 @@ setup:
|
||||||
npm install
|
npm install
|
||||||
|
|
||||||
lint: katex.js server.js cli.js $(wildcard src/*.js) $(wildcard test/*.js) $(wildcard contrib/*/*.js) $(wildcard dockers/*/*.js)
|
lint: katex.js server.js cli.js $(wildcard src/*.js) $(wildcard test/*.js) $(wildcard contrib/*/*.js) $(wildcard dockers/*/*.js)
|
||||||
./node_modules/.bin/jshint $^
|
./node_modules/.bin/eslint --fix $^
|
||||||
|
|
||||||
build/katex.js: katex.js $(wildcard src/*.js)
|
build/katex.js: katex.js $(wildcard src/*.js)
|
||||||
$(BROWSERIFY) $< --standalone katex > $@
|
$(BROWSERIFY) $< --standalone katex > $@
|
||||||
|
|
5
cli.js
5
cli.js
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
// Simple CLI for KaTeX.
|
// Simple CLI for KaTeX.
|
||||||
// Reads TeX from stdin, outputs HTML to stdout.
|
// Reads TeX from stdin, outputs HTML to stdout.
|
||||||
|
/* eslint no-console:0 */
|
||||||
|
|
||||||
var katex = require("./");
|
var katex = require("./");
|
||||||
var input = "";
|
var input = "";
|
||||||
|
@ -8,7 +9,7 @@ var input = "";
|
||||||
// Skip the first two args, which are just "node" and "cli.js"
|
// Skip the first two args, which are just "node" and "cli.js"
|
||||||
var args = process.argv.slice(2);
|
var args = process.argv.slice(2);
|
||||||
|
|
||||||
if (args.indexOf("--help") != -1) {
|
if (args.indexOf("--help") !== -1) {
|
||||||
console.log(process.argv[0] + " " + process.argv[1] +
|
console.log(process.argv[0] + " " + process.argv[1] +
|
||||||
" [ --help ]" +
|
" [ --help ]" +
|
||||||
" [ --display-mode ]");
|
" [ --display-mode ]");
|
||||||
|
@ -25,7 +26,7 @@ process.stdin.on("data", function(chunk) {
|
||||||
});
|
});
|
||||||
|
|
||||||
process.stdin.on("end", function() {
|
process.stdin.on("end", function() {
|
||||||
var options = { displayMode: args.indexOf("--display-mode") != -1 };
|
var options = { displayMode: args.indexOf("--display-mode") !== -1 };
|
||||||
var output = katex.renderToString(input, options);
|
var output = katex.renderToString(input, options);
|
||||||
console.log(output);
|
console.log(output);
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,12 +13,13 @@ beforeEach(function() {
|
||||||
compare: function(actual, left, right, result) {
|
compare: function(actual, left, right, result) {
|
||||||
var message = {
|
var message = {
|
||||||
pass: true,
|
pass: true,
|
||||||
message: "'" + actual + "' split correctly"
|
message: "'" + actual + "' split correctly",
|
||||||
};
|
};
|
||||||
|
|
||||||
var startData = [{type: "text", data: actual}];
|
var startData = [{type: "text", data: actual}];
|
||||||
|
|
||||||
var split = splitAtDelimiters(startData, left, right, false);
|
var split =
|
||||||
|
splitAtDelimiters(startData, left, right, false);
|
||||||
|
|
||||||
if (split.length !== result.length) {
|
if (split.length !== result.length) {
|
||||||
message.pass = false;
|
message.pass = false;
|
||||||
|
@ -58,9 +59,9 @@ beforeEach(function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return message;
|
return message;
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -69,12 +70,12 @@ describe("A delimiter splitter", function() {
|
||||||
expect("hello").toSplitInto("(", ")", [{type: "text", data: "hello"}]);
|
expect("hello").toSplitInto("(", ")", [{type: "text", data: "hello"}]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("doesn't create a math node when there's only a left delimiter", function() {
|
it("doesn't create a math node with only one left delimiter", function() {
|
||||||
expect("hello ( world").toSplitInto(
|
expect("hello ( world").toSplitInto(
|
||||||
"(", ")",
|
"(", ")",
|
||||||
[
|
[
|
||||||
{type: "text", data: "hello "},
|
{type: "text", data: "hello "},
|
||||||
{type: "text", data: "( world"}
|
{type: "text", data: "( world"},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -82,7 +83,7 @@ describe("A delimiter splitter", function() {
|
||||||
expect("hello ) world").toSplitInto(
|
expect("hello ) world").toSplitInto(
|
||||||
"(", ")",
|
"(", ")",
|
||||||
[
|
[
|
||||||
{type: "text", data: "hello ) world"}
|
{type: "text", data: "hello ) world"},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -93,7 +94,7 @@ describe("A delimiter splitter", function() {
|
||||||
{type: "text", data: "hello "},
|
{type: "text", data: "hello "},
|
||||||
{type: "math", data: " world ",
|
{type: "math", data: " world ",
|
||||||
rawData: "( world )", display: false},
|
rawData: "( world )", display: false},
|
||||||
{type: "text", data: " boo"}
|
{type: "text", data: " boo"},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -104,7 +105,7 @@ describe("A delimiter splitter", function() {
|
||||||
{type: "text", data: "hello "},
|
{type: "text", data: "hello "},
|
||||||
{type: "math", data: " world ",
|
{type: "math", data: " world ",
|
||||||
rawData: "[[ world ]]", display: false},
|
rawData: "[[ world ]]", display: false},
|
||||||
{type: "text", data: " boo"}
|
{type: "text", data: " boo"},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -118,7 +119,7 @@ describe("A delimiter splitter", function() {
|
||||||
{type: "text", data: " boo "},
|
{type: "text", data: " boo "},
|
||||||
{type: "math", data: " more ",
|
{type: "math", data: " more ",
|
||||||
rawData: "( more )", display: false},
|
rawData: "( more )", display: false},
|
||||||
{type: "text", data: " stuff"}
|
{type: "text", data: " stuff"},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -130,7 +131,7 @@ describe("A delimiter splitter", function() {
|
||||||
{type: "math", data: " world ",
|
{type: "math", data: " world ",
|
||||||
rawData: "( world )", display: false},
|
rawData: "( world )", display: false},
|
||||||
{type: "text", data: " boo "},
|
{type: "text", data: " boo "},
|
||||||
{type: "text", data: "( left"}
|
{type: "text", data: "( left"},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -141,7 +142,7 @@ describe("A delimiter splitter", function() {
|
||||||
{type: "text", data: "hello "},
|
{type: "text", data: "hello "},
|
||||||
{type: "math", data: " world { ) } ",
|
{type: "math", data: " world { ) } ",
|
||||||
rawData: "( world { ) } )", display: false},
|
rawData: "( world { ) } )", display: false},
|
||||||
{type: "text", data: " boo"}
|
{type: "text", data: " boo"},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect("hello ( world { { } ) } ) boo").toSplitInto(
|
expect("hello ( world { { } ) } ) boo").toSplitInto(
|
||||||
|
@ -150,7 +151,7 @@ describe("A delimiter splitter", function() {
|
||||||
{type: "text", data: "hello "},
|
{type: "text", data: "hello "},
|
||||||
{type: "math", data: " world { { } ) } ",
|
{type: "math", data: " world { { } ) } ",
|
||||||
rawData: "( world { { } ) } )", display: false},
|
rawData: "( world { { } ) } )", display: false},
|
||||||
{type: "text", data: " boo"}
|
{type: "text", data: " boo"},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -161,7 +162,7 @@ describe("A delimiter splitter", function() {
|
||||||
{type: "text", data: "hello "},
|
{type: "text", data: "hello "},
|
||||||
{type: "math", data: " world \\) ",
|
{type: "math", data: " world \\) ",
|
||||||
rawData: "( world \\) )", display: false},
|
rawData: "( world \\) )", display: false},
|
||||||
{type: "text", data: " boo"}
|
{type: "text", data: " boo"},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/* TODO(emily): make this work maybe?
|
/* TODO(emily): make this work maybe?
|
||||||
|
@ -171,7 +172,7 @@ describe("A delimiter splitter", function() {
|
||||||
{type: "text", data: "hello \\( "},
|
{type: "text", data: "hello \\( "},
|
||||||
{type: "math", data: " world ",
|
{type: "math", data: " world ",
|
||||||
rawData: "( world )", display: false},
|
rawData: "( world )", display: false},
|
||||||
{type: "text", data: " boo"}
|
{type: "text", data: " boo"},
|
||||||
]);
|
]);
|
||||||
*/
|
*/
|
||||||
});
|
});
|
||||||
|
@ -183,7 +184,7 @@ describe("A delimiter splitter", function() {
|
||||||
{type: "text", data: "hello "},
|
{type: "text", data: "hello "},
|
||||||
{type: "math", data: " world ",
|
{type: "math", data: " world ",
|
||||||
rawData: "$ world $", display: false},
|
rawData: "$ world $", display: false},
|
||||||
{type: "text", data: " boo"}
|
{type: "text", data: " boo"},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -195,7 +196,7 @@ describe("A delimiter splitter", function() {
|
||||||
{type: "text", data: "hello "},
|
{type: "text", data: "hello "},
|
||||||
{type: "math", data: " world ",
|
{type: "math", data: " world ",
|
||||||
rawData: "( world )", display: true},
|
rawData: "( world )", display: true},
|
||||||
{type: "text", data: " boo"}
|
{type: "text", data: " boo"},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -203,7 +204,7 @@ describe("A delimiter splitter", function() {
|
||||||
var startData = [
|
var startData = [
|
||||||
{type: "text", data: "hello ( world ) boo"},
|
{type: "text", data: "hello ( world ) boo"},
|
||||||
{type: "math", data: "math", rawData: "(math)", display: true},
|
{type: "math", data: "math", rawData: "(math)", display: true},
|
||||||
{type: "text", data: "hello ( world ) boo"}
|
{type: "text", data: "hello ( world ) boo"},
|
||||||
];
|
];
|
||||||
|
|
||||||
expect(splitAtDelimiters(startData, "(", ")", false)).toEqual(
|
expect(splitAtDelimiters(startData, "(", ")", false)).toEqual(
|
||||||
|
@ -216,7 +217,7 @@ describe("A delimiter splitter", function() {
|
||||||
{type: "text", data: "hello "},
|
{type: "text", data: "hello "},
|
||||||
{type: "math", data: " world ",
|
{type: "math", data: " world ",
|
||||||
rawData: "( world )", display: false},
|
rawData: "( world )", display: false},
|
||||||
{type: "text", data: " boo"}
|
{type: "text", data: " boo"},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -224,7 +225,7 @@ describe("A delimiter splitter", function() {
|
||||||
var startData = [
|
var startData = [
|
||||||
{type: "text", data: "hello ( world ) boo"},
|
{type: "text", data: "hello ( world ) boo"},
|
||||||
{type: "math", data: "hello ( world ) boo",
|
{type: "math", data: "hello ( world ) boo",
|
||||||
rawData: "(hello ( world ) boo)", display: true}
|
rawData: "(hello ( world ) boo)", display: true},
|
||||||
];
|
];
|
||||||
|
|
||||||
expect(splitAtDelimiters(startData, "(", ")", false)).toEqual(
|
expect(splitAtDelimiters(startData, "(", ")", false)).toEqual(
|
||||||
|
@ -234,7 +235,7 @@ describe("A delimiter splitter", function() {
|
||||||
rawData: "( world )", display: false},
|
rawData: "( world )", display: false},
|
||||||
{type: "text", data: " boo"},
|
{type: "text", data: " boo"},
|
||||||
{type: "math", data: "hello ( world ) boo",
|
{type: "math", data: "hello ( world ) boo",
|
||||||
rawData: "(hello ( world ) boo)", display: true}
|
rawData: "(hello ( world ) boo)", display: true},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* eslint no-console:0 */
|
||||||
/* global katex */
|
/* global katex */
|
||||||
|
|
||||||
var splitAtDelimiters = require("./splitAtDelimiters");
|
var splitAtDelimiters = require("./splitAtDelimiters");
|
||||||
|
@ -26,7 +27,7 @@ var renderMathInText = function(text, delimiters) {
|
||||||
var math = data[i].data;
|
var math = data[i].data;
|
||||||
try {
|
try {
|
||||||
katex.render(math, span, {
|
katex.render(math, span, {
|
||||||
displayMode: data[i].display
|
displayMode: data[i].display,
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (!(e instanceof katex.ParseError)) {
|
if (!(e instanceof katex.ParseError)) {
|
||||||
|
@ -72,19 +73,20 @@ var defaultOptions = {
|
||||||
delimiters: [
|
delimiters: [
|
||||||
{left: "$$", right: "$$", display: true},
|
{left: "$$", right: "$$", display: true},
|
||||||
{left: "\\[", right: "\\]", display: true},
|
{left: "\\[", right: "\\]", display: true},
|
||||||
{left: "\\(", right: "\\)", display: false}
|
{left: "\\(", right: "\\)", display: false},
|
||||||
// LaTeX uses this, but it ruins the display of normal `$` in text:
|
// LaTeX uses this, but it ruins the display of normal `$` in text:
|
||||||
// {left: "$", right: "$", display: false}
|
// {left: "$", right: "$", display: false},
|
||||||
],
|
],
|
||||||
|
|
||||||
ignoredTags: [
|
ignoredTags: [
|
||||||
"script", "noscript", "style", "textarea", "pre", "code"
|
"script", "noscript", "style", "textarea", "pre", "code",
|
||||||
]
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
var extend = function(obj) {
|
var extend = function(obj) {
|
||||||
// Adapted from underscore.js' `_.extend`. See LICENSE.txt for license.
|
// Adapted from underscore.js' `_.extend`. See LICENSE.txt for license.
|
||||||
var source, prop;
|
var source;
|
||||||
|
var prop;
|
||||||
for (var i = 1, length = arguments.length; i < length; i++) {
|
for (var i = 1, length = arguments.length; i < length; i++) {
|
||||||
source = arguments[i];
|
source = arguments[i];
|
||||||
for (prop in source) {
|
for (prop in source) {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* eslint no-constant-condition:0 */
|
||||||
var findEndOfMath = function(delimiter, text, startIndex) {
|
var findEndOfMath = function(delimiter, text, startIndex) {
|
||||||
// Adapted from
|
// Adapted from
|
||||||
// https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx
|
// https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx
|
||||||
|
@ -42,7 +43,7 @@ var splitAtDelimiters = function(startData, leftDelim, rightDelim, display) {
|
||||||
currIndex = nextIndex;
|
currIndex = nextIndex;
|
||||||
finalData.push({
|
finalData.push({
|
||||||
type: "text",
|
type: "text",
|
||||||
data: text.slice(0, currIndex)
|
data: text.slice(0, currIndex),
|
||||||
});
|
});
|
||||||
lookingForLeft = false;
|
lookingForLeft = false;
|
||||||
}
|
}
|
||||||
|
@ -56,7 +57,7 @@ var splitAtDelimiters = function(startData, leftDelim, rightDelim, display) {
|
||||||
|
|
||||||
finalData.push({
|
finalData.push({
|
||||||
type: "text",
|
type: "text",
|
||||||
data: text.slice(currIndex, nextIndex)
|
data: text.slice(currIndex, nextIndex),
|
||||||
});
|
});
|
||||||
|
|
||||||
currIndex = nextIndex;
|
currIndex = nextIndex;
|
||||||
|
@ -77,7 +78,7 @@ var splitAtDelimiters = function(startData, leftDelim, rightDelim, display) {
|
||||||
rawData: text.slice(
|
rawData: text.slice(
|
||||||
currIndex,
|
currIndex,
|
||||||
nextIndex + rightDelim.length),
|
nextIndex + rightDelim.length),
|
||||||
display: display
|
display: display,
|
||||||
});
|
});
|
||||||
|
|
||||||
currIndex = nextIndex + rightDelim.length;
|
currIndex = nextIndex + rightDelim.length;
|
||||||
|
@ -88,7 +89,7 @@ var splitAtDelimiters = function(startData, leftDelim, rightDelim, display) {
|
||||||
|
|
||||||
finalData.push({
|
finalData.push({
|
||||||
type: "text",
|
type: "text",
|
||||||
data: text.slice(currIndex)
|
data: text.slice(currIndex),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
finalData.push(startData[i]);
|
finalData.push(startData[i]);
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* eslint no-console:0, prefer-spread:0 */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var childProcess = require("child_process");
|
var childProcess = require("child_process");
|
||||||
|
@ -23,50 +24,50 @@ var opts = require("nomnom")
|
||||||
.option("browser", {
|
.option("browser", {
|
||||||
abbr: "b",
|
abbr: "b",
|
||||||
"default": "firefox",
|
"default": "firefox",
|
||||||
help: "Name of the browser to use"
|
help: "Name of the browser to use",
|
||||||
})
|
})
|
||||||
.option("container", {
|
.option("container", {
|
||||||
abbr: "c",
|
abbr: "c",
|
||||||
type: "string",
|
type: "string",
|
||||||
help: "Name or ID of a running docker container to contact"
|
help: "Name or ID of a running docker container to contact",
|
||||||
})
|
})
|
||||||
.option("seleniumURL", {
|
.option("seleniumURL", {
|
||||||
full: "selenium-url",
|
full: "selenium-url",
|
||||||
help: "Full URL of the Selenium web driver"
|
help: "Full URL of the Selenium web driver",
|
||||||
})
|
})
|
||||||
.option("seleniumIP", {
|
.option("seleniumIP", {
|
||||||
full: "selenium-ip",
|
full: "selenium-ip",
|
||||||
help: "IP address of the Selenium web driver"
|
help: "IP address of the Selenium web driver",
|
||||||
})
|
})
|
||||||
.option("seleniumPort", {
|
.option("seleniumPort", {
|
||||||
full: "selenium-port",
|
full: "selenium-port",
|
||||||
"default": 4444,
|
"default": 4444,
|
||||||
help: "Port number of the Selenium web driver"
|
help: "Port number of the Selenium web driver",
|
||||||
})
|
})
|
||||||
.option("katexURL", {
|
.option("katexURL", {
|
||||||
full: "katex-url",
|
full: "katex-url",
|
||||||
help: "Full URL of the KaTeX development server"
|
help: "Full URL of the KaTeX development server",
|
||||||
})
|
})
|
||||||
.option("katexIP", {
|
.option("katexIP", {
|
||||||
full: "katex-ip",
|
full: "katex-ip",
|
||||||
"default": "localhost",
|
"default": "localhost",
|
||||||
help: "Full URL of the KaTeX development server"
|
help: "Full URL of the KaTeX development server",
|
||||||
})
|
})
|
||||||
.option("katexPort", {
|
.option("katexPort", {
|
||||||
full: "katex-port",
|
full: "katex-port",
|
||||||
help: "Port number of the KaTeX development server"
|
help: "Port number of the KaTeX development server",
|
||||||
})
|
})
|
||||||
.option("include", {
|
.option("include", {
|
||||||
abbr: "i",
|
abbr: "i",
|
||||||
help: "Comma-separated list of test cases to process"
|
help: "Comma-separated list of test cases to process",
|
||||||
})
|
})
|
||||||
.option("exclude", {
|
.option("exclude", {
|
||||||
abbr: "x",
|
abbr: "x",
|
||||||
help: "Comma-separated list of test cases to exclude"
|
help: "Comma-separated list of test cases to exclude",
|
||||||
})
|
})
|
||||||
.option("verify", {
|
.option("verify", {
|
||||||
flag: true,
|
flag: true,
|
||||||
help: "Check whether screenshot matches current file content"
|
help: "Check whether screenshot matches current file content",
|
||||||
})
|
})
|
||||||
.parse();
|
.parse();
|
||||||
|
|
||||||
|
@ -121,7 +122,7 @@ if (!seleniumURL && opts.container) {
|
||||||
process.exit(2);
|
process.exit(2);
|
||||||
}
|
}
|
||||||
katexIP = config[1];
|
katexIP = config[1];
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
seleniumIP = katexIP = dockerCmd(
|
seleniumIP = katexIP = dockerCmd(
|
||||||
"inspect", "-f", "{{.NetworkSettings.Gateway}}", opts.container);
|
"inspect", "-f", "{{.NetworkSettings.Gateway}}", opts.container);
|
||||||
}
|
}
|
||||||
|
@ -185,7 +186,7 @@ function tryConnect() {
|
||||||
}
|
}
|
||||||
var sock = net.connect({
|
var sock = net.connect({
|
||||||
host: seleniumIP,
|
host: seleniumIP,
|
||||||
port: +seleniumPort
|
port: +seleniumPort,
|
||||||
});
|
});
|
||||||
sock.on("connect", function() {
|
sock.on("connect", function() {
|
||||||
sock.end();
|
sock.end();
|
||||||
|
@ -223,7 +224,8 @@ function buildDriver() {
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// Set the screen size
|
// Set the screen size
|
||||||
|
|
||||||
var targetW = 1024, targetH = 768;
|
var targetW = 1024;
|
||||||
|
var targetH = 768;
|
||||||
function setSize(reqW, reqH) {
|
function setSize(reqW, reqH) {
|
||||||
return driver.manage().window().setSize(reqW, reqH).then(function() {
|
return driver.manage().window().setSize(reqW, reqH).then(function() {
|
||||||
return driver.takeScreenshot();
|
return driver.takeScreenshot();
|
||||||
|
@ -247,7 +249,7 @@ function imageDimensions(img) {
|
||||||
return {
|
return {
|
||||||
buf: buf,
|
buf: buf,
|
||||||
width: buf.readUInt32BE(16),
|
width: buf.readUInt32BE(16),
|
||||||
height: buf.readUInt32BE(20)
|
height: buf.readUInt32BE(20),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,7 +312,7 @@ function takeScreenshot(key) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var opt = new jspngopt.Optimizer({
|
var opt = new jspngopt.Optimizer({
|
||||||
pako: pako
|
pako: pako,
|
||||||
});
|
});
|
||||||
var buf = opt.bufferSync(img.buf);
|
var buf = opt.bufferSync(img.buf);
|
||||||
if (loadExpected) {
|
if (loadExpected) {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* eslint no-console:0 */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var childProcess = require("child_process");
|
var childProcess = require("child_process");
|
||||||
|
@ -47,7 +48,7 @@ Q.all([
|
||||||
readFile(path.join(ssDir, "test.tex"), "utf-8"),
|
readFile(path.join(ssDir, "test.tex"), "utf-8"),
|
||||||
ensureDir(tmpDir),
|
ensureDir(tmpDir),
|
||||||
ensureDir(teximgDir),
|
ensureDir(teximgDir),
|
||||||
ensureDir(diffDir)
|
ensureDir(diffDir),
|
||||||
]).spread(function(data) {
|
]).spread(function(data) {
|
||||||
template = data;
|
template = data;
|
||||||
// dirs have been created, template has been read, now rasterize.
|
// dirs have been created, template has been read, now rasterize.
|
||||||
|
@ -78,14 +79,14 @@ function processTestCase(key) {
|
||||||
var fftLatex = writeFile(texFile, tex).then(function() {
|
var fftLatex = writeFile(texFile, tex).then(function() {
|
||||||
// Step 2: call "pdflatex key" to create key.pdf
|
// Step 2: call "pdflatex key" to create key.pdf
|
||||||
return execFile("pdflatex", [
|
return execFile("pdflatex", [
|
||||||
"-interaction", "nonstopmode", key
|
"-interaction", "nonstopmode", key,
|
||||||
], {cwd: tmpDir});
|
], {cwd: tmpDir});
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
console.log("Typeset " + key);
|
console.log("Typeset " + key);
|
||||||
// Step 3: call "convert ... key.pdf key.png" to create key.png
|
// Step 3: call "convert ... key.pdf key.png" to create key.png
|
||||||
return execFile("convert", [
|
return execFile("convert", [
|
||||||
"-density", dpi, "-units", "PixelsPerInch", "-flatten",
|
"-density", dpi, "-units", "PixelsPerInch", "-flatten",
|
||||||
pdfFile, pngFile
|
pdfFile, pngFile,
|
||||||
]);
|
]);
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
console.log("Rasterized " + key);
|
console.log("Rasterized " + key);
|
||||||
|
@ -99,7 +100,8 @@ function processTestCase(key) {
|
||||||
// Now we have the FFT result from both
|
// Now we have the FFT result from both
|
||||||
// Step 6: find alignment which maximizes overlap.
|
// Step 6: find alignment which maximizes overlap.
|
||||||
// This uses a FFT-based correlation computation.
|
// This uses a FFT-based correlation computation.
|
||||||
var x, y;
|
var x;
|
||||||
|
var y;
|
||||||
var real = createMatrix();
|
var real = createMatrix();
|
||||||
var imag = createMatrix();
|
var imag = createMatrix();
|
||||||
|
|
||||||
|
@ -164,8 +166,8 @@ function processTestCase(key) {
|
||||||
"(", "-clone", "0-1", "-compose", "darken", "-composite", ")",
|
"(", "-clone", "0-1", "-compose", "darken", "-composite", ")",
|
||||||
// First image is red, second green, third blue channel of result
|
// First image is red, second green, third blue channel of result
|
||||||
"-channel", "RGB", "-combine",
|
"-channel", "RGB", "-combine",
|
||||||
"-trim", // remove everything that has the same color as the corners
|
"-trim", // remove everything with the same color as the corners
|
||||||
diffFile // output file name
|
diffFile, // output file name
|
||||||
]);
|
]);
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
console.log("Compared " + key);
|
console.log("Compared " + key);
|
||||||
|
@ -241,7 +243,7 @@ function fftImage(image) {
|
||||||
real: real,
|
real: real,
|
||||||
imag: imag,
|
imag: imag,
|
||||||
width: image.width,
|
width: image.width,
|
||||||
height: image.height
|
height: image.height,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
3
katex.js
3
katex.js
|
@ -1,3 +1,4 @@
|
||||||
|
/* eslint no-console:0 */
|
||||||
/**
|
/**
|
||||||
* This is the main entry point for KaTeX. Here, we expose functions for
|
* This is the main entry point for KaTeX. Here, we expose functions for
|
||||||
* rendering expressions either to DOM nodes or to markup strings.
|
* rendering expressions either to DOM nodes or to markup strings.
|
||||||
|
@ -69,5 +70,5 @@ module.exports = {
|
||||||
* to change. Use at your own risk.
|
* to change. Use at your own risk.
|
||||||
*/
|
*/
|
||||||
__parse: generateParseTree,
|
__parse: generateParseTree,
|
||||||
ParseError: ParseError
|
ParseError: ParseError,
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,10 +10,10 @@ if len(sys.argv) > 1:
|
||||||
props.append('width')
|
props.append('width')
|
||||||
|
|
||||||
data = json.load(sys.stdin)
|
data = json.load(sys.stdin)
|
||||||
sep = "module.exports = {\n"
|
sep = "module.exports = {\n "
|
||||||
for font in sorted(data):
|
for font in sorted(data):
|
||||||
sys.stdout.write(sep + json.dumps(font))
|
sys.stdout.write(sep + json.dumps(font))
|
||||||
sep = ": {\n "
|
sep = ": {\n "
|
||||||
for glyph in sorted(data[font], key=int):
|
for glyph in sorted(data[font], key=int):
|
||||||
sys.stdout.write(sep + json.dumps(glyph) + ": ")
|
sys.stdout.write(sep + json.dumps(glyph) + ": ")
|
||||||
|
|
||||||
|
@ -21,6 +21,6 @@ for font in sorted(data):
|
||||||
[data[font][glyph][key] for key in props]]
|
[data[font][glyph][key] for key in props]]
|
||||||
|
|
||||||
sys.stdout.write(json.dumps(values))
|
sys.stdout.write(json.dumps(values))
|
||||||
sep = ",\n "
|
sep = ",\n "
|
||||||
sep = "\n},\n"
|
sep = ",\n },\n "
|
||||||
sys.stdout.write("\n}};\n")
|
sys.stdout.write(",\n },\n};\n")
|
||||||
|
|
|
@ -16,12 +16,12 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"browserify": "^10.2.4",
|
"browserify": "^10.2.4",
|
||||||
"clean-css": "~2.2.15",
|
"clean-css": "~2.2.15",
|
||||||
|
"eslint": "^1.10.2",
|
||||||
"express": "~3.3.3",
|
"express": "~3.3.3",
|
||||||
"glob": "^5.0.15",
|
"glob": "^5.0.15",
|
||||||
"jasmine": "^2.3.2",
|
"jasmine": "^2.3.2",
|
||||||
"jasmine-core": "^2.3.4",
|
"jasmine-core": "^2.3.4",
|
||||||
"js-yaml": "^3.3.1",
|
"js-yaml": "^3.3.1",
|
||||||
"jshint": "^2.5.6",
|
|
||||||
"jspngopt": "^0.1.0",
|
"jspngopt": "^0.1.0",
|
||||||
"less": "~1.7.5",
|
"less": "~1.7.5",
|
||||||
"nomnom": "^1.8.1",
|
"nomnom": "^1.8.1",
|
||||||
|
|
11
server.js
11
server.js
|
@ -1,3 +1,4 @@
|
||||||
|
/* eslint no-console:0 */
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
|
|
||||||
|
@ -41,7 +42,13 @@ var serveBrowserified = function(file, standaloneName) {
|
||||||
};
|
};
|
||||||
|
|
||||||
app.get("/katex.js", serveBrowserified("./katex", "katex"));
|
app.get("/katex.js", serveBrowserified("./katex", "katex"));
|
||||||
app.use("/test/jasmine", express["static"](path.dirname(require.resolve("jasmine-core/lib/jasmine-core/jasmine.js"))));
|
app.use("/test/jasmine",
|
||||||
|
express["static"](
|
||||||
|
path.dirname(
|
||||||
|
require.resolve("jasmine-core/lib/jasmine-core/jasmine.js")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
app.get("/test/katex-spec.js", serveBrowserified("./test/*[Ss]pec.js"));
|
app.get("/test/katex-spec.js", serveBrowserified("./test/*[Ss]pec.js"));
|
||||||
app.get("/contrib/auto-render/auto-render.js",
|
app.get("/contrib/auto-render/auto-render.js",
|
||||||
serveBrowserified("./contrib/auto-render/auto-render",
|
serveBrowserified("./contrib/auto-render/auto-render",
|
||||||
|
@ -56,7 +63,7 @@ app.get("/katex.css", function(req, res, next) {
|
||||||
|
|
||||||
var parser = new less.Parser({
|
var parser = new less.Parser({
|
||||||
paths: ["./static"],
|
paths: ["./static"],
|
||||||
filename: "katex.less"
|
filename: "katex.less",
|
||||||
});
|
});
|
||||||
|
|
||||||
parser.parse(data, function(err, tree) {
|
parser.parse(data, function(err, tree) {
|
||||||
|
|
|
@ -60,7 +60,7 @@ var whitespaceRegex = /\s*/;
|
||||||
*/
|
*/
|
||||||
Lexer.prototype._innerLex = function(pos, ignoreWhitespace) {
|
Lexer.prototype._innerLex = function(pos, ignoreWhitespace) {
|
||||||
var input = this._input;
|
var input = this._input;
|
||||||
if (pos == input.length) {
|
if (pos === input.length) {
|
||||||
return new Token("EOF", null, pos);
|
return new Token("EOF", null, pos);
|
||||||
}
|
}
|
||||||
var match = matchAt(tokenRegex, input, pos);
|
var match = matchAt(tokenRegex, input, pos);
|
||||||
|
@ -121,9 +121,9 @@ Lexer.prototype._innerLexSize = function(pos) {
|
||||||
throw new ParseError("Invalid unit: '" + unit + "'", this, pos);
|
throw new ParseError("Invalid unit: '" + unit + "'", this, pos);
|
||||||
}
|
}
|
||||||
return new Token(match[0], {
|
return new Token(match[0], {
|
||||||
number: +(match[1] + match[2]),
|
number: +(match[1] + match[2]),
|
||||||
unit: unit
|
unit: unit,
|
||||||
}, pos + match[0].length);
|
}, pos + match[0].length);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ParseError("Invalid size", this, pos);
|
throw new ParseError("Invalid size", this, pos);
|
||||||
|
|
|
@ -46,7 +46,7 @@ Options.prototype.extend = function(extension) {
|
||||||
parentStyle: this.style,
|
parentStyle: this.style,
|
||||||
parentSize: this.size,
|
parentSize: this.size,
|
||||||
phantom: this.phantom,
|
phantom: this.phantom,
|
||||||
font: this.font
|
font: this.font,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (var key in extension) {
|
for (var key in extension) {
|
||||||
|
@ -63,7 +63,7 @@ Options.prototype.extend = function(extension) {
|
||||||
*/
|
*/
|
||||||
Options.prototype.withStyle = function(style) {
|
Options.prototype.withStyle = function(style) {
|
||||||
return this.extend({
|
return this.extend({
|
||||||
style: style
|
style: style,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ Options.prototype.withStyle = function(style) {
|
||||||
*/
|
*/
|
||||||
Options.prototype.withSize = function(size) {
|
Options.prototype.withSize = function(size) {
|
||||||
return this.extend({
|
return this.extend({
|
||||||
size: size
|
size: size,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ Options.prototype.withSize = function(size) {
|
||||||
*/
|
*/
|
||||||
Options.prototype.withColor = function(color) {
|
Options.prototype.withColor = function(color) {
|
||||||
return this.extend({
|
return this.extend({
|
||||||
color: color
|
color: color,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ Options.prototype.withColor = function(color) {
|
||||||
*/
|
*/
|
||||||
Options.prototype.withPhantom = function() {
|
Options.prototype.withPhantom = function() {
|
||||||
return this.extend({
|
return this.extend({
|
||||||
phantom: true
|
phantom: true,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ Options.prototype.withPhantom = function() {
|
||||||
*/
|
*/
|
||||||
Options.prototype.withFont = function(font) {
|
Options.prototype.withFont = function(font) {
|
||||||
return this.extend({
|
return this.extend({
|
||||||
font: font
|
font: font,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ var colorMap = {
|
||||||
"katex-grayH": "#555555",
|
"katex-grayH": "#555555",
|
||||||
"katex-grayI": "#333333",
|
"katex-grayI": "#333333",
|
||||||
"katex-kaBlue": "#314453",
|
"katex-kaBlue": "#314453",
|
||||||
"katex-kaGreen": "#639b24"
|
"katex-kaGreen": "#639b24",
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* eslint no-constant-condition:0 */
|
||||||
var functions = require("./functions");
|
var functions = require("./functions");
|
||||||
var environments = require("./environments");
|
var environments = require("./environments");
|
||||||
var Lexer = require("./Lexer");
|
var Lexer = require("./Lexer");
|
||||||
|
@ -175,9 +176,8 @@ Parser.prototype.parseExpression = function(breakOnInfix, breakOnToken) {
|
||||||
*
|
*
|
||||||
* @returns {Array}
|
* @returns {Array}
|
||||||
*/
|
*/
|
||||||
Parser.prototype.handleInfixNodes = function (body) {
|
Parser.prototype.handleInfixNodes = function(body) {
|
||||||
var overIndex = -1;
|
var overIndex = -1;
|
||||||
var func;
|
|
||||||
var funcName;
|
var funcName;
|
||||||
|
|
||||||
for (var i = 0; i < body.length; i++) {
|
for (var i = 0; i < body.length; i++) {
|
||||||
|
@ -189,12 +189,12 @@ Parser.prototype.handleInfixNodes = function (body) {
|
||||||
}
|
}
|
||||||
overIndex = i;
|
overIndex = i;
|
||||||
funcName = node.value.replaceWith;
|
funcName = node.value.replaceWith;
|
||||||
func = functions[funcName];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (overIndex !== -1) {
|
if (overIndex !== -1) {
|
||||||
var numerNode, denomNode;
|
var numerNode;
|
||||||
|
var denomNode;
|
||||||
|
|
||||||
var numerBody = body.slice(0, overIndex);
|
var numerBody = body.slice(0, overIndex);
|
||||||
var denomBody = body.slice(overIndex + 1);
|
var denomBody = body.slice(overIndex + 1);
|
||||||
|
@ -236,7 +236,10 @@ Parser.prototype.handleSupSubscript = function(name) {
|
||||||
return this.handleUnsupportedCmd();
|
return this.handleUnsupportedCmd();
|
||||||
} else {
|
} else {
|
||||||
throw new ParseError(
|
throw new ParseError(
|
||||||
"Expected group after '" + symbol + "'", this.lexer, symPos + 1);
|
"Expected group after '" + symbol + "'",
|
||||||
|
this.lexer,
|
||||||
|
symPos + 1
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else if (group.isFunction) {
|
} else if (group.isFunction) {
|
||||||
// ^ and _ have a greediness, so handle interactions with functions'
|
// ^ and _ have a greediness, so handle interactions with functions'
|
||||||
|
@ -259,34 +262,34 @@ Parser.prototype.handleSupSubscript = function(name) {
|
||||||
* Converts the textual input of an unsupported command into a text node
|
* Converts the textual input of an unsupported command into a text node
|
||||||
* contained within a color node whose color is determined by errorColor
|
* contained within a color node whose color is determined by errorColor
|
||||||
*/
|
*/
|
||||||
Parser.prototype.handleUnsupportedCmd = function() {
|
Parser.prototype.handleUnsupportedCmd = function() {
|
||||||
var text = this.nextToken.text;
|
var text = this.nextToken.text;
|
||||||
var textordArray = [];
|
var textordArray = [];
|
||||||
|
|
||||||
for (var i = 0; i < text.length; i++) {
|
for (var i = 0; i < text.length; i++) {
|
||||||
textordArray.push(new ParseNode("textord", text[i], "text"));
|
textordArray.push(new ParseNode("textord", text[i], "text"));
|
||||||
}
|
}
|
||||||
|
|
||||||
var textNode = new ParseNode(
|
var textNode = new ParseNode(
|
||||||
"text",
|
"text",
|
||||||
{
|
{
|
||||||
body: textordArray,
|
body: textordArray,
|
||||||
type: "text"
|
type: "text",
|
||||||
},
|
},
|
||||||
this.mode);
|
this.mode);
|
||||||
|
|
||||||
var colorNode = new ParseNode(
|
var colorNode = new ParseNode(
|
||||||
"color",
|
"color",
|
||||||
{
|
{
|
||||||
color: this.settings.errorColor,
|
color: this.settings.errorColor,
|
||||||
value: [textNode],
|
value: [textNode],
|
||||||
type: "color"
|
type: "color",
|
||||||
},
|
},
|
||||||
this.mode);
|
this.mode);
|
||||||
|
|
||||||
this.consume();
|
this.consume();
|
||||||
return colorNode;
|
return colorNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a group with optional super/subscripts.
|
* Parses a group with optional super/subscripts.
|
||||||
|
@ -314,10 +317,10 @@ Parser.prototype.parseAtom = function() {
|
||||||
if (lex.text === "\\limits" || lex.text === "\\nolimits") {
|
if (lex.text === "\\limits" || lex.text === "\\nolimits") {
|
||||||
// We got a limit control
|
// We got a limit control
|
||||||
if (!base || base.type !== "op") {
|
if (!base || base.type !== "op") {
|
||||||
throw new ParseError("Limit controls must follow a math operator",
|
throw new ParseError(
|
||||||
|
"Limit controls must follow a math operator",
|
||||||
this.lexer, this.pos);
|
this.lexer, this.pos);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
var limits = lex.text === "\\limits";
|
var limits = lex.text === "\\limits";
|
||||||
base.value.limits = limits;
|
base.value.limits = limits;
|
||||||
base.value.alwaysHandleSupSub = true;
|
base.value.alwaysHandleSupSub = true;
|
||||||
|
@ -363,7 +366,7 @@ Parser.prototype.parseAtom = function() {
|
||||||
return new ParseNode("supsub", {
|
return new ParseNode("supsub", {
|
||||||
base: base,
|
base: base,
|
||||||
sup: superscript,
|
sup: superscript,
|
||||||
sub: subscript
|
sub: subscript,
|
||||||
}, this.mode);
|
}, this.mode);
|
||||||
} else {
|
} else {
|
||||||
// Otherwise return the original body
|
// Otherwise return the original body
|
||||||
|
@ -374,12 +377,12 @@ Parser.prototype.parseAtom = function() {
|
||||||
// A list of the size-changing functions, for use in parseImplicitGroup
|
// A list of the size-changing functions, for use in parseImplicitGroup
|
||||||
var sizeFuncs = [
|
var sizeFuncs = [
|
||||||
"\\tiny", "\\scriptsize", "\\footnotesize", "\\small", "\\normalsize",
|
"\\tiny", "\\scriptsize", "\\footnotesize", "\\small", "\\normalsize",
|
||||||
"\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge"
|
"\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge",
|
||||||
];
|
];
|
||||||
|
|
||||||
// A list of the style-changing functions, for use in parseImplicitGroup
|
// A list of the style-changing functions, for use in parseImplicitGroup
|
||||||
var styleFuncs = [
|
var styleFuncs = [
|
||||||
"\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle"
|
"\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle",
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -416,7 +419,7 @@ Parser.prototype.parseImplicitGroup = function() {
|
||||||
return new ParseNode("leftright", {
|
return new ParseNode("leftright", {
|
||||||
body: body,
|
body: body,
|
||||||
left: left.value.value,
|
left: left.value.value,
|
||||||
right: right.value.value
|
right: right.value.value,
|
||||||
}, this.mode);
|
}, this.mode);
|
||||||
} else if (func === "\\begin") {
|
} else if (func === "\\begin") {
|
||||||
// begin...end is similar to left...right
|
// begin...end is similar to left...right
|
||||||
|
@ -436,7 +439,7 @@ Parser.prototype.parseImplicitGroup = function() {
|
||||||
envName: envName,
|
envName: envName,
|
||||||
parser: this,
|
parser: this,
|
||||||
lexer: this.lexer,
|
lexer: this.lexer,
|
||||||
positions: args.pop()
|
positions: args.pop(),
|
||||||
};
|
};
|
||||||
var result = env.handler(context, args);
|
var result = env.handler(context, args);
|
||||||
this.expect("\\end", false);
|
this.expect("\\end", false);
|
||||||
|
@ -457,7 +460,7 @@ Parser.prototype.parseImplicitGroup = function() {
|
||||||
return new ParseNode("sizing", {
|
return new ParseNode("sizing", {
|
||||||
// Figure out what size to use based on the list of functions above
|
// Figure out what size to use based on the list of functions above
|
||||||
size: "size" + (utils.indexOf(sizeFuncs, func) + 1),
|
size: "size" + (utils.indexOf(sizeFuncs, func) + 1),
|
||||||
value: body
|
value: body,
|
||||||
}, this.mode);
|
}, this.mode);
|
||||||
} else if (utils.contains(styleFuncs, func)) {
|
} else if (utils.contains(styleFuncs, func)) {
|
||||||
// If we see a styling function, parse out the implict body
|
// If we see a styling function, parse out the implict body
|
||||||
|
@ -466,7 +469,7 @@ Parser.prototype.parseImplicitGroup = function() {
|
||||||
// Figure out what style to use by pulling out the style from
|
// Figure out what style to use by pulling out the style from
|
||||||
// the function name
|
// the function name
|
||||||
style: func.slice(1, func.length - 5),
|
style: func.slice(1, func.length - 5),
|
||||||
value: body
|
value: body,
|
||||||
}, this.mode);
|
}, this.mode);
|
||||||
} else {
|
} else {
|
||||||
// Defer to parseFunction if it's not a function we handle
|
// Defer to parseFunction if it's not a function we handle
|
||||||
|
@ -516,7 +519,7 @@ Parser.prototype.callFunction = function(name, args, positions) {
|
||||||
funcName: name,
|
funcName: name,
|
||||||
parser: this,
|
parser: this,
|
||||||
lexer: this.lexer,
|
lexer: this.lexer,
|
||||||
positions: positions
|
positions: positions,
|
||||||
};
|
};
|
||||||
return functions[name].handler(context, args);
|
return functions[name].handler(context, args);
|
||||||
};
|
};
|
||||||
|
|
|
@ -86,7 +86,7 @@ var sizeNames = [
|
||||||
"displaystyle textstyle",
|
"displaystyle textstyle",
|
||||||
"textstyle",
|
"textstyle",
|
||||||
"scriptstyle",
|
"scriptstyle",
|
||||||
"scriptscriptstyle"
|
"scriptscriptstyle",
|
||||||
];
|
];
|
||||||
|
|
||||||
// Reset names for the different sizes
|
// Reset names for the different sizes
|
||||||
|
@ -94,7 +94,7 @@ var resetNames = [
|
||||||
"reset-textstyle",
|
"reset-textstyle",
|
||||||
"reset-textstyle",
|
"reset-textstyle",
|
||||||
"reset-scriptstyle",
|
"reset-scriptstyle",
|
||||||
"reset-scriptscriptstyle"
|
"reset-scriptscriptstyle",
|
||||||
];
|
];
|
||||||
|
|
||||||
// Instances of the different styles
|
// Instances of the different styles
|
||||||
|
@ -106,7 +106,7 @@ var styles = [
|
||||||
new Style(S, 2, 0.7, false),
|
new Style(S, 2, 0.7, false),
|
||||||
new Style(Sc, 2, 0.7, true),
|
new Style(Sc, 2, 0.7, true),
|
||||||
new Style(SS, 3, 0.5, false),
|
new Style(SS, 3, 0.5, false),
|
||||||
new Style(SSc, 3, 0.5, true)
|
new Style(SSc, 3, 0.5, true),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Lookup tables for switching from one style to another
|
// Lookup tables for switching from one style to another
|
||||||
|
@ -122,5 +122,5 @@ module.exports = {
|
||||||
DISPLAY: styles[D],
|
DISPLAY: styles[D],
|
||||||
TEXT: styles[T],
|
TEXT: styles[T],
|
||||||
SCRIPT: styles[S],
|
SCRIPT: styles[S],
|
||||||
SCRIPTSCRIPT: styles[SS]
|
SCRIPTSCRIPT: styles[SS],
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* eslint no-console:0 */
|
||||||
/**
|
/**
|
||||||
* This module contains general functions that can be used for building
|
* This module contains general functions that can be used for building
|
||||||
* different kinds of domTree nodes in a consistent manner.
|
* different kinds of domTree nodes in a consistent manner.
|
||||||
|
@ -19,12 +20,12 @@ var greekCapitals = [
|
||||||
"\\Upsilon",
|
"\\Upsilon",
|
||||||
"\\Phi",
|
"\\Phi",
|
||||||
"\\Psi",
|
"\\Psi",
|
||||||
"\\Omega"
|
"\\Omega",
|
||||||
];
|
];
|
||||||
|
|
||||||
var dotlessLetters = [
|
var dotlessLetters = [
|
||||||
"\u0131", // dotless i, \imath
|
"\u0131", // dotless i, \imath
|
||||||
"\u0237" // dotless j, \jmath
|
"\u0237", // dotless j, \jmath
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -130,7 +131,8 @@ var makeOrd = function(group, options, type) {
|
||||||
} else {
|
} else {
|
||||||
var fontName = fontMap[font].fontName;
|
var fontName = fontMap[font].fontName;
|
||||||
if (fontMetrics.getCharacterMetrics(value, fontName)) {
|
if (fontMetrics.getCharacterMetrics(value, fontName)) {
|
||||||
return makeSymbol(value, fontName, mode, color, classes.concat([font]));
|
return makeSymbol(
|
||||||
|
value, fontName, mode, color, classes.concat([font]));
|
||||||
} else {
|
} else {
|
||||||
return mathDefault(value, mode, color, classes, type);
|
return mathDefault(value, mode, color, classes, type);
|
||||||
}
|
}
|
||||||
|
@ -201,7 +203,8 @@ var makeFragment = function(children) {
|
||||||
*/
|
*/
|
||||||
var makeFontSizer = function(options, fontSize) {
|
var makeFontSizer = function(options, fontSize) {
|
||||||
var fontSizeInner = makeSpan([], [new domTree.symbolNode("\u200b")]);
|
var fontSizeInner = makeSpan([], [new domTree.symbolNode("\u200b")]);
|
||||||
fontSizeInner.style.fontSize = (fontSize / options.style.sizeMultiplier) + "em";
|
fontSizeInner.style.fontSize =
|
||||||
|
(fontSize / options.style.sizeMultiplier) + "em";
|
||||||
|
|
||||||
var fontSizer = makeSpan(
|
var fontSizer = makeSpan(
|
||||||
["fontsize-ensurer", "reset-" + options.size, "size5"],
|
["fontsize-ensurer", "reset-" + options.size, "size5"],
|
||||||
|
@ -350,7 +353,7 @@ var sizingMultiplier = {
|
||||||
size7: 1.44,
|
size7: 1.44,
|
||||||
size8: 1.73,
|
size8: 1.73,
|
||||||
size9: 2.07,
|
size9: 2.07,
|
||||||
size10: 2.49
|
size10: 2.49,
|
||||||
};
|
};
|
||||||
|
|
||||||
// A map of spacing functions to their attributes, like size and corresponding
|
// A map of spacing functions to their attributes, like size and corresponding
|
||||||
|
@ -358,32 +361,32 @@ var sizingMultiplier = {
|
||||||
var spacingFunctions = {
|
var spacingFunctions = {
|
||||||
"\\qquad": {
|
"\\qquad": {
|
||||||
size: "2em",
|
size: "2em",
|
||||||
className: "qquad"
|
className: "qquad",
|
||||||
},
|
},
|
||||||
"\\quad": {
|
"\\quad": {
|
||||||
size: "1em",
|
size: "1em",
|
||||||
className: "quad"
|
className: "quad",
|
||||||
},
|
},
|
||||||
"\\enspace": {
|
"\\enspace": {
|
||||||
size: "0.5em",
|
size: "0.5em",
|
||||||
className: "enspace"
|
className: "enspace",
|
||||||
},
|
},
|
||||||
"\\;": {
|
"\\;": {
|
||||||
size: "0.277778em",
|
size: "0.277778em",
|
||||||
className: "thickspace"
|
className: "thickspace",
|
||||||
},
|
},
|
||||||
"\\:": {
|
"\\:": {
|
||||||
size: "0.22222em",
|
size: "0.22222em",
|
||||||
className: "mediumspace"
|
className: "mediumspace",
|
||||||
},
|
},
|
||||||
"\\,": {
|
"\\,": {
|
||||||
size: "0.16667em",
|
size: "0.16667em",
|
||||||
className: "thinspace"
|
className: "thinspace",
|
||||||
},
|
},
|
||||||
"\\!": {
|
"\\!": {
|
||||||
size: "-0.16667em",
|
size: "-0.16667em",
|
||||||
className: "negativethinspace"
|
className: "negativethinspace",
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -396,11 +399,11 @@ var fontMap = {
|
||||||
// styles
|
// styles
|
||||||
"mathbf": {
|
"mathbf": {
|
||||||
variant: "bold",
|
variant: "bold",
|
||||||
fontName: "Main-Bold"
|
fontName: "Main-Bold",
|
||||||
},
|
},
|
||||||
"mathrm": {
|
"mathrm": {
|
||||||
variant: "normal",
|
variant: "normal",
|
||||||
fontName: "Main-Regular"
|
fontName: "Main-Regular",
|
||||||
},
|
},
|
||||||
|
|
||||||
// "mathit" is missing because it requires the use of two fonts: Main-Italic
|
// "mathit" is missing because it requires the use of two fonts: Main-Italic
|
||||||
|
@ -410,28 +413,28 @@ var fontMap = {
|
||||||
// families
|
// families
|
||||||
"mathbb": {
|
"mathbb": {
|
||||||
variant: "double-struck",
|
variant: "double-struck",
|
||||||
fontName: "AMS-Regular"
|
fontName: "AMS-Regular",
|
||||||
},
|
},
|
||||||
"mathcal": {
|
"mathcal": {
|
||||||
variant: "script",
|
variant: "script",
|
||||||
fontName: "Caligraphic-Regular"
|
fontName: "Caligraphic-Regular",
|
||||||
},
|
},
|
||||||
"mathfrak": {
|
"mathfrak": {
|
||||||
variant: "fraktur",
|
variant: "fraktur",
|
||||||
fontName: "Fraktur-Regular"
|
fontName: "Fraktur-Regular",
|
||||||
},
|
},
|
||||||
"mathscr": {
|
"mathscr": {
|
||||||
variant: "script",
|
variant: "script",
|
||||||
fontName: "Script-Regular"
|
fontName: "Script-Regular",
|
||||||
},
|
},
|
||||||
"mathsf": {
|
"mathsf": {
|
||||||
variant: "sans-serif",
|
variant: "sans-serif",
|
||||||
fontName: "SansSerif-Regular"
|
fontName: "SansSerif-Regular",
|
||||||
},
|
},
|
||||||
"mathtt": {
|
"mathtt": {
|
||||||
variant: "monospace",
|
variant: "monospace",
|
||||||
fontName: "Typewriter-Regular"
|
fontName: "Typewriter-Regular",
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
@ -443,5 +446,5 @@ module.exports = {
|
||||||
makeVList: makeVList,
|
makeVList: makeVList,
|
||||||
makeOrd: makeOrd,
|
makeOrd: makeOrd,
|
||||||
sizingMultiplier: sizingMultiplier,
|
sizingMultiplier: sizingMultiplier,
|
||||||
spacingFunctions: spacingFunctions
|
spacingFunctions: spacingFunctions,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* eslint no-console:0 */
|
||||||
/**
|
/**
|
||||||
* This file does the main work of building a domTree structure from a parse
|
* This file does the main work of building a domTree structure from a parse
|
||||||
* tree. The entry point is the `buildHTML` function, which takes a parse tree.
|
* tree. The entry point is the `buildHTML` function, which takes a parse tree.
|
||||||
|
@ -53,7 +54,7 @@ var groupToType = {
|
||||||
rule: "mord",
|
rule: "mord",
|
||||||
leftright: "minner",
|
leftright: "minner",
|
||||||
sqrt: "mord",
|
sqrt: "mord",
|
||||||
accent: "mord"
|
accent: "mord",
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -104,7 +105,8 @@ var shouldHandleSupSub = function(group, options) {
|
||||||
// Operators handle supsubs differently when they have limits
|
// Operators handle supsubs differently when they have limits
|
||||||
// (e.g. `\displaystyle\sum_2^3`)
|
// (e.g. `\displaystyle\sum_2^3`)
|
||||||
return group.value.limits &&
|
return group.value.limits &&
|
||||||
(options.style.size === Style.DISPLAY.size || group.value.alwaysHandleSupSub);
|
(options.style.size === Style.DISPLAY.size ||
|
||||||
|
group.value.alwaysHandleSupSub);
|
||||||
} else if (group.type === "accent") {
|
} else if (group.type === "accent") {
|
||||||
return isCharacterBox(group.value.base);
|
return isCharacterBox(group.value.base);
|
||||||
} else {
|
} else {
|
||||||
|
@ -160,7 +162,7 @@ var makeNullDelimiter = function(options) {
|
||||||
return makeSpan([
|
return makeSpan([
|
||||||
"sizing", "reset-" + options.size, "size5",
|
"sizing", "reset-" + options.size, "size5",
|
||||||
options.style.reset(), Style.TEXT.cls(),
|
options.style.reset(), Style.TEXT.cls(),
|
||||||
"nulldelimiter"
|
"nulldelimiter",
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -263,7 +265,10 @@ groupTypes.supsub = function(group, options, prev) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var base = buildGroup(group.value.base, options.reset());
|
var base = buildGroup(group.value.base, options.reset());
|
||||||
var supmid, submid, sup, sub;
|
var supmid;
|
||||||
|
var submid;
|
||||||
|
var sup;
|
||||||
|
var sub;
|
||||||
|
|
||||||
if (group.value.sup) {
|
if (group.value.sup) {
|
||||||
sup = buildGroup(group.value.sup,
|
sup = buildGroup(group.value.sup,
|
||||||
|
@ -280,7 +285,8 @@ groupTypes.supsub = function(group, options, prev) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rule 18a
|
// Rule 18a
|
||||||
var supShift, subShift;
|
var supShift;
|
||||||
|
var subShift;
|
||||||
if (isCharacterBox(group.value.base)) {
|
if (isCharacterBox(group.value.base)) {
|
||||||
supShift = 0;
|
supShift = 0;
|
||||||
subShift = 0;
|
subShift = 0;
|
||||||
|
@ -314,7 +320,7 @@ groupTypes.supsub = function(group, options, prev) {
|
||||||
sub.height - 0.8 * fontMetrics.metrics.xHeight);
|
sub.height - 0.8 * fontMetrics.metrics.xHeight);
|
||||||
|
|
||||||
supsub = buildCommon.makeVList([
|
supsub = buildCommon.makeVList([
|
||||||
{type: "elem", elem: submid}
|
{type: "elem", elem: submid},
|
||||||
], "shift", subShift, options);
|
], "shift", subShift, options);
|
||||||
|
|
||||||
supsub.children[0].style.marginRight = scriptspace;
|
supsub.children[0].style.marginRight = scriptspace;
|
||||||
|
@ -331,7 +337,7 @@ groupTypes.supsub = function(group, options, prev) {
|
||||||
sup.depth + 0.25 * fontMetrics.metrics.xHeight);
|
sup.depth + 0.25 * fontMetrics.metrics.xHeight);
|
||||||
|
|
||||||
supsub = buildCommon.makeVList([
|
supsub = buildCommon.makeVList([
|
||||||
{type: "elem", elem: supmid}
|
{type: "elem", elem: supmid},
|
||||||
], "shift", -supShift, options);
|
], "shift", -supShift, options);
|
||||||
|
|
||||||
supsub.children[0].style.marginRight = scriptspace;
|
supsub.children[0].style.marginRight = scriptspace;
|
||||||
|
@ -357,7 +363,7 @@ groupTypes.supsub = function(group, options, prev) {
|
||||||
|
|
||||||
supsub = buildCommon.makeVList([
|
supsub = buildCommon.makeVList([
|
||||||
{type: "elem", elem: submid, shift: subShift},
|
{type: "elem", elem: submid, shift: subShift},
|
||||||
{type: "elem", elem: supmid, shift: -supShift}
|
{type: "elem", elem: supmid, shift: -supShift},
|
||||||
], "individualShift", null, options);
|
], "individualShift", null, options);
|
||||||
|
|
||||||
// See comment above about subscripts not being shifted
|
// See comment above about subscripts not being shifted
|
||||||
|
@ -436,7 +442,7 @@ groupTypes.genfrac = function(group, options, prev) {
|
||||||
|
|
||||||
frac = buildCommon.makeVList([
|
frac = buildCommon.makeVList([
|
||||||
{type: "elem", elem: denomreset, shift: denomShift},
|
{type: "elem", elem: denomreset, shift: denomShift},
|
||||||
{type: "elem", elem: numerreset, shift: -numShift}
|
{type: "elem", elem: numerreset, shift: -numShift},
|
||||||
], "individualShift", null, options);
|
], "individualShift", null, options);
|
||||||
} else {
|
} else {
|
||||||
// Rule 15d
|
// Rule 15d
|
||||||
|
@ -467,7 +473,7 @@ groupTypes.genfrac = function(group, options, prev) {
|
||||||
frac = buildCommon.makeVList([
|
frac = buildCommon.makeVList([
|
||||||
{type: "elem", elem: denomreset, shift: denomShift},
|
{type: "elem", elem: denomreset, shift: denomShift},
|
||||||
{type: "elem", elem: mid, shift: midShift},
|
{type: "elem", elem: mid, shift: midShift},
|
||||||
{type: "elem", elem: numerreset, shift: -numShift}
|
{type: "elem", elem: numerreset, shift: -numShift},
|
||||||
], "individualShift", null, options);
|
], "individualShift", null, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -484,7 +490,8 @@ groupTypes.genfrac = function(group, options, prev) {
|
||||||
delimSize = fontMetrics.metrics.getDelim2(fstyle);
|
delimSize = fontMetrics.metrics.getDelim2(fstyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
var leftDelim, rightDelim;
|
var leftDelim;
|
||||||
|
var rightDelim;
|
||||||
if (group.value.leftDelim == null) {
|
if (group.value.leftDelim == null) {
|
||||||
leftDelim = makeNullDelimiter(options);
|
leftDelim = makeNullDelimiter(options);
|
||||||
} else {
|
} else {
|
||||||
|
@ -507,7 +514,8 @@ groupTypes.genfrac = function(group, options, prev) {
|
||||||
};
|
};
|
||||||
|
|
||||||
groupTypes.array = function(group, options, prev) {
|
groupTypes.array = function(group, options, prev) {
|
||||||
var r, c;
|
var r;
|
||||||
|
var c;
|
||||||
var nr = group.value.body.length;
|
var nr = group.value.body.length;
|
||||||
var nc = 0;
|
var nc = 0;
|
||||||
var body = new Array(nr);
|
var body = new Array(nr);
|
||||||
|
@ -551,15 +559,15 @@ groupTypes.array = function(group, options, prev) {
|
||||||
if (group.value.rowGaps[r]) {
|
if (group.value.rowGaps[r]) {
|
||||||
gap = group.value.rowGaps[r].value;
|
gap = group.value.rowGaps[r].value;
|
||||||
switch (gap.unit) {
|
switch (gap.unit) {
|
||||||
case "em":
|
case "em":
|
||||||
gap = gap.number;
|
gap = gap.number;
|
||||||
break;
|
break;
|
||||||
case "ex":
|
case "ex":
|
||||||
gap = gap.number * fontMetrics.metrics.emPerEx;
|
gap = gap.number * fontMetrics.metrics.emPerEx;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.error("Can't handle unit " + gap.unit);
|
console.error("Can't handle unit " + gap.unit);
|
||||||
gap = 0;
|
gap = 0;
|
||||||
}
|
}
|
||||||
if (gap > 0) { // \@argarraycr
|
if (gap > 0) { // \@argarraycr
|
||||||
gap += arstrutDepth;
|
gap += arstrutDepth;
|
||||||
|
@ -719,7 +727,7 @@ groupTypes.op = function(group, options, prev) {
|
||||||
|
|
||||||
// Most operators have a large successor symbol, but these don't.
|
// Most operators have a large successor symbol, but these don't.
|
||||||
var noSuccessor = [
|
var noSuccessor = [
|
||||||
"\\smallint"
|
"\\smallint",
|
||||||
];
|
];
|
||||||
|
|
||||||
var large = false;
|
var large = false;
|
||||||
|
@ -769,7 +777,10 @@ groupTypes.op = function(group, options, prev) {
|
||||||
// in a new span so it is an inline, and works.
|
// in a new span so it is an inline, and works.
|
||||||
base = makeSpan([], [base]);
|
base = makeSpan([], [base]);
|
||||||
|
|
||||||
var supmid, supKern, submid, subKern;
|
var supmid;
|
||||||
|
var supKern;
|
||||||
|
var submid;
|
||||||
|
var subKern;
|
||||||
// We manually have to handle the superscripts and subscripts. This,
|
// We manually have to handle the superscripts and subscripts. This,
|
||||||
// aside from the kern calculations, is copied from supsub.
|
// aside from the kern calculations, is copied from supsub.
|
||||||
if (supGroup) {
|
if (supGroup) {
|
||||||
|
@ -797,7 +808,9 @@ groupTypes.op = function(group, options, prev) {
|
||||||
|
|
||||||
// Build the final group as a vlist of the possible subscript, base,
|
// Build the final group as a vlist of the possible subscript, base,
|
||||||
// and possible superscript.
|
// and possible superscript.
|
||||||
var finalGroup, top, bottom;
|
var finalGroup;
|
||||||
|
var top;
|
||||||
|
var bottom;
|
||||||
if (!supGroup) {
|
if (!supGroup) {
|
||||||
top = base.height - baseShift;
|
top = base.height - baseShift;
|
||||||
|
|
||||||
|
@ -805,7 +818,7 @@ groupTypes.op = function(group, options, prev) {
|
||||||
{type: "kern", size: fontMetrics.metrics.bigOpSpacing5},
|
{type: "kern", size: fontMetrics.metrics.bigOpSpacing5},
|
||||||
{type: "elem", elem: submid},
|
{type: "elem", elem: submid},
|
||||||
{type: "kern", size: subKern},
|
{type: "kern", size: subKern},
|
||||||
{type: "elem", elem: base}
|
{type: "elem", elem: base},
|
||||||
], "top", top, options);
|
], "top", top, options);
|
||||||
|
|
||||||
// Here, we shift the limits by the slant of the symbol. Note
|
// Here, we shift the limits by the slant of the symbol. Note
|
||||||
|
@ -820,7 +833,7 @@ groupTypes.op = function(group, options, prev) {
|
||||||
{type: "elem", elem: base},
|
{type: "elem", elem: base},
|
||||||
{type: "kern", size: supKern},
|
{type: "kern", size: supKern},
|
||||||
{type: "elem", elem: supmid},
|
{type: "elem", elem: supmid},
|
||||||
{type: "kern", size: fontMetrics.metrics.bigOpSpacing5}
|
{type: "kern", size: fontMetrics.metrics.bigOpSpacing5},
|
||||||
], "bottom", bottom, options);
|
], "bottom", bottom, options);
|
||||||
|
|
||||||
// See comment above about slants
|
// See comment above about slants
|
||||||
|
@ -843,7 +856,7 @@ groupTypes.op = function(group, options, prev) {
|
||||||
{type: "elem", elem: base},
|
{type: "elem", elem: base},
|
||||||
{type: "kern", size: supKern},
|
{type: "kern", size: supKern},
|
||||||
{type: "elem", elem: supmid},
|
{type: "elem", elem: supmid},
|
||||||
{type: "kern", size: fontMetrics.metrics.bigOpSpacing5}
|
{type: "kern", size: fontMetrics.metrics.bigOpSpacing5},
|
||||||
], "bottom", bottom, options);
|
], "bottom", bottom, options);
|
||||||
|
|
||||||
// See comment above about slants
|
// See comment above about slants
|
||||||
|
@ -909,7 +922,7 @@ groupTypes.overline = function(group, options, prev) {
|
||||||
{type: "elem", elem: innerGroup},
|
{type: "elem", elem: innerGroup},
|
||||||
{type: "kern", size: 3 * ruleWidth},
|
{type: "kern", size: 3 * ruleWidth},
|
||||||
{type: "elem", elem: line},
|
{type: "elem", elem: line},
|
||||||
{type: "kern", size: ruleWidth}
|
{type: "kern", size: ruleWidth},
|
||||||
], "firstBaseline", null, options);
|
], "firstBaseline", null, options);
|
||||||
|
|
||||||
return makeSpan(["overline", "mord"], [vlist], options.getColor());
|
return makeSpan(["overline", "mord"], [vlist], options.getColor());
|
||||||
|
@ -977,7 +990,7 @@ groupTypes.sqrt = function(group, options, prev) {
|
||||||
{type: "elem", elem: inner},
|
{type: "elem", elem: inner},
|
||||||
{type: "kern", size: lineClearance},
|
{type: "kern", size: lineClearance},
|
||||||
{type: "elem", elem: line},
|
{type: "elem", elem: line},
|
||||||
{type: "kern", size: ruleWidth}
|
{type: "kern", size: ruleWidth},
|
||||||
], "firstBaseline", null, options);
|
], "firstBaseline", null, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1041,7 +1054,7 @@ groupTypes.styling = function(group, options, prev) {
|
||||||
"display": Style.DISPLAY,
|
"display": Style.DISPLAY,
|
||||||
"text": Style.TEXT,
|
"text": Style.TEXT,
|
||||||
"script": Style.SCRIPT,
|
"script": Style.SCRIPT,
|
||||||
"scriptscript": Style.SCRIPTSCRIPT
|
"scriptscript": Style.SCRIPTSCRIPT,
|
||||||
};
|
};
|
||||||
|
|
||||||
var newStyle = style[group.value.style];
|
var newStyle = style[group.value.style];
|
||||||
|
@ -1243,7 +1256,7 @@ groupTypes.accent = function(group, options, prev) {
|
||||||
accentBody = buildCommon.makeVList([
|
accentBody = buildCommon.makeVList([
|
||||||
{type: "elem", elem: body},
|
{type: "elem", elem: body},
|
||||||
{type: "kern", size: -clearance},
|
{type: "kern", size: -clearance},
|
||||||
{type: "elem", elem: accentBody}
|
{type: "elem", elem: accentBody},
|
||||||
], "firstBaseline", null, options);
|
], "firstBaseline", null, options);
|
||||||
|
|
||||||
// Shift the accent over by the skew. Note we shift by twice the skew
|
// Shift the accent over by the skew. Note we shift by twice the skew
|
||||||
|
|
|
@ -249,7 +249,7 @@ groupTypes.sqrt = function(group, options) {
|
||||||
node = new mathMLTree.MathNode(
|
node = new mathMLTree.MathNode(
|
||||||
"mroot", [
|
"mroot", [
|
||||||
buildGroup(group.value.body, options),
|
buildGroup(group.value.body, options),
|
||||||
buildGroup(group.value.index, options)
|
buildGroup(group.value.index, options),
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
node = new mathMLTree.MathNode(
|
node = new mathMLTree.MathNode(
|
||||||
|
@ -381,7 +381,7 @@ groupTypes.styling = function(group, options) {
|
||||||
"display": ["0", "true"],
|
"display": ["0", "true"],
|
||||||
"text": ["0", "false"],
|
"text": ["0", "false"],
|
||||||
"script": ["1", "false"],
|
"script": ["1", "false"],
|
||||||
"scriptscript": ["2", "false"]
|
"scriptscript": ["2", "false"],
|
||||||
};
|
};
|
||||||
|
|
||||||
var attr = styleAttributes[group.value.style];
|
var attr = styleAttributes[group.value.style];
|
||||||
|
|
|
@ -18,7 +18,7 @@ var buildTree = function(tree, expression, settings) {
|
||||||
// Setup the default options
|
// Setup the default options
|
||||||
var options = new Options({
|
var options = new Options({
|
||||||
style: startStyle,
|
style: startStyle,
|
||||||
size: "size5"
|
size: "size5",
|
||||||
});
|
});
|
||||||
|
|
||||||
// `buildHTML` sometimes messes with the parse tree (like turning bins ->
|
// `buildHTML` sometimes messes with the parse tree (like turning bins ->
|
||||||
|
@ -27,7 +27,7 @@ var buildTree = function(tree, expression, settings) {
|
||||||
var htmlNode = buildHTML(tree, options);
|
var htmlNode = buildHTML(tree, options);
|
||||||
|
|
||||||
var katexNode = makeSpan(["katex"], [
|
var katexNode = makeSpan(["katex"], [
|
||||||
mathMLNode, htmlNode
|
mathMLNode, htmlNode,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (settings.displayMode) {
|
if (settings.displayMode) {
|
||||||
|
|
|
@ -144,7 +144,10 @@ var makeInner = function(symbol, font, mode) {
|
||||||
var makeStackedDelim = function(delim, heightTotal, center, options, mode) {
|
var makeStackedDelim = function(delim, heightTotal, center, options, mode) {
|
||||||
// There are four parts, the top, an optional middle, a repeated part, and a
|
// There are four parts, the top, an optional middle, a repeated part, and a
|
||||||
// bottom.
|
// bottom.
|
||||||
var top, middle, repeat, bottom;
|
var top;
|
||||||
|
var middle;
|
||||||
|
var repeat;
|
||||||
|
var bottom;
|
||||||
top = repeat = bottom = delim;
|
top = repeat = bottom = delim;
|
||||||
middle = null;
|
middle = null;
|
||||||
// Also keep track of what font the delimiters are in
|
// Also keep track of what font the delimiters are in
|
||||||
|
@ -325,7 +328,7 @@ var stackLargeDelimiters = [
|
||||||
"(", ")", "[", "\\lbrack", "]", "\\rbrack",
|
"(", ")", "[", "\\lbrack", "]", "\\rbrack",
|
||||||
"\\{", "\\lbrace", "\\}", "\\rbrace",
|
"\\{", "\\lbrace", "\\}", "\\rbrace",
|
||||||
"\\lfloor", "\\rfloor", "\\lceil", "\\rceil",
|
"\\lfloor", "\\rfloor", "\\lceil", "\\rceil",
|
||||||
"\\surd"
|
"\\surd",
|
||||||
];
|
];
|
||||||
|
|
||||||
// delimiters that always stack
|
// delimiters that always stack
|
||||||
|
@ -334,12 +337,12 @@ var stackAlwaysDelimiters = [
|
||||||
"\\Uparrow", "\\Downarrow", "\\Updownarrow",
|
"\\Uparrow", "\\Downarrow", "\\Updownarrow",
|
||||||
"|", "\\|", "\\vert", "\\Vert",
|
"|", "\\|", "\\vert", "\\Vert",
|
||||||
"\\lvert", "\\rvert", "\\lVert", "\\rVert",
|
"\\lvert", "\\rvert", "\\lVert", "\\rVert",
|
||||||
"\\lgroup", "\\rgroup", "\\lmoustache", "\\rmoustache"
|
"\\lgroup", "\\rgroup", "\\lmoustache", "\\rmoustache",
|
||||||
];
|
];
|
||||||
|
|
||||||
// and delimiters that never stack
|
// and delimiters that never stack
|
||||||
var stackNeverDelimiters = [
|
var stackNeverDelimiters = [
|
||||||
"<", ">", "\\langle", "\\rangle", "/", "\\backslash", "\\lt", "\\gt"
|
"<", ">", "\\langle", "\\rangle", "/", "\\backslash", "\\lt", "\\gt",
|
||||||
];
|
];
|
||||||
|
|
||||||
// Metrics of the different sizes. Found by looking at TeX's output of
|
// Metrics of the different sizes. Found by looking at TeX's output of
|
||||||
|
@ -390,7 +393,7 @@ var stackNeverDelimiterSequence = [
|
||||||
{type: "large", size: 1},
|
{type: "large", size: 1},
|
||||||
{type: "large", size: 2},
|
{type: "large", size: 2},
|
||||||
{type: "large", size: 3},
|
{type: "large", size: 3},
|
||||||
{type: "large", size: 4}
|
{type: "large", size: 4},
|
||||||
];
|
];
|
||||||
|
|
||||||
// Delimiters that always stack try the small delimiters first, then stack
|
// Delimiters that always stack try the small delimiters first, then stack
|
||||||
|
@ -398,7 +401,7 @@ var stackAlwaysDelimiterSequence = [
|
||||||
{type: "small", style: Style.SCRIPTSCRIPT},
|
{type: "small", style: Style.SCRIPTSCRIPT},
|
||||||
{type: "small", style: Style.SCRIPT},
|
{type: "small", style: Style.SCRIPT},
|
||||||
{type: "small", style: Style.TEXT},
|
{type: "small", style: Style.TEXT},
|
||||||
{type: "stack"}
|
{type: "stack"},
|
||||||
];
|
];
|
||||||
|
|
||||||
// Delimiters that stack when large try the small and then large delimiters, and
|
// Delimiters that stack when large try the small and then large delimiters, and
|
||||||
|
@ -411,7 +414,7 @@ var stackLargeDelimiterSequence = [
|
||||||
{type: "large", size: 2},
|
{type: "large", size: 2},
|
||||||
{type: "large", size: 3},
|
{type: "large", size: 3},
|
||||||
{type: "large", size: 4},
|
{type: "large", size: 4},
|
||||||
{type: "stack"}
|
{type: "stack"},
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -535,5 +538,5 @@ var makeLeftRightDelim = function(delim, height, depth, options, mode) {
|
||||||
module.exports = {
|
module.exports = {
|
||||||
sizedDelim: makeSizedDelim,
|
sizedDelim: makeSizedDelim,
|
||||||
customSizedDelim: makeCustomSizedDelim,
|
customSizedDelim: makeCustomSizedDelim,
|
||||||
leftRightDelim: makeLeftRightDelim
|
leftRightDelim: makeLeftRightDelim,
|
||||||
};
|
};
|
||||||
|
|
|
@ -265,5 +265,5 @@ symbolNode.prototype.toMarkup = function() {
|
||||||
module.exports = {
|
module.exports = {
|
||||||
span: span,
|
span: span,
|
||||||
documentFragment: documentFragment,
|
documentFragment: documentFragment,
|
||||||
symbolNode: symbolNode
|
symbolNode: symbolNode,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* eslint no-constant-condition:0 */
|
||||||
var fontMetrics = require("./fontMetrics");
|
var fontMetrics = require("./fontMetrics");
|
||||||
var parseData = require("./parseData");
|
var parseData = require("./parseData");
|
||||||
var ParseError = require("./ParseError");
|
var ParseError = require("./ParseError");
|
||||||
|
@ -10,7 +11,9 @@ var ParseNode = parseData.ParseNode;
|
||||||
* with one group per cell.
|
* with one group per cell.
|
||||||
*/
|
*/
|
||||||
function parseArray(parser, result) {
|
function parseArray(parser, result) {
|
||||||
var row = [], body = [row], rowGaps = [];
|
var row = [];
|
||||||
|
var body = [row];
|
||||||
|
var rowGaps = [];
|
||||||
while (true) {
|
while (true) {
|
||||||
var cell = parser.parseExpression(false, null);
|
var cell = parser.parseExpression(false, null);
|
||||||
row.push(new ParseNode("ordgroup", cell, parser.mode));
|
row.push(new ParseNode("ordgroup", cell, parser.mode));
|
||||||
|
@ -74,7 +77,7 @@ function defineEnvironment(names, props, handler) {
|
||||||
greediness: 1,
|
greediness: 1,
|
||||||
allowedInText: !!props.allowedInText,
|
allowedInText: !!props.allowedInText,
|
||||||
numOptionalArgs: props.numOptionalArgs || 0,
|
numOptionalArgs: props.numOptionalArgs || 0,
|
||||||
handler: handler
|
handler: handler,
|
||||||
};
|
};
|
||||||
for (var i = 0; i < names.length; ++i) {
|
for (var i = 0; i < names.length; ++i) {
|
||||||
module.exports[names[i]] = data;
|
module.exports[names[i]] = data;
|
||||||
|
@ -84,7 +87,7 @@ function defineEnvironment(names, props, handler) {
|
||||||
// Arrays are part of LaTeX, defined in lttab.dtx so its documentation
|
// Arrays are part of LaTeX, defined in lttab.dtx so its documentation
|
||||||
// is part of the source2e.pdf file of LaTeX2e source documentation.
|
// is part of the source2e.pdf file of LaTeX2e source documentation.
|
||||||
defineEnvironment("array", {
|
defineEnvironment("array", {
|
||||||
numArgs: 1
|
numArgs: 1,
|
||||||
}, function(context, args) {
|
}, function(context, args) {
|
||||||
var colalign = args[0];
|
var colalign = args[0];
|
||||||
colalign = colalign.value.map ? colalign.value : [colalign];
|
colalign = colalign.value.map ? colalign.value : [colalign];
|
||||||
|
@ -93,12 +96,12 @@ defineEnvironment("array", {
|
||||||
if ("lcr".indexOf(ca) !== -1) {
|
if ("lcr".indexOf(ca) !== -1) {
|
||||||
return {
|
return {
|
||||||
type: "align",
|
type: "align",
|
||||||
align: ca
|
align: ca,
|
||||||
};
|
};
|
||||||
} else if (ca === "|") {
|
} else if (ca === "|") {
|
||||||
return {
|
return {
|
||||||
type: "separator",
|
type: "separator",
|
||||||
separator: "|"
|
separator: "|",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
throw new ParseError(
|
throw new ParseError(
|
||||||
|
@ -108,7 +111,7 @@ defineEnvironment("array", {
|
||||||
var res = {
|
var res = {
|
||||||
type: "array",
|
type: "array",
|
||||||
cols: cols,
|
cols: cols,
|
||||||
hskipBeforeAndAfter: true // \@preamble in lttab.dtx
|
hskipBeforeAndAfter: true, // \@preamble in lttab.dtx
|
||||||
};
|
};
|
||||||
res = parseArray(context.parser, res);
|
res = parseArray(context.parser, res);
|
||||||
return res;
|
return res;
|
||||||
|
@ -122,7 +125,7 @@ defineEnvironment([
|
||||||
"bmatrix",
|
"bmatrix",
|
||||||
"Bmatrix",
|
"Bmatrix",
|
||||||
"vmatrix",
|
"vmatrix",
|
||||||
"Vmatrix"
|
"Vmatrix",
|
||||||
], {
|
], {
|
||||||
}, function(context) {
|
}, function(context) {
|
||||||
var delimiters = {
|
var delimiters = {
|
||||||
|
@ -131,18 +134,18 @@ defineEnvironment([
|
||||||
"bmatrix": ["[", "]"],
|
"bmatrix": ["[", "]"],
|
||||||
"Bmatrix": ["\\{", "\\}"],
|
"Bmatrix": ["\\{", "\\}"],
|
||||||
"vmatrix": ["|", "|"],
|
"vmatrix": ["|", "|"],
|
||||||
"Vmatrix": ["\\Vert", "\\Vert"]
|
"Vmatrix": ["\\Vert", "\\Vert"],
|
||||||
}[context.envName];
|
}[context.envName];
|
||||||
var res = {
|
var res = {
|
||||||
type: "array",
|
type: "array",
|
||||||
hskipBeforeAndAfter: false // \hskip -\arraycolsep in amsmath
|
hskipBeforeAndAfter: false, // \hskip -\arraycolsep in amsmath
|
||||||
};
|
};
|
||||||
res = parseArray(context.parser, res);
|
res = parseArray(context.parser, res);
|
||||||
if (delimiters) {
|
if (delimiters) {
|
||||||
res = new ParseNode("leftright", {
|
res = new ParseNode("leftright", {
|
||||||
body: [res],
|
body: [res],
|
||||||
left: delimiters[0],
|
left: delimiters[0],
|
||||||
right: delimiters[1]
|
right: delimiters[1],
|
||||||
}, context.mode);
|
}, context.mode);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
|
@ -160,19 +163,19 @@ defineEnvironment("cases", {
|
||||||
type: "align",
|
type: "align",
|
||||||
align: "l",
|
align: "l",
|
||||||
pregap: 0,
|
pregap: 0,
|
||||||
postgap: fontMetrics.metrics.quad
|
postgap: fontMetrics.metrics.quad,
|
||||||
}, {
|
}, {
|
||||||
type: "align",
|
type: "align",
|
||||||
align: "l",
|
align: "l",
|
||||||
pregap: 0,
|
pregap: 0,
|
||||||
postgap: 0
|
postgap: 0,
|
||||||
}]
|
}],
|
||||||
};
|
};
|
||||||
res = parseArray(context.parser, res);
|
res = parseArray(context.parser, res);
|
||||||
res = new ParseNode("leftright", {
|
res = new ParseNode("leftright", {
|
||||||
body: [res],
|
body: [res],
|
||||||
left: "\\{",
|
left: "\\{",
|
||||||
right: "."
|
right: ".",
|
||||||
}, context.mode);
|
}, context.mode);
|
||||||
return res;
|
return res;
|
||||||
});
|
});
|
||||||
|
@ -185,7 +188,7 @@ defineEnvironment("aligned", {
|
||||||
}, function(context) {
|
}, function(context) {
|
||||||
var res = {
|
var res = {
|
||||||
type: "array",
|
type: "array",
|
||||||
cols: []
|
cols: [],
|
||||||
};
|
};
|
||||||
res = parseArray(context.parser, res);
|
res = parseArray(context.parser, res);
|
||||||
var emptyGroup = new ParseNode("ordgroup", [], context.mode);
|
var emptyGroup = new ParseNode("ordgroup", [], context.mode);
|
||||||
|
@ -211,7 +214,7 @@ defineEnvironment("aligned", {
|
||||||
type: "align",
|
type: "align",
|
||||||
align: align,
|
align: align,
|
||||||
pregap: pregap,
|
pregap: pregap,
|
||||||
postgap: 0
|
postgap: 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* jshint unused:false */
|
/* eslint no-unused-vars:0 */
|
||||||
|
|
||||||
var Style = require("./Style");
|
var Style = require("./Style");
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ var metrics = {
|
||||||
return sigma21ScriptScript;
|
return sigma21ScriptScript;
|
||||||
}
|
}
|
||||||
throw new Error("Unexpected style size: " + style.size);
|
throw new Error("Unexpected style size: " + style.size);
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// This map contains a mapping from font name and character code to character
|
// This map contains a mapping from font name and character code to character
|
||||||
|
@ -136,12 +136,12 @@ var getCharacterMetrics = function(character, style) {
|
||||||
height: metrics[1],
|
height: metrics[1],
|
||||||
italic: metrics[2],
|
italic: metrics[2],
|
||||||
skew: metrics[3],
|
skew: metrics[3],
|
||||||
width: metrics[4]
|
width: metrics[4],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
metrics: metrics,
|
metrics: metrics,
|
||||||
getCharacterMetrics: getCharacterMetrics
|
getCharacterMetrics: getCharacterMetrics,
|
||||||
};
|
};
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
176
src/functions.js
176
src/functions.js
|
@ -91,7 +91,7 @@ function defineFunction(names, props, handler) {
|
||||||
greediness: (props.greediness === undefined) ? 1 : props.greediness,
|
greediness: (props.greediness === undefined) ? 1 : props.greediness,
|
||||||
allowedInText: !!props.allowedInText,
|
allowedInText: !!props.allowedInText,
|
||||||
numOptionalArgs: props.numOptionalArgs || 0,
|
numOptionalArgs: props.numOptionalArgs || 0,
|
||||||
handler: handler
|
handler: handler,
|
||||||
};
|
};
|
||||||
for (var i = 0; i < names.length; ++i) {
|
for (var i = 0; i < names.length; ++i) {
|
||||||
module.exports[names[i]] = data;
|
module.exports[names[i]] = data;
|
||||||
|
@ -101,14 +101,14 @@ function defineFunction(names, props, handler) {
|
||||||
// A normal square root
|
// A normal square root
|
||||||
defineFunction("\\sqrt", {
|
defineFunction("\\sqrt", {
|
||||||
numArgs: 1,
|
numArgs: 1,
|
||||||
numOptionalArgs: 1
|
numOptionalArgs: 1,
|
||||||
}, function(context, args) {
|
}, function(context, args) {
|
||||||
var index = args[0];
|
var index = args[0];
|
||||||
var body = args[1];
|
var body = args[1];
|
||||||
return {
|
return {
|
||||||
type: "sqrt",
|
type: "sqrt",
|
||||||
body: body,
|
body: body,
|
||||||
index: index
|
index: index,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ defineFunction("\\sqrt", {
|
||||||
defineFunction("\\text", {
|
defineFunction("\\text", {
|
||||||
numArgs: 1,
|
numArgs: 1,
|
||||||
argTypes: ["text"],
|
argTypes: ["text"],
|
||||||
greediness: 2
|
greediness: 2,
|
||||||
}, function(context, args) {
|
}, function(context, args) {
|
||||||
var body = args[0];
|
var body = args[0];
|
||||||
// Since the corresponding buildHTML/buildMathML function expects a
|
// Since the corresponding buildHTML/buildMathML function expects a
|
||||||
|
@ -131,7 +131,7 @@ defineFunction("\\text", {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: "text",
|
type: "text",
|
||||||
body: inner
|
body: inner,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ defineFunction("\\color", {
|
||||||
numArgs: 2,
|
numArgs: 2,
|
||||||
allowedInText: true,
|
allowedInText: true,
|
||||||
greediness: 3,
|
greediness: 3,
|
||||||
argTypes: ["color", "original"]
|
argTypes: ["color", "original"],
|
||||||
}, function(context, args) {
|
}, function(context, args) {
|
||||||
var color = args[0];
|
var color = args[0];
|
||||||
var body = args[1];
|
var body = args[1];
|
||||||
|
@ -155,18 +155,18 @@ defineFunction("\\color", {
|
||||||
return {
|
return {
|
||||||
type: "color",
|
type: "color",
|
||||||
color: color.value,
|
color: color.value,
|
||||||
value: inner
|
value: inner,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// An overline
|
// An overline
|
||||||
defineFunction("\\overline", {
|
defineFunction("\\overline", {
|
||||||
numArgs: 1
|
numArgs: 1,
|
||||||
}, function(context, args) {
|
}, function(context, args) {
|
||||||
var body = args[0];
|
var body = args[0];
|
||||||
return {
|
return {
|
||||||
type: "overline",
|
type: "overline",
|
||||||
body: body
|
body: body,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ defineFunction("\\overline", {
|
||||||
defineFunction("\\rule", {
|
defineFunction("\\rule", {
|
||||||
numArgs: 2,
|
numArgs: 2,
|
||||||
numOptionalArgs: 1,
|
numOptionalArgs: 1,
|
||||||
argTypes: ["size", "size", "size"]
|
argTypes: ["size", "size", "size"],
|
||||||
}, function(context, args) {
|
}, function(context, args) {
|
||||||
var shift = args[0];
|
var shift = args[0];
|
||||||
var width = args[1];
|
var width = args[1];
|
||||||
|
@ -183,21 +183,21 @@ defineFunction("\\rule", {
|
||||||
type: "rule",
|
type: "rule",
|
||||||
shift: shift && shift.value,
|
shift: shift && shift.value,
|
||||||
width: width.value,
|
width: width.value,
|
||||||
height: height.value
|
height: height.value,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// A KaTeX logo
|
// A KaTeX logo
|
||||||
defineFunction("\\KaTeX", {
|
defineFunction("\\KaTeX", {
|
||||||
numArgs: 0
|
numArgs: 0,
|
||||||
}, function(context) {
|
}, function(context) {
|
||||||
return {
|
return {
|
||||||
type: "katex"
|
type: "katex",
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
defineFunction("\\phantom", {
|
defineFunction("\\phantom", {
|
||||||
numArgs: 1
|
numArgs: 1,
|
||||||
}, function(context, args) {
|
}, function(context, args) {
|
||||||
var body = args[0];
|
var body = args[0];
|
||||||
var inner;
|
var inner;
|
||||||
|
@ -209,7 +209,7 @@ defineFunction("\\phantom", {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: "phantom",
|
type: "phantom",
|
||||||
value: inner
|
value: inner,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -230,7 +230,7 @@ var delimiterSizes = {
|
||||||
"\\big" : {type: "textord", size: 1},
|
"\\big" : {type: "textord", size: 1},
|
||||||
"\\Big" : {type: "textord", size: 2},
|
"\\Big" : {type: "textord", size: 2},
|
||||||
"\\bigg" : {type: "textord", size: 3},
|
"\\bigg" : {type: "textord", size: 3},
|
||||||
"\\Bigg" : {type: "textord", size: 4}
|
"\\Bigg" : {type: "textord", size: 4},
|
||||||
};
|
};
|
||||||
|
|
||||||
var delimiters = [
|
var delimiters = [
|
||||||
|
@ -245,13 +245,13 @@ var delimiters = [
|
||||||
"\\uparrow", "\\Uparrow",
|
"\\uparrow", "\\Uparrow",
|
||||||
"\\downarrow", "\\Downarrow",
|
"\\downarrow", "\\Downarrow",
|
||||||
"\\updownarrow", "\\Updownarrow",
|
"\\updownarrow", "\\Updownarrow",
|
||||||
"."
|
".",
|
||||||
];
|
];
|
||||||
|
|
||||||
var fontAliases = {
|
var fontAliases = {
|
||||||
"\\Bbb": "\\mathbb",
|
"\\Bbb": "\\mathbb",
|
||||||
"\\bold": "\\mathbf",
|
"\\bold": "\\mathbf",
|
||||||
"\\frak": "\\mathfrak"
|
"\\frak": "\\mathfrak",
|
||||||
};
|
};
|
||||||
|
|
||||||
// Single-argument color functions
|
// Single-argument color functions
|
||||||
|
@ -268,11 +268,11 @@ defineFunction([
|
||||||
"\\mintA", "\\mintB", "\\mintC",
|
"\\mintA", "\\mintB", "\\mintC",
|
||||||
"\\grayA", "\\grayB", "\\grayC", "\\grayD", "\\grayE",
|
"\\grayA", "\\grayB", "\\grayC", "\\grayD", "\\grayE",
|
||||||
"\\grayF", "\\grayG", "\\grayH", "\\grayI",
|
"\\grayF", "\\grayG", "\\grayH", "\\grayI",
|
||||||
"\\kaBlue", "\\kaGreen"
|
"\\kaBlue", "\\kaGreen",
|
||||||
], {
|
], {
|
||||||
numArgs: 1,
|
numArgs: 1,
|
||||||
allowedInText: true,
|
allowedInText: true,
|
||||||
greediness: 3
|
greediness: 3,
|
||||||
}, function(context, args) {
|
}, function(context, args) {
|
||||||
var body = args[0];
|
var body = args[0];
|
||||||
var atoms;
|
var atoms;
|
||||||
|
@ -285,7 +285,7 @@ defineFunction([
|
||||||
return {
|
return {
|
||||||
type: "color",
|
type: "color",
|
||||||
color: "katex-" + context.funcName.slice(1),
|
color: "katex-" + context.funcName.slice(1),
|
||||||
value: atoms
|
value: atoms,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -298,44 +298,44 @@ defineFunction([
|
||||||
"\\arcsin", "\\arccos", "\\arctan", "\\arg", "\\cos", "\\cosh",
|
"\\arcsin", "\\arccos", "\\arctan", "\\arg", "\\cos", "\\cosh",
|
||||||
"\\cot", "\\coth", "\\csc", "\\deg", "\\dim", "\\exp", "\\hom",
|
"\\cot", "\\coth", "\\csc", "\\deg", "\\dim", "\\exp", "\\hom",
|
||||||
"\\ker", "\\lg", "\\ln", "\\log", "\\sec", "\\sin", "\\sinh",
|
"\\ker", "\\lg", "\\ln", "\\log", "\\sec", "\\sin", "\\sinh",
|
||||||
"\\tan","\\tanh"
|
"\\tan", "\\tanh",
|
||||||
], {
|
], {
|
||||||
numArgs: 0
|
numArgs: 0,
|
||||||
}, function(context) {
|
}, function(context) {
|
||||||
return {
|
return {
|
||||||
type: "op",
|
type: "op",
|
||||||
limits: false,
|
limits: false,
|
||||||
symbol: false,
|
symbol: false,
|
||||||
body: context.funcName
|
body: context.funcName,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// Limits, not symbols
|
// Limits, not symbols
|
||||||
defineFunction([
|
defineFunction([
|
||||||
"\\det", "\\gcd", "\\inf", "\\lim", "\\liminf", "\\limsup", "\\max",
|
"\\det", "\\gcd", "\\inf", "\\lim", "\\liminf", "\\limsup", "\\max",
|
||||||
"\\min", "\\Pr", "\\sup"
|
"\\min", "\\Pr", "\\sup",
|
||||||
], {
|
], {
|
||||||
numArgs: 0
|
numArgs: 0,
|
||||||
}, function(context) {
|
}, function(context) {
|
||||||
return {
|
return {
|
||||||
type: "op",
|
type: "op",
|
||||||
limits: true,
|
limits: true,
|
||||||
symbol: false,
|
symbol: false,
|
||||||
body: context.funcName
|
body: context.funcName,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// No limits, symbols
|
// No limits, symbols
|
||||||
defineFunction([
|
defineFunction([
|
||||||
"\\int", "\\iint", "\\iiint", "\\oint"
|
"\\int", "\\iint", "\\iiint", "\\oint",
|
||||||
], {
|
], {
|
||||||
numArgs: 0
|
numArgs: 0,
|
||||||
}, function(context) {
|
}, function(context) {
|
||||||
return {
|
return {
|
||||||
type: "op",
|
type: "op",
|
||||||
limits: false,
|
limits: false,
|
||||||
symbol: true,
|
symbol: true,
|
||||||
body: context.funcName
|
body: context.funcName,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -343,25 +343,25 @@ defineFunction([
|
||||||
defineFunction([
|
defineFunction([
|
||||||
"\\coprod", "\\bigvee", "\\bigwedge", "\\biguplus", "\\bigcap",
|
"\\coprod", "\\bigvee", "\\bigwedge", "\\biguplus", "\\bigcap",
|
||||||
"\\bigcup", "\\intop", "\\prod", "\\sum", "\\bigotimes",
|
"\\bigcup", "\\intop", "\\prod", "\\sum", "\\bigotimes",
|
||||||
"\\bigoplus", "\\bigodot", "\\bigsqcup", "\\smallint"
|
"\\bigoplus", "\\bigodot", "\\bigsqcup", "\\smallint",
|
||||||
], {
|
], {
|
||||||
numArgs: 0
|
numArgs: 0,
|
||||||
}, function(context) {
|
}, function(context) {
|
||||||
return {
|
return {
|
||||||
type: "op",
|
type: "op",
|
||||||
limits: true,
|
limits: true,
|
||||||
symbol: true,
|
symbol: true,
|
||||||
body: context.funcName
|
body: context.funcName,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fractions
|
// Fractions
|
||||||
defineFunction([
|
defineFunction([
|
||||||
"\\dfrac", "\\frac", "\\tfrac",
|
"\\dfrac", "\\frac", "\\tfrac",
|
||||||
"\\dbinom", "\\binom", "\\tbinom"
|
"\\dbinom", "\\binom", "\\tbinom",
|
||||||
], {
|
], {
|
||||||
numArgs: 2,
|
numArgs: 2,
|
||||||
greediness: 2
|
greediness: 2,
|
||||||
}, function(context, args) {
|
}, function(context, args) {
|
||||||
var numer = args[0];
|
var numer = args[0];
|
||||||
var denom = args[1];
|
var denom = args[1];
|
||||||
|
@ -371,31 +371,31 @@ defineFunction([
|
||||||
var size = "auto";
|
var size = "auto";
|
||||||
|
|
||||||
switch (context.funcName) {
|
switch (context.funcName) {
|
||||||
case "\\dfrac":
|
case "\\dfrac":
|
||||||
case "\\frac":
|
case "\\frac":
|
||||||
case "\\tfrac":
|
case "\\tfrac":
|
||||||
hasBarLine = true;
|
hasBarLine = true;
|
||||||
break;
|
break;
|
||||||
case "\\dbinom":
|
case "\\dbinom":
|
||||||
case "\\binom":
|
case "\\binom":
|
||||||
case "\\tbinom":
|
case "\\tbinom":
|
||||||
hasBarLine = false;
|
hasBarLine = false;
|
||||||
leftDelim = "(";
|
leftDelim = "(";
|
||||||
rightDelim = ")";
|
rightDelim = ")";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error("Unrecognized genfrac command");
|
throw new Error("Unrecognized genfrac command");
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (context.funcName) {
|
switch (context.funcName) {
|
||||||
case "\\dfrac":
|
case "\\dfrac":
|
||||||
case "\\dbinom":
|
case "\\dbinom":
|
||||||
size = "display";
|
size = "display";
|
||||||
break;
|
break;
|
||||||
case "\\tfrac":
|
case "\\tfrac":
|
||||||
case "\\tbinom":
|
case "\\tbinom":
|
||||||
size = "text";
|
size = "text";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -405,19 +405,19 @@ defineFunction([
|
||||||
hasBarLine: hasBarLine,
|
hasBarLine: hasBarLine,
|
||||||
leftDelim: leftDelim,
|
leftDelim: leftDelim,
|
||||||
rightDelim: rightDelim,
|
rightDelim: rightDelim,
|
||||||
size: size
|
size: size,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// Left and right overlap functions
|
// Left and right overlap functions
|
||||||
defineFunction(["\\llap", "\\rlap"], {
|
defineFunction(["\\llap", "\\rlap"], {
|
||||||
numArgs: 1,
|
numArgs: 1,
|
||||||
allowedInText: true
|
allowedInText: true,
|
||||||
}, function(context, args) {
|
}, function(context, args) {
|
||||||
var body = args[0];
|
var body = args[0];
|
||||||
return {
|
return {
|
||||||
type: context.funcName.slice(1),
|
type: context.funcName.slice(1),
|
||||||
body: body
|
body: body,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -427,9 +427,9 @@ defineFunction([
|
||||||
"\\bigr", "\\Bigr", "\\biggr", "\\Biggr",
|
"\\bigr", "\\Bigr", "\\biggr", "\\Biggr",
|
||||||
"\\bigm", "\\Bigm", "\\biggm", "\\Biggm",
|
"\\bigm", "\\Bigm", "\\biggm", "\\Biggm",
|
||||||
"\\big", "\\Big", "\\bigg", "\\Bigg",
|
"\\big", "\\Big", "\\bigg", "\\Bigg",
|
||||||
"\\left", "\\right"
|
"\\left", "\\right",
|
||||||
], {
|
], {
|
||||||
numArgs: 1
|
numArgs: 1,
|
||||||
}, function(context, args) {
|
}, function(context, args) {
|
||||||
var delim = args[0];
|
var delim = args[0];
|
||||||
if (!utils.contains(delimiters, delim.value)) {
|
if (!utils.contains(delimiters, delim.value)) {
|
||||||
|
@ -444,14 +444,14 @@ defineFunction([
|
||||||
if (context.funcName === "\\left" || context.funcName === "\\right") {
|
if (context.funcName === "\\left" || context.funcName === "\\right") {
|
||||||
return {
|
return {
|
||||||
type: "leftright",
|
type: "leftright",
|
||||||
value: delim.value
|
value: delim.value,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
type: "delimsizing",
|
type: "delimsizing",
|
||||||
size: delimiterSizes[context.funcName].size,
|
size: delimiterSizes[context.funcName].size,
|
||||||
delimType: delimiterSizes[context.funcName].type,
|
delimType: delimiterSizes[context.funcName].type,
|
||||||
value: delim.value
|
value: delim.value,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -459,14 +459,14 @@ defineFunction([
|
||||||
// Sizing functions (handled in Parser.js explicitly, hence no handler)
|
// Sizing functions (handled in Parser.js explicitly, hence no handler)
|
||||||
defineFunction([
|
defineFunction([
|
||||||
"\\tiny", "\\scriptsize", "\\footnotesize", "\\small",
|
"\\tiny", "\\scriptsize", "\\footnotesize", "\\small",
|
||||||
"\\normalsize", "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge"
|
"\\normalsize", "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge",
|
||||||
], 0, null);
|
], 0, null);
|
||||||
|
|
||||||
// Style changing functions (handled in Parser.js explicitly, hence no
|
// Style changing functions (handled in Parser.js explicitly, hence no
|
||||||
// handler)
|
// handler)
|
||||||
defineFunction([
|
defineFunction([
|
||||||
"\\displaystyle", "\\textstyle", "\\scriptstyle",
|
"\\displaystyle", "\\textstyle", "\\scriptstyle",
|
||||||
"\\scriptscriptstyle"
|
"\\scriptscriptstyle",
|
||||||
], 0, null);
|
], 0, null);
|
||||||
|
|
||||||
defineFunction([
|
defineFunction([
|
||||||
|
@ -478,11 +478,11 @@ defineFunction([
|
||||||
"\\mathtt",
|
"\\mathtt",
|
||||||
|
|
||||||
// aliases
|
// aliases
|
||||||
"\\Bbb", "\\bold", "\\frak"
|
"\\Bbb", "\\bold", "\\frak",
|
||||||
], {
|
], {
|
||||||
numArgs: 1,
|
numArgs: 1,
|
||||||
greediness: 2
|
greediness: 2,
|
||||||
}, function (context, args) {
|
}, function(context, args) {
|
||||||
var body = args[0];
|
var body = args[0];
|
||||||
var func = context.funcName;
|
var func = context.funcName;
|
||||||
if (func in fontAliases) {
|
if (func in fontAliases) {
|
||||||
|
@ -491,45 +491,45 @@ defineFunction([
|
||||||
return {
|
return {
|
||||||
type: "font",
|
type: "font",
|
||||||
font: func.slice(1),
|
font: func.slice(1),
|
||||||
body: body
|
body: body,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// Accents
|
// Accents
|
||||||
defineFunction([
|
defineFunction([
|
||||||
"\\acute", "\\grave", "\\ddot", "\\tilde", "\\bar", "\\breve",
|
"\\acute", "\\grave", "\\ddot", "\\tilde", "\\bar", "\\breve",
|
||||||
"\\check", "\\hat", "\\vec", "\\dot"
|
"\\check", "\\hat", "\\vec", "\\dot",
|
||||||
// We don't support expanding accents yet
|
// We don't support expanding accents yet
|
||||||
// "\\widetilde", "\\widehat"
|
// "\\widetilde", "\\widehat"
|
||||||
], {
|
], {
|
||||||
numArgs: 1
|
numArgs: 1,
|
||||||
}, function(context, args) {
|
}, function(context, args) {
|
||||||
var base = args[0];
|
var base = args[0];
|
||||||
return {
|
return {
|
||||||
type: "accent",
|
type: "accent",
|
||||||
accent: context.funcName,
|
accent: context.funcName,
|
||||||
base: base
|
base: base,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// Infix generalized fractions
|
// Infix generalized fractions
|
||||||
defineFunction(["\\over", "\\choose"], {
|
defineFunction(["\\over", "\\choose"], {
|
||||||
numArgs: 0
|
numArgs: 0,
|
||||||
}, function (context) {
|
}, function(context) {
|
||||||
var replaceWith;
|
var replaceWith;
|
||||||
switch (context.funcName) {
|
switch (context.funcName) {
|
||||||
case "\\over":
|
case "\\over":
|
||||||
replaceWith = "\\frac";
|
replaceWith = "\\frac";
|
||||||
break;
|
break;
|
||||||
case "\\choose":
|
case "\\choose":
|
||||||
replaceWith = "\\binom";
|
replaceWith = "\\binom";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error("Unrecognized infix genfrac command");
|
throw new Error("Unrecognized infix genfrac command");
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
type: "infix",
|
type: "infix",
|
||||||
replaceWith: replaceWith
|
replaceWith: replaceWith,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -537,19 +537,19 @@ defineFunction(["\\over", "\\choose"], {
|
||||||
defineFunction(["\\\\", "\\cr"], {
|
defineFunction(["\\\\", "\\cr"], {
|
||||||
numArgs: 0,
|
numArgs: 0,
|
||||||
numOptionalArgs: 1,
|
numOptionalArgs: 1,
|
||||||
argTypes: ["size"]
|
argTypes: ["size"],
|
||||||
}, function(context, args) {
|
}, function(context, args) {
|
||||||
var size = args[0];
|
var size = args[0];
|
||||||
return {
|
return {
|
||||||
type: "cr",
|
type: "cr",
|
||||||
size: size
|
size: size,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// Environment delimiters
|
// Environment delimiters
|
||||||
defineFunction(["\\begin", "\\end"], {
|
defineFunction(["\\begin", "\\end"], {
|
||||||
numArgs: 1,
|
numArgs: 1,
|
||||||
argTypes: ["text"]
|
argTypes: ["text"],
|
||||||
}, function(context, args) {
|
}, function(context, args) {
|
||||||
var nameGroup = args[0];
|
var nameGroup = args[0];
|
||||||
if (nameGroup.type !== "ordgroup") {
|
if (nameGroup.type !== "ordgroup") {
|
||||||
|
@ -564,6 +564,6 @@ defineFunction(["\\begin", "\\end"], {
|
||||||
return {
|
return {
|
||||||
type: "environment",
|
type: "environment",
|
||||||
name: name,
|
name: name,
|
||||||
namepos: context.positions[1]
|
namepos: context.positions[1],
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -98,5 +98,5 @@ TextNode.prototype.toMarkup = function() {
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
MathNode: MathNode,
|
MathNode: MathNode,
|
||||||
TextNode: TextNode
|
TextNode: TextNode,
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,6 +8,6 @@ function ParseNode(type, value, mode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
ParseNode: ParseNode
|
ParseNode: ParseNode,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,20 +18,17 @@
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
math: {},
|
math: {},
|
||||||
text: {}
|
text: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
function defineSymbol(mode, font, group, replace, name) {
|
function defineSymbol(mode, font, group, replace, name) {
|
||||||
module.exports[mode][name] = {
|
module.exports[mode][name] = {
|
||||||
font: font,
|
font: font,
|
||||||
group: group,
|
group: group,
|
||||||
replace: replace
|
replace: replace,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// (For some reason jshint believes open and close to be global symbols.)
|
|
||||||
/* globals -open, -close */
|
|
||||||
|
|
||||||
// Some abbreviations for commonly used strings.
|
// Some abbreviations for commonly used strings.
|
||||||
// This helps minify the code, and also spotting typos using jshint.
|
// This helps minify the code, and also spotting typos using jshint.
|
||||||
|
|
||||||
|
@ -597,25 +594,27 @@ defineSymbol(text, main, spacing, "\u00a0", " ");
|
||||||
defineSymbol(text, main, spacing, "\u00a0", "~");
|
defineSymbol(text, main, spacing, "\u00a0", "~");
|
||||||
|
|
||||||
// There are lots of symbols which are the same, so we add them in afterwards.
|
// There are lots of symbols which are the same, so we add them in afterwards.
|
||||||
|
var i;
|
||||||
|
var ch;
|
||||||
|
|
||||||
// All of these are textords in math mode
|
// All of these are textords in math mode
|
||||||
var mathTextSymbols = "0123456789/@.\"";
|
var mathTextSymbols = "0123456789/@.\"";
|
||||||
for (var i = 0; i < mathTextSymbols.length; i++) {
|
for (i = 0; i < mathTextSymbols.length; i++) {
|
||||||
var ch = mathTextSymbols.charAt(i);
|
ch = mathTextSymbols.charAt(i);
|
||||||
defineSymbol(math, main, textord, ch, ch);
|
defineSymbol(math, main, textord, ch, ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
// All of these are textords in text mode
|
// All of these are textords in text mode
|
||||||
var textSymbols = "0123456789`!@*()-=+[]'\";:?/.,";
|
var textSymbols = "0123456789`!@*()-=+[]'\";:?/.,";
|
||||||
for (var i = 0; i < textSymbols.length; i++) {
|
for (i = 0; i < textSymbols.length; i++) {
|
||||||
var ch = textSymbols.charAt(i);
|
ch = textSymbols.charAt(i);
|
||||||
defineSymbol(text, main, textord, ch, ch);
|
defineSymbol(text, main, textord, ch, ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
// All of these are textords in text mode, and mathords in math mode
|
// All of these are textords in text mode, and mathords in math mode
|
||||||
var letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
var letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
for (var i = 0; i < letters.length; i++) {
|
for (i = 0; i < letters.length; i++) {
|
||||||
var ch = letters.charAt(i);
|
ch = letters.charAt(i);
|
||||||
defineSymbol(math, main, mathord, ch, ch);
|
defineSymbol(math, main, mathord, ch, ch);
|
||||||
defineSymbol(text, main, textord, ch, ch);
|
defineSymbol(text, main, textord, ch, ch);
|
||||||
}
|
}
|
||||||
|
|
19
src/utils.js
19
src/utils.js
|
@ -15,7 +15,8 @@ var indexOf = function(list, elem) {
|
||||||
if (nativeIndexOf && list.indexOf === nativeIndexOf) {
|
if (nativeIndexOf && list.indexOf === nativeIndexOf) {
|
||||||
return list.indexOf(elem);
|
return list.indexOf(elem);
|
||||||
}
|
}
|
||||||
var i = 0, l = list.length;
|
var i = 0;
|
||||||
|
var l = list.length;
|
||||||
for (; i < l; i++) {
|
for (; i < l; i++) {
|
||||||
if (list[i] === elem) {
|
if (list[i] === elem) {
|
||||||
return i;
|
return i;
|
||||||
|
@ -46,17 +47,17 @@ var hyphenate = function(str) {
|
||||||
};
|
};
|
||||||
|
|
||||||
var ESCAPE_LOOKUP = {
|
var ESCAPE_LOOKUP = {
|
||||||
"&": "&",
|
"&": "&",
|
||||||
">": ">",
|
">": ">",
|
||||||
"<": "<",
|
"<": "<",
|
||||||
"\"": """,
|
"\"": """,
|
||||||
"'": "'"
|
"'": "'",
|
||||||
};
|
};
|
||||||
|
|
||||||
var ESCAPE_REGEX = /[&><"']/g;
|
var ESCAPE_REGEX = /[&><"']/g;
|
||||||
|
|
||||||
function escaper(match) {
|
function escaper(match) {
|
||||||
return ESCAPE_LOOKUP[match];
|
return ESCAPE_LOOKUP[match];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -66,7 +67,7 @@ function escaper(match) {
|
||||||
* @return {string} An escaped string.
|
* @return {string} An escaped string.
|
||||||
*/
|
*/
|
||||||
function escape(text) {
|
function escape(text) {
|
||||||
return ("" + text).replace(ESCAPE_REGEX, escaper);
|
return ("" + text).replace(ESCAPE_REGEX, escaper);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -101,5 +102,5 @@ module.exports = {
|
||||||
hyphenate: hyphenate,
|
hyphenate: hyphenate,
|
||||||
indexOf: indexOf,
|
indexOf: indexOf,
|
||||||
setTextContent: setTextContent,
|
setTextContent: setTextContent,
|
||||||
clearNode: clearNode
|
clearNode: clearNode,
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,13 +19,13 @@ beforeEach(function() {
|
||||||
parseTree(actual, defaultSettings);
|
parseTree(actual, defaultSettings);
|
||||||
return {
|
return {
|
||||||
pass: false,
|
pass: false,
|
||||||
message: "'" + actual + "' parsed without error"
|
message: "'" + actual + "' parsed without error",
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (expected === undefined) {
|
if (expected === undefined) {
|
||||||
return {
|
return {
|
||||||
pass: true,
|
pass: true,
|
||||||
message: "'" + actual + "' parsed with error"
|
message: "'" + actual + "' parsed with error",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
var msg = e.message;
|
var msg = e.message;
|
||||||
|
@ -34,27 +34,27 @@ beforeEach(function() {
|
||||||
return {
|
return {
|
||||||
pass: true,
|
pass: true,
|
||||||
message: "'" + actual + "'" +
|
message: "'" + actual + "'" +
|
||||||
" parsed with error '" + expected + "'"
|
" parsed with error '" + expected + "'",
|
||||||
};
|
};
|
||||||
} else if (msg.slice(0, 19) === prefix) {
|
} else if (msg.slice(0, 19) === prefix) {
|
||||||
return {
|
return {
|
||||||
pass: false,
|
pass: false,
|
||||||
message: "'" + actual + "'" +
|
message: "'" + actual + "'" +
|
||||||
" parsed with error '" + msg.slice(19) +
|
" parsed with error '" + msg.slice(19) +
|
||||||
"' but expected '" + expected + "'"
|
"' but expected '" + expected + "'",
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
pass: false,
|
pass: false,
|
||||||
message: "'" + actual + "'" +
|
message: "'" + actual + "'" +
|
||||||
" caused error '" + msg +
|
" caused error '" + msg +
|
||||||
"' but expected '" + exp + "'"
|
"' but expected '" + exp + "'",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* eslint max-len:0 */
|
||||||
/* global beforeEach: false */
|
/* global beforeEach: false */
|
||||||
/* global jasmine: false */
|
/* global jasmine: false */
|
||||||
/* global expect: false */
|
/* global expect: false */
|
||||||
|
@ -16,7 +17,7 @@ var Style = require("../src/Style");
|
||||||
var defaultSettings = new Settings({});
|
var defaultSettings = new Settings({});
|
||||||
var defaultOptions = new Options({
|
var defaultOptions = new Options({
|
||||||
style: Style.TEXT,
|
style: Style.TEXT,
|
||||||
size: "size5"
|
size: "size5",
|
||||||
});
|
});
|
||||||
|
|
||||||
var _getBuilt = function(expr, settings) {
|
var _getBuilt = function(expr, settings) {
|
||||||
|
@ -65,7 +66,7 @@ beforeEach(function() {
|
||||||
|
|
||||||
var result = {
|
var result = {
|
||||||
pass: true,
|
pass: true,
|
||||||
message: "'" + actual + "' succeeded parsing"
|
message: "'" + actual + "' succeeded parsing",
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -82,7 +83,7 @@ beforeEach(function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -94,7 +95,7 @@ beforeEach(function() {
|
||||||
var result = {
|
var result = {
|
||||||
pass: false,
|
pass: false,
|
||||||
message: "Expected '" + actual + "' to fail " +
|
message: "Expected '" + actual + "' to fail " +
|
||||||
"parsing, but it succeeded"
|
"parsing, but it succeeded",
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -111,7 +112,7 @@ beforeEach(function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -122,7 +123,7 @@ beforeEach(function() {
|
||||||
|
|
||||||
var result = {
|
var result = {
|
||||||
pass: true,
|
pass: true,
|
||||||
message: "'" + actual + "' succeeded in building"
|
message: "'" + actual + "' succeeded in building",
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(actual).toParse(usedSettings);
|
expect(actual).toParse(usedSettings);
|
||||||
|
@ -141,9 +142,9 @@ beforeEach(function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -425,7 +426,7 @@ describe("A parser with limit controls", function() {
|
||||||
|
|
||||||
parsedInput = getParsed("\\int\\limits_2\\nolimits^2");
|
parsedInput = getParsed("\\int\\limits_2\\nolimits^2");
|
||||||
expect(parsedInput[0].value.base.value.limits).toBe(false);
|
expect(parsedInput[0].value.base.value.limits).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("A group parser", function() {
|
describe("A group parser", function() {
|
||||||
|
@ -562,7 +563,7 @@ describe("An over parser", function() {
|
||||||
var simpleOver = "1 \\over x";
|
var simpleOver = "1 \\over x";
|
||||||
var complexOver = "1+2i \\over 3+4i";
|
var complexOver = "1+2i \\over 3+4i";
|
||||||
|
|
||||||
it("should not fail", function () {
|
it("should not fail", function() {
|
||||||
expect(simpleOver).toParse();
|
expect(simpleOver).toParse();
|
||||||
expect(complexOver).toParse();
|
expect(complexOver).toParse();
|
||||||
});
|
});
|
||||||
|
@ -583,21 +584,21 @@ describe("An over parser", function() {
|
||||||
expect(parse.value.denom).toBeDefined();
|
expect(parse.value.denom).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should create a numerator from the atoms before \\over", function () {
|
it("should create a numerator from the atoms before \\over", function() {
|
||||||
var parse = getParsed(complexOver)[0];
|
var parse = getParsed(complexOver)[0];
|
||||||
|
|
||||||
var numer = parse.value.numer;
|
var numer = parse.value.numer;
|
||||||
expect(numer.value.length).toEqual(4);
|
expect(numer.value.length).toEqual(4);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should create a demonimator from the atoms after \\over", function () {
|
it("should create a demonimator from the atoms after \\over", function() {
|
||||||
var parse = getParsed(complexOver)[0];
|
var parse = getParsed(complexOver)[0];
|
||||||
|
|
||||||
var denom = parse.value.numer;
|
var denom = parse.value.numer;
|
||||||
expect(denom.value.length).toEqual(4);
|
expect(denom.value.length).toEqual(4);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should handle empty numerators", function () {
|
it("should handle empty numerators", function() {
|
||||||
var emptyNumerator = "\\over x";
|
var emptyNumerator = "\\over x";
|
||||||
var parse = getParsed(emptyNumerator)[0];
|
var parse = getParsed(emptyNumerator)[0];
|
||||||
expect(parse.type).toEqual("genfrac");
|
expect(parse.type).toEqual("genfrac");
|
||||||
|
@ -605,7 +606,7 @@ describe("An over parser", function() {
|
||||||
expect(parse.value.denom).toBeDefined();
|
expect(parse.value.denom).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should handle empty denominators", function () {
|
it("should handle empty denominators", function() {
|
||||||
var emptyDenominator = "1 \\over";
|
var emptyDenominator = "1 \\over";
|
||||||
var parse = getParsed(emptyDenominator)[0];
|
var parse = getParsed(emptyDenominator)[0];
|
||||||
expect(parse.type).toEqual("genfrac");
|
expect(parse.type).toEqual("genfrac");
|
||||||
|
@ -613,7 +614,7 @@ describe("An over parser", function() {
|
||||||
expect(parse.value.denom).toBeDefined();
|
expect(parse.value.denom).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should handle \\displaystyle correctly", function () {
|
it("should handle \\displaystyle correctly", function() {
|
||||||
var displaystyleExpression = "\\displaystyle 1 \\over 2";
|
var displaystyleExpression = "\\displaystyle 1 \\over 2";
|
||||||
var parse = getParsed(displaystyleExpression)[0];
|
var parse = getParsed(displaystyleExpression)[0];
|
||||||
expect(parse.type).toEqual("genfrac");
|
expect(parse.type).toEqual("genfrac");
|
||||||
|
@ -621,7 +622,7 @@ describe("An over parser", function() {
|
||||||
expect(parse.value.denom).toBeDefined();
|
expect(parse.value.denom).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should handle nested factions", function () {
|
it("should handle nested factions", function() {
|
||||||
var nestedOverExpression = "{1 \\over 2} \\over 3";
|
var nestedOverExpression = "{1 \\over 2} \\over 3";
|
||||||
var parse = getParsed(nestedOverExpression)[0];
|
var parse = getParsed(nestedOverExpression)[0];
|
||||||
expect(parse.type).toEqual("genfrac");
|
expect(parse.type).toEqual("genfrac");
|
||||||
|
@ -632,7 +633,7 @@ describe("An over parser", function() {
|
||||||
expect(parse.value.denom.value[0].value).toEqual("3");
|
expect(parse.value.denom.value[0].value).toEqual("3");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should fail with multiple overs in the same group", function () {
|
it("should fail with multiple overs in the same group", function() {
|
||||||
var badMultipleOvers = "1 \\over 2 + 3 \\over 4";
|
var badMultipleOvers = "1 \\over 2 + 3 \\over 4";
|
||||||
expect(badMultipleOvers).toNotParse();
|
expect(badMultipleOvers).toNotParse();
|
||||||
|
|
||||||
|
@ -757,7 +758,7 @@ describe("A color parser", function() {
|
||||||
expect(badCustomColorExpression).toNotParse();
|
expect(badCustomColorExpression).toNotParse();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should parse new colors from the branding guide", function(){
|
it("should parse new colors from the branding guide", function() {
|
||||||
expect(newColorExpression).toParse();
|
expect(newColorExpression).toParse();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1025,7 +1026,7 @@ describe("A TeX-compliant parser", function() {
|
||||||
"\\rule{1em}",
|
"\\rule{1em}",
|
||||||
"\\llap",
|
"\\llap",
|
||||||
"\\bigl",
|
"\\bigl",
|
||||||
"\\text"
|
"\\text",
|
||||||
];
|
];
|
||||||
|
|
||||||
for (var i = 0; i < missingGroups.length; i++) {
|
for (var i = 0; i < missingGroups.length; i++) {
|
||||||
|
@ -1052,7 +1053,7 @@ describe("A TeX-compliant parser", function() {
|
||||||
// work
|
// work
|
||||||
// "\\llap \\frac x y",
|
// "\\llap \\frac x y",
|
||||||
"\\llap \\llap x",
|
"\\llap \\llap x",
|
||||||
"\\sqrt \\llap x"
|
"\\sqrt \\llap x",
|
||||||
];
|
];
|
||||||
|
|
||||||
for (var i = 0; i < badArguments.length; i++) {
|
for (var i = 0; i < badArguments.length; i++) {
|
||||||
|
@ -1070,7 +1071,7 @@ describe("A TeX-compliant parser", function() {
|
||||||
"\\frac x {\\llap y}",
|
"\\frac x {\\llap y}",
|
||||||
"\\llap {\\frac x y}",
|
"\\llap {\\frac x y}",
|
||||||
"\\llap {\\llap x}",
|
"\\llap {\\llap x}",
|
||||||
"\\sqrt {\\llap x}"
|
"\\sqrt {\\llap x}",
|
||||||
];
|
];
|
||||||
|
|
||||||
for (var i = 0; i < goodArguments.length; i++) {
|
for (var i = 0; i < goodArguments.length; i++) {
|
||||||
|
@ -1083,7 +1084,7 @@ describe("A TeX-compliant parser", function() {
|
||||||
"x^\\sqrt x",
|
"x^\\sqrt x",
|
||||||
"x^\\llap x",
|
"x^\\llap x",
|
||||||
"x_\\sqrt x",
|
"x_\\sqrt x",
|
||||||
"x_\\llap x"
|
"x_\\llap x",
|
||||||
];
|
];
|
||||||
|
|
||||||
for (var i = 0; i < badSupSubscripts.length; i++) {
|
for (var i = 0; i < badSupSubscripts.length; i++) {
|
||||||
|
@ -1096,7 +1097,7 @@ describe("A TeX-compliant parser", function() {
|
||||||
"x^{\\sqrt x}",
|
"x^{\\sqrt x}",
|
||||||
"x^{\\llap x}",
|
"x^{\\llap x}",
|
||||||
"x_{\\sqrt x}",
|
"x_{\\sqrt x}",
|
||||||
"x_{\\llap x}"
|
"x_{\\llap x}",
|
||||||
];
|
];
|
||||||
|
|
||||||
for (var i = 0; i < goodSupSubscripts.length; i++) {
|
for (var i = 0; i < goodSupSubscripts.length; i++) {
|
||||||
|
@ -1135,7 +1136,7 @@ describe("A TeX-compliant parser", function() {
|
||||||
"\\frac x \\left( y \\right)",
|
"\\frac x \\left( y \\right)",
|
||||||
"\\llap \\left( x \\right)",
|
"\\llap \\left( x \\right)",
|
||||||
"\\sqrt \\left( x \\right)",
|
"\\sqrt \\left( x \\right)",
|
||||||
"x^\\left( x \\right)"
|
"x^\\left( x \\right)",
|
||||||
];
|
];
|
||||||
|
|
||||||
for (var i = 0; i < badLeftArguments.length; i++) {
|
for (var i = 0; i < badLeftArguments.length; i++) {
|
||||||
|
@ -1149,7 +1150,7 @@ describe("A TeX-compliant parser", function() {
|
||||||
"\\frac x {\\left( y \\right)}",
|
"\\frac x {\\left( y \\right)}",
|
||||||
"\\llap {\\left( x \\right)}",
|
"\\llap {\\left( x \\right)}",
|
||||||
"\\sqrt {\\left( x \\right)}",
|
"\\sqrt {\\left( x \\right)}",
|
||||||
"x^{\\left( x \\right)}"
|
"x^{\\left( x \\right)}",
|
||||||
];
|
];
|
||||||
|
|
||||||
for (var i = 0; i < goodLeftArguments.length; i++) {
|
for (var i = 0; i < goodLeftArguments.length; i++) {
|
||||||
|
@ -1189,8 +1190,8 @@ describe("A style change parser", function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("A font parser", function () {
|
describe("A font parser", function() {
|
||||||
it("should parse \\mathrm, \\mathbb, and \\mathit", function () {
|
it("should parse \\mathrm, \\mathbb, and \\mathit", function() {
|
||||||
expect("\\mathrm x").toParse();
|
expect("\\mathrm x").toParse();
|
||||||
expect("\\mathbb x").toParse();
|
expect("\\mathbb x").toParse();
|
||||||
expect("\\mathit x").toParse();
|
expect("\\mathit x").toParse();
|
||||||
|
@ -1199,12 +1200,12 @@ describe("A font parser", function () {
|
||||||
expect("\\mathit {x + 1}").toParse();
|
expect("\\mathit {x + 1}").toParse();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should parse \\mathcal and \\mathfrak", function () {
|
it("should parse \\mathcal and \\mathfrak", function() {
|
||||||
expect("\\mathcal{ABC123}").toParse();
|
expect("\\mathcal{ABC123}").toParse();
|
||||||
expect("\\mathfrak{abcABC123}").toParse();
|
expect("\\mathfrak{abcABC123}").toParse();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should produce the correct fonts", function () {
|
it("should produce the correct fonts", function() {
|
||||||
var mathbbParse = getParsed("\\mathbb x")[0];
|
var mathbbParse = getParsed("\\mathbb x")[0];
|
||||||
expect(mathbbParse.value.font).toEqual("mathbb");
|
expect(mathbbParse.value.font).toEqual("mathbb");
|
||||||
expect(mathbbParse.value.type).toEqual("font");
|
expect(mathbbParse.value.type).toEqual("font");
|
||||||
|
@ -1226,7 +1227,7 @@ describe("A font parser", function () {
|
||||||
expect(mathfrakParse.value.type).toEqual("font");
|
expect(mathfrakParse.value.type).toEqual("font");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should parse nested font commands", function () {
|
it("should parse nested font commands", function() {
|
||||||
var nestedParse = getParsed("\\mathbb{R \\neq \\mathrm{R}}")[0];
|
var nestedParse = getParsed("\\mathbb{R \\neq \\mathrm{R}}")[0];
|
||||||
expect(nestedParse.value.font).toEqual("mathbb");
|
expect(nestedParse.value.font).toEqual("mathbb");
|
||||||
expect(nestedParse.value.type).toEqual("font");
|
expect(nestedParse.value.type).toEqual("font");
|
||||||
|
@ -1240,7 +1241,7 @@ describe("A font parser", function () {
|
||||||
expect(bbBody[2].value.type).toEqual("font");
|
expect(bbBody[2].value.type).toEqual("font");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should work with \\color", function () {
|
it("should work with \\color", function() {
|
||||||
var colorMathbbParse = getParsed("\\color{blue}{\\mathbb R}")[0];
|
var colorMathbbParse = getParsed("\\color{blue}{\\mathbb R}")[0];
|
||||||
expect(colorMathbbParse.value.type).toEqual("color");
|
expect(colorMathbbParse.value.type).toEqual("color");
|
||||||
expect(colorMathbbParse.value.color).toEqual("blue");
|
expect(colorMathbbParse.value.color).toEqual("blue");
|
||||||
|
@ -1250,11 +1251,11 @@ describe("A font parser", function () {
|
||||||
expect(body[0].value.font).toEqual("mathbb");
|
expect(body[0].value.font).toEqual("mathbb");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not parse a series of font commands", function () {
|
it("should not parse a series of font commands", function() {
|
||||||
expect("\\mathbb \\mathrm R").toNotParse();
|
expect("\\mathbb \\mathrm R").toNotParse();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should nest fonts correctly", function () {
|
it("should nest fonts correctly", function() {
|
||||||
var bf = getParsed("\\mathbf{a\\mathrm{b}c}")[0];
|
var bf = getParsed("\\mathbf{a\\mathrm{b}c}")[0];
|
||||||
expect(bf.value.type).toEqual("font");
|
expect(bf.value.type).toEqual("font");
|
||||||
expect(bf.value.font).toEqual("mathbf");
|
expect(bf.value.font).toEqual("mathbf");
|
||||||
|
@ -1270,28 +1271,28 @@ describe("A font parser", function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("An HTML font tree-builder", function () {
|
describe("An HTML font tree-builder", function() {
|
||||||
it("should render \\mathbb{R} with the correct font", function () {
|
it("should render \\mathbb{R} with the correct font", function() {
|
||||||
var markup = katex.renderToString("\\mathbb{R}");
|
var markup = katex.renderToString("\\mathbb{R}");
|
||||||
expect(markup).toContain("<span class=\"mord mathbb\">R</span>");
|
expect(markup).toContain("<span class=\"mord mathbb\">R</span>");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should render \\mathrm{R} with the correct font", function () {
|
it("should render \\mathrm{R} with the correct font", function() {
|
||||||
var markup = katex.renderToString("\\mathrm{R}");
|
var markup = katex.renderToString("\\mathrm{R}");
|
||||||
expect(markup).toContain("<span class=\"mord mathrm\">R</span>");
|
expect(markup).toContain("<span class=\"mord mathrm\">R</span>");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should render \\mathcal{R} with the correct font", function () {
|
it("should render \\mathcal{R} with the correct font", function() {
|
||||||
var markup = katex.renderToString("\\mathcal{R}");
|
var markup = katex.renderToString("\\mathcal{R}");
|
||||||
expect(markup).toContain("<span class=\"mord mathcal\">R</span>");
|
expect(markup).toContain("<span class=\"mord mathcal\">R</span>");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should render \\mathfrak{R} with the correct font", function () {
|
it("should render \\mathfrak{R} with the correct font", function() {
|
||||||
var markup = katex.renderToString("\\mathfrak{R}");
|
var markup = katex.renderToString("\\mathfrak{R}");
|
||||||
expect(markup).toContain("<span class=\"mord mathfrak\">R</span>");
|
expect(markup).toContain("<span class=\"mord mathfrak\">R</span>");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should render a combination of font and color changes", function () {
|
it("should render a combination of font and color changes", function() {
|
||||||
var markup = katex.renderToString("\\color{blue}{\\mathbb R}");
|
var markup = katex.renderToString("\\color{blue}{\\mathbb R}");
|
||||||
var span = "<span class=\"mord mathbb\" style=\"color:blue;\">R</span>";
|
var span = "<span class=\"mord mathbb\" style=\"color:blue;\">R</span>";
|
||||||
expect(markup).toContain(span);
|
expect(markup).toContain(span);
|
||||||
|
@ -1303,10 +1304,10 @@ describe("An HTML font tree-builder", function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
describe("A MathML font tree-builder", function () {
|
describe("A MathML font tree-builder", function() {
|
||||||
var contents = "Ax2k\\omega\\Omega\\imath+";
|
var contents = "Ax2k\\omega\\Omega\\imath+";
|
||||||
|
|
||||||
it("should render " + contents + " with the correct mathvariants", function () {
|
it("should render " + contents + " with the correct mathvariants", function() {
|
||||||
var tree = getParsed(contents);
|
var tree = getParsed(contents);
|
||||||
var markup = buildMathML(tree, contents, defaultOptions).toMarkup();
|
var markup = buildMathML(tree, contents, defaultOptions).toMarkup();
|
||||||
expect(markup).toContain("<mi>A</mi>");
|
expect(markup).toContain("<mi>A</mi>");
|
||||||
|
@ -1318,7 +1319,7 @@ describe("A MathML font tree-builder", function () {
|
||||||
expect(markup).toContain("<mo>+</mo>");
|
expect(markup).toContain("<mo>+</mo>");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should render \\mathbb{" + contents + "} with the correct mathvariants", function () {
|
it("should render \\mathbb{" + contents + "} with the correct mathvariants", function() {
|
||||||
var tex = "\\mathbb{" + contents + "}";
|
var tex = "\\mathbb{" + contents + "}";
|
||||||
var tree = getParsed(tex);
|
var tree = getParsed(tex);
|
||||||
var markup = buildMathML(tree, tex, defaultOptions).toMarkup();
|
var markup = buildMathML(tree, tex, defaultOptions).toMarkup();
|
||||||
|
@ -1331,7 +1332,7 @@ describe("A MathML font tree-builder", function () {
|
||||||
expect(markup).toContain("<mo>+</mo>");
|
expect(markup).toContain("<mo>+</mo>");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should render \\mathrm{" + contents + "} with the correct mathvariants", function () {
|
it("should render \\mathrm{" + contents + "} with the correct mathvariants", function() {
|
||||||
var tex = "\\mathrm{" + contents + "}";
|
var tex = "\\mathrm{" + contents + "}";
|
||||||
var tree = getParsed(tex);
|
var tree = getParsed(tex);
|
||||||
var markup = buildMathML(tree, tex, defaultOptions).toMarkup();
|
var markup = buildMathML(tree, tex, defaultOptions).toMarkup();
|
||||||
|
@ -1344,7 +1345,7 @@ describe("A MathML font tree-builder", function () {
|
||||||
expect(markup).toContain("<mo>+</mo>");
|
expect(markup).toContain("<mo>+</mo>");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should render \\mathit{" + contents + "} with the correct mathvariants", function () {
|
it("should render \\mathit{" + contents + "} with the correct mathvariants", function() {
|
||||||
var tex = "\\mathit{" + contents + "}";
|
var tex = "\\mathit{" + contents + "}";
|
||||||
var tree = getParsed(tex);
|
var tree = getParsed(tex);
|
||||||
var markup = buildMathML(tree, tex, defaultOptions).toMarkup();
|
var markup = buildMathML(tree, tex, defaultOptions).toMarkup();
|
||||||
|
@ -1357,7 +1358,7 @@ describe("A MathML font tree-builder", function () {
|
||||||
expect(markup).toContain("<mo>+</mo>");
|
expect(markup).toContain("<mo>+</mo>");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should render \\mathbf{" + contents + "} with the correct mathvariants", function () {
|
it("should render \\mathbf{" + contents + "} with the correct mathvariants", function() {
|
||||||
var tex = "\\mathbf{" + contents + "}";
|
var tex = "\\mathbf{" + contents + "}";
|
||||||
var tree = getParsed(tex);
|
var tree = getParsed(tex);
|
||||||
var markup = buildMathML(tree, tex, defaultOptions).toMarkup();
|
var markup = buildMathML(tree, tex, defaultOptions).toMarkup();
|
||||||
|
@ -1370,7 +1371,7 @@ describe("A MathML font tree-builder", function () {
|
||||||
expect(markup).toContain("<mo>+</mo>");
|
expect(markup).toContain("<mo>+</mo>");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should render \\mathcal{" + contents + "} with the correct mathvariants", function () {
|
it("should render \\mathcal{" + contents + "} with the correct mathvariants", function() {
|
||||||
var tex = "\\mathcal{" + contents + "}";
|
var tex = "\\mathcal{" + contents + "}";
|
||||||
var tree = getParsed(tex);
|
var tree = getParsed(tex);
|
||||||
var markup = buildMathML(tree, tex, defaultOptions).toMarkup();
|
var markup = buildMathML(tree, tex, defaultOptions).toMarkup();
|
||||||
|
@ -1385,7 +1386,7 @@ describe("A MathML font tree-builder", function () {
|
||||||
expect(markup).toContain("<mo>+</mo>");
|
expect(markup).toContain("<mo>+</mo>");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should render \\mathfrak{" + contents + "} with the correct mathvariants", function () {
|
it("should render \\mathfrak{" + contents + "} with the correct mathvariants", function() {
|
||||||
var tex = "\\mathfrak{" + contents + "}";
|
var tex = "\\mathfrak{" + contents + "}";
|
||||||
var tree = getParsed(tex);
|
var tree = getParsed(tex);
|
||||||
var markup = buildMathML(tree, tex, defaultOptions).toMarkup();
|
var markup = buildMathML(tree, tex, defaultOptions).toMarkup();
|
||||||
|
@ -1400,7 +1401,7 @@ describe("A MathML font tree-builder", function () {
|
||||||
expect(markup).toContain("<mo>+</mo>");
|
expect(markup).toContain("<mo>+</mo>");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should render \\mathscr{" + contents + "} with the correct mathvariants", function () {
|
it("should render \\mathscr{" + contents + "} with the correct mathvariants", function() {
|
||||||
var tex = "\\mathscr{" + contents + "}";
|
var tex = "\\mathscr{" + contents + "}";
|
||||||
var tree = getParsed(tex);
|
var tree = getParsed(tex);
|
||||||
var markup = buildMathML(tree, tex, defaultOptions).toMarkup();
|
var markup = buildMathML(tree, tex, defaultOptions).toMarkup();
|
||||||
|
@ -1415,7 +1416,7 @@ describe("A MathML font tree-builder", function () {
|
||||||
expect(markup).toContain("<mo>+</mo>");
|
expect(markup).toContain("<mo>+</mo>");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should render \\mathsf{" + contents + "} with the correct mathvariants", function () {
|
it("should render \\mathsf{" + contents + "} with the correct mathvariants", function() {
|
||||||
var tex = "\\mathsf{" + contents + "}";
|
var tex = "\\mathsf{" + contents + "}";
|
||||||
var tree = getParsed(tex);
|
var tree = getParsed(tex);
|
||||||
var markup = buildMathML(tree, tex, defaultOptions).toMarkup();
|
var markup = buildMathML(tree, tex, defaultOptions).toMarkup();
|
||||||
|
@ -1428,7 +1429,7 @@ describe("A MathML font tree-builder", function () {
|
||||||
expect(markup).toContain("<mo>+</mo>");
|
expect(markup).toContain("<mo>+</mo>");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should render a combination of font and color changes", function () {
|
it("should render a combination of font and color changes", function() {
|
||||||
var tex = "\\color{blue}{\\mathbb R}";
|
var tex = "\\color{blue}{\\mathbb R}";
|
||||||
var tree = getParsed(tex);
|
var tree = getParsed(tex);
|
||||||
var markup = buildMathML(tree, tex, defaultOptions).toMarkup();
|
var markup = buildMathML(tree, tex, defaultOptions).toMarkup();
|
||||||
|
@ -1504,17 +1505,17 @@ describe("A parse tree generator", function() {
|
||||||
"base": {
|
"base": {
|
||||||
"type": "mathord",
|
"type": "mathord",
|
||||||
"value": "\\sigma",
|
"value": "\\sigma",
|
||||||
"mode": "math"
|
"mode": "math",
|
||||||
},
|
},
|
||||||
"sup": {
|
"sup": {
|
||||||
"type": "textord",
|
"type": "textord",
|
||||||
"value": "2",
|
"value": "2",
|
||||||
"mode": "math"
|
"mode": "math",
|
||||||
},
|
},
|
||||||
"sub": undefined
|
"sub": undefined,
|
||||||
},
|
},
|
||||||
"mode": "math"
|
"mode": "math",
|
||||||
}
|
},
|
||||||
]));
|
]));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1600,8 +1601,8 @@ describe("A phantom builder", function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("A parser error", function () {
|
describe("A parser error", function() {
|
||||||
it("should report the position of an error", function () {
|
it("should report the position of an error", function() {
|
||||||
try {
|
try {
|
||||||
parseTree("\\sqrt}", defaultSettings);
|
parseTree("\\sqrt}", defaultSettings);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -1643,7 +1644,7 @@ describe("An array environment", function() {
|
||||||
var parse = getParsed("\\begin{array}r1\\\\20\\end{array}");
|
var parse = getParsed("\\begin{array}r1\\\\20\\end{array}");
|
||||||
expect(parse[0].type).toBe("array");
|
expect(parse[0].type).toBe("array");
|
||||||
expect(parse[0].value.cols).toEqual([
|
expect(parse[0].value.cols).toEqual([
|
||||||
{ type: "align", align: "r" }
|
{ type: "align", align: "r" },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1656,7 +1657,7 @@ describe("An array environment", function() {
|
||||||
{ type: "separator", separator: "|" },
|
{ type: "separator", separator: "|" },
|
||||||
{ type: "separator", separator: "|" },
|
{ type: "separator", separator: "|" },
|
||||||
{ type: "align", align: "c" },
|
{ type: "align", align: "c" },
|
||||||
{ type: "separator", separator: "|" }
|
{ type: "separator", separator: "|" },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1731,7 +1732,7 @@ describe("A parser that does not throw on unsupported commands", function() {
|
||||||
var errorColor = "#933";
|
var errorColor = "#933";
|
||||||
var noThrowSettings = new Settings({
|
var noThrowSettings = new Settings({
|
||||||
throwOnError: false,
|
throwOnError: false,
|
||||||
errorColor: errorColor
|
errorColor: errorColor,
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should still parse on unrecognized control sequences", function() {
|
it("should still parse on unrecognized control sequences", function() {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* eslint no-console:0 */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
|
@ -6,7 +7,7 @@ var childProcess = require("child_process");
|
||||||
var opts = require("nomnom")
|
var opts = require("nomnom")
|
||||||
.option("spacing", {
|
.option("spacing", {
|
||||||
flag: true,
|
flag: true,
|
||||||
help: "Print mismatches involving spacing commands"
|
help: "Print mismatches involving spacing commands",
|
||||||
})
|
})
|
||||||
.parse();
|
.parse();
|
||||||
|
|
||||||
|
@ -15,7 +16,7 @@ var keys = Object.keys(symbols.math);
|
||||||
keys.sort();
|
keys.sort();
|
||||||
var types = [
|
var types = [
|
||||||
"mathord", "op", "bin", "rel", "open", "close", "punct", "inner",
|
"mathord", "op", "bin", "rel", "open", "close", "punct", "inner",
|
||||||
"spacing", "accent", "textord"
|
"spacing", "accent", "textord",
|
||||||
];
|
];
|
||||||
|
|
||||||
process.nextTick(writeTexFile);
|
process.nextTick(writeTexFile);
|
||||||
|
@ -94,7 +95,8 @@ function evaluate(err, log) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
var match, nextIndex = 0;
|
var match;
|
||||||
|
var nextIndex = 0;
|
||||||
while ((match = reMM.exec(log)) !== null) {
|
while ((match = reMM.exec(log)) !== null) {
|
||||||
var list = match[1];
|
var list = match[1];
|
||||||
match = reParts.exec(list);
|
match = reParts.exec(list);
|
||||||
|
@ -143,7 +145,8 @@ function evaluate(err, log) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractDigits(str) {
|
function extractDigits(str) {
|
||||||
var match, res = "";
|
var match;
|
||||||
|
var res = "";
|
||||||
while ((match = reDigit.exec(str)) !== null) {
|
while ((match = reDigit.exec(str)) !== null) {
|
||||||
res += match[1];
|
res += match[1];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user