From 9a6401fb0920fe77ab61c261020c06bd6bf84ac9 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Fri, 5 Jan 2018 09:56:38 -0500 Subject: [PATCH 01/10] Update to jsdom v10 interface. Resolves issue #325. --- lib/main.js | 27 +++-- lib/patch/jsdom.js | 297 +-------------------------------------------- package-lock.json | 58 ++++++++- package.json | 2 +- 4 files changed, 74 insertions(+), 310 deletions(-) diff --git a/lib/main.js b/lib/main.js index 9cb2b6a0..92e53e9c 100644 --- a/lib/main.js +++ b/lib/main.js @@ -30,10 +30,11 @@ var http = require('http'); var fs = require('fs'); var path = require('path'); var url = require('url'); -var jsdom = require('jsdom').jsdom; +var jsdom = require('jsdom'); +var JSDOM = jsdom.JSDOM; var isFullwidthCodePoint = require('is-fullwidth-code-point'); -require('./patch/jsdom.js').patch(jsdom); // Fix some bugs in jsdom +require('./patch/jsdom.js').patch(JSDOM); // Fix some bugs in jsdom var displayMessages = false; // don't log Message.Set() calls var displayErrors = true; // show error messages on the console @@ -114,22 +115,22 @@ var CHTMLSTYLES; // filled in when CommonHTML is loaded // the jax to be loaded completely) // function GetWindow() { - document = jsdom('',{userAgent: "Node.js"}); +var virtualConsole = new jsdom.VirtualConsole(); +virtualConsole.sendTo(console); + window = new JSDOM('',{ + virtualConsole: virtualConsole, + userAgent: "Node.js", + runScripts: "dangerously", + resources: "usable" + }).window; + document = window.document; html = document.firstChild; - window = document.defaultView; - window.console = console; window.addEventListener("error",function (event) {AddError("Error: "+event.error.stack)}); content = document.body.appendChild(document.createElement("div")); content.id = "MathJax_Content"; content.innerHTML = '' + '' + ''; - // - // Node's url.resolve() has a problem with resolving a file:// URL when - // the base URL is "about:blank", so force it to be something else (HACK) - // since jsdom 3.x sets the base to "about:blank". - // - if (document._URL === "about:blank") document._URL = "file:///blank.html"; } // @@ -511,7 +512,7 @@ function StartMathJax() { serverState = STATE.STARTED; var script = document.createElement("script"); script.src = MathJaxPath; - script.onerror = function () {AddError("Can't load MathJax.js from "+MathJaxPath)} + script.onerror = function () {AddError("Can't load MathJax.js from "+MathJaxPath)}; document.head.appendChild(script); } @@ -557,7 +558,7 @@ function GetMML(result) { return MathJax.Callback.After(window.Array(GetMML,result),err.restart); } if (data.mml) result.mml = mml; - if (data.mmlNode) result.mmlNode = jsdom(mml).body.firstChild; + if (data.mmlNode) result.mmlNode = JSDOM.fragment(mml).firstChild; } // diff --git a/lib/patch/jsdom.js b/lib/patch/jsdom.js index bbbad23a..f3a1bb41 100644 --- a/lib/patch/jsdom.js +++ b/lib/patch/jsdom.js @@ -3,174 +3,7 @@ // between node 4 and node 5, so check which one we have. // -var PARSERS = 'jsdom/node_modules/cssstyle/lib/parsers.js'; // node 4 hierarchy -try {require(PARSERS)} catch (e) {PARSERS = 'cssstyle/lib/parsers.js'} // node 5 heirarchy - -// -// Companion to implicitSetter, but for the individual parts. -// This sets the individual value, and checks to see if all four -// sub-parts are set. If so, it sets the shorthand version and removes -// the individual parts from the cssText. -// -var subImplicitSetter = function (prefix, part, isValid, parser) { - var property = prefix + '-' + part; - var subparts = [prefix+"-top", prefix+"-right", prefix+"-bottom", prefix+"-left"]; - - return function (v) { - if (typeof v === 'number') v = v.toString(); - if (typeof v !== 'string') return undefined; - if (!isValid(v)) return undefined; - v = parser(v); - this._setProperty(property,v); - var parts = []; - for (var i = 0; i < 4; i++) { - if (this._values[subparts[i]] == null || this._values[subparts[i]] === '') break; - parts.push(this._values[subparts[i]]); - } - if (parts.length === 4) { - for (i = 0; i < 4; i++) { - this.removeProperty(subparts[i]); - this._values[subparts[i]] = parts[i]; - } - this._setProperty(prefix,parts.join(" ")); - } - return v; - }; -}; - -// -// Patch for CSSStyleDeclaration padding property so that it sets/clears -// the Top, Right, Bottom, and Left properties (and also validates the -// padding value) -// -var PADDING = (function () { - var parsers = require(PARSERS); - var TYPES = parsers.TYPES; - - var isValid = function (v) { - var type = parsers.valueType(v); - return type === TYPES.LENGTH || type === TYPES.PERCENT || v === "0"; - }; - - var parser = function (v) { - if (v === "0") return "0px"; - return parsers.parseMeasurement(v); - }; - - var mySetter = parsers.implicitSetter('padding', '', isValid, parser); - var myGlobal = parsers.implicitSetter('padding', '', function () {return true}, function (v) {return v}); - - return { - definition: { - set: function (v) { - if (typeof v === "number") v = String(v); - if (typeof v !== "string") return; - var V = v.toLowerCase(); - switch (V) { - case 'inherit': - case 'initial': - case 'unset': - case '': - myGlobal.call(this, V); - break; - - default: - mySetter.call(this, v); - break; - } - }, - get: function () { - return this.getPropertyValue('padding'); - }, - enumerable: true, - configurable: true - }, - isValid: isValid, - parser: parser - }; -})(); - -// -// Patch for CSSStyleDeclaration margin property so that it sets/clears -// the Top, Right, Bottom, and Left properties (and also validates the -// margin value) -// -var MARGIN = (function () { - var parsers = require(PARSERS); - var TYPES = parsers.TYPES; - - var isValid = function (v) { - if (v.toLowerCase() === "auto") return true; - var type = parsers.valueType(v); - return type === TYPES.LENGTH || type === TYPES.PERCENT || v === "0"; - }; - - var parser = function (v) { - var V = v.toLowerCase(); - if (V === "auto") return V; - if (v === "0") return "0px"; - return parsers.parseMeasurement(v); - }; - - var mySetter = parsers.implicitSetter('margin', '', isValid, parser); - var myGlobal = parsers.implicitSetter('margin', '', function () {return true}, function (v) {return v}); - - return { - definition: { - set: function (v) { - if (typeof v === "number") v = String(v); - if (typeof v !== "string") return; - var V = v.toLowerCase(); - switch (V) { - case 'inherit': - case 'initial': - case 'unset': - case '': - myGlobal.call(this, V); - break; - - default: - mySetter.call(this, v); - break; - } - }, - get: function () { - return this.getPropertyValue('margin'); - }, - enumerable: true, - configurable: true - }, - isValid: isValid, - parser: parser - }; -})(); - -// -// Patch for CSSStyleDeclaration width property that handles -// values of "auto" properly -// -var WIDTH = (function () { - var parseMeasurement = require(PARSERS).parseMeasurement; - - function parse(v) { - if (String(v).toLowerCase() === "auto") { - return "auto"; - } - return parseMeasurement(v); - } - - return { - set: function (v) { - this._setProperty('width', parse(v)); - }, - get: function () { - return this.getPropertyValue('width'); - }, - enumerable: true, - configurable: true - }; -})(); - +var PARSERS = 'cssstyle/lib/parsers.js'; // // Patch for CSSStyleDeclaration lengthRegEx so that it includes ex units @@ -282,132 +115,12 @@ var FixValueType = function () { // // Patch jsdom functions // -exports.patch = function (jsdom) { - var document = jsdom(''); - var window = document.defaultView; - // - // Fix setting of style attributes so shorthands work properly. - // +exports.patch = function (JSDOM) { + var window = new JSDOM('').window; + var document = window.document; + var div = document.createElement("div"); - div.style.border = "1px solid black"; - if (div.style.border !== "1px solid black") { - var INIT = window.HTMLElement._init; - window.HTMLElement._init = function () { - INIT.apply(this,arguments); - var that = this; - this.style._onChange = function (csstext) { - if (!that._settingCssText) { - that._settingCssText = true; - that.setAttribute('style', csstext); - that._settingCssText = false; - } - }; - } - } - // - // Add missing nodeName to Attr (after jsdom 7.1.0, it is no longer defined) - // since this is used in mml2jax. - // - if (!("nodeName" in window.Attr.prototype)) { - Object.defineProperties(window.Attr.prototype,{ - nodeName: {get: function() {return this.name}} - }); - } - - // - // Fix CSSStyleDeclaration properties that are broken (padding, margin, width) - // - // - // Check if padding resets paddingTop - // - div.style.paddingTop = "10px"; - div.style.padding = "1px"; - if (div.style.paddingTop !== "1px") { - var core = require("jsdom/lib/jsdom/living"); - Object.defineProperties(core.CSSStyleDeclaration.prototype,{ - padding: PADDING.definition, - margin: MARGIN.definition - }); - } - // - // Check if 0 pixels without "px" is OK - // - div.style.padding = ""; - div.style.padding = "1px 0 3px 4px"; - if (div.style.padding !== "1px 0px 3px 4px") { - var core = require("jsdom/lib/jsdom/living"); - Object.defineProperties(core.CSSStyleDeclaration.prototype,{ - padding: PADDING.definition, - margin: MARGIN.definition - }); - } - // - // Check if paddingTop sets padding - // - div.style.padding = "1px 2px 3px 4px"; - div.style.paddingTop = "10px"; - if (div.style.padding !== "10px 2px 3px 4px") { - var core = require("jsdom/lib/jsdom/living"); - Object.defineProperties(core.CSSStyleDeclaration.prototype,{ - marginTop: { - set: subImplicitSetter('margin', 'top', MARGIN.isValid, MARGIN.parser), - get: function () { - return this.getPropertyValue('margin-top'); - } - }, - marginRight: { - set: subImplicitSetter('margin', 'right', MARGIN.isValid, MARGIN.parser), - get: function () { - return this.getPropertyValue('margin-right'); - } - }, - marginBottom: { - set: subImplicitSetter('margin', 'bottom', MARGIN.isValid, MARGIN.parser), - get: function () { - return this.getPropertyValue('margin-bottom'); - } - }, - marginLeft: { - set: subImplicitSetter('margin', 'left', MARGIN.isValid, MARGIN.parser), - get: function () { - return this.getPropertyValue('margin-left'); - } - }, - paddingTop: { - set: subImplicitSetter('padding', 'top', PADDING.isValid, PADDING.parser), - get: function () { - return this.getPropertyValue('padding-top'); - } - }, - paddingRight: { - set: subImplicitSetter('padding', 'right', PADDING.isValid, PADDING.parser), - get: function () { - return this.getPropertyValue('padding-right'); - } - }, - paddingBottom: { - set: subImplicitSetter('padding', 'bottom', PADDING.isValid, PADDING.parser), - get: function () { - return this.getPropertyValue('padding-bottom'); - } - }, - paddingLeft: { - set: subImplicitSetter('padding', 'left', PADDING.isValid, PADDING.parser), - get: function () { - return this.getPropertyValue('padding-left'); - } - } - }); - } - // - // Check if width can be "auto" - // - div.style.width = "auto"; - if (div.style.width !== "auto") { - var core = require("jsdom/lib/jsdom/living"); - Object.defineProperties(core.CSSStyleDeclaration.prototype,{width: WIDTH}); - } // // Check if units of ex are allowed // diff --git a/package-lock.json b/package-lock.json index 25b9bdd0..e90b7fe5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mathjax-node", - "version": "1.2.0", + "version": "1.3.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -438,6 +438,11 @@ "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", "dev": true }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, "is-function": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", @@ -476,9 +481,9 @@ "optional": true }, "jsdom": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-9.12.0.tgz", - "integrity": "sha1-6MVG//ywbADUgzyoRBD+1/igl9Q=", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-10.1.0.tgz", + "integrity": "sha1-d2XgD9XDVn80mFochv9GamHazGo=", "requires": { "abab": "1.0.3", "acorn": "4.0.13", @@ -491,7 +496,9 @@ "html-encoding-sniffer": "1.0.1", "nwmatcher": "1.4.1", "parse5": "1.5.1", + "pn": "1.1.0", "request": "2.81.0", + "request-promise-native": "1.0.5", "sax": "1.2.4", "symbol-tree": "3.2.2", "tough-cookie": "2.3.2", @@ -551,6 +558,11 @@ "type-check": "0.3.2" } }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + }, "mathjax": { "version": "2.7.2", "resolved": "https://registry.npmjs.org/mathjax/-/mathjax-2.7.2.tgz", @@ -650,6 +662,11 @@ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=" }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==" + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -694,6 +711,34 @@ "uuid": "3.1.0" } }, + "request-promise-core": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", + "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", + "requires": { + "lodash": "4.17.4" + } + }, + "request-promise-native": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.5.tgz", + "integrity": "sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU=", + "requires": { + "request-promise-core": "1.1.1", + "stealthy-require": "1.1.1", + "tough-cookie": "2.3.3" + }, + "dependencies": { + "tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "requires": { + "punycode": "1.4.1" + } + } + } + }, "resolve": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", @@ -761,6 +806,11 @@ } } }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" + }, "string.prototype.trim": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", diff --git a/package.json b/package.json index 125b753c..2c4e20cb 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ }, "dependencies": { "is-fullwidth-code-point": "^2.0.0", - "jsdom": "7.0 - 9.12", + "jsdom": "^10.0", "mathjax": "^2.7.2" }, "scripts": { From 0b48155640f838099895c56466b735a5918caaeb Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Fri, 5 Jan 2018 10:32:34 -0500 Subject: [PATCH 02/10] Fix tests for jsdom 10 --- test/issue104.js | 6 +++--- test/issue175.js | 10 +++++----- test/issue207.js | 8 ++++---- test/issue215.js | 9 ++++----- test/issue219.js | 4 ++-- test/issue220.js | 7 +++---- test/issue223.js | 13 +++++-------- test/issue241.js | 1 - test/issue260.js | 1 - test/issue276.js | 7 +++---- test/mathjax-config-combined.js | 1 - test/output-html-linebreaks-manual.js | 1 - test/userconfig-jax.js | 1 - 13 files changed, 29 insertions(+), 40 deletions(-) diff --git a/test/issue104.js b/test/issue104.js index bedd0eaa..a67a84ea 100644 --- a/test/issue104.js +++ b/test/issue104.js @@ -1,6 +1,6 @@ var tape = require('tape'); var mjAPI = require("../lib/main.js"); -var jsdom = require('jsdom').jsdom; +var JSDOM = require('jsdom').JSDOM; tape('the SVG width should match the default', function(t) { t.plan(1); @@ -14,8 +14,8 @@ tape('the SVG width should match the default', function(t) { format: "TeX", svg: true }, function(data) { - var document = jsdom(data.svg); - var window = document.defaultView; + var window = new JSDOM(data.svg).window; + var document = window.document; var element = window.document.getElementsByTagName("svg")[0]; var width = element.getAttribute('width'); t.equal(width, expected); diff --git a/test/issue175.js b/test/issue175.js index ec62a01a..63a5cc67 100644 --- a/test/issue175.js +++ b/test/issue175.js @@ -1,6 +1,6 @@ var tape = require('tape'); var mjAPI = require("../lib/main.js"); -var jsdom = require('jsdom').jsdom; +var JSDOM = require('jsdom').JSDOM; tape('color extension should be reset', function(t) { t.plan(3); @@ -20,9 +20,9 @@ tape('color extension should be reset', function(t) { format: "TeX", mml: true }, function(data) { - var document = jsdom(data.mml); - var mstyle = document.defaultView.document.querySelector('mstyle'); - t.ok(document.defaultView.document.querySelectorAll('mi')[0].parentNode === mstyle, 'Color macro behaves correctly (1 of 2)'); - t.notOk(document.defaultView.document.querySelectorAll('mi')[1].parentNode === mstyle, 'Color macro behaves correctly (2 of 2)'); + var document = new JSDOM(data.mml).window.document; + var mstyle = document.querySelector('mstyle'); + t.ok(document.querySelectorAll('mi')[0].parentNode === mstyle, 'Color macro behaves correctly (1 of 2)'); + t.notOk(document.querySelectorAll('mi')[1].parentNode === mstyle, 'Color macro behaves correctly (2 of 2)'); }); }); diff --git a/test/issue207.js b/test/issue207.js index 40c675b6..34a7cb1a 100644 --- a/test/issue207.js +++ b/test/issue207.js @@ -1,6 +1,6 @@ var tape = require('tape'); var mjAPI = require("../lib/main.js"); -var jsdom = require('jsdom').jsdom; +var JSDOM = require('jsdom').JSDOM; tape('Generate dummy speechText', function(t) { t.plan(9); @@ -16,15 +16,15 @@ tape('Generate dummy speechText', function(t) { var desc3 = 'default dummy value'; mjSpeechTest = function(data, expected, desc) { - var document = jsdom(data.html).defaultView.document; + var document = new JSDOM(data.html).window.document; var element = document.querySelector('.mjx-math'); var actual = element.getAttribute('aria-label'); t.equal(actual, expected, 'HTML output contains speechText from ' + desc); - document = jsdom(data.mml).defaultView.document; + document = new JSDOM(data.mml).window.document; element = document.querySelector('math'); actual = element.getAttribute('alttext'); t.equal(actual, expected, 'MathML output contains speechText from ' + desc); - document = jsdom(data.svg).defaultView.document; + document = new JSDOM(data.svg).window.document; var svgTitle = document.querySelector('title'); actual = svgTitle.innerHTML; t.equal(actual, expected, 'SVG output contains speechText from ' + desc); diff --git a/test/issue215.js b/test/issue215.js index e6388b48..b97fe05f 100644 --- a/test/issue215.js +++ b/test/issue215.js @@ -1,6 +1,6 @@ var tape = require('tape'); var mjAPI = require("../lib/main.js"); -var jsdom = require('jsdom').jsdom; +var JSDOM = require('jsdom').JSDOM; tape('HTML output should remove automatically generated IDs', function(t) { t.plan(2); @@ -14,10 +14,9 @@ tape('HTML output should remove automatically generated IDs', function(t) { format: "TeX", html: true }, function(data) { - var document = jsdom(data.html); - var window = document.defaultView; - var id = window.document.querySelector('[id^="MJXc-Node-"]'); - var frame = window.document.querySelector('[id^="MathJax-Element-"]'); + var document = new JSDOM(data.html).window.document; + var id = document.querySelector('[id^="MJXc-Node-"]'); + var frame = document.querySelector('[id^="MathJax-Element-"]'); t.notOk(id, 'automatic ids successfully removed'); t.notOk(frame, 'MathJax-Element-[n]-frame id successfully removed'); }); diff --git a/test/issue219.js b/test/issue219.js index d469c56d..52b83c60 100644 --- a/test/issue219.js +++ b/test/issue219.js @@ -1,6 +1,6 @@ var tape = require('tape'); var mjAPI = require("../lib/main.js"); -var jsdom = require('jsdom').jsdom; +var JSDOM = require('jsdom').JSDOM; tape('Basic Check: pass jsdom object to output', function(t) { t.plan(3); @@ -18,7 +18,7 @@ tape('Basic Check: pass jsdom object to output', function(t) { mml: true, mmlNode: true }, function(data) { - var window = jsdom().defaultView; + var window = new JSDOM().window; t.ok(data.htmlNode instanceof window.HTMLElement, 'htmlNode is an HTMLElement'); t.ok(data.svgNode instanceof window.HTMLElement, 'svgNode is an HTMLElement'); t.ok(data.mmlNode instanceof window.HTMLElement, 'mmlNode is an HTMLElement'); diff --git a/test/issue220.js b/test/issue220.js index bedaf0e8..23c7d89b 100644 --- a/test/issue220.js +++ b/test/issue220.js @@ -1,6 +1,6 @@ var tape = require('tape'); var mjAPI = require("../lib/main.js"); -var jsdom = require('jsdom').jsdom; +var JSDOM = require('jsdom').JSDOM; tape('displayAlign:left in HTML output', function(t) { t.plan(1); @@ -14,9 +14,8 @@ tape('displayAlign:left in HTML output', function(t) { format: "TeX", html: true }, function(data) { - var document = jsdom(data.html); - var window = document.defaultView; - var element = window.document.getElementsByClassName("MJXc-display")[0]; + var document = new JSDOM(data.html).window.document; + var element = document.getElementsByClassName("MJXc-display")[0]; var result = element.getAttribute('style'); t.equal(result, expected); }); diff --git a/test/issue223.js b/test/issue223.js index 1cd26792..6ba16c7d 100644 --- a/test/issue223.js +++ b/test/issue223.js @@ -1,7 +1,6 @@ - var tape = require('tape'); var mjAPI = require("../lib/main.js"); -var jsdom = require('jsdom').jsdom; +var JSDOM = require('jsdom').JSDOM; tape('displayIndent:left in HTML output', function(t) { t.plan(2); @@ -17,9 +16,8 @@ tape('displayIndent:left in HTML output', function(t) { format: "TeX", html: true }, function(data) { - var document = jsdom(data.html); - var window = document.defaultView; - var element = window.document.getElementsByClassName('MJXc-display')[0]; + var document = new JSDOM(data.html).window.document; + var element = document.getElementsByClassName('MJXc-display')[0]; var result = element.style.marginLeft; t.ok((result === expected), 'style includes a margin'); }); @@ -30,9 +28,8 @@ tape('displayIndent:left in HTML output', function(t) { format: "TeX", html: true }, function(data) { - var document = jsdom(data.html); - var window = document.defaultView; - var element = window.document.getElementsByClassName('mjx-table')[0]; + var document = new JSDOM(data.html).window.document; + var element = document.getElementsByClassName('mjx-table')[0]; var result = element.style.marginLeft; t.ok((result === expected), 'style includes a margin'); }); diff --git a/test/issue241.js b/test/issue241.js index 21968afb..e5eb2301 100644 --- a/test/issue241.js +++ b/test/issue241.js @@ -1,6 +1,5 @@ var tape = require('tape'); var mjAPI = require("../lib/main.js"); -var jsdom = require('jsdom').jsdom; tape('SVG output: add xlink to href in ', function(t) { t.plan(1); diff --git a/test/issue260.js b/test/issue260.js index 51692a60..1fc1877c 100644 --- a/test/issue260.js +++ b/test/issue260.js @@ -1,6 +1,5 @@ var tape = require('tape'); var mjAPI = require('../lib/main.js'); -var jsdom = require('jsdom').jsdom; tape('getSVG should increment state.ID', function(t) { t.plan(1); diff --git a/test/issue276.js b/test/issue276.js index f225b29e..30c56316 100644 --- a/test/issue276.js +++ b/test/issue276.js @@ -1,6 +1,6 @@ var tape = require('tape'); var mjAPI = require("../lib/main.js"); -var jsdom = require('jsdom').jsdom; +var JSDOM = require('jsdom').JSDOM; tape('SVG output: physical units', function(t) { t.plan(1); @@ -12,9 +12,8 @@ tape('SVG output: physical units', function(t) { format: "MathML", svg: true }, function(data) { - var document = jsdom(data.svg); - var doc = document.defaultView.document; - var width = doc.querySelector('svg').getAttribute('width'); + var document = new JSDOM(data.svg).window.document; + var width = document.querySelector('svg').getAttribute('width'); t.notEqual(width, '0', ''); }); }); diff --git a/test/mathjax-config-combined.js b/test/mathjax-config-combined.js index aee36440..13bc9d10 100644 --- a/test/mathjax-config-combined.js +++ b/test/mathjax-config-combined.js @@ -1,6 +1,5 @@ var tape = require('tape'); var mjAPI = require("../lib/main.js"); -var jsdom = require('jsdom').jsdom; tape('MathJax configuration: strip config block', function (t) { t.plan(1); diff --git a/test/output-html-linebreaks-manual.js b/test/output-html-linebreaks-manual.js index 11f8b764..0505976d 100644 --- a/test/output-html-linebreaks-manual.js +++ b/test/output-html-linebreaks-manual.js @@ -1,6 +1,5 @@ var tape = require('tape'); var mjAPI = require("../lib/main.js"); -var jsdom = require('jsdom').jsdom; tape('Output, HTML: linebreaks, manual', function(t) { t.plan(1); diff --git a/test/userconfig-jax.js b/test/userconfig-jax.js index 385de89e..7bd3f8c1 100644 --- a/test/userconfig-jax.js +++ b/test/userconfig-jax.js @@ -1,6 +1,5 @@ var tape = require('tape'); var mjAPI = require('../lib/main.js'); -var jsdom = require('jsdom').jsdom; tape('User configuration with jax array', function (t) { t.plan(1); From c732d701f442f06745197d1d39a2ef43df592fa7 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Fri, 5 Jan 2018 12:15:31 -0500 Subject: [PATCH 03/10] Update travis to not use node 4 and 5 any more (jsdom10 requires node 6). --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6d8d084c..f13ced9c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,5 @@ language: node_js node_js: -- '4' -- '5' - '6' - '7' - '8' From b9cb78bbdb8ae01337c75ba465d126a4f10437c2 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Fri, 5 Jan 2018 13:54:21 -0500 Subject: [PATCH 04/10] Override mglyph handling so as not to try to load the source image. This requires explicit width and height to be set, and now produces errors if that isn't the case. --- lib/main.js | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/lib/main.js b/lib/main.js index 92e53e9c..9baef798 100644 --- a/lib/main.js +++ b/lib/main.js @@ -325,6 +325,30 @@ function ConfigureMathJax() { this.d = this.D = (bbox.height + bbox.y)*scale; } }); + + // + // Don't have mglyph load images + // + MathJax.Hub.Register.StartupHook("SVG mglyph Ready",function () { + var MML = MathJax.ElementJax.mml; + var MGLYPH = MML.mglyph; + var TOSVG = MGLYPH.prototype.toSVG; + MGLYPH.Augment({ + toSVG: function (variant,scale) { + var values = this.getValues("src","width","height"); + if (values.src !== "" && !MGLYPH.GLYPH[values.src]) { + if (!values.width || !values.height) { + AddError("mglyphs must have explicit width and height in mathjax-node"); + } + MGLYPH.GLYPH[values.src] = { + img: {SRC: values.src, width: 0, height: 0}, + status: "OK" + }; + } + return TOSVG.apply(this,arguments); + } + }); + }); }); @@ -428,6 +452,30 @@ function ConfigureMathJax() { }); + // + // Don't have mglyph load images + // + MathJax.Hub.Register.StartupHook("CommonHTML mglyph Ready",function () { + var MML = MathJax.ElementJax.mml; + var MGLYPH = MML.mglyph; + var TOCHTML = MGLYPH.prototype.toCommonHTML; + MGLYPH.Augment({ + toCommonHTML: function (node,options) { + var values = this.getValues("src","width","height"); + if (values.src !== "" && !MGLYPH.GLYPH[values.src]) { + if (!values.width || !values.height) { + AddError("mglyphs must have explicit width and height in mathjax-node"); + } + MGLYPH.GLYPH[values.src] = { + img: {SRC: values.src, width: 0, height: 0}, + status: "OK" + }; + } + return TOCHTML.apply(this,arguments); + } + }); + }); + }); // From 0d0c48bfdbfba21586ae90e8623bc9b9a1f6a390 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Sun, 14 Jan 2018 11:32:01 -0500 Subject: [PATCH 05/10] Add engine dependency (issue #377), and bump version number (issue #325). --- package.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 2c4e20cb..6e76909c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mathjax-node", - "version": "1.3.0", + "version": "2.0.0", "description": "API's for calling MathJax from node.js", "keywords": [ "MathJax", @@ -24,9 +24,12 @@ }, "dependencies": { "is-fullwidth-code-point": "^2.0.0", - "jsdom": "^10.0", + "jsdom": "^10.0.0", "mathjax": "^2.7.2" }, + "engines": { + "node": ">=6.0.0" + }, "scripts": { "test": "tape test/*.js" }, From c5a328f12cf249cc2b1ea5654c4812c62278459a Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Mon, 15 Jan 2018 09:57:06 -0500 Subject: [PATCH 06/10] Spacing in package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6e76909c..369457cb 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "mathjax": "^2.7.2" }, "engines": { - "node": ">=6.0.0" + "node": ">=6.0.0" }, "scripts": { "test": "tape test/*.js" From 663700b0ca5d87ea5d3202f490084ceb12dedc58 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Mon, 15 Jan 2018 10:10:12 -0500 Subject: [PATCH 07/10] Update version in package-log.json --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index e90b7fe5..b450687f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mathjax-node", - "version": "1.3.0", + "version": "2.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { From 546c014d06af2016c1bd0d74c1a8668ff2b86272 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Mon, 15 Jan 2018 10:11:37 -0500 Subject: [PATCH 08/10] Use NativeMML output for mml-only output --- lib/main.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/main.js b/lib/main.js index 9baef798..cf796832 100644 --- a/lib/main.js +++ b/lib/main.js @@ -749,7 +749,13 @@ function StartQueue() { // GetState(data.state); - var renderer = ( (data.html || data.htmlNode || data.css) ? "CommonHTML" : "SVG"); + // + // Get the renderer to use + // + var renderer = ( + (data.html || data.htmlNode || data.css) ? "CommonHTML" : + (data.svg || data.svgNode) ? "SVG" : "NativeMML" + ); // // Set up a timeout timer to restart MathJax if it runs too long, From 8386df93e4f283fb4ea16a7b48612edc7cea7361 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Sat, 20 Jan 2018 10:32:03 -0500 Subject: [PATCH 09/10] Add output jax 'None' for the caase of jsut MathML (or no output). --- lib/main.js | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/lib/main.js b/lib/main.js index cf796832..81e6c473 100644 --- a/lib/main.js +++ b/lib/main.js @@ -115,8 +115,8 @@ var CHTMLSTYLES; // filled in when CommonHTML is loaded // the jax to be loaded completely) // function GetWindow() { -var virtualConsole = new jsdom.VirtualConsole(); -virtualConsole.sendTo(console); + var virtualConsole = new jsdom.VirtualConsole(); + virtualConsole.sendTo(console); window = new JSDOM('',{ virtualConsole: virtualConsole, userAgent: "Node.js", @@ -141,7 +141,6 @@ function ConfigureMathJax() { // // Load all input jax and preprocessors // Load AMS extensions and the autoload extension for TeX - // Allow $...$ delimiters and don't create previews for any preprocessor, // Create stand-alone SVG elements with font caches by default // (users can override that) // @@ -478,6 +477,18 @@ function ConfigureMathJax() { }); + // + // Set up None output jax (for when only MathML output is needed) + // + MathJax.OutputJax.None = MathJax.OutputJax({ + id: "None", + preTranslate: function () {}, + Translate: function () {}, + postTranslate: function () {} + }); + MathJax.OutputJax.None.loadComplete("jax.js"); + MathJax.OutputJax.None.Register("jax/mml"); + // // Reset the color extension after `autoload-all` // @@ -497,14 +508,14 @@ function ConfigureMathJax() { // (reseting the counters so that the initial math doesn't affect them) // MathJax.Hub.Register.StartupHook("End",function () { - MathJax.OutputJax.SVG.resetGlyphs(true); + if (MathJax.OutputJax.SVG.resetGlyphs) MathJax.OutputJax.SVG.resetGlyphs(true); MathJax.ElementJax.mml.ID = 0; serverState = STATE.READY; MathJax.Hub.Queue(StartQueue); }); } }; - + if (extensions) { // // Parse added extensions list and add to standard ones @@ -592,7 +603,7 @@ function AddError(message,nopush) { function GetMML(result) { if (!data.mml && !data.mmlNode) return; var jax = MathJax.Hub.getAllJax()[0]; - if (data.speakText && !jax.root.alttext){ + if (data.speakText && !jax.root.alttext) { jax.root.alttext = result.speakText; var attrNames = jax.root.attrNames; if (attrNames && attrNames.indexOf("alttext") === -1) { @@ -754,7 +765,7 @@ function StartQueue() { // var renderer = ( (data.html || data.htmlNode || data.css) ? "CommonHTML" : - (data.svg || data.svgNode) ? "SVG" : "NativeMML" + (data.svg || data.svgNode) ? "SVG" : "None" ); // @@ -786,7 +797,7 @@ function GetState(state) { MML = MathJax.ElementJax.mml, AMS = MathJax.Extension["TeX/AMSmath"], HUB = MathJax.Hub, HTML = MathJax.HTML, - GLYPH = SVG.BBOX.GLYPH; + GLYPH = (SVG.BBOX||{}).GLYPH; if (state && state.AMS) { AMS.startNumber = state.AMS.startNumber; @@ -799,7 +810,7 @@ function GetState(state) { ID = state.ID; } else { if (state) {state.AMS = {}} - SVG.resetGlyphs(true); + if (SVG.resetGlyphs) SVG.resetGlyphs(true); if (data.useGlobalCache) { state.glyphs = {}; state.defs = HTML.Element("defs"); @@ -832,7 +843,7 @@ function ReturnResult(result) { var state = data.state; if (state) { var AMS = MathJax.Extension["TeX/AMSmath"]; - var GLYPH = MathJax.OutputJax.SVG.BBOX.GLYPH; + var GLYPH = (MathJax.OutputJax.SVG||{}).BBOX.GLYPH; state.AMS.startNumber = AMS.startNumber; state.AMS.labels = AMS.labels; state.AMS.IDs = AMS.IDs; From bbc1f265c40856769ad85eb2ccbdd15b09912392 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Mon, 5 Feb 2018 19:35:22 -0500 Subject: [PATCH 10/10] Update travis key --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f13ced9c..bb650cbf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,6 @@ deploy: provider: npm email: manager@mathjax.org api_key: - secure: aJ/ZDGLods2x/Iss0bNgZ3xNHR7K8kkjEZ9jMAjTNxRlgC1oTbmjnPVVwybznUoIf8e13vpEyLHVNCZFWiE1rHwsguJCa1FoANKjpw51o/B811DZ65Nvj0qFuSi9UrHUwuVcnVCp2Qn2XEschCgT9yVWmiOmstq3557qg2iUJ1o= + secure: MG7sE1EsJd1wvcy1HPqX1YD3kvW0JODhgxN5xquHxitF8ua9Wevn0xwNnYMZdHhaiimaRn63L6wE1Rx6B41Z07uOAIPzcGi9Z6qqqQjrxhGC7WKdLd8gLD7RULhneTZ/ABjPgH2YQ31zcR17QEo34O4HbpKYmcrfSNfHd1IOgvA= on: tags: true