mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-05 19:28:39 +00:00
\newcommand, \renewcommand, \providecommand (#1382)
* \newcommand, \renewcommand, \providecommand * Tests * Add comment * Add symbols to the set of already defined things * Add implicitCommands, catch \hline outside array * Add \relax * Move isDefined to be a method of MacroExpander * Namespace.has * Reword error messages * Add \hdashline given #1407
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
* until only non-macro tokens remain.
|
||||
*/
|
||||
|
||||
import functions from "./functions";
|
||||
import symbols from "./symbols";
|
||||
import Lexer from "./Lexer";
|
||||
import {Token} from "./Token";
|
||||
import type {Mode} from "./types";
|
||||
@@ -15,6 +17,16 @@ import type {MacroContextInterface, MacroDefinition, MacroExpansion}
|
||||
from "./macros";
|
||||
import type Settings from "./Settings";
|
||||
|
||||
// List of commands that act like macros but aren't defined as a macro,
|
||||
// function, or symbol. Used in `isDefined`.
|
||||
export const implicitCommands = {
|
||||
"\\relax": true, // MacroExpander.js
|
||||
"^": true, // Parser.js
|
||||
"_": true, // Parser.js
|
||||
"\\limits": true, // Parser.js
|
||||
"\\nolimits": true, // Parser.js
|
||||
};
|
||||
|
||||
export default class MacroExpander implements MacroContextInterface {
|
||||
maxExpand: number;
|
||||
lexer: Lexer;
|
||||
@@ -316,5 +328,19 @@ export default class MacroExpander implements MacroContextInterface {
|
||||
|
||||
return expansion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether a command is currently "defined" (has some
|
||||
* functionality), meaning that it's a macro (in the current group),
|
||||
* a function, a symbol, or one of the special commands listed in
|
||||
* `implicitCommands`.
|
||||
*/
|
||||
isDefined(name: string): boolean {
|
||||
return this.macros.has(name) ||
|
||||
functions.hasOwnProperty(name) ||
|
||||
symbols.math.hasOwnProperty(name) ||
|
||||
symbols.text.hasOwnProperty(name) ||
|
||||
implicitCommands.hasOwnProperty(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -56,7 +56,21 @@ export default class Namespace<Value> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current value of a name.
|
||||
* Detect whether `name` has a definition. Equivalent to
|
||||
* `get(name) != null`.
|
||||
*/
|
||||
has(name: string): boolean {
|
||||
return this.current.hasOwnProperty(name) ||
|
||||
this.builtins.hasOwnProperty(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current value of a name, or `undefined` if there is no value.
|
||||
*
|
||||
* Note: Do not use `if (namespace.get(...))` to detect whether a macro
|
||||
* is defined, as the definition may be the empty string which evaluates
|
||||
* to `false` in JavaScript. Use `if (namespace.get(...) != null)` or
|
||||
* `if (namespace.has(...))`.
|
||||
*/
|
||||
get(name: string): ?Value {
|
||||
if (this.current.hasOwnProperty(name)) {
|
||||
|
@@ -1,6 +1,7 @@
|
||||
// @flow
|
||||
import buildCommon from "../buildCommon";
|
||||
import defineEnvironment from "../defineEnvironment";
|
||||
import defineFunction from "../defineFunction";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import ParseError from "../ParseError";
|
||||
import ParseNode from "../ParseNode";
|
||||
@@ -659,3 +660,18 @@ defineEnvironment({
|
||||
htmlBuilder,
|
||||
mathmlBuilder,
|
||||
});
|
||||
|
||||
// Catch \hline outside array environment
|
||||
defineFunction({
|
||||
type: "text", // Doesn't matter what this is.
|
||||
names: ["\\hline", "\\hdashline"],
|
||||
props: {
|
||||
numArgs: 0,
|
||||
allowedInText: true,
|
||||
allowedInMath: true,
|
||||
},
|
||||
handler(context, args) {
|
||||
throw new ParseError(
|
||||
`${context.funcName} valid only within array environment`);
|
||||
},
|
||||
});
|
||||
|
@@ -38,6 +38,11 @@ export interface MacroContextInterface {
|
||||
*/
|
||||
expandAfterFuture(): Token;
|
||||
|
||||
/**
|
||||
* Recursively expand first token, then return first non-expandable token.
|
||||
*/
|
||||
expandNextToken(): Token;
|
||||
|
||||
/**
|
||||
* Fully expand the given macro name and return the resulting list of
|
||||
* tokens, or return `undefined` if no such macro is defined.
|
||||
@@ -55,6 +60,14 @@ export interface MacroContextInterface {
|
||||
* and return the resulting array of arguments.
|
||||
*/
|
||||
consumeArgs(numArgs: number): Token[][];
|
||||
|
||||
/**
|
||||
* Determine whether a command is currently "defined" (has some
|
||||
* functionality), meaning that it's a macro (in the current group),
|
||||
* a function, a symbol, or one of the special commands listed in
|
||||
* `implicitCommands`.
|
||||
*/
|
||||
isDefined(name: string): boolean;
|
||||
}
|
||||
|
||||
/** Macro tokens (in reverse order). */
|
||||
@@ -118,11 +131,12 @@ defineMacro("\\TextOrMath", function(context) {
|
||||
}
|
||||
});
|
||||
|
||||
// Basic support for global macro definitions:
|
||||
// \gdef\macro{expansion}
|
||||
// \gdef\macro#1{expansion}
|
||||
// \gdef\macro#1#2{expansion}
|
||||
// \gdef\macro#1#2#3#4#5#6#7#8#9{expansion}
|
||||
// Basic support for macro definitions:
|
||||
// \def\macro{expansion}
|
||||
// \def\macro#1{expansion}
|
||||
// \def\macro#1#2{expansion}
|
||||
// \def\macro#1#2#3#4#5#6#7#8#9{expansion}
|
||||
// Also the \gdef and \global\def equivalents
|
||||
const def = (context, global: boolean) => {
|
||||
let arg = context.consumeArgs(1)[0];
|
||||
if (arg.length !== 1) {
|
||||
@@ -161,6 +175,7 @@ defineMacro("\\global", (context) => {
|
||||
throw new ParseError("Invalid command after \\global");
|
||||
}
|
||||
const command = next[0].text;
|
||||
// TODO: Should expand command
|
||||
if (command === "\\def") {
|
||||
// \global\def is equivalent to \gdef
|
||||
return def(context, true);
|
||||
@@ -169,6 +184,55 @@ defineMacro("\\global", (context) => {
|
||||
}
|
||||
});
|
||||
|
||||
// \newcommand{\macro}[args]{definition}
|
||||
// \renewcommand{\macro}[args]{definition}
|
||||
// TODO: Optional arguments: \newcommand{\macro}[args][default]{definition}
|
||||
const newcommand = (context, existsOK: boolean, nonexistsOK: boolean) => {
|
||||
let arg = context.consumeArgs(1)[0];
|
||||
if (arg.length !== 1) {
|
||||
throw new ParseError(
|
||||
"\\newcommand's first argument must be a macro name");
|
||||
}
|
||||
const name = arg[0].text;
|
||||
|
||||
const exists = context.isDefined(name);
|
||||
if (exists && !existsOK) {
|
||||
throw new ParseError(`\\newcommand{${name}} attempting to redefine ` +
|
||||
`${name}; use \\renewcommand`);
|
||||
}
|
||||
if (!exists && !nonexistsOK) {
|
||||
throw new ParseError(`\\renewcommand{${name}} when command ${name} ` +
|
||||
`does not yet exist; use \\newcommand`);
|
||||
}
|
||||
|
||||
let numArgs = 0;
|
||||
arg = context.consumeArgs(1)[0];
|
||||
if (arg.length === 1 && arg[0].text === "[") {
|
||||
let argText = '';
|
||||
let token = context.expandNextToken();
|
||||
while (token.text !== "]" && token.text !== "EOF") {
|
||||
// TODO: Should properly expand arg, e.g., ignore {}s
|
||||
argText += token.text;
|
||||
token = context.expandNextToken();
|
||||
}
|
||||
if (!argText.match(/^\s*[0-9]+\s*$/)) {
|
||||
throw new ParseError(`Invalid number of arguments: ${argText}`);
|
||||
}
|
||||
numArgs = parseInt(argText);
|
||||
arg = context.consumeArgs(1)[0];
|
||||
}
|
||||
|
||||
// Final arg is the expansion of the macro
|
||||
context.macros.set(name, {
|
||||
tokens: arg,
|
||||
numArgs,
|
||||
});
|
||||
return '';
|
||||
};
|
||||
defineMacro("\\newcommand", (context) => newcommand(context, false, true));
|
||||
defineMacro("\\renewcommand", (context) => newcommand(context, true, false));
|
||||
defineMacro("\\providecommand", (context) => newcommand(context, true, true));
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Grouping
|
||||
// \let\bgroup={ \let\egroup=}
|
||||
|
@@ -5,15 +5,10 @@ import ParseError from "../src/ParseError";
|
||||
import parseTree from "../src/parseTree";
|
||||
import Settings from "../src/Settings";
|
||||
|
||||
export const defaultSettings = new Settings({
|
||||
strict: false, // deal with warnings only when desired
|
||||
});
|
||||
export const nonstrictSettings = new Settings({strict: false});
|
||||
export const strictSettings = new Settings({strict: true});
|
||||
|
||||
export const _getBuilt = function(expr, settings = defaultSettings) {
|
||||
if (settings === defaultSettings) {
|
||||
settings.macros = {};
|
||||
}
|
||||
export const _getBuilt = function(expr, settings = new Settings()) {
|
||||
let rootNode = katex.__renderToDomTree(expr, settings);
|
||||
|
||||
if (rootNode.classes.indexOf('katex-error') >= 0) {
|
||||
@@ -43,7 +38,7 @@ export const _getBuilt = function(expr, settings = defaultSettings) {
|
||||
* @param settings
|
||||
* @returns {Object}
|
||||
*/
|
||||
export const getBuilt = function(expr, settings = defaultSettings) {
|
||||
export const getBuilt = function(expr, settings = new Settings()) {
|
||||
expect(expr).toBuild(settings);
|
||||
return _getBuilt(expr, settings);
|
||||
};
|
||||
@@ -54,7 +49,7 @@ export const getBuilt = function(expr, settings = defaultSettings) {
|
||||
* @param settings
|
||||
* @returns {Object}
|
||||
*/
|
||||
export const getParsed = function(expr, settings = defaultSettings) {
|
||||
export const getParsed = function(expr, settings = new Settings()) {
|
||||
expect(expr).toParse(settings);
|
||||
return parseTree(expr, settings);
|
||||
};
|
||||
@@ -73,7 +68,7 @@ export const stripPositions = function(expr) {
|
||||
};
|
||||
|
||||
export const parseAndSetResult = function(expr, result,
|
||||
settings = defaultSettings) {
|
||||
settings = new Settings()) {
|
||||
try {
|
||||
return parseTree(expr, settings);
|
||||
} catch (e) {
|
||||
@@ -89,7 +84,7 @@ export const parseAndSetResult = function(expr, result,
|
||||
};
|
||||
|
||||
export const buildAndSetResult = function(expr, result,
|
||||
settings = defaultSettings) {
|
||||
settings = new Settings()) {
|
||||
try {
|
||||
return _getBuilt(expr, settings);
|
||||
} catch (e) {
|
||||
|
@@ -11,7 +11,7 @@ import Options from "../src/Options";
|
||||
import Settings from "../src/Settings";
|
||||
import Style from "../src/Style";
|
||||
import {
|
||||
defaultSettings, strictSettings,
|
||||
strictSettings, nonstrictSettings,
|
||||
_getBuilt, getBuilt, getParsed, stripPositions,
|
||||
} from "./helpers";
|
||||
|
||||
@@ -1140,6 +1140,10 @@ describe("A begin/end parser", function() {
|
||||
expect("\\begin{matrix}\\hdashline a&b\\\\ \\hdashline c&d\\end{matrix}").toParse();
|
||||
});
|
||||
|
||||
it("should forbid hlines outside array environment", () => {
|
||||
expect("\\hline").toNotParse();
|
||||
});
|
||||
|
||||
it("should error when name is mismatched", function() {
|
||||
expect("\\begin{matrix}a&b\\\\c&d\\end{pmatrix}").toNotParse();
|
||||
});
|
||||
@@ -2282,7 +2286,7 @@ describe("A smash builder", function() {
|
||||
describe("A parser error", function() {
|
||||
it("should report the position of an error", function() {
|
||||
try {
|
||||
parseTree("\\sqrt}", defaultSettings);
|
||||
parseTree("\\sqrt}", new Settings());
|
||||
} catch (e) {
|
||||
expect(e.position).toEqual(5);
|
||||
}
|
||||
@@ -2490,7 +2494,7 @@ describe("A macro expander", function() {
|
||||
const compareParseTree = function(actual, expected, macros) {
|
||||
const settings = new Settings({macros: macros});
|
||||
actual = stripPositions(parseTree(actual, settings));
|
||||
expected = stripPositions(parseTree(expected, defaultSettings));
|
||||
expected = stripPositions(parseTree(expected, new Settings()));
|
||||
expect(actual).toEqual(expected);
|
||||
};
|
||||
|
||||
@@ -2775,6 +2779,57 @@ describe("A macro expander", function() {
|
||||
expect(macros["\\foo"]).toBeFalsy();
|
||||
});
|
||||
|
||||
it("\\newcommand defines new macros", () => {
|
||||
compareParseTree("\\newcommand\\foo{x^2}\\foo+\\foo", "x^2+x^2");
|
||||
compareParseTree("\\newcommand{\\foo}{x^2}\\foo+\\foo", "x^2+x^2");
|
||||
// Function detection
|
||||
expect("\\newcommand\\bar{x^2}\\bar+\\bar").toNotParse();
|
||||
expect("\\newcommand{\\bar}{x^2}\\bar+\\bar").toNotParse();
|
||||
// Symbol detection
|
||||
expect("\\newcommand\\lambda{x^2}\\lambda").toNotParse();
|
||||
expect("\\newcommand\\textdollar{x^2}\\textdollar").toNotParse();
|
||||
// Macro detection
|
||||
expect("\\newcommand{\\foo}{1}\\foo\\newcommand{\\foo}{2}\\foo")
|
||||
.toNotParse();
|
||||
// Implicit detection
|
||||
expect("\\newcommand\\limits{}").toNotParse();
|
||||
});
|
||||
|
||||
it("\\renewcommand redefines macros", () => {
|
||||
expect("\\renewcommand\\foo{x^2}\\foo+\\foo").toNotParse();
|
||||
expect("\\renewcommand{\\foo}{x^2}\\foo+\\foo").toNotParse();
|
||||
compareParseTree("\\renewcommand\\bar{x^2}\\bar+\\bar", "x^2+x^2");
|
||||
compareParseTree("\\renewcommand{\\bar}{x^2}\\bar+\\bar", "x^2+x^2");
|
||||
expect("\\newcommand{\\foo}{1}\\foo\\renewcommand{\\foo}{2}\\foo")
|
||||
.toParseLike("12");
|
||||
});
|
||||
|
||||
it("\\providecommand (re)defines macros", () => {
|
||||
compareParseTree("\\providecommand\\foo{x^2}\\foo+\\foo", "x^2+x^2");
|
||||
compareParseTree("\\providecommand{\\foo}{x^2}\\foo+\\foo", "x^2+x^2");
|
||||
compareParseTree("\\providecommand\\bar{x^2}\\bar+\\bar", "x^2+x^2");
|
||||
compareParseTree("\\providecommand{\\bar}{x^2}\\bar+\\bar", "x^2+x^2");
|
||||
expect("\\newcommand{\\foo}{1}\\foo\\providecommand{\\foo}{2}\\foo")
|
||||
.toParseLike("12");
|
||||
expect("\\providecommand{\\foo}{1}\\foo\\renewcommand{\\foo}{2}\\foo")
|
||||
.toParseLike("12");
|
||||
expect("\\providecommand{\\foo}{1}\\foo\\providecommand{\\foo}{2}\\foo")
|
||||
.toParseLike("12");
|
||||
});
|
||||
|
||||
it("\\newcommand is local", () => {
|
||||
expect("\\newcommand\\foo{1}\\foo{\\renewcommand\\foo{2}\\foo}\\foo")
|
||||
.toParseLike("1{2}1");
|
||||
});
|
||||
|
||||
it("\\newcommand accepts number of arguments", () => {
|
||||
compareParseTree("\\newcommand\\foo[1]{#1^2}\\foo x+\\foo{y}",
|
||||
"x^2+y^2");
|
||||
compareParseTree("\\newcommand\\foo[10]{#1^2}\\foo 0123456789", "0^2");
|
||||
expect("\\newcommand\\foo[x]{}").toNotParse();
|
||||
expect("\\newcommand\\foo[1.5]{}").toNotParse();
|
||||
});
|
||||
|
||||
// This may change in the future, if we support the extra features of
|
||||
// \hspace.
|
||||
it("should treat \\hspace, \\hskip like \\kern", function() {
|
||||
@@ -2847,7 +2902,7 @@ describe("Unicode accents", function() {
|
||||
"\\tilde n" +
|
||||
"\\grave o\\acute o\\hat o\\tilde o\\ddot o" +
|
||||
"\\grave u\\acute u\\hat u\\ddot u" +
|
||||
"\\acute y\\ddot y");
|
||||
"\\acute y\\ddot y", nonstrictSettings);
|
||||
});
|
||||
|
||||
it("should parse Latin-1 letters in text mode", function() {
|
||||
@@ -2877,19 +2932,19 @@ describe("Unicode accents", function() {
|
||||
});
|
||||
|
||||
it("should parse combining characters", function() {
|
||||
expect("A\u0301C\u0301").toParseLike("Á\\acute C");
|
||||
expect("A\u0301C\u0301").toParseLike("Á\\acute C", nonstrictSettings);
|
||||
expect("\\text{A\u0301C\u0301}").toParseLike("\\text{Á\\'C}", strictSettings);
|
||||
});
|
||||
|
||||
it("should parse multi-accented characters", function() {
|
||||
expect("ấā́ắ\\text{ấā́ắ}").toParse();
|
||||
expect("ấā́ắ\\text{ấā́ắ}").toParse(nonstrictSettings);
|
||||
// Doesn't parse quite the same as
|
||||
// "\\text{\\'{\\^a}\\'{\\=a}\\'{\\u a}}" because of the ordgroups.
|
||||
});
|
||||
|
||||
it("should parse accented i's and j's", function() {
|
||||
expect("íȷ́").toParseLike("\\acute ı\\acute ȷ");
|
||||
expect("ấā́ắ\\text{ấā́ắ}").toParse();
|
||||
expect("íȷ́").toParseLike("\\acute ı\\acute ȷ", nonstrictSettings);
|
||||
expect("ấā́ắ\\text{ấā́ắ}").toParse(nonstrictSettings);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3076,8 +3131,8 @@ describe("Symbols", function() {
|
||||
|
||||
describe("strict setting", function() {
|
||||
it("should allow unicode text when not strict", () => {
|
||||
expect("é").toParse(new Settings({strict: false}));
|
||||
expect("試").toParse(new Settings({strict: false}));
|
||||
expect("é").toParse(new Settings(nonstrictSettings));
|
||||
expect("試").toParse(new Settings(nonstrictSettings));
|
||||
expect("é").toParse(new Settings({strict: "ignore"}));
|
||||
expect("試").toParse(new Settings({strict: "ignore"}));
|
||||
expect("é").toParse(new Settings({strict: () => false}));
|
||||
@@ -3103,7 +3158,7 @@ describe("strict setting", function() {
|
||||
});
|
||||
|
||||
it("should always allow unicode text in text mode", () => {
|
||||
expect("\\text{é試}").toParse(new Settings({strict: false}));
|
||||
expect("\\text{é試}").toParse(nonstrictSettings);
|
||||
expect("\\text{é試}").toParse(strictSettings);
|
||||
expect("\\text{é試}").toParse();
|
||||
});
|
||||
|
@@ -8,13 +8,9 @@ import Options from "../src/Options";
|
||||
import Settings from "../src/Settings";
|
||||
import Style from "../src/Style";
|
||||
|
||||
const defaultSettings = new Settings({});
|
||||
|
||||
const getMathML = function(expr, settings) {
|
||||
const usedSettings = settings ? settings : defaultSettings;
|
||||
|
||||
const getMathML = function(expr, settings = new Settings()) {
|
||||
let startStyle = Style.TEXT;
|
||||
if (usedSettings.displayMode) {
|
||||
if (settings.displayMode) {
|
||||
startStyle = Style.DISPLAY;
|
||||
}
|
||||
|
||||
@@ -24,7 +20,7 @@ const getMathML = function(expr, settings) {
|
||||
maxSize: Infinity,
|
||||
});
|
||||
|
||||
const built = buildMathML(parseTree(expr, usedSettings), expr, options);
|
||||
const built = buildMathML(parseTree(expr, settings), expr, options);
|
||||
|
||||
// Strip off the surrounding <span>
|
||||
return built.children[0].toMarkup();
|
||||
|
@@ -4,10 +4,10 @@
|
||||
import katex from "../katex";
|
||||
import ParseError from "../src/ParseError";
|
||||
import parseTree from "../src/parseTree";
|
||||
import Settings from "../src/Settings";
|
||||
import Warning from "./Warning";
|
||||
import stringify from 'json-stable-stringify';
|
||||
import {
|
||||
defaultSettings,
|
||||
_getBuilt, buildAndSetResult, parseAndSetResult, stripPositions,
|
||||
} from "./helpers";
|
||||
|
||||
@@ -44,7 +44,7 @@ global.console.warn = jest.fn((warning) => {
|
||||
// Expect extensions
|
||||
|
||||
expect.extend({
|
||||
toParse: function(actual, settings = defaultSettings) {
|
||||
toParse: function(actual, settings = new Settings()) {
|
||||
const result = {
|
||||
pass: true,
|
||||
message: () => `'${actual}' succeeded parsing`,
|
||||
@@ -53,7 +53,7 @@ expect.extend({
|
||||
return result;
|
||||
},
|
||||
|
||||
toNotParse: function(actual, settings = defaultSettings) {
|
||||
toNotParse: function(actual, settings = new Settings()) {
|
||||
const result = {
|
||||
pass: false,
|
||||
message: () =>
|
||||
@@ -79,7 +79,7 @@ expect.extend({
|
||||
toFailWithParseError: function(actual, expected) {
|
||||
const prefix = "KaTeX parse error: ";
|
||||
try {
|
||||
parseTree(actual, defaultSettings);
|
||||
parseTree(actual, new Settings());
|
||||
return {
|
||||
pass: false,
|
||||
message: () => `'${actual}' parsed without error`,
|
||||
@@ -115,7 +115,7 @@ expect.extend({
|
||||
}
|
||||
},
|
||||
|
||||
toBuild: function(actual, settings = defaultSettings) {
|
||||
toBuild: function(actual, settings = new Settings()) {
|
||||
const result = {
|
||||
pass: true,
|
||||
message: () => `'${actual}' succeeded in building`,
|
||||
@@ -124,7 +124,7 @@ expect.extend({
|
||||
return result;
|
||||
},
|
||||
|
||||
toNotBuild: function(actual, settings = defaultSettings) {
|
||||
toNotBuild: function(actual, settings = new Settings()) {
|
||||
const result = {
|
||||
pass: false,
|
||||
message: () =>
|
||||
@@ -147,7 +147,7 @@ expect.extend({
|
||||
return result;
|
||||
},
|
||||
|
||||
toParseLike: function(actual, expected, settings = defaultSettings) {
|
||||
toParseLike: function(actual, expected, settings = new Settings()) {
|
||||
const result = {
|
||||
pass: true,
|
||||
message: () =>
|
||||
@@ -174,7 +174,7 @@ expect.extend({
|
||||
return result;
|
||||
},
|
||||
|
||||
toBuildLike: function(actual, expected, settings = defaultSettings) {
|
||||
toBuildLike: function(actual, expected, settings = new Settings()) {
|
||||
const result = {
|
||||
pass: true,
|
||||
message: () =>
|
||||
@@ -201,7 +201,7 @@ expect.extend({
|
||||
return result;
|
||||
},
|
||||
|
||||
toWarn: function(actual, settings = defaultSettings) {
|
||||
toWarn: function(actual, settings = new Settings()) {
|
||||
const result = {
|
||||
pass: false,
|
||||
message: () =>
|
||||
|
@@ -4,7 +4,7 @@
|
||||
/* global describe: false */
|
||||
import Settings from "../src/Settings";
|
||||
import {scriptFromCodepoint, supportedCodepoint} from "../src/unicodeScripts";
|
||||
import {strictSettings} from "./helpers";
|
||||
import {strictSettings, nonstrictSettings} from "./helpers";
|
||||
|
||||
describe("unicode", function() {
|
||||
it("should parse Latin-1 inside \\text{}", function() {
|
||||
@@ -21,7 +21,7 @@ describe("unicode", function() {
|
||||
|
||||
it("should parse Latin-1 outside \\text{}", function() {
|
||||
expect('ÀÁÂÃÄÅÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝàáâãäåèéêëìíîïñòóôõöùúûüýÿ' +
|
||||
'ÇÐÞçðþ').toParse();
|
||||
'ÇÐÞçðþ').toParse(nonstrictSettings);
|
||||
});
|
||||
|
||||
it("should parse all lower case Greek letters", function() {
|
||||
|
Reference in New Issue
Block a user