diff --git a/.eslintrc b/.eslintrc index fd613b83..df9d7d57 100644 --- a/.eslintrc +++ b/.eslintrc @@ -6,18 +6,37 @@ "parserOptions": { "sourceType": "module" }, - "plugins": ["compat", "qunit", "testcafe"], + "plugins": ["compat", "qunit", "testcafe", "jsdoc", "markdown"], "env": { "node": false, "browser": true }, "settings": { - "polyfills": ["url", "promises", "fetch", "queryselector"] + "polyfills": ["url", "promises", "fetch", "queryselector"], + "jsdoc": { + "additionalTagNames": { + "customTags": [] + }, + "tagNamePreference": { + "arg": "param", + "return": "returns" + }, + "allowOverrideWithoutParam": true, + "allowImplementsWithoutParam": true, + "allowAugmentsExtendsWithoutParam": true + } }, + "overrides": [{ + "files": ["**/*.md"], + "rules": { + "no-undef": ["off"], + "no-unused-vars": ["warn"], + "padded-blocks": ["off"] + } + }], "rules": { "semi": [2, "always"], "indent": ["error", 2, {"outerIIFEBody": 0}], - "no-tabs": 0, "object-property-newline": 0, "one-var": 0, "no-var": 2, @@ -25,6 +44,23 @@ "no-extra-semi": 2, "quote-props": [2, "as-needed"], "object-curly-spacing": ["error", "never"], + "jsdoc/check-param-names": 1, + "jsdoc/check-tag-names": 1, + "jsdoc/check-types": 1, + "jsdoc/newline-after-description": 0, + "jsdoc/require-description": 0, + "jsdoc/require-description-complete-sentence": 0, + "jsdoc/require-example": 0, + "jsdoc/require-hyphen-before-param-description": 0, + "jsdoc/require-param-description": 0, + "jsdoc/require-param": 1, + "jsdoc/require-param-name": 1, + "jsdoc/require-param-type": 1, + "jsdoc/require-returns-description": 0, + "jsdoc/require-returns-type": 1, + + "jsdoc/no-undefined-types": ["off"], + "jsdoc/valid-types": ["error"], "valid-jsdoc": ["off", { "prefer": { "arg": "param", diff --git a/CHANGES.md b/CHANGES.md index 69837d02..29bc81f8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,13 +2,26 @@ ## 3.2.0 -- Refactoring: Avoid unnecessary addEventListener `false`; change internal +- Refactoring: Avoid unnecessary `addEventListener` `false`; change internal jPicker function to class (used with `new`) -- Linting (ESLint): Add `valid-jsdoc` rule and make fixes; but turn off for - now due to and - -- Linting (ESLint compat): Add eslint-plugin-compat to get browser support +- Linting (ESLint): Add `valid-jsdoc` rule and make fixes, but turn off for + now due to and + +- Linting (ESLint compat): Add `eslint-plugin-compat` to get browser support warnings +- Linting (ESLint Markdown JavaScript): Add `eslint-plugin-markdown` with + slightly loosened config (`no-undef` and `padded-blocks` off and + `no-unused-vars` as a warning) +- Linting (ESLint JSDoc code comments): Add `eslint-plugin-jsdoc` and apply to + JSDoc code comments though disable `jsdoc/valid-types` rule for now due to and disable rule + `jsdoc/require-param` due to + ; also of + possible interest: , + , + , + , + , + - Docs (README): Indicate minimal polyfills needed for older browsers (IE <= 11, IE Mobile, Opera Mini, Blackberry Browser <= 10, Android Browser 4.4.3-4.4.4) diff --git a/demos/canvas.html b/demos/canvas.html index d5d9ee3d..6a58d595 100644 --- a/demos/canvas.html +++ b/demos/canvas.html @@ -6,6 +6,7 @@ + diff --git a/docs/Linting.md b/docs/Linting.md new file mode 100644 index 00000000..ad1ce81f --- /dev/null +++ b/docs/Linting.md @@ -0,0 +1,29 @@ +## Command line + +``` +npm run eslint +``` + +This will query both JavaScript files and will query JavaScript within +Markdown files. It will also check for some JSDoc issues. + +## JSDoc + +To check for JSDoc issues, besides the eslint script, one may run the +following to find any overly generic types in use (types should be as +specific as possible): + +``` +npm run types-doc +``` + +See also [ReleaseInstructions](./ReleaseInstructions.md). + +## Atom usage + +If using the Atom package `linter-eslint`, one may add `source.gfm` to the +"List of scopes to run ESLint on..." setting to get reporting of JavaScript +errors in Markdown. + +One may also add `source.embedded.js` though configuration comments +and skip directives (not currently in use) don't seem to work there. diff --git a/docs/jsdoc-config.js b/docs/jsdoc-config.js index 890f061f..170f7a1f 100644 --- a/docs/jsdoc-config.js +++ b/docs/jsdoc-config.js @@ -4,6 +4,8 @@ module.exports = { plugins: ['plugins/markdown'], markdown: { + // tags: ['examples'] + /* // "The highlighter function should escape the code block's contents and wrap them in
 tags"
     highlight (code, language) {
       function ret () {
@@ -11,6 +13,8 @@ module.exports = {
         return '
' + code + ' in this language: ' + language + '
'; } if (language !== 'js') { // E.g., we have one URL in some tutorial Markdown + // Seems to be only for full triple-backticked fences + // console.log('lll', code); return ret(); } @@ -48,8 +52,8 @@ module.exports = { console.log('\n' + code); return ret(); - }, - tags: [] + } + */ }, recurseDepth: 10, source: { @@ -69,15 +73,15 @@ module.exports = { }, templates: { cleverLinks: true, - monospaceLinks: false, + monospaceLinks: false /* , default: { layoutFile: 'docs/layout.tmpl' - } + } */ }, opts: { recurse: true, verbose: true, - destination: 'docs/jsdoc', + // destination: 'docs/jsdoc', tutorials: 'docs/tutorials' } }; diff --git a/editor/browser.js b/editor/browser.js index dcf8ab9d..b21e1bd5 100644 --- a/editor/browser.js +++ b/editor/browser.js @@ -132,8 +132,10 @@ const crect = rect.cloneNode(false); const retValue = (!crect.getAttribute('x').includes(',')); if (!retValue) { // Todo: i18nize or remove - $.alert('NOTE: This version of Opera is known to contain bugs in SVG-edit.\n' + - 'Please upgrade to the latest version in which the problems have been fixed.'); + $.alert( + 'NOTE: This version of Opera is known to contain bugs in SVG-edit.\n' + + 'Please upgrade to the latest version in which the problems have been fixed.' + ); } return retValue; }()); @@ -152,13 +154,13 @@ rxform.appendItem(t1); const r1 = rxform.getItem(0); // Todo: Do frame-independent instance checking return r1 instanceof SVGTransform && t1 instanceof SVGTransform && - r1.type === t1.type && r1.angle === t1.angle && - r1.matrix.a === t1.matrix.a && - r1.matrix.b === t1.matrix.b && - r1.matrix.c === t1.matrix.c && - r1.matrix.d === t1.matrix.d && - r1.matrix.e === t1.matrix.e && - r1.matrix.f === t1.matrix.f; + r1.type === t1.type && r1.angle === t1.angle && + r1.matrix.a === t1.matrix.a && + r1.matrix.b === t1.matrix.b && + r1.matrix.c === t1.matrix.c && + r1.matrix.d === t1.matrix.d && + r1.matrix.e === t1.matrix.e && + r1.matrix.f === t1.matrix.f; }()); // Public API diff --git a/editor/canvg/canvg.js b/editor/canvg/canvg.js index 7dadc289..f5a09937 100644 --- a/editor/canvg/canvg.js +++ b/editor/canvg/canvg.js @@ -9,7 +9,7 @@ */ import RGBColor from './rgbcolor.js'; -import {canvasRGBA} from './StackBlur.js'; +import {canvasRGBA} from '../external/stackblur-canvas/dist/stackblur-es.js'; let canvasRGBA_ = canvasRGBA; @@ -57,7 +57,7 @@ export const setStackBlurCanvasRGBA = (cb) => { * with `` elements. * @function module:canvg.canvg * @param {HTMLCanvasElement|string} target canvas element or the id of a canvas element -* @param {string|XMLDocument} s: svg string, url to svg file, or xml document +* @param {string|XMLDocument} s - svg string, url to svg file, or xml document * @param {module:canvg.CanvgOptions} [opts] Optional hash of options * @returns {Promise} All the function after the first render is completed with dom */ diff --git a/editor/extensions/ext-foreignobject.js b/editor/extensions/ext-foreignobject.js index 78420564..a39f88c7 100644 --- a/editor/extensions/ext-foreignobject.js +++ b/editor/extensions/ext-foreignobject.js @@ -49,11 +49,10 @@ export default { /** * This function sets the content of element elt to the input XML. * @param {string} xmlString - The XML text - * @param {Element} elt - the parent element to append to * @returns {boolean} This function returns false if the set was unsuccessful, true otherwise. */ function setForeignString (xmlString) { - const elt = selElems[0]; + const elt = selElems[0]; // The parent `Element` to append to try { // convert string into XML document const newDoc = text2xml('' + xmlString + ''); diff --git a/editor/canvg/StackBlur.js b/editor/external/stackblur-canvas/dist/stackblur-es.js similarity index 52% rename from editor/canvg/StackBlur.js rename to editor/external/stackblur-canvas/dist/stackblur-es.js index 4e3c59b2..f7b00402 100644 --- a/editor/canvg/StackBlur.js +++ b/editor/external/stackblur-canvas/dist/stackblur-es.js @@ -1,80 +1,44 @@ /** * StackBlur - a fast almost Gaussian Blur For Canvas - -In case you find this class useful - especially in commercial projects - -I am not totally unhappy for a small donation to my PayPal account -mario@quasimondo.de - -Or support me on flattr: -https://flattr.com/thing/72791/StackBlur-a-fast-almost-Gaussian-Blur-Effect-for-CanvasJavascript - +* +* In case you find this class useful - especially in commercial projects - +* I am not totally unhappy for a small donation to my PayPal account +* mario@quasimondo.de +* +* Or support me on flattr: +* {@link https://flattr.com/thing/72791/StackBlur-a-fast-almost-Gaussian-Blur-Effect-for-CanvasJavascript} * @module StackBlur * @version 0.5 * @author Mario Klingemann -Contact: mario@quasimondo.com -Website: http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html -Twitter: @quasimondo - +* Contact: mario@quasimondo.com +* Website: {@link http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html} +* Twitter: @quasimondo +* * @copyright (c) 2010 Mario Klingemann - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. +* +* Permission is hereby granted, free of charge, to any person +* obtaining a copy of this software and associated documentation +* files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, +* copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following +* conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. */ - -const mulTable = [ - 512, 512, 456, 512, 328, 456, 335, 512, 405, 328, 271, 456, 388, 335, 292, 512, - 454, 405, 364, 328, 298, 271, 496, 456, 420, 388, 360, 335, 312, 292, 273, 512, - 482, 454, 428, 405, 383, 364, 345, 328, 312, 298, 284, 271, 259, 496, 475, 456, - 437, 420, 404, 388, 374, 360, 347, 335, 323, 312, 302, 292, 282, 273, 265, 512, - 497, 482, 468, 454, 441, 428, 417, 405, 394, 383, 373, 364, 354, 345, 337, 328, - 320, 312, 305, 298, 291, 284, 278, 271, 265, 259, 507, 496, 485, 475, 465, 456, - 446, 437, 428, 420, 412, 404, 396, 388, 381, 374, 367, 360, 354, 347, 341, 335, - 329, 323, 318, 312, 307, 302, 297, 292, 287, 282, 278, 273, 269, 265, 261, 512, - 505, 497, 489, 482, 475, 468, 461, 454, 447, 441, 435, 428, 422, 417, 411, 405, - 399, 394, 389, 383, 378, 373, 368, 364, 359, 354, 350, 345, 341, 337, 332, 328, - 324, 320, 316, 312, 309, 305, 301, 298, 294, 291, 287, 284, 281, 278, 274, 271, - 268, 265, 262, 259, 257, 507, 501, 496, 491, 485, 480, 475, 470, 465, 460, 456, - 451, 446, 442, 437, 433, 428, 424, 420, 416, 412, 408, 404, 400, 396, 392, 388, - 385, 381, 377, 374, 370, 367, 363, 360, 357, 354, 350, 347, 344, 341, 338, 335, - 332, 329, 326, 323, 320, 318, 315, 312, 310, 307, 304, 302, 299, 297, 294, 292, - 289, 287, 285, 282, 280, 278, 275, 273, 271, 269, 267, 265, 263, 261, 259]; - -const shgTable = [ - 9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, - 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24]; - +const mulTable = [512, 512, 456, 512, 328, 456, 335, 512, 405, 328, 271, 456, 388, 335, 292, 512, 454, 405, 364, 328, 298, 271, 496, 456, 420, 388, 360, 335, 312, 292, 273, 512, 482, 454, 428, 405, 383, 364, 345, 328, 312, 298, 284, 271, 259, 496, 475, 456, 437, 420, 404, 388, 374, 360, 347, 335, 323, 312, 302, 292, 282, 273, 265, 512, 497, 482, 468, 454, 441, 428, 417, 405, 394, 383, 373, 364, 354, 345, 337, 328, 320, 312, 305, 298, 291, 284, 278, 271, 265, 259, 507, 496, 485, 475, 465, 456, 446, 437, 428, 420, 412, 404, 396, 388, 381, 374, 367, 360, 354, 347, 341, 335, 329, 323, 318, 312, 307, 302, 297, 292, 287, 282, 278, 273, 269, 265, 261, 512, 505, 497, 489, 482, 475, 468, 461, 454, 447, 441, 435, 428, 422, 417, 411, 405, 399, 394, 389, 383, 378, 373, 368, 364, 359, 354, 350, 345, 341, 337, 332, 328, 324, 320, 316, 312, 309, 305, 301, 298, 294, 291, 287, 284, 281, 278, 274, 271, 268, 265, 262, 259, 257, 507, 501, 496, 491, 485, 480, 475, 470, 465, 460, 456, 451, 446, 442, 437, 433, 428, 424, 420, 416, 412, 408, 404, 400, 396, 392, 388, 385, 381, 377, 374, 370, 367, 363, 360, 357, 354, 350, 347, 344, 341, 338, 335, 332, 329, 326, 323, 320, 318, 315, 312, 310, 307, 304, 302, 299, 297, 294, 292, 289, 287, 285, 282, 280, 278, 275, 273, 271, 269, 267, 265, 263, 261, 259]; +const shgTable = [9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24]; /** * @param {string|HTMLImageElement} img * @param {string|HTMLCanvasElement} canvas @@ -82,19 +46,23 @@ const shgTable = [ * @param {boolean} blurAlphaChannel * @returns {undefined} */ -function processImage (img, canvas, radius, blurAlphaChannel) { + +function processImage(img, canvas, radius, blurAlphaChannel) { if (typeof img === 'string') { img = document.getElementById(img); } + if (!img || !('naturalWidth' in img)) { return; } + const w = img.naturalWidth; const h = img.naturalHeight; if (typeof canvas === 'string') { canvas = document.getElementById(canvas); } + if (!canvas || !('getContext' in canvas)) { return; } @@ -103,12 +71,13 @@ function processImage (img, canvas, radius, blurAlphaChannel) { canvas.style.height = h + 'px'; canvas.width = w; canvas.height = h; - const context = canvas.getContext('2d'); context.clearRect(0, 0, w, h); context.drawImage(img, 0, 0); - if (isNaN(radius) || radius < 1) { return; } + if (isNaN(radius) || radius < 1) { + return; + } if (blurAlphaChannel) { processCanvasRGBA(canvas, 0, 0, w, h, radius); @@ -116,7 +85,6 @@ function processImage (img, canvas, radius, blurAlphaChannel) { processCanvasRGB(canvas, 0, 0, w, h, radius); } } - /** * @param {string|HTMLCanvasElement} canvas * @param {Integer} topX @@ -126,10 +94,13 @@ function processImage (img, canvas, radius, blurAlphaChannel) { * @throws {Error} * @returns {ImageData} See {@link https://html.spec.whatwg.org/multipage/canvas.html#imagedata} */ -function getImageDataFromCanvas (canvas, topX, topY, width, height) { + + +function getImageDataFromCanvas(canvas, topX, topY, width, height) { if (typeof canvas === 'string') { canvas = document.getElementById(canvas); } + if (!canvas || !('getContext' in canvas)) { return; } @@ -142,7 +113,6 @@ function getImageDataFromCanvas (canvas, topX, topY, width, height) { throw new Error('unable to access image data: ' + e); } } - /** * @param {HTMLCanvasElement} canvas * @param {Integer} topX @@ -152,17 +122,18 @@ function getImageDataFromCanvas (canvas, topX, topY, width, height) { * @param {Float} radius * @returns {undefined} */ -function processCanvasRGBA (canvas, topX, topY, width, height, radius) { - if (isNaN(radius) || radius < 1) { return; } + + +function processCanvasRGBA(canvas, topX, topY, width, height, radius) { + if (isNaN(radius) || radius < 1) { + return; + } + radius |= 0; - let imageData = getImageDataFromCanvas(canvas, topX, topY, width, height); - imageData = processImageDataRGBA(imageData, topX, topY, width, height, radius); - canvas.getContext('2d').putImageData(imageData, topX, topY); } - /** * @param {ImageData} imageData * @param {Integer} topX @@ -172,52 +143,46 @@ function processCanvasRGBA (canvas, topX, topY, width, height, radius) { * @param {Float} radius * @returns {ImageData} */ -function processImageDataRGBA (imageData, topX, topY, width, height, radius) { + + +function processImageDataRGBA(imageData, topX, topY, width, height, radius) { const pixels = imageData.data; + let x, y, i, p, yp, yi, yw, rSum, gSum, bSum, aSum, rOutSum, gOutSum, bOutSum, aOutSum, rInSum, gInSum, bInSum, aInSum, pr, pg, pb, pa, rbs; + const div = radius + radius + 1; // const w4 = width << 2; - let x, y, i, p, yp, yi, yw, rSum, gSum, bSum, aSum, - rOutSum, gOutSum, bOutSum, aOutSum, - rInSum, gInSum, bInSum, aInSum, - pr, pg, pb, pa, rbs; - - const div = radius + radius + 1; - // const w4 = width << 2; const widthMinus1 = width - 1; const heightMinus1 = height - 1; const radiusPlus1 = radius + 1; const sumFactor = radiusPlus1 * (radiusPlus1 + 1) / 2; - const stackStart = new BlurStack(); let stack = stackStart; let stackEnd; + for (i = 1; i < div; i++) { stack = stack.next = new BlurStack(); + if (i === radiusPlus1) { stackEnd = stack; } } + stack.next = stackStart; let stackIn = null; let stackOut = null; - yw = yi = 0; - const mulSum = mulTable[radius]; const shgSum = shgTable[radius]; for (y = 0; y < height; y++) { rInSum = gInSum = bInSum = aInSum = rSum = gSum = bSum = aSum = 0; - rOutSum = radiusPlus1 * (pr = pixels[yi]); gOutSum = radiusPlus1 * (pg = pixels[yi + 1]); bOutSum = radiusPlus1 * (pb = pixels[yi + 2]); aOutSum = radiusPlus1 * (pa = pixels[yi + 3]); - rSum += sumFactor * pr; gSum += sumFactor * pg; bSum += sumFactor * pb; aSum += sumFactor * pa; - stack = stackStart; for (i = 0; i < radiusPlus1; i++) { @@ -230,28 +195,28 @@ function processImageDataRGBA (imageData, topX, topY, width, height, radius) { for (i = 1; i < radiusPlus1; i++) { p = yi + ((widthMinus1 < i ? widthMinus1 : i) << 2); - rSum += (stack.r = (pr = pixels[p])) * (rbs = radiusPlus1 - i); - gSum += (stack.g = (pg = pixels[p + 1])) * rbs; - bSum += (stack.b = (pb = pixels[p + 2])) * rbs; - aSum += (stack.a = (pa = pixels[p + 3])) * rbs; - + rSum += (stack.r = pr = pixels[p]) * (rbs = radiusPlus1 - i); + gSum += (stack.g = pg = pixels[p + 1]) * rbs; + bSum += (stack.b = pb = pixels[p + 2]) * rbs; + aSum += (stack.a = pa = pixels[p + 3]) * rbs; rInSum += pr; gInSum += pg; bInSum += pb; aInSum += pa; - stack = stack.next; } stackIn = stackStart; stackOut = stackEnd; + for (x = 0; x < width; x++) { - pixels[yi + 3] = pa = (aSum * mulSum) >> shgSum; + pixels[yi + 3] = pa = aSum * mulSum >> shgSum; + if (pa !== 0) { pa = 255 / pa; - pixels[yi] = ((rSum * mulSum) >> shgSum) * pa; - pixels[yi + 1] = ((gSum * mulSum) >> shgSum) * pa; - pixels[yi + 2] = ((bSum * mulSum) >> shgSum) * pa; + pixels[yi] = (rSum * mulSum >> shgSum) * pa; + pixels[yi + 1] = (gSum * mulSum >> shgSum) * pa; + pixels[yi + 2] = (bSum * mulSum >> shgSum) * pa; } else { pixels[yi] = pixels[yi + 1] = pixels[yi + 2] = 0; } @@ -260,57 +225,46 @@ function processImageDataRGBA (imageData, topX, topY, width, height, radius) { gSum -= gOutSum; bSum -= bOutSum; aSum -= aOutSum; - rOutSum -= stackIn.r; gOutSum -= stackIn.g; bOutSum -= stackIn.b; aOutSum -= stackIn.a; - - p = (yw + ((p = x + radius + 1) < widthMinus1 ? p : widthMinus1)) << 2; - - rInSum += (stackIn.r = pixels[p]); - gInSum += (stackIn.g = pixels[p + 1]); - bInSum += (stackIn.b = pixels[p + 2]); - aInSum += (stackIn.a = pixels[p + 3]); - + p = yw + ((p = x + radius + 1) < widthMinus1 ? p : widthMinus1) << 2; + rInSum += stackIn.r = pixels[p]; + gInSum += stackIn.g = pixels[p + 1]; + bInSum += stackIn.b = pixels[p + 2]; + aInSum += stackIn.a = pixels[p + 3]; rSum += rInSum; gSum += gInSum; bSum += bInSum; aSum += aInSum; - stackIn = stackIn.next; - - rOutSum += (pr = stackOut.r); - gOutSum += (pg = stackOut.g); - bOutSum += (pb = stackOut.b); - aOutSum += (pa = stackOut.a); - + rOutSum += pr = stackOut.r; + gOutSum += pg = stackOut.g; + bOutSum += pb = stackOut.b; + aOutSum += pa = stackOut.a; rInSum -= pr; gInSum -= pg; bInSum -= pb; aInSum -= pa; - stackOut = stackOut.next; - yi += 4; } + yw += width; } for (x = 0; x < width; x++) { gInSum = bInSum = aInSum = rInSum = gSum = bSum = aSum = rSum = 0; - yi = x << 2; rOutSum = radiusPlus1 * (pr = pixels[yi]); gOutSum = radiusPlus1 * (pg = pixels[yi + 1]); bOutSum = radiusPlus1 * (pb = pixels[yi + 2]); aOutSum = radiusPlus1 * (pa = pixels[yi + 3]); - rSum += sumFactor * pr; gSum += sumFactor * pg; bSum += sumFactor * pb; aSum += sumFactor * pa; - stack = stackStart; for (i = 0; i < radiusPlus1; i++) { @@ -324,18 +278,15 @@ function processImageDataRGBA (imageData, topX, topY, width, height, radius) { yp = width; for (i = 1; i <= radius; i++) { - yi = (yp + x) << 2; - - rSum += (stack.r = (pr = pixels[yi])) * (rbs = radiusPlus1 - i); - gSum += (stack.g = (pg = pixels[yi + 1])) * rbs; - bSum += (stack.b = (pb = pixels[yi + 2])) * rbs; - aSum += (stack.a = (pa = pixels[yi + 3])) * rbs; - + yi = yp + x << 2; + rSum += (stack.r = pr = pixels[yi]) * (rbs = radiusPlus1 - i); + gSum += (stack.g = pg = pixels[yi + 1]) * rbs; + bSum += (stack.b = pb = pixels[yi + 2]) * rbs; + aSum += (stack.a = pa = pixels[yi + 3]) * rbs; rInSum += pr; gInSum += pg; bInSum += pb; aInSum += pa; - stack = stack.next; if (i < heightMinus1) { @@ -346,14 +297,16 @@ function processImageDataRGBA (imageData, topX, topY, width, height, radius) { yi = x; stackIn = stackStart; stackOut = stackEnd; + for (y = 0; y < height; y++) { p = yi << 2; - pixels[p + 3] = pa = (aSum * mulSum) >> shgSum; + pixels[p + 3] = pa = aSum * mulSum >> shgSum; + if (pa > 0) { pa = 255 / pa; - pixels[p] = ((rSum * mulSum) >> shgSum) * pa; - pixels[p + 1] = ((gSum * mulSum) >> shgSum) * pa; - pixels[p + 2] = ((bSum * mulSum) >> shgSum) * pa; + pixels[p] = (rSum * mulSum >> shgSum) * pa; + pixels[p + 1] = (gSum * mulSum >> shgSum) * pa; + pixels[p + 2] = (bSum * mulSum >> shgSum) * pa; } else { pixels[p] = pixels[p + 1] = pixels[p + 2] = 0; } @@ -362,39 +315,31 @@ function processImageDataRGBA (imageData, topX, topY, width, height, radius) { gSum -= gOutSum; bSum -= bOutSum; aSum -= aOutSum; - rOutSum -= stackIn.r; gOutSum -= stackIn.g; bOutSum -= stackIn.b; aOutSum -= stackIn.a; - - p = (x + (((p = y + radiusPlus1) < heightMinus1 ? p : heightMinus1) * width)) << 2; - - rSum += (rInSum += (stackIn.r = pixels[p])); - gSum += (gInSum += (stackIn.g = pixels[p + 1])); - bSum += (bInSum += (stackIn.b = pixels[p + 2])); - aSum += (aInSum += (stackIn.a = pixels[p + 3])); - + p = x + ((p = y + radiusPlus1) < heightMinus1 ? p : heightMinus1) * width << 2; + rSum += rInSum += stackIn.r = pixels[p]; + gSum += gInSum += stackIn.g = pixels[p + 1]; + bSum += bInSum += stackIn.b = pixels[p + 2]; + aSum += aInSum += stackIn.a = pixels[p + 3]; stackIn = stackIn.next; - - rOutSum += (pr = stackOut.r); - gOutSum += (pg = stackOut.g); - bOutSum += (pb = stackOut.b); - aOutSum += (pa = stackOut.a); - + rOutSum += pr = stackOut.r; + gOutSum += pg = stackOut.g; + bOutSum += pb = stackOut.b; + aOutSum += pa = stackOut.a; rInSum -= pr; gInSum -= pg; bInSum -= pb; aInSum -= pa; - stackOut = stackOut.next; - yi += width; } } + return imageData; } - /** * @param {HTMLCanvasElement} canvas * @param {Integer} topX @@ -404,16 +349,18 @@ function processImageDataRGBA (imageData, topX, topY, width, height, radius) { * @param {Float} radius * @returns {undefined} */ -function processCanvasRGB (canvas, topX, topY, width, height, radius) { - if (isNaN(radius) || radius < 1) { return; } - radius |= 0; + +function processCanvasRGB(canvas, topX, topY, width, height, radius) { + if (isNaN(radius) || radius < 1) { + return; + } + + radius |= 0; let imageData = getImageDataFromCanvas(canvas, topX, topY, width, height); imageData = processImageDataRGB(imageData, topX, topY, width, height, radius); - canvas.getContext('2d').putImageData(imageData, topX, topY); } - /** * @param {ImageData} imageData * @param {Integer} topX @@ -423,50 +370,44 @@ function processCanvasRGB (canvas, topX, topY, width, height, radius) { * @param {Float} radius * @returns {ImageData} */ -function processImageDataRGB (imageData, topX, topY, width, height, radius) { + + +function processImageDataRGB(imageData, topX, topY, width, height, radius) { const pixels = imageData.data; + let x, y, i, p, yp, yi, yw, rSum, gSum, bSum, rOutSum, gOutSum, bOutSum, rInSum, gInSum, bInSum, pr, pg, pb, rbs; + const div = radius + radius + 1; // const w4 = width << 2; - let x, y, i, p, yp, yi, yw, rSum, gSum, bSum, - rOutSum, gOutSum, bOutSum, - rInSum, gInSum, bInSum, - pr, pg, pb, rbs; - - const div = radius + radius + 1; - // const w4 = width << 2; const widthMinus1 = width - 1; const heightMinus1 = height - 1; const radiusPlus1 = radius + 1; const sumFactor = radiusPlus1 * (radiusPlus1 + 1) / 2; - const stackStart = new BlurStack(); let stack = stackStart; let stackEnd; + for (i = 1; i < div; i++) { stack = stack.next = new BlurStack(); + if (i === radiusPlus1) { stackEnd = stack; } } + stack.next = stackStart; let stackIn = null; let stackOut = null; - yw = yi = 0; - const mulSum = mulTable[radius]; const shgSum = shgTable[radius]; for (y = 0; y < height; y++) { rInSum = gInSum = bInSum = rSum = gSum = bSum = 0; - rOutSum = radiusPlus1 * (pr = pixels[yi]); gOutSum = radiusPlus1 * (pg = pixels[yi + 1]); bOutSum = radiusPlus1 * (pb = pixels[yi + 2]); - rSum += sumFactor * pr; gSum += sumFactor * pg; bSum += sumFactor * pb; - stack = stackStart; for (i = 0; i < radiusPlus1; i++) { @@ -478,71 +419,58 @@ function processImageDataRGB (imageData, topX, topY, width, height, radius) { for (i = 1; i < radiusPlus1; i++) { p = yi + ((widthMinus1 < i ? widthMinus1 : i) << 2); - rSum += (stack.r = (pr = pixels[p])) * (rbs = radiusPlus1 - i); - gSum += (stack.g = (pg = pixels[p + 1])) * rbs; - bSum += (stack.b = (pb = pixels[p + 2])) * rbs; - + rSum += (stack.r = pr = pixels[p]) * (rbs = radiusPlus1 - i); + gSum += (stack.g = pg = pixels[p + 1]) * rbs; + bSum += (stack.b = pb = pixels[p + 2]) * rbs; rInSum += pr; gInSum += pg; bInSum += pb; - stack = stack.next; } stackIn = stackStart; stackOut = stackEnd; - for (x = 0; x < width; x++) { - pixels[yi] = (rSum * mulSum) >> shgSum; - pixels[yi + 1] = (gSum * mulSum) >> shgSum; - pixels[yi + 2] = (bSum * mulSum) >> shgSum; + for (x = 0; x < width; x++) { + pixels[yi] = rSum * mulSum >> shgSum; + pixels[yi + 1] = gSum * mulSum >> shgSum; + pixels[yi + 2] = bSum * mulSum >> shgSum; rSum -= rOutSum; gSum -= gOutSum; bSum -= bOutSum; - rOutSum -= stackIn.r; gOutSum -= stackIn.g; bOutSum -= stackIn.b; - - p = (yw + ((p = x + radius + 1) < widthMinus1 ? p : widthMinus1)) << 2; - - rInSum += (stackIn.r = pixels[p]); - gInSum += (stackIn.g = pixels[p + 1]); - bInSum += (stackIn.b = pixels[p + 2]); - + p = yw + ((p = x + radius + 1) < widthMinus1 ? p : widthMinus1) << 2; + rInSum += stackIn.r = pixels[p]; + gInSum += stackIn.g = pixels[p + 1]; + bInSum += stackIn.b = pixels[p + 2]; rSum += rInSum; gSum += gInSum; bSum += bInSum; - stackIn = stackIn.next; - - rOutSum += (pr = stackOut.r); - gOutSum += (pg = stackOut.g); - bOutSum += (pb = stackOut.b); - + rOutSum += pr = stackOut.r; + gOutSum += pg = stackOut.g; + bOutSum += pb = stackOut.b; rInSum -= pr; gInSum -= pg; bInSum -= pb; - stackOut = stackOut.next; - yi += 4; } + yw += width; } for (x = 0; x < width; x++) { gInSum = bInSum = rInSum = gSum = bSum = rSum = 0; - yi = x << 2; rOutSum = radiusPlus1 * (pr = pixels[yi]); gOutSum = radiusPlus1 * (pg = pixels[yi + 1]); bOutSum = radiusPlus1 * (pb = pixels[yi + 2]); - rSum += sumFactor * pr; gSum += sumFactor * pg; bSum += sumFactor * pb; - stack = stackStart; for (i = 0; i < radiusPlus1; i++) { @@ -555,16 +483,13 @@ function processImageDataRGB (imageData, topX, topY, width, height, radius) { yp = width; for (i = 1; i <= radius; i++) { - yi = (yp + x) << 2; - - rSum += (stack.r = (pr = pixels[yi])) * (rbs = radiusPlus1 - i); - gSum += (stack.g = (pg = pixels[yi + 1])) * rbs; - bSum += (stack.b = (pb = pixels[yi + 2])) * rbs; - + yi = yp + x << 2; + rSum += (stack.r = pr = pixels[yi]) * (rbs = radiusPlus1 - i); + gSum += (stack.g = pg = pixels[yi + 1]) * rbs; + bSum += (stack.b = pb = pixels[yi + 2]) * rbs; rInSum += pr; gInSum += pg; bInSum += pb; - stack = stack.next; if (i < heightMinus1) { @@ -575,82 +500,50 @@ function processImageDataRGB (imageData, topX, topY, width, height, radius) { yi = x; stackIn = stackStart; stackOut = stackEnd; + for (y = 0; y < height; y++) { p = yi << 2; - pixels[p] = (rSum * mulSum) >> shgSum; - pixels[p + 1] = (gSum * mulSum) >> shgSum; - pixels[p + 2] = (bSum * mulSum) >> shgSum; - + pixels[p] = rSum * mulSum >> shgSum; + pixels[p + 1] = gSum * mulSum >> shgSum; + pixels[p + 2] = bSum * mulSum >> shgSum; rSum -= rOutSum; gSum -= gOutSum; bSum -= bOutSum; - rOutSum -= stackIn.r; gOutSum -= stackIn.g; bOutSum -= stackIn.b; - - p = (x + (((p = y + radiusPlus1) < heightMinus1 ? p : heightMinus1) * width)) << 2; - - rSum += (rInSum += (stackIn.r = pixels[p])); - gSum += (gInSum += (stackIn.g = pixels[p + 1])); - bSum += (bInSum += (stackIn.b = pixels[p + 2])); - + p = x + ((p = y + radiusPlus1) < heightMinus1 ? p : heightMinus1) * width << 2; + rSum += rInSum += stackIn.r = pixels[p]; + gSum += gInSum += stackIn.g = pixels[p + 1]; + bSum += bInSum += stackIn.b = pixels[p + 2]; stackIn = stackIn.next; - - rOutSum += (pr = stackOut.r); - gOutSum += (pg = stackOut.g); - bOutSum += (pb = stackOut.b); - + rOutSum += pr = stackOut.r; + gOutSum += pg = stackOut.g; + bOutSum += pb = stackOut.b; rInSum -= pr; gInSum -= pg; bInSum -= pb; - stackOut = stackOut.next; - yi += width; } } return imageData; } - /** * */ -export class BlurStack { - constructor () { + + +class BlurStack { + constructor() { this.r = 0; this.g = 0; this.b = 0; this.a = 0; this.next = null; } + } -export { - /** - * @class module:StackBlur.image - * @see module:StackBlur~processImage - */ - processImage as image, - /** - * @class module:StackBlur.canvasRGBA - * @see module:StackBlur~processCanvasRGBA - */ - processCanvasRGBA as canvasRGBA, - /** - * @class module:StackBlur.canvasRGB - * @see module:StackBlur~processCanvasRGB - */ - processCanvasRGB as canvasRGB, - /** - * @class module:StackBlur.imageDataRGBA - * @see module:StackBlur~processImageDataRGBA - */ - processImageDataRGBA as imageDataRGBA, - /** - * @class module:StackBlur.imageDataRGB - * @see module:StackBlur~processImageDataRGB - */ - processImageDataRGB as imageDataRGB -}; +export { BlurStack, processImage as image, processCanvasRGBA as canvasRGBA, processCanvasRGB as canvasRGB, processImageDataRGBA as imageDataRGBA, processImageDataRGB as imageDataRGB }; diff --git a/editor/layer.js b/editor/layer.js index c4e4a9a4..cc3ca743 100644 --- a/editor/layer.js +++ b/editor/layer.js @@ -185,7 +185,6 @@ class Layer { /** * Remove this layer's group from the DOM. No more functions on group can be called after this. - * @param {SVGGElement} children - The children to append to this layer. * @returns {SVGGElement} The layer SVG group that was just removed. */ removeGroup () { diff --git a/editor/svg-editor.js b/editor/svg-editor.js index 1974239a..09c2c981 100644 --- a/editor/svg-editor.js +++ b/editor/svg-editor.js @@ -324,15 +324,17 @@ function loadSvgString (str, callback) { /** * @function module:SVGEditor~getImportLocale - * @param {string} defaultLang - * @param {string} defaultName + * @param {PlainObject} defaults + * @param {string} defaults.defaultLang + * @param {string} defaults.defaultName * @returns {module:SVGEditor~ImportLocale} */ function getImportLocale ({defaultLang, defaultName}) { /** * @function module:SVGEditor~ImportLocale - * @param {string} [name] Defaults to `defaultName` of {@link module:SVGEditor~getImportLocale} - * @param {string} [lang=defaultLang] Defaults to `defaultLang` of {@link module:SVGEditor~getImportLocale} + * @param {PlainObject} localeInfo + * @param {string} [localeInfo.name] Defaults to `defaultName` of {@link module:SVGEditor~getImportLocale} + * @param {string} [localeInfo.lang=defaultLang] Defaults to `defaultLang` of {@link module:SVGEditor~getImportLocale} * @returns {Promise} Resolves to {@link module:locale.LocaleStrings} */ return async function importLocale ({name = defaultName, lang = defaultLang} = {}) { @@ -2771,7 +2773,7 @@ editor.init = function () { const allHolders = {}; /** - * @param {GenericObject.} holders Key is a selector + * @param {PlainObject.} holders Key is a selector * @returns {undefined} */ const setupFlyouts = function (holders) { @@ -3440,8 +3442,9 @@ editor.init = function () { 'updateCanvas', /** * @param {external:Window} win - * @param {false} center - * @param {module:math.XYObject} newCtr + * @param {PlainObject} centerInfo + * @param {false} centerInfo.center + * @param {module:math.XYObject} centerInfo.newCtr * @listens module:svgcanvas.SvgCanvas#event:updateCanvas * @returns {undefined} */ @@ -6042,8 +6045,9 @@ editor.ready(() => { let extensionsAdded = false; const messageQueue = []; /** - * @param {Any} data - * @param {string} origin + * @param {PlainObject} info + * @param {Any} info.data + * @param {string} info.origin * @fires module:svgcanvas.SvgCanvas#event:message * @returns {undefined} */ diff --git a/editor/svgcanvas.js b/editor/svgcanvas.js index 98cb478e..bd5a7317 100644 --- a/editor/svgcanvas.js +++ b/editor/svgcanvas.js @@ -814,8 +814,9 @@ pathModule.init( return rubberBox; }, /** - * @param {boolean} closedSubpath - * @param {SVGCircleElement[]} grips + * @param {PlainObject} ptsInfo + * @param {boolean} ptsInfo.closedSubpath + * @param {SVGCircleElement[]} ptsInfo.grips * @fires module:svgcanvas.SvgCanvas#event:pointsAdded * @fires module:svgcanvas.SvgCanvas#event:selected * @returns {undefined} @@ -828,8 +829,9 @@ pathModule.init( call('selected', grips); }, /** - * @param {ChangeElementCommand} cmd - * @param {SVGPathElement} elem + * @param {PlainObject} changes + * @param {ChangeElementCommand} changes.cmd + * @param {SVGPathElement} changes.elem * @fires module:svgcanvas.SvgCanvas#event:changed * @returns {undefined} */ @@ -3809,7 +3811,7 @@ this.save = function (opts) { }; /** -* @typedef {GenericObject} module:svgcanvas.IssuesAndCodes +* @typedef {PlainObject} module:svgcanvas.IssuesAndCodes * @property {string[]} issueCodes The locale-independent code names * @property {string[]} issues The localized descriptions */ diff --git a/editor/utilities.js b/editor/utilities.js index fe7d0805..8a89a6df 100644 --- a/editor/utilities.js +++ b/editor/utilities.js @@ -1346,6 +1346,7 @@ export const copyElem = function (el, getNextId) { /** * Overwrite methods for unit testing. * @function module:utilities.mock +* @param {PlainObject} mockMethods * @returns {undefined} */ export const mock = ({ diff --git a/package-lock.json b/package-lock.json index 7a0ad824..4d880f3c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1131,7 +1131,7 @@ }, "async": { "version": "0.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.6.tgz", + "resolved": "http://registry.npmjs.org/async/-/async-0.2.6.tgz", "integrity": "sha1-rT83PZJJrjJIgVZVgryQ4VKrvWg=", "dev": true }, @@ -1883,7 +1883,7 @@ }, "regjsgen": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "resolved": "http://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", "dev": true }, @@ -2901,6 +2901,15 @@ "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true }, + "comment-parser": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-0.5.0.tgz", + "integrity": "sha512-sNM+U6+Kme4WDxjVJ+1N92BQm5SC0RbFD4TLXLJ+hThX3crW1q+7ObjUhylMYAjR/rWdB+7ZNLPjujVbGruHGQ==", + "dev": true, + "requires": { + "readable-stream": "^2.0.4" + } + }, "component-emitter": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", @@ -3686,6 +3695,85 @@ } } }, + "eslint-plugin-jsdoc": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-3.9.1.tgz", + "integrity": "sha512-kSQ62uraDa9QSv/5YncMZoKLScqrq7kt4lGGokH7Iyuqqzo2rZhERdrkPELLdnX4jWwkh+gYFZBt0PVIseKH1g==", + "dev": true, + "requires": { + "comment-parser": "^0.5.0", + "jsdoctypeparser": "^2.0.0-alpha-8", + "lodash": "^4.17.11" + } + }, + "eslint-plugin-markdown": { + "version": "1.0.0-rc.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-markdown/-/eslint-plugin-markdown-1.0.0-rc.0.tgz", + "integrity": "sha512-28Ioje4p8QAmpxDL91jR4rU+x6+UEx6IW/b+nVnXuS7CMCuOttQl+8BGSu04bm0+8ibOlNsvt5QXc7D847oOkw==", + "dev": true, + "requires": { + "object-assign": "^4.0.1", + "remark-parse": "^5.0.0", + "unified": "^6.1.2" + }, + "dependencies": { + "remark-parse": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", + "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", + "dev": true, + "requires": { + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^1.1.0", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^1.0.0", + "vfile-location": "^2.0.0", + "xtend": "^4.0.1" + } + }, + "unified": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/unified/-/unified-6.2.0.tgz", + "integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==", + "dev": true, + "requires": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^1.1.0", + "trough": "^1.0.0", + "vfile": "^2.0.0", + "x-is-string": "^0.1.0" + } + }, + "vfile": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", + "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", + "dev": true, + "requires": { + "is-buffer": "^1.1.4", + "replace-ext": "1.0.0", + "unist-util-stringify-position": "^1.0.0", + "vfile-message": "^1.0.0" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, "eslint-plugin-node": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-8.0.0.tgz", @@ -5948,6 +6036,12 @@ "underscore": "~1.8.3" } }, + "jsdoctypeparser": { + "version": "2.0.0-alpha-8", + "resolved": "https://registry.npmjs.org/jsdoctypeparser/-/jsdoctypeparser-2.0.0-alpha-8.tgz", + "integrity": "sha1-uvE3+44qVYgQrc8Z0tKi9oDpCl8=", + "dev": true + }, "jsdom": { "version": "13.0.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-13.0.0.tgz", @@ -8887,6 +8981,12 @@ "tweetnacl": "~0.14.0" } }, + "stackblur-canvas": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.0.0.tgz", + "integrity": "sha512-660gH1SpjeKyfUYnne9nuIya7CDGds6NdIrxzOToSgaSlOqbh7UYGP9VlxlQ8IX7af/nPuAHLkN03l84OesX7Q==", + "dev": true + }, "stackframe": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-0.3.1.tgz", @@ -9240,7 +9340,7 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } @@ -9428,7 +9528,7 @@ }, "core-js": { "version": "1.2.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "resolved": "http://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", "dev": true } @@ -9555,7 +9655,7 @@ }, "core-js": { "version": "1.2.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "resolved": "http://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", "dev": true }, @@ -9584,37 +9684,37 @@ }, "testcafe-reporter-json": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/testcafe-reporter-json/-/testcafe-reporter-json-2.1.0.tgz", + "resolved": "http://registry.npmjs.org/testcafe-reporter-json/-/testcafe-reporter-json-2.1.0.tgz", "integrity": "sha1-gLm1pt/y7h3h+R4mcHBsFHLmQAY=", "dev": true }, "testcafe-reporter-list": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/testcafe-reporter-list/-/testcafe-reporter-list-2.1.0.tgz", + "resolved": "http://registry.npmjs.org/testcafe-reporter-list/-/testcafe-reporter-list-2.1.0.tgz", "integrity": "sha1-n6ifcbl9Pf5ktDAtXiJ97mmuxrk=", "dev": true }, "testcafe-reporter-minimal": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/testcafe-reporter-minimal/-/testcafe-reporter-minimal-2.1.0.tgz", + "resolved": "http://registry.npmjs.org/testcafe-reporter-minimal/-/testcafe-reporter-minimal-2.1.0.tgz", "integrity": "sha1-Z28DVHY0FDxurzq1KGgnOkvr9CE=", "dev": true }, "testcafe-reporter-spec": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/testcafe-reporter-spec/-/testcafe-reporter-spec-2.1.1.tgz", + "resolved": "http://registry.npmjs.org/testcafe-reporter-spec/-/testcafe-reporter-spec-2.1.1.tgz", "integrity": "sha1-gVb87Q9RMkhlWa1WC8gGdkaSdew=", "dev": true }, "testcafe-reporter-xunit": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/testcafe-reporter-xunit/-/testcafe-reporter-xunit-2.1.0.tgz", + "resolved": "http://registry.npmjs.org/testcafe-reporter-xunit/-/testcafe-reporter-xunit-2.1.0.tgz", "integrity": "sha1-5tZsVyzhWvJmcGrw/WELKoQd1EM=", "dev": true }, "text-encoding": { "version": "0.6.4", - "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", + "resolved": "http://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", "dev": true }, diff --git a/package.json b/package.json index 8facc69e..2fe7522a 100644 --- a/package.json +++ b/package.json @@ -18,9 +18,9 @@ "build-doc": "rm -rf docs/jsdoc/*;jsdoc --pedantic -c docs/jsdoc-config.js editor", "build-html": "node build-html.js", "compress-images": "imageoptim 'chrome-app/*.png' && imageoptim 'editor/extensions/*.png' && imageoptim 'editor/spinbtn/*.png' && imageoptim 'editor/jgraduate/images/*.{png,gif}' && imageoptim 'editor/images/*.png'", - "copy-deps": "cp node_modules/load-stylesheets/dist/index-es.js editor/external/load-stylesheets/index-es.js && cp node_modules/@babel/polyfill/dist/polyfill.min.js editor/external/@babel/polyfill/polyfill.min.js && cp node_modules/@babel/polyfill/dist/polyfill.js editor/external/@babel/polyfill/polyfill.js && cp node_modules/jamilih/dist/jml-es.js editor/external/jamilih/jml-es.js && cp node_modules/query-result/esm/index.js editor/external/query-result/esm/index.js && cp node_modules/qr-manipulation/dist/index-es.js editor/external/qr-manipulation/dist/index-es.js", + "copy": "cp node_modules/load-stylesheets/dist/index-es.js editor/external/load-stylesheets/index-es.js && cp node_modules/@babel/polyfill/dist/polyfill.min.js editor/external/@babel/polyfill/polyfill.min.js && cp node_modules/@babel/polyfill/dist/polyfill.js editor/external/@babel/polyfill/polyfill.js && cp node_modules/jamilih/dist/jml-es.js editor/external/jamilih/jml-es.js && cp node_modules/query-result/esm/index.js editor/external/query-result/esm/index.js && cp node_modules/qr-manipulation/dist/index-es.js editor/external/qr-manipulation/dist/index-es.js && cp node_modules/stackblur-canvas/dist/stackblur-es.js editor/external/stackblur-canvas/dist/stackblur-es.js", "remark": "remark -q -f .", - "eslint": "eslint .", + "eslint": "eslint --ext js,md .", "rollup": "rollup -c", "start-embedded": "echo \"Open file to http://localhost:8000/editor/embedapi.html\" && static -p 8000 | static -p 8001 -H '{\"Access-Control-Allow-Origin\": \"*\"}'", "start": "echo \"Open file to http://localhost:8000/test/all_tests.html\" && static -p 8000", @@ -83,6 +83,8 @@ "eslint-config-standard": "12.0.0", "eslint-plugin-compat": "2.6.3", "eslint-plugin-import": "2.14.0", + "eslint-plugin-jsdoc": "https://github.com/brettz9/eslint-plugin-jsdoc#origin/ArrayPattern", + "eslint-plugin-markdown": "^1.0.0-rc.0", "eslint-plugin-node": "8.0.0", "eslint-plugin-promise": "4.0.1", "eslint-plugin-qunit": "^4.0.0", @@ -111,6 +113,7 @@ "rollup-plugin-terser": "^3.0.0", "sinon": "^7.1.1", "sinon-test": "^2.4.0", + "stackblur-canvas": "^2.0.0", "testcafe": "^0.23.0" } } diff --git a/test/sanitize_test.js b/test/sanitize_test.js index 46589871..d7261964 100644 --- a/test/sanitize_test.js +++ b/test/sanitize_test.js @@ -15,7 +15,7 @@ QUnit.test('Test sanitizeSvg() strips ws from style attr', function (assert) { assert.expect(2); const rect = document.createElementNS(NS.SVG, 'rect'); - rect.setAttribute('style', 'stroke: blue ; stroke-width : 40;'); + rect.setAttribute('style', 'stroke: blue ;\t\tstroke-width :\t\t40;'); // sanitizeSvg() requires the node to have a parent and a document. svg.append(rect); sanitize.sanitizeSvg(rect); diff --git a/test/utilities_performance_test.js b/test/utilities_performance_test.js index 3796c13f..7db1e0d1 100644 --- a/test/utilities_performance_test.js +++ b/test/utilities_performance_test.js @@ -89,27 +89,27 @@ const mockPathActions = { // Chrome // Before Optimization -// Pass1 svgCanvas.getStrokedBBox total ms 4,218, ave ms 41.0, min/max 37 51 -// Pass2 svgCanvas.getStrokedBBox total ms 4,458, ave ms 43.3, min/max 32 63 +// Pass1 svgCanvas.getStrokedBBox total ms 4,218, ave ms 41.0, min/max 37 51 +// Pass2 svgCanvas.getStrokedBBox total ms 4,458, ave ms 43.3, min/max 32 63 // Optimized Code -// Pass1 svgCanvas.getStrokedBBox total ms 1,112, ave ms 10.8, min/max 9 20 -// Pass2 svgCanvas.getStrokedBBox total ms 34, ave ms 0.3, min/max 0 20 +// Pass1 svgCanvas.getStrokedBBox total ms 1,112, ave ms 10.8, min/max 9 20 +// Pass2 svgCanvas.getStrokedBBox total ms 34, ave ms 0.3, min/max 0 20 // Firefox // Before Optimization -// Pass1 svgCanvas.getStrokedBBox total ms 3,794, ave ms 36.8, min/max 33 48 -// Pass2 svgCanvas.getStrokedBBox total ms 4,049, ave ms 39.3, min/max 28 53 +// Pass1 svgCanvas.getStrokedBBox total ms 3,794, ave ms 36.8, min/max 33 48 +// Pass2 svgCanvas.getStrokedBBox total ms 4,049, ave ms 39.3, min/max 28 53 // Optimized Code -// Pass1 svgCanvas.getStrokedBBox total ms 104, ave ms 1.0, min/max 0 23 -// Pass2 svgCanvas.getStrokedBBox total ms 71, ave ms 0.7, min/max 0 23 +// Pass1 svgCanvas.getStrokedBBox total ms 104, ave ms 1.0, min/max 0 23 +// Pass2 svgCanvas.getStrokedBBox total ms 71, ave ms 0.7, min/max 0 23 // Safari // Before Optimization -// Pass1 svgCanvas.getStrokedBBox total ms 4,840, ave ms 47.0, min/max 45 62 -// Pass2 svgCanvas.getStrokedBBox total ms 4,849, ave ms 47.1, min/max 34 62 +// Pass1 svgCanvas.getStrokedBBox total ms 4,840, ave ms 47.0, min/max 45 62 +// Pass2 svgCanvas.getStrokedBBox total ms 4,849, ave ms 47.1, min/max 34 62 // Optimized Code -// Pass1 svgCanvas.getStrokedBBox total ms 42, ave ms 0.4, min/max 0 23 -// Pass2 svgCanvas.getStrokedBBox total ms 17, ave ms 0.2, min/max 0 23 +// Pass1 svgCanvas.getStrokedBBox total ms 42, ave ms 0.4, min/max 0 23 +// Pass2 svgCanvas.getStrokedBBox total ms 17, ave ms 0.2, min/max 0 23 QUnit.test('Test svgCanvas.getStrokedBBox() performance with matrix transforms', function (assert) { const done = assert.async();