- Breaking change: loadSvgString now returns a Promise rather than accepting a callback

- Breaking change: Treat callbacks to `editor.ready` as Promises, only resolving after all resolve
- Breaking change: Make `editor.runCallbacks` return a `Promise` which resolves upon all callbacks resolving
- Breaking change: Require `npx` (used with `babel-node`) to allow Node files
  for HTML building and JSDoc type checking to be expressed as ESM.
- Breaking change: `addExtension` now throws upon a repeated attempt to add an already-added extension
- Breaking change (storage preference cookies): Namespace the cookie as "svgeditstore" instead of just "store"
- Breaking change (API): Remove `svgCanvas.rasterExport` fourth (callback) argument, collapsing fifth (options) to fourth
- Breaking change (API): Remove `svgCanvas.exportPDF` third (callback) argument
- Breaking change (API): `editor/contextmenu.js` `add` now throws instead of giving a console error only upon detecting a bad menuitem or preexisting context menu
- Breaking change (API): Remove `svgCanvas.embedImage` second (callback) argument
- Breaking change (API): Make `getHelpXML` a class instead of instance method of `RGBColor`
- Breaking change (internal API): Refactor `dbox` (and `alert`/`confirm`/`process`/`prompt`/`select`) to avoid a callback argument in favor of return a Promise
- Fix: Avoid running in extension `langReady` multiple times or serially
- Enhancement (API): Add svgCanvas.runExtension to run just one extension and add `nameFilter` callback to `runExtensions`
- Enhancement (API): Supply `$` (our wrapped jQuery) to extensions so can use its plugins, e.g., dbox with its `alert`
- Enhancement: Use alert dialog in place of `alert` in webappfind
- Enhancement: `editor.ready` now returns a Promise resolving when all callbacks have resolved
- Enhancement: Allow `noAlert` option as part of second argument to `loadSvgString` (and `loadFromURL` and `loadFromDataURI`) to avoid UI alert (and trigger promise rejection)
- Enhancement: Make `dbox` as a separate module for alert, prompt, etc. dialogs
- Refactoring: Internal `PaintBox` as class; other misc. tweaks; no bitwise in canvg
- Linting (ESLint): Further linting changes (for editor); rename `.eslintrc` -> `.eslintrc.json` per recommendation
- Optimization: Recompress images (imageoptim-cli updated)
- npm: Update devDeps
- npm: Bump to 4.0.0
This commit is contained in:
Brett Zamir
2018-11-08 14:48:01 +08:00
parent 7c470e9909
commit 2e5c7557a9
159 changed files with 25502 additions and 15658 deletions

View File

