diff --git a/.eslintignore b/.eslintignore index af297a3d..8cfe15d9 100644 --- a/.eslintignore +++ b/.eslintignore @@ -30,4 +30,3 @@ src/editor/jspdf/underscore-min.js src/editor/extensions/ext-mathjax/mathjax -src/external/**/* diff --git a/.eslintrc.js b/.eslintrc.js index d17f013b..937b032a 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -140,7 +140,6 @@ module.exports = { // These browser files don't do importing or requiring { files: [ - 'src/editor/svgpathseg.js', 'src/editor/touch.js', 'src/editor/typedefs.js', 'src/editor/redirect-on-no-module-support.js', diff --git a/badges/coverage-badge.svg b/badges/coverage-badge.svg index 59803bc8..c5aa6c72 100644 --- a/badges/coverage-badge.svg +++ b/badges/coverage-badge.svg @@ -1 +1 @@ -Statements 50.85%Statements 50.85%Branches 40.86%Branches 40.86%Lines 51.97%Lines 51.97%Functions 55.07%Functions 55.07% +Statements 51.06%Statements 51.06%Branches 40.68%Branches 40.68%Lines 51.77%Lines 51.77%Functions 58.33%Functions 58.33% diff --git a/badges/tests-badge.svg b/badges/tests-badge.svg index b874e50f..3a714e8d 100644 --- a/badges/tests-badge.svg +++ b/badges/tests-badge.svg @@ -1 +1 @@ -TestsTests136/137136/137 \ No newline at end of file +TestsTests138/138138/138 \ No newline at end of file diff --git a/cypress/integration/ui/__snapshots__/scenario.js.snap b/cypress/integration/ui/__snapshots__/scenario.js.snap index d5d1ca50..3802d721 100644 --- a/cypress/integration/ui/__snapshots__/scenario.js.snap +++ b/cypress/integration/ui/__snapshots__/scenario.js.snap @@ -27,6 +27,37 @@ exports[`use various parts of svg-edit > check tool_source #0`] = ` `; +exports[`use various parts of svg-edit > check tool_fhpath #0`] = ` + + + Layer 1 + + + +`; + exports[`use various parts of svg-edit > check tool_text #0`] = ` check tool_text #0`] = ` x="69.5" y="51.5" style="pointer-events:inherit" + fill-opacity="1" + stroke-opacity="1" > check tool_clone #0`] = ` x="69.5" y="51.5" style="pointer-events:inherit" + fill-opacity="1" + stroke-opacity="1" > check tool_italic #0`] = ` x="69.5" y="51.5" style="pointer-events:inherit" + fill-opacity="1" + stroke-opacity="1" > check tool_bold #0`] = ` x="69.5" y="51.5" style="pointer-events:inherit" + fill-opacity="1" + stroke-opacity="1" > func(jq), jQuery); const homePage = 'https://github.com/SVG-Edit/svgedit'; diff --git a/src/external/qr-manipulation/dist/index-es.js b/src/external/qr-manipulation/dist/index-es.js deleted file mode 100644 index 0ad74694..00000000 --- a/src/external/qr-manipulation/dist/index-es.js +++ /dev/null @@ -1,556 +0,0 @@ -function _typeof(obj) { - "@babel/helpers - typeof"; - - if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { - _typeof = function (obj) { - return typeof obj; - }; - } else { - _typeof = function (obj) { - return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; - }; - } - - return _typeof(obj); -} - -function _slicedToArray(arr, i) { - return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); -} - -function _toConsumableArray(arr) { - return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); -} - -function _arrayWithoutHoles(arr) { - if (Array.isArray(arr)) return _arrayLikeToArray(arr); -} - -function _arrayWithHoles(arr) { - if (Array.isArray(arr)) return arr; -} - -function _iterableToArray(iter) { - if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); -} - -function _iterableToArrayLimit(arr, i) { - if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; - var _arr = []; - var _n = true; - var _d = false; - var _e = undefined; - - try { - for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { - _arr.push(_s.value); - - if (i && _arr.length === i) break; - } - } catch (err) { - _d = true; - _e = err; - } finally { - try { - if (!_n && _i["return"] != null) _i["return"](); - } finally { - if (_d) throw _e; - } - } - - return _arr; -} - -function _unsupportedIterableToArray(o, minLen) { - if (!o) return; - if (typeof o === "string") return _arrayLikeToArray(o, minLen); - var n = Object.prototype.toString.call(o).slice(8, -1); - if (n === "Object" && o.constructor) n = o.constructor.name; - if (n === "Map" || n === "Set") return Array.from(o); - if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); -} - -function _arrayLikeToArray(arr, len) { - if (len == null || len > arr.length) len = arr.length; - - for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; - - return arr2; -} - -function _nonIterableSpread() { - throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); -} - -function _nonIterableRest() { - throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); -} - -function convertToString(content, type) { - switch (_typeof(content)) { - case 'object': - { - if (!content) { - throw new TypeError('Cannot supply `null`'); - } - - switch (content.nodeType) { - case 1: - { - // ELEMENT - return content.outerHTML; - } - - case 3: - { - // TEXT - return content.nodeValue; - } - - case 11: - { - // DOCUMENT_FRAGMENT_NODE - return _toConsumableArray(content.childNodes).reduce(function (s, node) { - return s + convertToString(node, type); - }, ''); - } - - case undefined: - // Array of nodes, QueryResult objects - // if (Array.isArray(content)) { - if (typeof content.reduce === 'function') { - return content.reduce(function (s, node) { - return s + convertToString(node, type); - }, ''); - } - - break; - } - - return undefined; - } - - case 'string': - { - return content; - } - - default: - throw new TypeError('Bad content for ' + type + '; type: ' + _typeof(content)); - } -} - -function convertToDOM(content, type, avoidClone) { - switch (_typeof(content)) { - case 'object': - { - if (!content) { - throw new TypeError('Cannot supply `null`'); - } - - if ([1, // ELEMENT - 3, // TEXT - 11 // Document fragment - ].includes(content.nodeType)) { - return avoidClone ? content : content.cloneNode(true); - } - - if (typeof content.reduce !== 'function') { - throw new TypeError('Unrecognized type of object for conversion to DOM'); - } // Array of nodes, QueryResult objects - - - return avoidClone ? content : content.map(function (node) { - if (!node || !node.cloneNode) { - // Allows for arrays of HTML strings - return convertToDOM(node, type, false); - } - - return node.cloneNode(true); - }); - } - - case 'string': - { - var div = document.createElement('div'); // eslint-disable-next-line no-unsanitized/property - - div.innerHTML = content; - return div.firstElementChild || div.firstChild; - } - - default: - throw new TypeError('Bad content for ' + type + '; type: ' + _typeof(content)); - } -} - -function insert(type) { - return function () { - var _this = this; - - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } - - var cbOrContent = args[0]; - - switch (_typeof(cbOrContent)) { - case 'function': - { - this.forEach(function (node, i) { - var ret = cbOrContent.call(_this, i, node.textContent); - node[type](ret); - }); - break; - } - - default: - { - this.forEach(function (node, i, arr) { - node[type].apply(node, _toConsumableArray(args.flatMap(function (content) { - return convertToDOM(content, type, i === arr.length - 1); - }))); - }); - break; - } - } - - return this; - }; -} - -function insertText(type) { - return function (cbOrContent) { - var _this2 = this; - - switch (_typeof(cbOrContent)) { - case 'function': - { - this.forEach(function (node, i) { - var ret = cbOrContent.call(_this2, i, node[type]); - node[type] = convertToString(ret, type); - }); - break; - } - - default: - { - this.forEach(function (node) { - node[type] = convertToString(cbOrContent, type); - }); - break; - } - } - - return this; - }; -} - -var after = insert('after'); -var before = insert('before'); -var append = insert('append'); -var prepend = insert('prepend'); -var html = insertText('innerHTML'); -var text = insertText('textContent'); -/* -// Todo: -export const val = function (valueOrFunc) { - -}; -*/ -// Given that these types require a selector engine and -// in order to avoid the absence of optimization of `document.querySelectorAll` -// for `:first-child` and different behavior in different contexts, -// and to avoid making a mutual dependency with query-result, -// exports of this type accept a QueryResult instance; -// if selected without a second argument, we do default to -// `document.querySelectorAll`, however. - -var insertTo = function insertTo(method) { - var $ = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function (sel) { - return _toConsumableArray(document.querySelectorAll(sel)); - }; - var type = { - appendTo: 'append', - prependTo: 'prepend', - insertAfter: 'after', - insertBefore: 'before' - }[method] || 'append'; - return function (target) { - var toType = type + 'To'; - this.forEach(function (node, i, arr) { - if (typeof target === 'string' && target.charAt(0) !== '<') { - target = $(target); - } - - target = Array.isArray(target) ? target : [target]; - node[type].apply(node, _toConsumableArray(target.flatMap(function (content) { - return convertToDOM(content, toType, i === arr.length - 1); - }))); - }); - return this; - }; -}; // Todo: optional `withDataAndEvents` and `deepWithDataAndEvents` arguments? - -var clone = function clone() { - return this.map(function (node) { - // Still a QueryResult with such a map - return node.cloneNode(true); - }); -}; -var empty = function empty() { - this.forEach(function (node) { - node.textContent = ''; - }); -}; -var remove = function remove(selector) { - if (selector) { - this.forEach(function (node) { - if (node.matches(selector)) { - // Todo: Use query-result instead? - node.remove(); - } - }); - } else { - this.forEach(function (node) { - node.remove(); - }); - } - - return this; -}; -/* -// Todo: -export const detach = function (selector) { - // Should preserve attached data - return remove(selector); -}; -*/ - -var attr = function attr(attributeNameOrAtts, valueOrCb) { - var _this3 = this; - - if (valueOrCb === undefined) { - switch (_typeof(attributeNameOrAtts)) { - case 'string': - { - return this[0].hasAttribute(attributeNameOrAtts) ? this[0].getAttribute(attributeNameOrAtts) : undefined; - } - - case 'object': - { - if (attributeNameOrAtts) { - this.forEach(function (node, i) { - Object.entries(attributeNameOrAtts).forEach(function (_ref) { - var _ref2 = _slicedToArray(_ref, 2), - att = _ref2[0], - val = _ref2[1]; - - node.setAttribute(att, val); - }); - }); - return this; - } - } - // Fallthrough - - default: - { - throw new TypeError('Unexpected type for attribute name: ' + _typeof(attributeNameOrAtts)); - } - } - } - - switch (_typeof(valueOrCb)) { - case 'function': - { - this.forEach(function (node, i) { - var ret = valueOrCb.call(_this3, i, node.getAttribute(valueOrCb)); - - if (ret === null) { - node.removeAttribute(attributeNameOrAtts); - } else { - node.setAttribute(attributeNameOrAtts, ret); - } - }); - break; - } - - case 'string': - { - this.forEach(function (node, i) { - node.setAttribute(attributeNameOrAtts, valueOrCb); - }); - break; - } - - case 'object': - { - if (!valueOrCb) { - // `null` - return removeAttr.call(this, attributeNameOrAtts); - } - } - // Fallthrough - - default: - { - throw new TypeError('Unexpected type for attribute name: ' + _typeof(attributeNameOrAtts)); - } - } - - return this; -}; -var removeAttr = function removeAttr(attributeName) { - if (typeof attributeName !== 'string') { - throw new TypeError('Unexpected type for attribute name: ' + _typeof(attributeName)); - } - - this.forEach(function (node) { - node.removeAttribute(attributeName); - }); -}; - -function classAttManipulation(type) { - return function (cbOrContent) { - var _this4 = this; - - switch (_typeof(cbOrContent)) { - case 'function': - { - this.forEach(function (node, i) { - var _node$classList; - - var ret = cbOrContent.call(_this4, i, node.className); - - (_node$classList = node.classList)[type].apply(_node$classList, _toConsumableArray(ret.split(' '))); - }); - break; - } - - default: - { - if (type === 'remove' && !cbOrContent) { - this.forEach(function (node) { - node.className = ''; - }); - break; - } - - this.forEach(function (node) { - var _node$classList2; - - (_node$classList2 = node.classList)[type].apply(_node$classList2, _toConsumableArray(cbOrContent.split(' '))); - }); - break; - } - } - - return this; - }; -} - -var addClass = classAttManipulation('add'); -var removeClass = classAttManipulation('remove'); -var hasClass = function hasClass(className) { - return this.some(function (node) { - return node.classList.contains(className); - }); -}; -var toggleClass = function toggleClass(classNameOrCb, state) { - var _this5 = this; - - switch (typeof cbOrContent === "undefined" ? "undefined" : _typeof(cbOrContent)) { - case 'function': - { - if (typeof state === 'boolean') { - this.forEach(function (node, i) { - var _node$classList3; - - var ret = classNameOrCb.call(_this5, i, node.className, state); - - (_node$classList3 = node.classList).toggle.apply(_node$classList3, _toConsumableArray(ret.split(' ')).concat([state])); - }); - } else { - this.forEach(function (node, i) { - var _node$classList4; - - var ret = classNameOrCb.call(_this5, i, node.className, state); - - (_node$classList4 = node.classList).toggle.apply(_node$classList4, _toConsumableArray(ret.split(' '))); - }); - } - - break; - } - - case 'string': - { - if (typeof state === 'boolean') { - this.forEach(function (node) { - var _node$classList5; - - (_node$classList5 = node.classList).toggle.apply(_node$classList5, _toConsumableArray(classNameOrCb.split(' ')).concat([state])); - }); - } else { - this.forEach(function (node) { - var _node$classList6; - - (_node$classList6 = node.classList).toggle.apply(_node$classList6, _toConsumableArray(classNameOrCb.split(' '))); - }); - } - - break; - } - } -}; -var methods = { - after: after, - before: before, - append: append, - prepend: prepend, - html: html, - text: text, - clone: clone, - empty: empty, - remove: remove, - // detach - attr: attr, - removeAttr: removeAttr, - addClass: addClass, - hasClass: hasClass, - removeClass: removeClass, - toggleClass: toggleClass -}; - -var manipulation = function manipulation($, jml) { - ['after', 'before', 'append', 'prepend', 'html', 'text', 'clone', 'empty', 'remove', // 'detach' - 'attr', 'removeAttr', 'addClass', 'hasClass', 'removeClass', 'toggleClass'].forEach(function (method) { - $.extend(method, methods[method]); - }); - ['appendTo', 'prependTo', 'insertAfter', 'insertBefore'].forEach(function (method) { - $.extend(method, insertTo(method, $)); - }); - - if (jml) { - $.extend('jml', function () { - var _this6 = this; - - for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { - args[_key2] = arguments[_key2]; - } - - this.forEach(function (node) { - while (node.hasChildNodes()) { - node.firstChild.remove(); - } - - var n = jml.apply(void 0, args); - return append.call(_this6, n); - }); - }); - } - - return $; -}; - -export { addClass, after, append, attr, before, clone, empty, hasClass, html, insertTo, manipulation, prepend, remove, removeAttr, removeClass, text, toggleClass }; diff --git a/src/external/query-result/esm/index.js b/src/external/query-result/esm/index.js deleted file mode 100644 index 28712305..00000000 --- a/src/external/query-result/esm/index.js +++ /dev/null @@ -1,124 +0,0 @@ -/** - * ISC License - * - * Copyright (c) 2018, Andrea Giammarchi, @WebReflection - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ -class QueryResult extends Array {} -const {create, defineProperty} = Object; -const AP = Array.prototype; -const DOM_CONTENT_LOADED = 'DOMContentLoaded'; -const LOAD = 'load'; -const NO_TRANSPILER_ISSUES = (new QueryResult) instanceof QueryResult; -const QRP = QueryResult.prototype; -// fixes methods returning non QueryResult -/* istanbul ignore if */ -if (!NO_TRANSPILER_ISSUES) - Object.getOwnPropertyNames(AP).forEach(name => { - const desc = Object.getOwnPropertyDescriptor(AP, name); - if (typeof desc.value === 'function') { - const fn = desc.value; - desc.value = function () { - const result = fn.apply(this, arguments); - return result instanceof Array ? patch(result) : result; - }; - } - defineProperty(QRP, name, desc); - }); -// fixes badly transpiled classes -const patch = NO_TRANSPILER_ISSUES ? - qr => qr : - /* istanbul ignore next */ - qr => { - const nqr = create(QRP); - push.apply(nqr, slice(qr)); - return nqr; - }; -const push = AP.push; -const search = (list, el) => { - const nodes = []; - const length = list.length; - for (let i = 0; i < length; i++) { - const css = list[i].trim(); - if (css.slice(-6) === ':first') { - const node = el.querySelector(css.slice(0, -6)); - if (node) push.call(nodes, node); - } else - push.apply(nodes, slice(el.querySelectorAll(css))); - } - return new QueryResult(...nodes); -}; -const slice = NO_TRANSPILER_ISSUES ? - patch : - /* istanbul ignore next */ - all => { - // do not use slice.call(...) due old IE gotcha - const nodes = []; - const length = all.length; - for (let i = 0; i < length; i++) - nodes[i] = all[i]; - return nodes; - } -// use function to avoid usage of Symbol.hasInstance -// (broken in older browsers anyway) -const $ = function $(CSS, parent = document) { - switch (typeof CSS) { - case 'string': return patch(search(CSS.split(','), parent)); - case 'object': - // needed to avoid iterator dance (breaks in older IEs) - const nodes = []; - const all = ('nodeType' in CSS || 'postMessage' in CSS) ? [CSS] : CSS; - push.apply(nodes, slice(all)); - return patch(new QueryResult(...nodes)); - case 'function': - const $parent = $(parent); - const $window = $(parent.defaultView); - const handler = {handleEvent(event) { - $parent.off(DOM_CONTENT_LOADED, handler); - $window.off(LOAD, handler); - CSS(event); - }}; - $parent.on(DOM_CONTENT_LOADED, handler); - $window.on(LOAD, handler); - const rs = parent.readyState; - if (rs == 'complete' || (rs != 'loading' && !parent.documentElement.doScroll)) - setTimeout(() => $parent.dispatch(DOM_CONTENT_LOADED)); - return $; - } -}; -$.prototype = QRP; -$.extend = (key, value) => - (defineProperty(QRP, key, {configurable: true, value}), $); -// dropped usage of for-of to avoid broken iteration dance in older IEs -$.extend('dispatch', function dispatch(type, init = {}) { - const event = new CustomEvent(type, init); - const length = this.length; - for (let i = 0; i < length; i++) - this[i].dispatchEvent(event); - return this; -}) -.extend('off', function off(type, handler, options = false) { - const length = this.length; - for (let i = 0; i < length; i++) - this[i].removeEventListener(type, handler, options); - return this; -}) -.extend('on', function on(type, handler, options = false) { - const length = this.length; - for (let i = 0; i < length; i++) - this[i].addEventListener(type, handler, options); - return this; -}); - -export default $;