svgedit/docs/versions/3.0.0.md

466 lines
24 KiB
Markdown
Raw Normal View History

# Version 3.0.0
3.0.0 offers a number of changes since 2.8.1, including many refactoring
ones meant to make the code more maintainable and leverage current standards
for more readable and semantic code, as well as a good number of fixes and
enhancements.
Please see the CHANGES file (or the Git history or Github tracker) for more
detailed descriptions of individual changes than that provided by the
below summaries.
## Breaking changes
There were also the following breaking changes. Not included among these are
those handful of breaking changes which only applied to those adopting
3.0.0 pre-release versions and which are marked as
"Breaking change (prerelease)" in CHANGES).
### Modularization-related breaking changes
A number of changes were made to improve modularization.
#### Source code converted to ES6 Modules
If you were modifying source files directly, the module format has now changed
to ES6 Modules. This allows us to specify, in a standard fashion, all of
the external dependencies of a file, without any "magic" variables appearing
in the code with no indication of their source (unless they are browser
globals which should be well-known). Use of modules also avoids the need
to keep track of dependencies non-contextually within the HTML and allows us
to avoid polluting our HTML with additional script tags.
File names were also changed. See "Other breaking changes" for these.
Note that compilation no longer occurs with a Makefile but is handled by
Rollup, a library for bundling ES6 Modules. Our Rollup routine also
handles applying Babel and minification.
Note that while the number of script tags in the HTML has been reduced,
certain polyfill files (dom-polyfill and @babel/polyfill) have now been
added and are required for older browsers. They could be dropped in the
future once browser support is available or if you are only targeting
browser versions that have no need of them.
For ES6 Modules being available as a distribution option, see "Enhancements".
##### Design choices for applying modules (Technical)
The jQuery files have not been added in ES6 Modules format, however, because
they do not have such a distribution and adding an import in source would
require compilation whereas we'd like the modular file to work without
compilation for faster debugging (note that rather than importing our
external npm dependencies directly from `node_modules`, we have a `copy-deps`
script for copying these files into our repository, so experimenting on
these files should probably be done within the `editor/external` directory,
though such changes should not be committed unless the source packages
are also updated and the `copy-deps` routine brings them in).
The file `redirect-on-lacking-support.js` has not been bundled with the main
`svgedit-config-es.js` script so that browsers not supporting SVG are
redirected faster (and, in the same vein as polyfills, it may be more
logically consistent to add this externally anyways).
The `redirect-on-no-module-support.js`, which redirects when module
support is not available, is not bundled for the same essential reason.
#### JavaScript config file breaking changes
In place of looking for `config.js` in the `editor` directory,
Unlike version 2.8.1 which had a `config-sample.js` file which needed
to be copied to `config.js` in the same directory, in version 3.0.0,
things work out of the box by pointing to the pre-built config files (also
an advantage for our use of Github-based project hosts like
raw.githack.com), but these config files have been moved out of the
`editor` folder and are looked for in the parent directory (project root
if using the editor within our repository).
These files also now have different names (`svgedit-config-es.js`
for `svg-editor-es.html` and `svgedit-config-iife.js` for `svg-editor.html`).
This move is intended to allow config to be stored semi-independently
of editor files.
#### Stylesheet breaking changes
In version 2.8.1, one could place a `custom.css` file in the same directory
as the editor and it would be used.
The default is now looked for in the parent directory of the editor HTML
and is expected as `svgedit-custom.css`.
You may change the stylesheets which are loaded by changing the default
JavaScript stylesheet config (see the
"JavaScript config file breaking changes" section for the location of
these files). The default is:
```js
svgEditor.setConfig({
stylesheets: ['@default', '../svgedit-custom.css']
});
```
...which indicates it will load all default stylesheets and then
one's custom file. You may omit either of these and/or add your own.
See "Other breaking changes -> HTML" for removal of the "scoped"
attribute on a stylesheet within the HTML.
#### Base path breaking changes
With extensions and locales now also expressed as ES6 modules in source
(see their respective breaking changes section below), the non-modular
versions of these files have been compiled into the new `dist` directory,
and in order to avoid path resolution problems, the config properties
`extPath` and `langPath` now have different defaults, depending
on whether a module environment is detected or not.
The non-modular versions will now default to "../dist/extensions/" and
"../dist/locale/", respectively, whereas the modular version will use the
old default paths ("extensions/" and "locale/").
Also, since we have not copying extension icons over to `dist` and the path
resolution of extension icons would otherwise break, we have now added new
config `extIconsPath`, distinct from `extPath`, which points by default to
"extensions/" for both modular and non-modular environments.
And because canvg and jspdf are now building from module and would break as
a result of this move as well, we have added the config `canvgPath` and
`jspdfPath` which default respectively to "canvg/" and "jspdf/" for modular
loads and to "../dist/" for both path types with non-modular loads.
(`imgPath` and `jGraduatePath` remain unchanged since they, as with
`extIconsPath`, are not looking for module-only files.)
#### Locale breaking changes
Locale files are now formatted as ES6 Module exports.
In order for their value to be discovered when compiled and loaded
in a non-modular context, in such contexts they will be auto-defined
as global variables (as "svgEditorLang_" followed by the
locale file name with any hyphens replaced as underscores).
In the spirit of modularization and only loading what is needed,
locale strings pertaining solely to extensions were moved to
`editor/extensons/ext-locale/<extension name>/<language code>.js`.
A new method, `importLocale`, is passed to extensions
(see "Summary of enhancements -> APIs") which can load locale files
within this hierarchy, requiring no arguments if relying on the detected
locale.
The `npm run rollup` routine (also a part of `npm test`) will build
any properly named and formatted ES6 Modules locale file into a non-modular
file within `dist/locale`.
#### Extension breaking changes
Extension files are now formatted as ES6 Module exports rather than as
calls to `svgEditor.addExtension`. The latter may still be used, but
support for passing an object (with a `callback` method as an init function)
is not (`callback` may be present on the *return* object of extension `init`
method, however).
In order for their value to be discovered when compiled and loaded
in a non-modular context, in such contexts they will be auto-defined
as global variables (as "svgEditorExtension_" followed by the
extension file name with any hyphens replaced as underscores).
The name supplied as the first argument to `addExtension` should instead
be expressed as a property on an object exported by the extension (or
it can be omitted to default to a name derived from the file name; this is
only used as a unique identifier).
Any init function previously supplied as second argument to `addExtension`
should be expressed as an `init` method on the object exported by the
extension and it should return what the init function had been returning.
Its `this` value will be set to the editor object.
For the object returned by `init`, invocation of any `callback` method
will also be invoked with the `this` value set to the editor object.
The `npm run rollup` routine (also a part of `npm test`) will build
any properly named and formatted ES6 Modules extension file into a non-modular
file within `dist/extensions`.
See also "Locale breaking changes".
### Other breaking changes
- **Usage** - Avoid zoom with scroll unless shift key pressed; checkbox
for persisting choice of initial use storage approval in storage
extension dialog is now turned on by default for convenience of
most users (must still hit "ok" and users can still turn off the checkbox)
- **Process changes**:
- Change PDF export to check `exportWindowName` for filename and change
default from `download` to `svg.pdf`, distinguishing from other downloads
- **HTML changes**: Remove now obsolete `scoped` attribute from `style`
and move tag to head
- **File renames/removal** - Files were renamed for greater clarity and
consistency
- **Minified file renaming/removal**
- `jquery.js` to `jquery.min.js`
- `extensions/mathjax/MathJax.js` to `extensions/mathjax/MathJax.min.js`
- Remove minified jgraduate/spinbtn files (minified now within Rollup
bundling)
- Avoid **"SVG" in file names** except for main file, `svg-editor.js`,
long-time core, `svgcanvas.js`, and polyfills with "SVG" in actual
variable name ("pathseg.js" to "svgpathseg.js"); also make clear
distinct file purpose ("svgedit.js" to "namespaces.js" and
"svgutils.js" to "utilities.js")
- Consistent **jQuery-based-file naming** (and reflect name of class):
"jquery-svg.js" to "jQuery.attr.js"
"jquery.contextMenu.js" to "jQuery.contextMenu.js",
"jquery.jpicker.js" to "jQuery.jPicker.js",
"JQuerySpinBtn.css" to "jQuery.SpinButton.css",
"JQuerySpinBtn.js" to "jQuery.SpinButton.js",
"jquery.svgicons.js" to "jQuery.svgIcons.js",
"jquery.jgraduate.js" to "jQuery.jGraduate.js"
- **Method naming**:
- Switch where feasible to **capitalized acronyms**
(`addSvgElementFromJson()` to `addSVGElementFromJson`,
`changeSvgContent()` to `changeSVGContent()`)
- **APIs**
- **Modularity/removing globals**
- Remove `window.svgCanvas` and `svgCanvas.ready` (use
`svgEditor.canvas` and `svgEditor.ready` instead)
- Avoid passing `canvg` to extensions (have them import)
- As part of possible deprecation of "private" methods separate from public
methods of SvgCanvas or svgEditor, avoid adding the following methods
already available on canvas to `getPrivateMethods` which is passed to
extensions: `assignAttributes`, `addSVGElementFromJson`,
`call`, `copyElem`, `findDefs`, `getElem`, `getId`,
`getIntersectionList`, `getMouseTarget`, `getNextId`, `getUrlFromAttr`,
`hasMatrixTransform`, `matrixMultiply`,
`recalculateAllSelectedDimensions`, `recalculateDimensions`,
`remapElement`, `removeUnusedDefElems`, `round`, `runExtensions`,
`sanitizeSvg`, `setGradient` `transformListToTransform` (and mistaken
`toString` export)
- **Other breaking API changes** - To allow extensions to add images without
select image dialog, only "image" mode will trigger dialog; require `new`
with `EmbeddedSVGEdit`; for `ext-imagelib`, change to an object-based
encoding for namespacing of messages (though will keep stringifying/parsing
internally until we remove IE9 support); the WebAppFind extension was
modified to use its new API; `svgcanvas.setUiStrings` must now be called
if not using `svg-editor.js` in order to get strings (for sake of i18n)
(and if using `path.js` alone, it must also have its `setUiStrings`
called); `RGBColor` must accept `new`; `readLang` no longer calls
`setLang` (locales need not call this anymore anyways; it will be
imported); The dropping of XML internal subsets might cause breakage with
documents using entities (though browser support for entity declarations
has been low); remove `storagePromptClosed` state boolean in favor of
`storagePromptState`
- **Extensions**
- **ext-arrows** - Change name from `Arrows` to `arrows`
for sake of consistency with file path (not localized anyways; only
used for unique identification)
- **ext-overview-window** - Avoid global `overviewWindowGlobals`
## Deprecations and situational regressions
- While string based messaging continues to work with `ext-imagelib`, the
**object-based messaging** should be used instead (as also used now in
the embedded editor API and `ext-xdomain-messaging`)
- The IAN image library, for which access is built-in from svgedit, has
already adjusted to deploy our new recommended object-based messaging
format. After more of their users migrate to version 3.\* of svgedit,
we should then hopefully be able to avoid passing this site an argument,
(`svgedit=3`) within their URL (a flag, if not present, which they are
using to employ the old object messaging mode).
- **Situational regression**: Remove Openclipart as its site's now setting of
`X-Frame-Options` to `"sameorigin"` makes it unusable on our end
for our cross-origin uses (even with an attempt to use their API)
## Summary of fixes
Since 2.8.1, there have been a number of fixes. Here is a summary (though
we do not include regressions made during the 3.0.0 prereleases which
have since been fixed; search CHANGES for "regression" for these):
- **Security fixes**:
- **URL Config**: 'extPath', 'imgPath', 'langPath' were not being prevented
from URL setting
- **Imagelib extension**: Avoid XSS, prevent billion laughs attack, only
allow `imgLibs` origins for messaging
- **xdomain HTML**: Namespace this file to avoid it being used to modify
non-domain storage on the same domain
- **Embedded API**: Avoid arbitrary property setting for trusted domains
- **toXml**: Ensure all apostrophes are escaped for `toXml` utility
- **Localization/i18n**: French and German updates; adding simplified Chinese
to pull-down; bad characters in Persian locale file; fix "lv" locale;
clarify locale messages re: save as; fix `lang` and `dir` for locales
(though not in use currently); allow language in settings to be properly
set back to a different locale, ensure language changes are retained and
available before settings dialog is closed; ensure `langReady` changes
are available when dialog is closed and that its changes have occurred
by extensions' first load to ensure extension loading complete and the
updating of canvas at this time based on `storagePromptState` has seen
`langReady` including the storage extension possibly having set a
`storagePromptState` of "waiting"
- **Directly user-visible fixes**: imported images with rubberband
box placement and unattached dragtool, hidden font-size setting, and
resizing nullifying the stroke, layers panel, zoom centered on cursor
when scrolled, avoiding when shift key is pressed, Document Properties
dialog positioning; ensure repeated selection of same file overwrites
with that file's contents; center canvas properly on load
- **Export fixes** - Alert if `exportWindow` blocked; avoid error
if `URL` is not defined; see also browser-specific;
polygon/polyline in PDF export
- **Keyboard/Command** with keypress double binding and text element
being triggered by input as well as keyup events, and pasting some lines
with markers; backspace key in Firefox navigating out of frame;
Ensure shift-key cycling through flyouts works with extension-added
`includeWith` as well as toolbarbuttons; ensure line tool shows as
selected when "L" key command is used
- **Processing fixes** such as browser feature detection
(`supportsPathInsertItemBefore` and `supportsPathReplaceItem`), layer fixes,
multiple selection, cloning of path segments during moving, `convertPath`
with complex paths, preserving `rx` and `ry` on ellipses to allow disabling
of rendering; proper handling in `ext-connector` of 2 connecting elements
with same y-coordinate; `removeFromSelection` length issues; avoid errors
for `tspan` passed to `getGradient`; avoid race condition in applying arrows
revealing flyouts and ensure this icon is cloned so can be applied to
more than one extension; avoid setting `Math.precision` pseudo-global in
jPicker; precision argument had not been passed in previously to jPicker;
for image import, avoid race condition and avoid 0 width/neight import
- **API fixes**: Triggering of `svgEditorReady` when canvas is ready and via
iframe; properly default `rasterExport` without `imgType`
- **Embedded editor**:
- Do not add parent URL to iframe src URL when query string is empty.
- **Cross-origin issues**: Due to Chrome having applied more restrictions
on cross-origin iframes, the embedded editor broke in some contexts.
We now avoid errors for same-origin checking, and avoid or recover
from exceptions with cross-origin `localStorage` or `contentDocument`
access; apparently works on at least https sites (at least not localhost)
with `Access-Control-Allow-Origin` header and
locally set with `allowedOrigins` with `*` or the given origin(s)
(such as in the xdomain editor); however, `localStorage`, as is
needed for clipboard and saving in storage, does not work regardless;
we should allow a listener in the parent frame (made configurable
through the embedded API), so it can get and set its own storage in
response to SVG-Edit events. We are also still throwing for some
`localStorage` access (e.g., context menu cut).
- **Browser/device-specific fixes** impacting Overview panel performance,
Multiselect with zoom, multiple element selection, `getInsectionList`,
pathseg, `supportsNativeTransformLists` detection, and save/export,
removing identity matrices, recover from `tspan` having no `getBBox`
image export, `supportsGoodTextCharPos`; force PDF download in Chrome
(dropped dataURI with window opening); map extension click events to
"mousedown" so they can be received on touch devices
- **Extension fixes**: ForeignObject editor dialog had not been opening; fix
`name` for moinsave; error during resize with MathML; add images
for fallback and referenced relative to new `extIconsPath`; extension
`includeWith` flyout button conflicts; avoid erring if `inradius` is `NaN`
in Star extension. A fix was added to allow `mouseup` triggering for
extensions in "zoom" and "select" modes, but was reverted in 3.0.1.
- **Linting-discovered fixes**: Inadvertent global assignments; bad variable
scope declarations including within `jquery.jgraduate.js`
- **Minor fixes** such as broken links and switching to `https`, adding of
ignore files, etc.
## Summary of enhancements
- **Directly user-visible changes**: If adding a new image, delete that image
upon dialog cancel
- **i18n**: i18nize `path.js` strings and canvas notifications; more i18n
of extensions; have general locales load first so extensions may use;
placeholders for picking stroke and fill paint opacity and
`popupWindowBlocked`; update `saveFromBrowser`
- **Configuration**: Configure text font and stroke; add StackBlur to
canvg by default; allow path config for canvg and jspdf (not needed
for built-in)
- **Security**: Link placeholder defaults to `https`
- **APIs**: Current zoom level, `addSvgElementFromJson` capabilities,
ability to set SVG drawings without adding to the undo stack; add
to methods passed to extensions; allow `addSvgElementFromJson` to
accept non-SVG namespaces as well with explicit `namespace` property;
add `extensions_added` event; make `setStrings` public on editor for
late setting; add `message` event to relay messages; return promise
for `rasterExport`, `exportPDF`, and `embedImage`; add
`pointsAdded` canvas event; supply `importLocale` to `init`,
`langReady` and `addLangData` for extension locale loading; allow
avoiding "name" in extension export
- **Optimizations**: `getBBox` and loading time; remove unused scripts,
compress images; for `setSvgString`, return `false` earlier if element
content is not SVG; avoid rewriting `points` attribute for free-hand path
- **Error handling**: Extension loading error logging and recovery
- **Keys/Commands**: Clipboard works across tabs and windows, "Escape"
to work with hotkeys within text boxes such as source textarea;
allow 'a' also with meta key to select all; global escape key listener
to clear the selection
- **Publishing options**: npm, `packagist.org`; `unpkg.com` and
`raw.githack.com`; for Github.io, add `latest` directory for hosting
latest release
- **Cross-origin option**: New and auto-generated `xdomain-svg-editor-es.html`
and `xdomain-svg-editor.html` files are now available which possess default
config which allows cross-origin use. It saves in a storage namespace
distinct from the main editor so as to avoid potential data corruption
or unauthorized retrieval of data created in the main editor by other domains.
- **Modular JavaScript**: ES6 modules distribution format and module-based
`svg-editor-es.html` HTML (for modern browsers only; otherwise, use one of
the UMD distributions or `svg-editor.html` file) and also separate versions
for `xdomain-svg-editor-es.html`; make SpinButton plugin independent of
svgedit (though still bundled)
- **JavaScript-only distribution files** - While SVG-Edit's JavaScript
currently very much presumes a certain HTML structure, for anyone who
wishes to copy and possibly modify that HTML file outside of the editor
folder (bearing in mind that certain paths may need to be adjusted),
they may reference the JavaScript builds within `dist`. There is an
ES6 Module distribution (for modern browsers only) as well as a UMD
distribution. In the `package.json` file, for the sake of minimizing
config needed by any bundlers of SVG-Edit, the ES distribution is
pointed to by the `module` property and the UMD distribution is pointed
to by `main`.
- **Modular stylesheets** - Add `stylesheets` config for indicating custom
stylesheets to load in parallel with any built-in; use `"@default"`
within this array of stylesheet paths to indicate inclusion of default
stylesheets (or omit `"@default"` to exclude them).
- **Process improvements**: Sort SVG attributes alphabetically
## Refactoring/Testing
- **ES6 Modules**: Use in source, including jQuery plugins, extensions,
locales, tests; see "Breaking Changes"
- **Updates**: QUnit and jQuery version within imagelib extension; include
Mathjax local copy
- **Other code refactoring**: `HistoryRecordingService`, `Command` base class,
migration away from svgcanvas to separate files (e.g., `layer.js`); various
clean-up, readability, simplification, and consistency changes; avoid
inline listeners and styles; more ES5/ES6 usage (e.g., `class`,
`includes`, destructuring, object shorthand, arrow functions), prefer
`const` and then `let` and place closer to used block, add favicons;
clearer and more camelCase variable names;
throw error objects instead of strings; allow Promises; add polyfills for
Babel and `ChildNode`/`ParentNode`; use new Event constructors
- **Linting**: Move to ESLint, using a derivative of the "standard" convention;
80 char. lines; use LGTM
- **Testing**: Add skeleton support for UI and accessibility testing with
TestCafe along with ESLint plugin/rules for it; add a draw test file;
separate JavaScript files out of HTML; use static server; fix
timing of `all_tests.html` for iframe size; comment out unused jQuery SVG
test while adding test1 and svgutils_performance_test to all tests page; fix
inadequate mocking in Path test
## Non-code/meta changes
- **License**: Indicate license types and rename files to reflect
type; rename/add license file name for jgraduate and screencast to reflect
type (Apache 2.0)
- **npm**: SVG-Edit is now published on npm; add ESLint, uglify, start, and
test scripts
- **Documentation**: Moved to JSDocs (with Markdown plugin, a custom template
to support overflow, and an script to check for overly generic types)
and added documentation for public module methods as well as adding mutual
linking between JSDocs tutorial docs; included online at <https://svg-edit.github.io/svgedit/releases/svg-edit-3.0.0/docs/jsdoc/>
(or for the latest release, use
<https://svg-edit.github.io/svgedit/releases/latest/docs/jsdoc/>);
update Release notes and add Contributing file, integrate Github wiki pages
into docs, and copy over old docs. Begin "Editor" doc file to help general
users
- **Demos**: Add svgcanvas demo
- **i18n**: Locales now use ES6 Modules and extension locales are now
contained in separate files relative to the extensions directory (for
the sake of true modularity); see "Breaking Changes"