@@ -37,7 +37,43 @@ var svgEditorExtension_storage = (function () {
};
}
/* globals jQuery */
function _slicedToArray(arr, i) {
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest();
}
function _arrayWithHoles(arr) {
if (Array.isArray(arr)) return arr;
}
function _iterableToArrayLimit(arr, i) {
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 _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance");
}
/**
* ext-storage.js
@@ -63,9 +99,9 @@ var svgEditorExtension_storage = (function () {
*/
var extStorage = {
name: 'storage',
init: function init() {
init: function init(_ref) {
var $ = _ref.$;
var svgEditor = this;
var $ = jQuery;
var svgCanvas = svgEditor.canvas; // We could empty any already-set data for users when they decline storage,
// but it would be a risk for users who wanted to store but accidentally
// said "no"; instead, we'll let those who already set it, delete it themselves;
@@ -78,6 +114,11 @@ var svgEditorExtension_storage = (function () {
forceStorage = _svgEditor$curConfig.forceStorage;
var storage = svgEditor.storage,
updateCanvas = svgEditor.updateCanvas;
/**
* Replace `storagePrompt` parameter within URL.
* @param {string} val
* @returns {undefined}
*/
function replaceStoragePrompt(val) {
val = val ? 'storagePrompt=' + val : '';
@@ -91,6 +132,13 @@ var svgEditorExtension_storage = (function () {
loc.href += (loc.href.includes('?') ? '&' : '?') + val;
}
}
/**
* Sets SVG content as a string with "svgedit-" and the current
* canvas name as namespace.
* @param {string} val
* @returns {undefined}
*/
function setSVGContentStorage(val) {
if (storage) {
@@ -103,29 +151,42 @@ var svgEditorExtension_storage = (function () {
}
}
}
/**
* Set the cookie to expire.
* @param {string} cookie
* @returns {undefined}
*/
function expireCookie(cookie) {
document.cookie = encodeURIComponent(cookie) + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT';
}
/**
* Expire the storage cookie.
* @returns {undefined}
*/
function removeStoragePrefCookie() {
expireCookie('store');
expireCookie('svgeditstore');
}
/**
* Empties storage for each of the current preferences.
* @returns {undefined}
*/
function emptyStorage() {
setSVGContentStorage('');
Object.keys(svgEditor.curPrefs).forEach(function (name) {
name = 'svg-edit-' + name;
for (var name in svgEditor.curPrefs) {
if (svgEditor.curPrefs.hasOwnProperty(name)) {
name = 'svg-edit-' + name;
if (storage) {
storage.removeItem(name);
}
expireCookie(name);
if (storage) {
storage.removeItem(name);
}
}
expireCookie(name);
});
} // emptyStorage();
/**
@@ -142,11 +203,11 @@ var svgEditorExtension_storage = (function () {
function setupBeforeUnloadListener() {
window.addEventListener('beforeunload', function (e) {
// Don't save anything unless the user opted in to storage
if (!document.cookie.match(/(?:^|;\s*)store=(?:prefsAndContent|prefsOnly)/)) {
if (!document.cookie.match(/(?:^|;\s*)svgeditstore=(?:prefsAndContent|prefsOnly)/)) {
return;
}
if (document.cookie.match(/(?:^|;\s*)store=prefsAndContent/)) {
if (document.cookie.match(/(?:^|;\s*)svgeditstore=prefsAndContent/)) {
setSVGContentStorage(svgCanvas.getSvgString());
}
@@ -156,28 +217,27 @@ var svgEditorExtension_storage = (function () {
// svgEditor.showSaveWarning = false;
var curPrefs = svgEditor.curPrefs;
Object.entries(curPrefs).forEach(function (_ref2) {
var _ref3 = _slicedToArray(_ref2, 2),
key = _ref3[0],
val = _ref3[1];
for (var key in curPrefs) {
if (curPrefs.hasOwnProperty(key)) {
// It's our own config, so we don't need to iterate up the prototype chain
var val = curPrefs[key];
var store = val !== undefined;
key = 'svg-edit-' + key;
var store = val !== undefined;
key = 'svg-edit-' + key;
if (!store) {
continue;
}
if (storage) {
storage.setItem(key, val);
} else if (window.widget) {
window.widget.setPreferenceForKey(val, key);
} else {
val = encodeURIComponent(val);
document.cookie = encodeURIComponent(key) + '=' + val + '; expires=Fri, 31 Dec 9999 23:59:59 GMT';
}
if (!store) {
return;
}
}
if (storage) {
storage.setItem(key, val);
} else if (window.widget) {
window.widget.setPreferenceForKey(val, key);
} else {
val = encodeURIComponent(val);
document.cookie = encodeURIComponent(key) + '=' + val + '; expires=Fri, 31 Dec 9999 23:59:59 GMT';
}
});
});
}
@@ -187,14 +247,14 @@ var svgEditorExtension_storage = (function () {
langReady: function () {
var _langReady = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee(_ref) {
var importLocale, _$$deparam$querystrin, storagePrompt, confirmSetStorage, message, storagePrefsAndContent, storagePrefsOnly, storagePrefs, storageNoPrefsOrContent, storageNoPrefs, rememberLabel, rememberTooltip, options, oldContainerWidth, oldContainerMarginLeft, oldContentHeight, oldContainerHeight;
regeneratorRuntime.mark(function _callee(_ref4) {
var importLocale, _$$deparam$querystrin, storagePrompt, confirmSetStorage, message, storagePrefsAndContent, storagePrefsOnly, storagePrefs, storageNoPrefsOrContent, storageNoPrefs, rememberLabel, rememberTooltip, options, oldContainerWidth, oldContainerMarginLeft, oldContentHeight, oldContainerHeight, _ref5, pref, checked;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
importLocale = _ref.importLocale;
importLocale = _ref4.importLocale;
_$$deparam$querystrin = $.deparam.querystring(true), storagePrompt = _$$deparam$querystrin.storagePrompt;
_context.next = 4;
return importLocale();
@@ -217,7 +277,7 @@ var svgEditorExtension_storage = (function () {
// extension! (and to avoid using any prior storage, set the
// config option "noStorageOnLoad" to true).
if (!forceStorage && ( // If the URL has been explicitly set to always prompt the
if (!(!forceStorage && ( // If the URL has been explicitly set to always prompt the
// user (e.g., so one can be pointed to a URL where one
// can alter one's settings, say to prevent future storage)...
storagePrompt === true || // ...or...if the URL at least doesn't explicitly prevent a
@@ -225,100 +285,129 @@ var svgEditorExtension_storage = (function () {
// don't want to set cookies at all but who don't want
// continual prompts about it)...
storagePrompt !== false && // ...and this user hasn't previously indicated a desire for storage
!document.cookie.match(/(?:^|;\s*)store=(?:prefsAndContent|prefsOnly)/) // ...then show the storage prompt.
)) {
options = [];
!document.cookie.match(/(?:^|;\s*)svgeditstore=(?:prefsAndContent|prefsOnly)/) // ...then show the storage prompt.
))) {
_context.next = 44;
break;
}
if (storage) {
options.unshift({
value: 'prefsAndContent',
text: storagePrefsAndContent
}, {
value: 'prefsOnly',
text: storagePrefsOnly
}, {
value: 'noPrefsOrContent',
text: storageNoPrefsOrContent
});
} else {
options.unshift({
value: 'prefsOnly',
text: storagePrefs
}, {
value: 'noPrefsOrContent',
text: storageNoPrefs
});
} // Hack to temporarily provide a wide and high enough dialog
options = [];
oldContainerWidth = $('#dialog_container')[0].style.width, oldContainerMarginLeft = $('#dialog_container')[0].style.marginLeft, oldContentHeight = $('#dialog_content')[0].style.height, oldContainerHeight = $('#dialog_container')[0].style.height;
$('#dialog_content')[0].style.height = '120px';
$('#dialog_container')[0].style.height = '170px';
$('#dialog_container')[0].style.width = '800px';
$('#dialog_container')[0].style.marginLeft = '-400px'; // Open select-with-checkbox dialog
// From svg-editor.js
$.select(message, options, function (pref, checked) {
if (pref && pref !== 'noPrefsOrContent') {
// Regardless of whether the user opted
// to remember the choice (and move to a URL which won't
// ask them again), we have to assume the user
// doesn't even want to remember their not wanting
// storage, so we don't set the cookie or continue on with
// setting storage on beforeunload
document.cookie = 'store=' + encodeURIComponent(pref) + '; expires=Fri, 31 Dec 9999 23:59:59 GMT'; // 'prefsAndContent' | 'prefsOnly'
// If the URL was configured to always insist on a prompt, if
// the user does indicate a wish to store their info, we
// don't want ask them again upon page refresh so move
// them instead to a URL which does not always prompt
if (storagePrompt === true && checked) {
replaceStoragePrompt();
return;
}
} else {
// The user does not wish storage (or cancelled, which we treat equivalently)
removeStoragePrefCookie();
if (pref && // If the user explicitly expresses wish for no storage
emptyStorageOnDecline) {
emptyStorage();
}
if (pref && checked) {
// Open a URL which won't set storage and won't prompt user about storage
replaceStoragePrompt('false');
return;
}
} // Reset width/height of dialog (e.g., for use by Export)
$('#dialog_container')[0].style.width = oldContainerWidth;
$('#dialog_container')[0].style.marginLeft = oldContainerMarginLeft;
$('#dialog_content')[0].style.height = oldContentHeight;
$('#dialog_container')[0].style.height = oldContainerHeight; // It should be enough to (conditionally) add to storage on
// beforeunload, but if we wished to update immediately,
// we might wish to try setting:
// svgEditor.setConfig({noStorageOnLoad: true});
// and then call:
// svgEditor.loadContentAndPrefs();
// We don't check for noStorageOnLoad here because
// the prompt gives the user the option to store data
setupBeforeUnloadListener();
svgEditor.storagePromptState = 'closed';
updateCanvas(true);
}, null, null, {
label: rememberLabel,
checked: true,
tooltip: rememberTooltip
if (storage) {
options.unshift({
value: 'prefsAndContent',
text: storagePrefsAndContent
}, {
value: 'prefsOnly',
text: storagePrefsOnly
}, {
value: 'noPrefsOrContent',
text: storageNoPrefsOrContent
});
svgEditor.storagePromptState = 'waiting';
} else if (!noStorageOnLoad || forceStorage) {
} else {
options.unshift({
value: 'prefsOnly',
text: storagePrefs
}, {
value: 'noPrefsOrContent',
text: storageNoPrefs
});
} // Hack to temporarily provide a wide and high enough dialog
oldContainerWidth = $('#dialog_container')[0].style.width, oldContainerMarginLeft = $('#dialog_container')[0].style.marginLeft, oldContentHeight = $('#dialog_content')[0].style.height, oldContainerHeight = $('#dialog_container')[0].style.height;
$('#dialog_content')[0].style.height = '120px';
$('#dialog_container')[0].style.height = '170px';
$('#dialog_container')[0].style.width = '800px';
$('#dialog_container')[0].style.marginLeft = '-400px'; // Open select-with-checkbox dialog
// From svg-editor.js
svgEditor.storagePromptState = 'waiting';
_context.next = 20;
return $.select(message, options, null, null, {
label: rememberLabel,
checked: true,
tooltip: rememberTooltip
});
case 20:
_ref5 = _context.sent;
pref = _ref5.response;
checked = _ref5.checked;
if (!(pref && pref !== 'noPrefsOrContent')) {
_context.next = 30;
break;
}
// Regardless of whether the user opted
// to remember the choice (and move to a URL which won't
// ask them again), we have to assume the user
// doesn't even want to remember their not wanting
// storage, so we don't set the cookie or continue on with
// setting storage on beforeunload
document.cookie = 'svgeditstore=' + encodeURIComponent(pref) + '; expires=Fri, 31 Dec 9999 23:59:59 GMT'; // 'prefsAndContent' | 'prefsOnly'
// If the URL was configured to always insist on a prompt, if
// the user does indicate a wish to store their info, we
// don't want ask them again upon page refresh so move
// them instead to a URL which does not always prompt
if (!(storagePrompt === true && checked)) {
_context.next = 28;
break;
}
replaceStoragePrompt();
return _context.abrupt("return");
case 28:
_context.next = 35;
break;
case 30:
// The user does not wish storage (or cancelled, which we treat equivalently)
removeStoragePrefCookie();
if (pref && // If the user explicitly expresses wish for no storage
emptyStorageOnDecline) {
emptyStorage();
}
if (!(pref && checked)) {
_context.next = 35;
break;
}
// Open a URL which won't set storage and won't prompt user about storage
replaceStoragePrompt('false');
return _context.abrupt("return");
case 35:
// Reset width/height of dialog (e.g., for use by Export)
$('#dialog_container')[0].style.width = oldContainerWidth;
$('#dialog_container')[0].style.marginLeft = oldContainerMarginLeft;
$('#dialog_content')[0].style.height = oldContentHeight;
$('#dialog_container')[0].style.height = oldContainerHeight; // It should be enough to (conditionally) add to storage on
// beforeunload, but if we wished to update immediately,
// we might wish to try setting:
// svgEditor.setConfig({noStorageOnLoad: true});
// and then call:
// svgEditor.loadContentAndPrefs();
// We don't check for noStorageOnLoad here because
// the prompt gives the user the option to store data
setupBeforeUnloadListener();
svgEditor.storagePromptState = 'closed';
updateCanvas(true);
_context.next = 45;
break;
case 44:
if (!noStorageOnLoad || forceStorage) {
setupBeforeUnloadListener();
}
case 10:
case 45:
case "end":
return _context.stop();
}