8.4 KiB
Introduction
SVG-Edit has support for extensions (as of v2.5). This is a guide for creating SVG-Edit extensions.
Means to have extensions loaded
SVG-Edit extensions are standalone JavaScript files that can be either
included in the HTML file, loaded using setConfig
, or indicated through
the URL (see [ConfigOptions]{@tutorial ConfigOptions} for usage).
Note that, as of v3.0, if you create a svgedit-config-iife.js
file in
the project root directory (config.js
in the editor
directory for
v2.8), this will be used to execute commands before extensions are loaded,
e.g., if you wish to make configuration changes which affect extension
loading behavior. Normally, however, it should be preferable for modularity
to use the extension mechanism, as this can allow you or users to customize
which extensions are loaded (whereas svgedit-config-iife.js
will always
run if present).
Basic format
This is the general format for an extension:
export default {
name: 'extensionname',
init (methods) {
return extensionData;
}
};
Extensions must export an object. (For the API docs of this object, see [ExtensionObject]{@link module:SVGEditor.ExtensionObject}.)
The first property on the object exported above, name
, is the unique
ID for this extension. It can actually be omitted, in which case the
ID (not shown visually) will instead be determined from the file name
(omitting the initial "ext-" and ending ".js"). These are not displayed
visually, so the only purpose is to avoid name conflicts with other
extensions.
The other property above (init
) is a function (see
[ExtensionInitCallback
]{@link module:svgcanvas.ExtensionInitCallback}
for its API) that is supplied methods and variables from svgCanvas (see
[ExtensionArgumentObject
]{@link module:svgcanvas.ExtensionArgumentObject})
and can return an object that includes properties and functions that may
be required for further processing by
the extension, depending on the type of methods desired by the extension
being added. See [ExtensionInitResponse
]{@link module:svgcanvas.ExtensionInitResponse}
for API documentation on the response type(s) available for init
.
Its this
value is bound to the editor, so
[those methods]{@link module:SVGEditor} are also available.
In order to await execution of set-up such as calls to langReady
and
svgIcons
, the callback callback
can be added to the object returned with
the call to init
. The callback is invoked upon addition of the extension,
or, if svgicons are set, then after the icons are ready. See
[ExtensionInitResponse#callback
]{@link module:svgcanvas.ExtensionInitResponse#callback}
in the API for more on this.
Example
The basic Hello world extension (in /editor/extensions/ext-helloworld.js
)
can be seen as an example on how to create a basic extension. This extension
adds a "mode" button to the bottom of the left panel that changes the mode,
then shows a "Hello world" message whenever the canvas is clicked on. See
extension in action.
The basic structure of this extension looks like this:
export default {
name: 'helloworld',
init () {
return {
svgicons: 'extensions/helloworld-icon.xml',
buttons: [{...}],
mouseDown () {
...
},
mouseUp (opts) {
...
}
};
}
};
Note how the returned properties may include information on the buttons, as well as the functions that should be run when certain events take place.
The "Hello World" extension also demonstrates internationalization (see the next section).
Internationalization of extensions
The locale files for extensions (which need translation as with the main
locales) are hosted in editor/extensions/ext-locale/<ext name>/
.
Both addLangData
([JSDocs]{@link module:svgcanvas.ExtensionInitResponse#addLangData})
(invoked early)
and langReady
([JSDocs]{@link module:svgcanvas.ExtensionInitResponse#langReady})
are passed objects with an importLocale
function
([JSDocs]{@link module:SVGEditor~ImportLocale}) that you can use to
import your own extension locales hosted in the above-mentioned directory.
The importLocale
function will use the detected locale and detected
extension name by default (no need for arguments), and returns a
Promise
that will resolve to the locale strings found within a
file you place at:
${svgEditor.curConfig.extPath}ext-locale/<extNameWithoutExtPrefix>/<lang>.js
(<lang>
is the detected lang
returned on
[langReady
]{@link module:SVGEditor.ExtensionVars_langReady} and
<extNameWithoutExtPrefix>
is your extension name without the initial
required "ext-" prefix and without the trailing ".js").
The resolved Promise
value is expected to adhere to
[LocaleStrings
]{@link module:locale.LocaleStrings} (as with SVGEdit's
global locale files).
You could also use your own means to store and retrieve locale data for
your extension (and
[importSetGlobalDefault
]{@link module:importModule.importSetGlobalDefault}
is available should this be of assistance) in which case the global
property should follow the format
svgEditorExtensionLocale_<extNameWithoutExtPrefix>_<lang>
to avoid global
naming conflicts in the non-modular version of SVGEdit.
import {importSetGlobalDefault} from '../external/dynamic-import-polyfill/importModule.js';
// ...
(async () => {
const url = `${svgEditor.curConfig.extPath}ext-locale/<extNameWithoutExtPrefix>/<lang>.js`;
const localeStrings = await importSetGlobalDefault(url, {
global: 'svgEditorExtensionLocale_imagelib_' + lang
});
// Use `localeStrings`
})();
In addition to your own extension's locale strings,
[langReady
]{@link module:svgcanvas.ExtensionInitResponse#langReady}
also has access to the global internationalization strings through the
uiStrings
property on the object passed to it (see
[event:ext-langReady]{@link module:svgcanvas.SvgCanvas#event:ext-langReady}).
See also [LocaleDocs]{@tutorial LocaleDocs}, including for information on formatting of locale strings (the current lack of any standard beyond a convention of using brackets for variables).
Creating buttons
Buttons can appear either in the "mode" panel (left panel) or the "context" panel (top panel, changes depending on selection). Their icons can either consist of SVG icons (recommended) or just raster images.
Each button is an object (added to the
array "buttons" on the object returned by the extension's init
method).
Its properties are outlined at
[SVGEditor.Button
]{@link module:SVGEditor.Button}.
Creating SVG icons
The SVG-Edit project uses icons created using basic SVG (generally
using SVG-Edit as design tool), and extensions are encouraged to do so
too. This allows the interface toolbars to be resized and icons to be
reused at various sizes. If your extension uses multiple icons, they can
all be stored in the same file. To specify icon file used, set the path
under the extension's returned svgicons
property.
An SVG icon file is an XML document that consists of a root SVG element
with child group elements (<g></g>
). Each of these has an ID that
should match the ID specified in the associated button object.
Its content should be the SVG source of the icon. See the "Hello World"
icon as an example.
For further information, see the SVG Icon Loader project.
Creating context tools
Context tools appear in the top toolbar whenever a certain type of element is selected.
These are added by the extension returning an object with the property "context_tools". See [this object's API]{@link module:SVGEditor.ContextTool} for details.
SVG-Edit extension events
See [Events]{@tutorial Events} for the events that lead to the triggering of extension callbacks. (Mostly of relevance for developers of SVGEdit itself.)
Helpers
A variety of properties and methods can be accessed within extensions.
svgCanvas
properties and methods
These are supplied in an object through the first parameter of the extension function (see "methods" variable in above example).
See
[ExtensionArgumentObject
]{@link module:svgcanvas.ExtensionArgumentObject}.
Note that this object also has these
[surfaced private methods and properties from Canvas]{@link module:svgcanvas.PrivateMethods}.
svgEditor
public properties and methods
The this
value of the init
([JSDocs]{@link module:svgcanvas.ExtensionInitCallback}) method
is the [Editor object]{@link module:SVGEditor}. Its methods may be invoked
from on this
within that method.