svgedit
Version:
Powerful SVG-Editor for your browser
232 lines (211 loc) • 17.6 kB
HTML
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Tutorial: Extension Docs</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Tutorial: Extension Docs</h1>
<section>
<header>
<h2>Extension Docs</h2>
</header>
<article>
<h1>Introduction</h1>
<p>SVG-Edit has support for extensions. This is a guide for creating
SVG-Edit extensions.</p>
<h2>Means to have extensions loaded</h2>
<p>SVG-Edit extensions are standalone JavaScript files that can be either
included in the HTML file, loaded using <code>setConfig</code>, or indicated through
the URL (see <a href="tutorial-ConfigOptions.html">ConfigOptions</a> for usage).</p>
<p><code>svgedit-config-iife.js</code> in the <code>src</code> directory (if
through Git clone, by running <code>npm run build-by-config</code>) is the file used
by <code>svg-editor.html</code> to execute commands before extensions are loaded,
e.g., if you wish to make configuration changes which affect extension
loading behavior.</p>
<p>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 <code>svgedit-config-iife.js</code> will always
run if present).</p>
<h2>Basic format</h2>
<p>This is the general format for an extension:</p>
<pre class="prettyprint source lang-js"><code>export default {
name: 'extensionname',
init (_methods) {
return extensionData
}
}
</code></pre>
<p>Extensions must export an object. (For the API docs of this object, see
<code>ExtensionObject</code>.)</p>
<p>The first property on the object exported above, <code>name</code>, 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.</p>
<p>The other property above (<code>init</code>) is a function (see
<code><code>ExtensionInitCallback</code></code>
for its API) that is supplied methods and variables from svgCanvas (see
<code><code>ExtensionArgumentObject</code></code>)
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 <code><code>ExtensionInitResponse</code></code>
for API documentation on the response type(s) available for <code>init</code>.</p>
<p>Its <code>this</code> value is bound to the editor, so
<a href="module-SVGEditor.html"><code>those methods</code></a> are also available.</p>
<p>In order to await execution of set-up such as calls to <code>langReady</code> and
<code>svgIcons</code>, the callback <code>callback</code> can be added to the object returned with
the call to <code>init</code>. The callback is invoked upon addition of the extension,
or, if svgicons are set, then after the icons are ready. See
<code><code>ExtensionInitResponse#callback</code></code>
in the API for more on this.</p>
<h2>Example</h2>
<p>The basic Hello world extension (in <code>/editor/extensions/ext-helloworld.js</code>)
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
<a href="https://svg-edit.github.io/svgedit/releases/latest/editor/svg-editor.html?extensions=ext-helloworld.js">extension in action</a>.</p>
<p>The basic structure of this extension looks like this:</p>
<pre class="prettyprint source lang-js"><code>export default {
name: 'helloworld',
init () {
return {
svgicons: 'extensions/helloworld-icon.xml',
buttons: [ { /* ... */ } ],
mouseDown () {
// ...
},
mouseUp (_opts) {
// ...
}
}
}
}
</code></pre>
<p>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.</p>
<p>The "Hello World" extension also demonstrates internationalization (see
the next section).</p>
<h2>Internationalization of extensions</h2>
<p>The locale files for extensions (which need translation as with the main
locales) are hosted in <code>editor/extensions/ext-locale/<ext name>/</code>.</p>
<p>Both <code>addLangData</code>
(<code>JSDocs</code>)
(invoked early)
and <code>langReady</code>
(<code>JSDocs</code>)
are passed objects with an <code>importLocale</code> function
(<code>JSDocs</code>) (as well as
<code>init</code>--see the Basic Format section) that you can use to
import your own extension locales hosted in the above-mentioned directory.</p>
<p>The <code>importLocale</code> function will use the detected locale and detected
extension name by default (no need for arguments), and returns a
<code>Promise</code> that will resolve to the locale strings found within a
file you place at:</p>
<p><code>${svgEditor.curConfig.extPath}ext-locale/<extNameWithoutExtPrefix>/<lang>.js</code>
(<code><lang></code> is the detected <code>lang</code> returned on
<code><code>langReady</code></code> and
<code><extNameWithoutExtPrefix></code> is your extension name without the initial
required "ext-" prefix and without the trailing ".js").</p>
<p>The resolved <code>Promise</code> value is expected to adhere to
<a href="module-locale.html#.LocaleStrings"><code><code>LocaleStrings</code></code></a> (as with SVGEdit's
global locale files).</p>
<p>One may return a Promise (including by <code>async</code>/<code>await</code>) waiting for
<code>importLocale</code> to resolve so as to delay further processing until complete.</p>
<p>You could also use your own means to store and retrieve locale data for
your extension (and
<code><code>importSetGlobalDefault</code></code>
is available should this be of assistance) in which case the <code>global</code>
property should follow the format
<code>svgEditorExtensionLocale_<extNameWithoutExtPrefix>_<lang></code> to avoid global
naming conflicts in the non-modular version of SVGEdit.</p>
<pre class="prettyprint source lang-js"><code>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`
console.info(localeStrings)
})()
</code></pre>
<p>In addition to your own extension's locale strings,
<code><code>langReady</code></code>
also has access to the global internationalization strings through the
<code>uiStrings</code> property on the object passed to it (see
<code>event:ext_langReady</code>).</p>
<p>See also <a href="tutorial-LocaleDocs.html">LocaleDocs</a>, including for information on
formatting of locale strings (the current lack of any standard beyond a
convention of using brackets for variables).</p>
<h2>Creating buttons</h2>
<p>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.</p>
<p>Each button is an object (added to the
array "buttons" on the object returned by the extension's <code>init</code> method).
Its properties are outlined at
<code><code>SVGEditor.Button</code></code>.</p>
<h2>Creating SVG icons</h2>
<p>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 <code>svgicons</code> property.</p>
<p>An SVG icon file is an XML document that consists of a root SVG element
with child group elements (<code><g></g></code>). 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.</p>
<p>For further information, see the SVG Icon Loader project.</p>
<h2>Creating context tools</h2>
<p>Context tools appear in the top toolbar whenever a certain type of
element is selected.</p>
<p>These are added by the extension returning an object with the
property "context_tools". See <code>this object's API</code>
for details.</p>
<h2>SVG-Edit extension events</h2>
<p>See <a href="tutorial-Events.html">Events</a> for the events that lead to the triggering
of extension callbacks. (Mostly of relevance for developers of SVGEdit itself.)</p>
<h2>Helpers</h2>
<p>A variety of properties and methods can be accessed within extensions.</p>
<h3><code>svgCanvas</code> properties and methods</h3>
<p>These are supplied in an object through the first parameter of the
extension function (see "methods" variable in above example).</p>
<p>See
<code><code>ExtensionArgumentObject</code></code>.
Note that this object also has these
<code>surfaced private methods and properties from Canvas</code>.</p>
<h3><code>svgEditor</code> public properties and methods</h3>
<p>The <code>this</code> value of the <code>init</code>
(<code>JSDocs</code>) method
is the <a href="module-SVGEditor.html"><code>Editor object</code></a>. Its methods may be invoked
from on <code>this</code> within that method.</p>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="editor_extensions_ext-layer_view_locale_zh-CN.module_js.html">editor/extensions/ext-layer_view/locale/zh-CN.js</a></li><li><a href="module-SVGEditor.html">SVGEditor</a></li><li><a href="module-contextmenu.html">contextmenu</a></li><li><a href="module-jGraduate.html">jGraduate</a></li><li><a href="module-jPicker.html">jPicker</a></li><li><a href="module-locale.html">locale</a></li></ul><h3>Externals</h3><ul><li><a href="external-JamilihArray.html">JamilihArray</a></li><li><a href="external-Math.html">Math</a></li><li><a href="external-Window.html">Window</a></li><li><a href="external-jQuery.html">jQuery</a></li></ul><h3>Namespaces</h3><ul><li><a href="external-jQuery.fn.html">fn</a></li><li><a href="external-jQuery.fn.$.fn.jPicker.defaults.html">defaults</a></li><li><a href="external-jQuery.fn.exports.jPickerMethod.html">exports.jPickerMethod</a></li><li><a href="external-jQuery.fn.jGraduateDefaults.html">jGraduateDefaults</a></li><li><a href="external-jQuery.fn.jGraduateDefaults.images.html">images</a></li><li><a href="external-jQuery.fn.jGraduateDefaults.window.html">window</a></li><li><a href="external-jQuery.jGraduate.html">jGraduate</a></li><li><a href="external-jQuery.jPicker.html">jPicker</a></li><li><a href="external-jQuery.jPicker.ColorMethods.html">ColorMethods</a></li></ul><h3>Classes</h3><ul><li><a href="BottomPanel.html">BottomPanel</a></li><li><a href="Dropdown.html">Dropdown</a></li><li><a href="EditorStartup.html">EditorStartup</a></li><li><a href="ElixMenuButton.html">ElixMenuButton</a></li><li><a href="ElixNumberSpinBox.html">ElixNumberSpinBox</a></li><li><a href="ExplorerButton.html">ExplorerButton</a></li><li><a href="FlyingButton.html">FlyingButton</a></li><li><a href="LayersPanel.html">LayersPanel</a></li><li><a href="LeftPanel.html">LeftPanel</a></li><li><a href="MainMenu.html">MainMenu</a></li><li><a href="NumberSpinBox.html">NumberSpinBox</a></li><li><a href="PaintBox.html">PaintBox</a></li><li><a href="PlainNumberSpinBox.html">PlainNumberSpinBox</a></li><li><a href="Rulers.html">Rulers</a></li><li><a href="SEInput.html">SEInput</a></li><li><a href="SEPalette.html">SEPalette</a></li><li><a href="SESpinInput.html">SESpinInput</a></li><li><a href="SeCMenuDialog.html">SeCMenuDialog</a></li><li><a href="SeCMenuLayerDialog.html">SeCMenuLayerDialog</a></li><li><a href="SeColorPicker.html">SeColorPicker</a></li><li><a href="SeEditPrefsDialog.html">SeEditPrefsDialog</a></li><li><a href="SeExportDialog.html">SeExportDialog</a></li><li><a href="SeImgPropDialog.html">SeImgPropDialog</a></li><li><a href="SeList.html">SeList</a></li><li><a href="SeMenu.html">SeMenu</a></li><li><a href="SeMenuItem.html">SeMenuItem</a></li><li><a href="SePlainAlertDialog.html">SePlainAlertDialog</a></li><li><a href="SePlainBorderButton.html">SePlainBorderButton</a></li><li><a href="SePromptDialog.html">SePromptDialog</a></li><li><a href="SeStorageDialog.html">SeStorageDialog</a></li><li><a href="SeSvgSourceEditorDialog.html">SeSvgSourceEditorDialog</a></li><li><a href="SeText.html">SeText</a></li><li><a href="ToolButton.html">ToolButton</a></li><li><a href="TopPanel.html">TopPanel</a></li><li><a href="configObj.html">configObj</a></li><li><a href="external-jQuery.jGraduate.Paint.html">Paint</a></li><li><a href="external-jQuery.jPicker.Color.html">Color</a></li><li><a href="module.exports.html">exports</a></li><li><a href="module.exports_module.exports.html">exports</a></li><li><a href="module-SVGEditor-Editor.html">Editor</a></li><li><a href="module-jPicker.module.exports.html">module.exports</a></li></ul><h3>Interfaces</h3><ul><li><a href="module-SVGEditor.Config.html">Config</a></li><li><a href="module-SVGEditor.Prefs.html">Prefs</a></li><li><a href="module-SVGthis.CustomHandler.html">CustomHandler</a></li><li><a href="module-locale.LocaleEditorInit.html">LocaleEditorInit</a></li></ul><h3>Events</h3><ul><li><a href="module-SVGEditor.html#event:event:svgEditorReadyEvent">svgEditorReadyEvent</a></li></ul><h3>Tutorials</h3><ul><li><a href="tutorial-CanvasAPI.html">CanvasAPI</a></li><li><a href="tutorial-Editor.html">Editor</a></li><li><a href="tutorial-EditorAPI.html">EditorAPI</a></li><li><a href="tutorial-Events.html">Events</a></li><li><a href="tutorial-FrequentlyAskedQuestions.html">Frequently Asked Questions (FAQ)</a></li></ul><h3>Global</h3><ul><li><a href="global.html#attributeChangedCallback">attributeChangedCallback</a></li><li><a href="global.html#connectedCallback">connectedCallback</a></li><li><a href="global.html#constructor">constructor</a></li><li><a href="global.html#createTemplate">createTemplate</a></li><li><a href="global.html#decrement">decrement</a></li><li><a href="global.html#expireCookie">expireCookie</a></li><li><a href="global.html#formatValueFormatthenumericvalueasastring.Thisisusedafterincrementing/decrementingthevaluetoreformatthevalueasastring.">formatValue
Format the numeric value as a string.
This is used after incrementing/decrementing the value to reformat the
value as a string.</a></li><li><a href="global.html#get">get</a></li><li><a href="global.html#handleClick">handleClick</a></li><li><a href="global.html#handleClose">handleClose</a></li><li><a href="global.html#handleInput">handleInput</a></li><li><a href="global.html#handleKeyDown">handleKeyDown</a></li><li><a href="global.html#handleMouseDown">handleMouseDown</a></li><li><a href="global.html#handleMouseUp">handleMouseUp</a></li><li><a href="global.html#handleOptionsChange">handleOptionsChange</a></li><li><a href="global.html#handleSelect">handleSelect</a></li><li><a href="global.html#handleShow">handleShow</a></li><li><a href="global.html#increment">increment</a></li><li><a href="global.html#init">init</a></li><li><a href="global.html#inputsize">inputsize</a></li><li><a href="global.html#isNullish">isNullish</a></li><li><a href="global.html#loadloadConfig">load load Config</a></li><li><a href="global.html#loadFromURLLoadconfig/datafromURLifgiven">loadFromURL Load config/data from URL if given</a></li><li><a href="global.html#name">name</a></li><li><a href="global.html#observedAttributes">observedAttributes</a></li><li><a href="global.html#parseValue">parseValue</a></li><li><a href="global.html#pref">pref</a></li><li><a href="global.html#readySignal">readySignal</a></li><li><a href="global.html#regexEscape">regexEscape</a></li><li><a href="global.html#removeStoragePrefCookie">removeStoragePrefCookie</a></li><li><a href="global.html#replaceStoragePrompt">replaceStoragePrompt</a></li><li><a href="global.html#set">set</a></li><li><a href="global.html#setupCurConfig">setupCurConfig</a></li><li><a href="global.html#setupCurPrefs">setupCurPrefs</a></li><li><a href="global.html#src">src</a></li><li><a href="global.html#stateEffects">stateEffects</a></li><li><a href="global.html#stepDown">stepDown</a></li><li><a href="global.html#stepUp">stepUp</a></li><li><a href="global.html#triggerInputChanged">triggerInputChanged</a></li><li><a href="global.html#updateLib">updateLib</a></li><li><a href="global.html#value">value</a></li></ul>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.5</a> on Sun Dec 07 2025 19:46:40 GMT+0100 (Central European Standard Time)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>