feat: add type declarations for viewer and modeler

Related to #1829
This commit is contained in:
Philipp
2023-03-06 11:37:33 +01:00
committed by Philipp Fromme
parent 7e95f1d507
commit ab130b0d1f
15 changed files with 761 additions and 162 deletions

5
lib/BaseModeler.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
import BaseViewer from "./BaseViewer";
export type Moddle = Object;
export default class BaseModeler extends BaseViewer {}

View File

@ -6,21 +6,19 @@ import BaseViewer from './BaseViewer';
/** /**
* @typedef { import('didi').ModuleDeclaration } Module * @typedef {import('./BaseViewer').BaseModelerOptions} BaseModelerOptions
* @typedef {import('./BaseViewer').ModdleElement} ModdleElement
* @typedef {import('./BaseViewer').ModdleElementsById} ModdleElementsById
*
* @typedef {import('.').Moddle} Moddle
*/ */
/** /**
* A base modeler for BPMN 2.0 diagrams. * A base modeler for BPMN 2.0 diagrams.
* *
* Have a look at {@link Modeler} for a bundle that includes actual features. * See {@link Modeler} for a fully-featured modeler.
* *
* @param {Object} [options] configuration options to pass to the viewer * @param {BaseModelerOptions} [options] The options to configure the modeler.
* @param {DOMElement} [options.container] the container to render the viewer in, defaults to body.
* @param {string|number} [options.width] the width of the viewer
* @param {string|number} [options.height] the height of the viewer
* @param {Object} [options.moddleExtensions] extension packages to provide
* @param {Module[]} [options.modules] a list of modules to override the default modules
* @param {Module[]} [options.additionalModules] a list of modules to use with the default modules
*/ */
export default function BaseModeler(options) { export default function BaseModeler(options) {
BaseViewer.call(this, options); BaseViewer.call(this, options);
@ -41,27 +39,27 @@ inherits(BaseModeler, BaseViewer);
/** /**
* Create a moddle instance, attaching ids to it. * Create a moddle instance, attaching IDs to it.
* *
* @param {Object} options * @param {BaseModelerOptions} options
*
* @return {Moddle}
*/ */
BaseModeler.prototype._createModdle = function(options) { BaseModeler.prototype._createModdle = function(options) {
var moddle = BaseViewer.prototype._createModdle.call(this, options); var moddle = BaseViewer.prototype._createModdle.call(this, options);
// attach ids to moddle to be able to track // attach ids to moddle to be able to track and validated ids in the BPMN 2.0
// and validated ids in the BPMN 2.0 XML document // XML document tree
// tree
moddle.ids = new Ids([ 32, 36, 1 ]); moddle.ids = new Ids([ 32, 36, 1 ]);
return moddle; return moddle;
}; };
/** /**
* Collect ids processed during parsing of the * Collect IDs processed during parsing of the definitions object.
* definitions object.
* *
* @param {ModdleElement} definitions * @param {ModdleElement} definitions
* @param {Context} context * @param {ModdleElementsById} elementsById
*/ */
BaseModeler.prototype._collectIds = function(definitions, elementsById) { BaseModeler.prototype._collectIds = function(definitions, elementsById) {
@ -73,6 +71,6 @@ BaseModeler.prototype._collectIds = function(definitions, elementsById) {
ids.clear(); ids.clear();
for (id in elementsById) { for (id in elementsById) {
ids.claim(id, elementsById[id]); ids.claim(id, elementsById[ id ]);
} }
}; };

9
lib/BaseModeler.spec.ts Normal file
View File

@ -0,0 +1,9 @@
import BaseModeler from './BaseModeler';
import { testViewer } from './BaseViewer.spec';
const modeler = new BaseModeler({
container: 'container'
});
testViewer(modeler);

366
lib/BaseViewer.d.ts vendored Normal file
View File

@ -0,0 +1,366 @@
import { ModuleDeclaration } from "didi";
import Diagram from 'diagram-js/lib/Diagram';
import {
Event,
EventCallback
} from 'diagram-js/lib/core/EventBus';
export type ModdleExtension = Object;
export type ModdleExtensions = {
[key: string]: ModdleExtension;
};
export type BaseViewerOptions = {
width?: number|string;
height?: number|string;
position?: string;
container?: string|HTMLElement;
moddleExtensions?: ModdleExtensions;
additionalModules?: ModuleDeclaration[];
};
export type ModdleElement = Object;
export type ModdleElementsById = {
[id: string]: ModdleElement;
};
export type ImportXMLResult = {
/**
* The warnings produced when parsing the XML.
*/
warnings: string[];
};
export type ImportXMLError = ImportXMLResult & Error;
export type ImportDefinitionsResult = ImportXMLResult;
export type ImportDefinitionsError = ImportXMLError;
export type OpenResult = ImportXMLResult;
export type OpenError = ImportXMLError;
export type SaveXMLOptions = {
/**
* Whether to format the XML. Defaults to `false`.
*/
format?: boolean;
/**
* Whether to include the preamble. Defaults to `true`.
*/
preamble?: boolean;
};
export type SaveXMLResult = {
/**
* The saved XML.
*/
xml?: string;
/**
* An error thrown when saving the XML.
*/
error?: Error;
};
export type SaveSVGResult = {
svg: string;
};
declare namespace Events {
/**
* A `import.parse.start` event.
*/
export type ImportParseStart = {
/**
* The XML that is to be parsed.
*/
xml: string;
} & Event;
/**
* A `import.parse.complete` event.
*/
export type ImportParseComplete = {
/**
* An error thrown when parsing the XML.
*/
error?: ImportXMLError;
/**
* The definitions model element.
*/
definitions?: ModdleElement;
/**
* The model elements by ID.
*/
elementsById?: ModdleElementsById;
/**
* The referenced model elements.
*/
references?: ModdleElement[];
/**
* The warnings produced when parsing the XML.
*/
warnings: string[];
} & Event;
/**
* A `import.done` event.
*/
export type ImportDone = {
/**
* An error thrown when parsing the XML.
*/
error?: ImportXMLError;
/**
* The warnings produced when parsing the XML.
*/
warnings: string[];
} & Event;
/**
* A `saveXML.start` event.
*/
export type SaveXMLStart = {
/**
* The definitions model element.
*/
definitions: ModdleElement;
} & Event;
/**
* A `saveXML.done` event.
*/
export type SaveXMLDone = SaveXMLResult & Event;
/**
* A `saveSVG.done` event.
*/
export type SaveSVGDone = {
/**
* An error thrown when saving the SVG.
*/
error?: Error;
/**
* The saved SVG.
*/
svg: string;
} & Event;
}
export default class BaseViewer extends Diagram {
/**
* The constructor.
*
* @param options The options to configure the viewer.
*/
constructor(options?: BaseViewerOptions);
/**
* Parse and render a BPMN 2.0 diagram.
*
* Once finished the viewer reports back the result to the
* provided callback function with (err, warnings).
*
* ## Life-Cycle Events
*
* During import the viewer will fire life-cycle events:
*
* * import.parse.start (about to read model from XML)
* * import.parse.complete (model read; may have worked or not)
* * import.render.start (graphical import start)
* * import.render.complete (graphical import finished)
* * import.done (everything done)
*
* You can use these events to hook into the life-cycle.
*
* @throws An error thrown during the import of the XML.
*
* @param xml The BPMN 2.0 XML to be imported.
* @param bpmnDiagram The optional diagram or Id of the BPMN diagram to open.
*
* @return A promise resolving with warnings that were produced during the import.
*/
importXML(xml: string, bpmnDiagram?: ModdleElement | string): Promise<ImportXMLResult>;
/**
* Import parsed definitions and render a BPMN 2.0 diagram.
*
* Once finished the viewer reports back the result to the
* provided callback function with (err, warnings).
*
* ## Life-Cycle Events
*
* During import the viewer will fire life-cycle events:
*
* * import.render.start (graphical import start)
* * import.render.complete (graphical import finished)
*
* You can use these events to hook into the life-cycle.
*
* @throws An error thrown during the import of the definitions.
*
* @param definitions The definitions.
* @param bpmnDiagram The optional diagram or ID of the BPMN diagram to open.
*
* @return A promise resolving with warnings that were produced during the import.
*/
importDefinitions(definitions: ModdleElement, bpmnDiagram?: ModdleElement | string): Promise<ImportDefinitionsResult>;
/**
* Open diagram of previously imported XML.
*
* Once finished the viewer reports back the result to the
* provided callback function with (err, warnings).
*
* ## Life-Cycle Events
*
* During switch the viewer will fire life-cycle events:
*
* * import.render.start (graphical import start)
* * import.render.complete (graphical import finished)
*
* You can use these events to hook into the life-cycle.
*
* @throws An error thrown during opening.
*
* @param bpmnDiagramOrId The diagram or Id of the BPMN diagram to open.
*
* @return A promise resolving with warnings that were produced during opening.
*/
open(bpmnDiagramOrId: ModdleElement | string): Promise<OpenResult>;
/**
* Export the currently displayed BPMN 2.0 diagram as
* a BPMN 2.0 XML document.
*
* ## Life-Cycle Events
*
* During XML saving the viewer will fire life-cycle events:
*
* * saveXML.start (before serialization)
* * saveXML.serialized (after xml generation)
* * saveXML.done (everything done)
*
* You can use these events to hook into the life-cycle.
*
* @throws An error thrown during export.
*
* @param options The options.
*
* @return A promise resolving with the XML.
*/
saveXML(options: SaveXMLOptions): Promise<SaveXMLResult>;
/**
* Export the currently displayed BPMN 2.0 diagram as
* an SVG image.
*
* ## Life-Cycle Events
*
* During SVG saving the viewer will fire life-cycle events:
*
* * saveSVG.start (before serialization)
* * saveSVG.done (everything done)
*
* You can use these events to hook into the life-cycle.
*
* @throws An error thrown during export.
*
* @return A promise resolving with the SVG.
*/
saveSVG(): Promise<SaveSVGResult>;
/**
* Return modules to instantiate with.
*
* @return The modules.
*/
getModules(): ModuleDeclaration[];
/**
* Remove all drawn elements from the viewer.
*
* After calling this method the viewer can still be reused for opening another
* diagram.
*/
clear(): void;
/**
* Destroy the viewer instance and remove all its remainders from the document
* tree.
*/
destroy(): void;
/**
* Register an event listener.
*
* Remove a previously added listener via {@link BaseViewer#off}.
*
* @param events The event(s) to listen to.
* @param callback The callback.
* @param that Value of `this` the callback will be called with.
*/
on<T extends Event>(events: string | string[], callback: EventCallback<T>, that?: any): void;
/**
* Register an event listener.
*
* Remove a previously added listener via {@link BaseViewer#off}.
*
* @param events The event(s) to listen to.
* @param priority The priority with which to listen.
* @param callback The callback.
* @param that Value of `this` the callback will be called with.
*/
on<T extends Event>(events: string | string[], priority: number, callback: EventCallback<T>, that?: any): void;
/**
* Remove an event listener.
*
* @param events The event(s).
* @param callback The callback.
*/
off(events: string | string[], callback?: EventCallback<any>): void;
/**
* Attach the viewer to an HTML element.
*
* @param parentNode The parent node to attach to.
*/
attachTo(parentNode: HTMLElement): void;
/**
* Get the definitions model element.
*
* @returns The definitions model element.
*/
getDefinitions(): ModdleElement | undefined;
/**
* Detach the viewer.
*/
detach(): void;
}

View File

@ -37,7 +37,20 @@ import {
/** /**
* @typedef { import('didi').ModuleDeclaration } Module * @typedef {import('didi').ModuleDeclaration} ModuleDeclaration
*
* @typedef {import('./BaseViewer').BaseModelerOptions} BaseModelerOptions
* @typedef {import('./BaseViewer').ModdleElement} ModdleElement
* @typedef {import('./BaseViewer').ImportXMLResult} ImportXMLResult
* @typedef {import('./BaseViewer').ImportXMLError} ImportXMLError
* @typedef {import('./BaseViewer').ImportDefinitionsResult} ImportDefinitionsResult
* @typedef {import('./BaseViewer').ImportDefinitionsError} ImportDefinitionsError
* @typedef {import('./BaseViewer').ModdleElement} ModdleElement
* @typedef {import('./BaseViewer').ModdleElementsById} ModdleElementsById
* @typedef {import('./BaseViewer').OpenResult} OpenResult
* @typedef {import('./BaseViewer').OpenError} OpenError
* @typedef {import('./BaseViewer').SaveXMLOptions} SaveXMLOptions
* @typedef {import('./BaseViewer').SaveXMLResult} SaveXMLResult
*/ */
/** /**
@ -46,20 +59,20 @@ import {
* Have a look at {@link Viewer}, {@link NavigatedViewer} or {@link Modeler} for * Have a look at {@link Viewer}, {@link NavigatedViewer} or {@link Modeler} for
* bundles that include actual features. * bundles that include actual features.
* *
* @param {Object} [options] configuration options to pass to the viewer * @param {BaseModelerOptions} [options] The options to configure the viewer.
* @param {DOMElement} [options.container] the container to render the viewer in, defaults to body.
* @param {string|number} [options.width] the width of the viewer
* @param {string|number} [options.height] the height of the viewer
* @param {Object} [options.moddleExtensions] extension packages to provide
* @param {Module[]} [options.modules] a list of modules to override the default modules
* @param {Module[]} [options.additionalModules] a list of modules to use with the default modules
*/ */
export default function BaseViewer(options) { export default function BaseViewer(options) {
/**
* @type {BaseModelerOptions}
*/
options = assign({}, DEFAULT_OPTIONS, options); options = assign({}, DEFAULT_OPTIONS, options);
this._moddle = this._createModdle(options); this._moddle = this._createModdle(options);
/**
* @type {HTMLElement}
*/
this._container = this._createContainer(options); this._container = this._createContainer(options);
/* <project-logo> */ /* <project-logo> */
@ -73,22 +86,6 @@ export default function BaseViewer(options) {
inherits(BaseViewer, Diagram); inherits(BaseViewer, Diagram);
/**
* The importXML result.
*
* @typedef {Object} ImportXMLResult
*
* @property {Array<string>} warnings
*/
/**
* The importXML error.
*
* @typedef {Error} ImportXMLError
*
* @property {Array<string>} warnings
*/
/** /**
* Parse and render a BPMN 2.0 diagram. * Parse and render a BPMN 2.0 diagram.
* *
@ -99,7 +96,7 @@ inherits(BaseViewer, Diagram);
* *
* During import the viewer will fire life-cycle events: * During import the viewer will fire life-cycle events:
* *
* * import.parse.start (about to read model from xml) * * import.parse.start (about to read model from XML)
* * import.parse.complete (model read; may have worked or not) * * import.parse.complete (model read; may have worked or not)
* * import.render.start (graphical import start) * * import.render.start (graphical import start)
* * import.render.complete (graphical import finished) * * import.render.complete (graphical import finished)
@ -107,10 +104,18 @@ inherits(BaseViewer, Diagram);
* *
* You can use these events to hook into the life-cycle. * You can use these events to hook into the life-cycle.
* *
* @param {string} xml the BPMN 2.0 xml * @throws {ImportXMLError} An error thrown during the import of the XML.
* @param {ModdleElement<BPMNDiagram>|string} [bpmnDiagram] BPMN diagram or id of diagram to render (if not provided, the first one will be rendered)
* *
* Returns {Promise<ImportXMLResult, ImportXMLError>} * @fires BaseViewer#ImportParseStart
* @fires BaseViewer#ImportParseComplete
* @fires Importer#ImportRenderStart
* @fires Importer#ImportRenderComplete
* @fires BaseViewer#ImportDone
*
* @param {string} xml The BPMN 2.0 XML to be imported.
* @param {ModdleElement|string} [bpmnDiagram] The optional diagram or Id of the BPMN diagram to open.
*
* @return {Promise<ImportXMLResult>} A promise resolving with warnings that were produced during the import.
*/ */
BaseViewer.prototype.importXML = wrapForCompatibility(async function importXML(xml, bpmnDiagram) { BaseViewer.prototype.importXML = wrapForCompatibility(async function importXML(xml, bpmnDiagram) {
@ -146,6 +151,14 @@ BaseViewer.prototype.importXML = wrapForCompatibility(async function importXML(x
// hook in pre-parse listeners + // hook in pre-parse listeners +
// allow xml manipulation // allow xml manipulation
/**
* A `import.parse.start` event.
*
* @event BaseViewer#ImportParseStart
* @type {Object}
* @property {string} xml The XML that is to be parsed.
*/
xml = this._emit('import.parse.start', { xml: xml }) || xml; xml = this._emit('import.parse.start', { xml: xml }) || xml;
let parseResult; let parseResult;
@ -168,6 +181,18 @@ BaseViewer.prototype.importXML = wrapForCompatibility(async function importXML(x
// hook in post parse listeners + // hook in post parse listeners +
// allow definitions manipulation // allow definitions manipulation
/**
* A `import.parse.complete` event.
*
* @event BaseViewer#ImportParseComplete
* @type {Object}
* @property {Error|null} error An error thrown when parsing the XML.
* @property {ModdleElement} definitions The definitions model element.
* @property {ModdleElementsById} elementsById The model elements by ID.
* @property {ModdleElement[]} references The referenced model elements.
* @property {string[]} warnings The warnings produced when parsing the XML.
*/
definitions = this._emit('import.parse.complete', ParseCompleteEvent({ definitions = this._emit('import.parse.complete', ParseCompleteEvent({
error: null, error: null,
definitions: definitions, definitions: definitions,
@ -180,6 +205,14 @@ BaseViewer.prototype.importXML = wrapForCompatibility(async function importXML(x
aggregatedWarnings = aggregatedWarnings.concat(importResult.warnings); aggregatedWarnings = aggregatedWarnings.concat(importResult.warnings);
/**
* A `import.parse.complete` event.
*
* @event BaseViewer#ImportDone
* @type {Object}
* @property {ImportXMLError|null} error An error thrown during import.
* @property {string[]} warnings The warnings.
*/
this._emit('import.done', { error: null, warnings: aggregatedWarnings }); this._emit('import.done', { error: null, warnings: aggregatedWarnings });
return { warnings: aggregatedWarnings }; return { warnings: aggregatedWarnings };
@ -196,21 +229,6 @@ BaseViewer.prototype.importXML = wrapForCompatibility(async function importXML(x
} }
}); });
/**
* The importDefinitions result.
*
* @typedef {Object} ImportDefinitionsResult
*
* @property {Array<string>} warnings
*/
/**
* The importDefinitions error.
*
* @typedef {Error} ImportDefinitionsError
*
* @property {Array<string>} warnings
*/
/** /**
* Import parsed definitions and render a BPMN 2.0 diagram. * Import parsed definitions and render a BPMN 2.0 diagram.
@ -227,10 +245,12 @@ BaseViewer.prototype.importXML = wrapForCompatibility(async function importXML(x
* *
* You can use these events to hook into the life-cycle. * You can use these events to hook into the life-cycle.
* *
* @param {ModdleElement<Definitions>} definitions parsed BPMN 2.0 definitions * @throws {ImportDefinitionsError} An error thrown during the import of the definitions.
* @param {ModdleElement<BPMNDiagram>|string} [bpmnDiagram] BPMN diagram or id of diagram to render (if not provided, the first one will be rendered)
* *
* Returns {Promise<ImportDefinitionsResult, ImportDefinitionsError>} * @param {ModdleElement} definitions The definitions.
* @param {ModdleElement|string} [bpmnDiagram] The optional diagram or ID of the BPMN diagram to open.
*
* @return {Promise<ImportDefinitionsResult>} A promise resolving with warnings that were produced during the import.
*/ */
BaseViewer.prototype.importDefinitions = wrapForCompatibility(async function importDefinitions(definitions, bpmnDiagram) { BaseViewer.prototype.importDefinitions = wrapForCompatibility(async function importDefinitions(definitions, bpmnDiagram) {
this._setDefinitions(definitions); this._setDefinitions(definitions);
@ -239,21 +259,6 @@ BaseViewer.prototype.importDefinitions = wrapForCompatibility(async function imp
return { warnings: result.warnings }; return { warnings: result.warnings };
}); });
/**
* The open result.
*
* @typedef {Object} OpenResult
*
* @property {Array<string>} warnings
*/
/**
* The open error.
*
* @typedef {Error} OpenError
*
* @property {Array<string>} warnings
*/
/** /**
* Open diagram of previously imported XML. * Open diagram of previously imported XML.
@ -270,9 +275,11 @@ BaseViewer.prototype.importDefinitions = wrapForCompatibility(async function imp
* *
* You can use these events to hook into the life-cycle. * You can use these events to hook into the life-cycle.
* *
* @param {string|ModdleElement<BPMNDiagram>} [bpmnDiagramOrId] id or the diagram to open * @throws {OpenError} An error thrown during opening.
* *
* Returns {Promise<OpenResult, OpenError>} * @param {ModdleElement|string} bpmnDiagramOrId The diagram or Id of the BPMN diagram to open.
*
* @return {Promise<OpenResult>} A promise resolving with warnings that were produced during opening.
*/ */
BaseViewer.prototype.open = wrapForCompatibility(async function open(bpmnDiagramOrId) { BaseViewer.prototype.open = wrapForCompatibility(async function open(bpmnDiagramOrId) {
@ -313,14 +320,6 @@ BaseViewer.prototype.open = wrapForCompatibility(async function open(bpmnDiagram
return { warnings }; return { warnings };
}); });
/**
* The saveXML result.
*
* @typedef {Object} SaveXMLResult
*
* @property {string} xml
*/
/** /**
* Export the currently displayed BPMN 2.0 diagram as * Export the currently displayed BPMN 2.0 diagram as
* a BPMN 2.0 XML document. * a BPMN 2.0 XML document.
@ -335,11 +334,14 @@ BaseViewer.prototype.open = wrapForCompatibility(async function open(bpmnDiagram
* *
* You can use these events to hook into the life-cycle. * You can use these events to hook into the life-cycle.
* *
* @param {Object} [options] export options * @throws {Error} An error thrown during export.
* @param {boolean} [options.format=false] output formatted XML
* @param {boolean} [options.preamble=true] output preamble
* *
* Returns {Promise<SaveXMLResult, Error>} * @fires BaseViewer#SaveXMLStart
* @fires BaseViewer#SaveXMLDone
*
* @param {SaveXMLOptions} [options] The options.
*
* @return {Promise<SaveXMLResult>} A promise resolving with the XML.
*/ */
BaseViewer.prototype.saveXML = wrapForCompatibility(async function saveXML(options) { BaseViewer.prototype.saveXML = wrapForCompatibility(async function saveXML(options) {
@ -354,6 +356,14 @@ BaseViewer.prototype.saveXML = wrapForCompatibility(async function saveXML(optio
} }
// allow to fiddle around with definitions // allow to fiddle around with definitions
/**
* A `saveXML.start` event.
*
* @event BaseViewer#SaveXMLStart
* @type {Object}
* @property {ModdleElement} definitions The definitions model element.
*/
definitions = this._emit('saveXML.start', { definitions = this._emit('saveXML.start', {
definitions definitions
}) || definitions; }) || definitions;
@ -370,6 +380,14 @@ BaseViewer.prototype.saveXML = wrapForCompatibility(async function saveXML(optio
const result = error ? { error } : { xml }; const result = error ? { error } : { xml };
/**
* A `saveXML.done` event.
*
* @event BaseViewer#SaveXMLDone
* @type {Object}
* @property {Error} [error] An error thrown when saving the XML.
* @property {string} [xml] The saved XML.
*/
this._emit('saveXML.done', result); this._emit('saveXML.done', result);
if (error) { if (error) {
@ -379,13 +397,6 @@ BaseViewer.prototype.saveXML = wrapForCompatibility(async function saveXML(optio
return result; return result;
}); });
/**
* The saveSVG result.
*
* @typedef {Object} SaveSVGResult
*
* @property {string} svg
*/
/** /**
* Export the currently displayed BPMN 2.0 diagram as * Export the currently displayed BPMN 2.0 diagram as
@ -400,11 +411,13 @@ BaseViewer.prototype.saveXML = wrapForCompatibility(async function saveXML(optio
* *
* You can use these events to hook into the life-cycle. * You can use these events to hook into the life-cycle.
* *
* @param {Object} [options] * @throws {Error} An error thrown during export.
* *
* Returns {Promise<SaveSVGResult, Error>} * @fires BaseViewer#SaveSVGDone
*
* @return {Promise<SaveSVGResult>} A promise resolving with the SVG.
*/ */
BaseViewer.prototype.saveSVG = wrapForCompatibility(async function saveSVG(options = {}) { BaseViewer.prototype.saveSVG = wrapForCompatibility(async function saveSVG() {
this._emit('saveSVG.start'); this._emit('saveSVG.start');
let svg, err; let svg, err;
@ -433,6 +446,14 @@ BaseViewer.prototype.saveSVG = wrapForCompatibility(async function saveSVG(optio
err = e; err = e;
} }
/**
* A `saveSVG.done` event.
*
* @event BaseViewer#SaveSVGDone
* @type {Object}
* @property {Error} [error] An error thrown when saving the SVG.
* @property {string} [svg] The saved SVG.
*/
this._emit('saveSVG.done', { this._emit('saveSVG.done', {
error: err, error: err,
svg: svg svg: svg
@ -484,21 +505,17 @@ BaseViewer.prototype._setDefinitions = function(definitions) {
/** /**
* Return modules to instantiate with. * Return modules to instantiate with.
* *
* @param {any} options the instance got created with * @return {ModuleDeclaration[]} The modules.
*
* @return {Module[]}
*/ */
BaseViewer.prototype.getModules = function(options) { BaseViewer.prototype.getModules = function() {
return this._modules; return this._modules;
}; };
/** /**
* Remove all drawn elements from the viewer. * Remove all drawn elements from the viewer.
* *
* After calling this method the viewer can still * After calling this method the viewer can still be reused for opening another
* be reused for opening another diagram. * diagram.
*
* @method BaseViewer#clear
*/ */
BaseViewer.prototype.clear = function() { BaseViewer.prototype.clear = function() {
if (!this.getDefinitions()) { if (!this.getDefinitions()) {
@ -512,8 +529,8 @@ BaseViewer.prototype.clear = function() {
}; };
/** /**
* Destroy the viewer instance and remove all its * Destroy the viewer instance and remove all its remainders from the document
* remainders from the document tree. * tree.
*/ */
BaseViewer.prototype.destroy = function() { BaseViewer.prototype.destroy = function() {
@ -525,29 +542,34 @@ BaseViewer.prototype.destroy = function() {
}; };
/** /**
* Register an event listener * Register an event listener.
* *
* Remove a previously added listener via {@link #off(event, callback)}. * Remove an event listener via {@link BaseViewer#off}.
* *
* @param {string} event * @param {string|string[]} events The event(s) to listen to.
* @param {number} [priority] * @param {number} [priority] The priority with which to listen.
* @param {Function} callback * @param {EventCallback} callback The callback.
* @param {Object} [that] * @param {*} [that] Value of `this` the callback will be called with.
*/ */
BaseViewer.prototype.on = function(event, priority, callback, target) { BaseViewer.prototype.on = function(events, priority, callback, that) {
return this.get('eventBus').on(event, priority, callback, target); return this.get('eventBus').on(events, priority, callback, that);
}; };
/** /**
* De-register an event listener * Remove an event listener.
* *
* @param {string} event * @param {string|string[]} events The event(s).
* @param {Function} callback * @param {Function} [callback] The callback.
*/ */
BaseViewer.prototype.off = function(event, callback) { BaseViewer.prototype.off = function(events, callback) {
this.get('eventBus').off(event, callback); this.get('eventBus').off(events, callback);
}; };
/**
* Attach the viewer to an HTML element.
*
* @param {HTMLElement} parentNode The parent node to attach to.
*/
BaseViewer.prototype.attachTo = function(parentNode) { BaseViewer.prototype.attachTo = function(parentNode) {
if (!parentNode) { if (!parentNode) {
@ -574,10 +596,20 @@ BaseViewer.prototype.attachTo = function(parentNode) {
this.get('canvas').resized(); this.get('canvas').resized();
}; };
/**
* Get the definitions model element.
*
* @returns {ModdleElement} The definitions model element.
*/
BaseViewer.prototype.getDefinitions = function() { BaseViewer.prototype.getDefinitions = function() {
return this._definitions; return this._definitions;
}; };
/**
* Detach the viewer.
*
* @fires BaseViewer#DetachEvent
*/
BaseViewer.prototype.detach = function() { BaseViewer.prototype.detach = function() {
const container = this._container, const container = this._container,
@ -587,6 +619,12 @@ BaseViewer.prototype.detach = function() {
return; return;
} }
/**
* A `detach` event.
*
* @event BaseViewer#DetachEvent
* @type {Object}
*/
this._emit('detach', {}); this._emit('detach', {});
parentNode.removeChild(container); parentNode.removeChild(container);
@ -624,7 +662,7 @@ BaseViewer.prototype._init = function(container, moddle, options) {
* @param {string} type * @param {string} type
* @param {Object} event * @param {Object} event
* *
* @return {Object} event processing result (if any) * @return {Object} The return value after calling all event listeners.
*/ */
BaseViewer.prototype._emit = function(type, event) { BaseViewer.prototype._emit = function(type, event) {
return this.get('eventBus').fire(type, event); return this.get('eventBus').fire(type, event);

155
lib/BaseViewer.spec.ts Normal file
View File

@ -0,0 +1,155 @@
import CommandStack from 'diagram-js/lib/command/CommandStack';
import { Event } from 'diagram-js/lib/core/EventBus';
import BaseViewer, { Events } from './BaseViewer';
import OverlaysModule from 'diagram-js/lib/features/overlays';
let viewer = new BaseViewer();
viewer = new BaseViewer({
width: 100,
height: 100,
position: 'absolute',
container: 'container',
moddleExtensions: {
foo: {}
},
additionalModules: [
OverlaysModule
]
});
testViewer(viewer);
export function testViewer(viewer: BaseViewer) {
viewer.importXML('<?xml version="1.0" encoding="UTF-8"?>', 'BPMNDiagram_1');
viewer.importXML('<?xml version="1.0" encoding="UTF-8"?>')
.then(({ warnings }) => {
console.log(warnings);
})
.catch(error => {
const {
message,
warnings
} = error;
console.log(message, warnings);
});
viewer.importDefinitions({ $type: 'bpmn:Definitions' }, 'BPMNDiagram_1');
viewer.importDefinitions({ $type: 'bpmn:Definitions' })
.then(({ warnings }) => {
console.log(warnings);
})
.catch(error => {
const {
message,
warnings
} = error;
console.log(message, warnings);
});
viewer.open('BPMNDiagram_1');
viewer.open({ $type: 'bpmn:BPMNDiagram' })
.then(({ warnings }) => {
console.log(warnings);
})
.catch(error => {
const {
message,
warnings
} = error;
console.log(message, warnings);
});
viewer.saveXML({ format: true, preamble: false })
.then(({ xml, error }) => {
if (error) {
console.log(error);
} else {
console.log(xml);
}
})
.catch(error => {
console.log(error);
});
viewer.getModules();
viewer.clear();
viewer.destroy();
viewer.get<CommandStack>('commandStack').undo();
viewer.invoke((commandStack: CommandStack) => commandStack.undo());
viewer.on('foo', () => console.log('foo'));
viewer.on([ 'foo', 'bar' ], () => console.log('foo'));
viewer.on('foo', 2000, () => console.log('foo'));
viewer.on('foo', 2000, () => console.log('foo'), { foo: 'bar' });
viewer.off('foo', () => console.log('foo'));
viewer.attachTo(document.createElement('div'));
viewer.getDefinitions();
viewer.detach();
viewer.on<Events.ImportParseStart>('import.parse.start', ({ xml }) => {
console.log(xml);
});
viewer.on<Events.ImportParseComplete>('import.parse.complete', ({
error,
definitions,
elementsById,
references,
warnings
}) => {
if (error) {
console.error(error);
}
if (warnings.length) {
warnings.forEach(warning => console.log(warning));
}
console.log(definitions, elementsById, references);
});
viewer.on<Events.ImportDone>('import.done', ({ error, warnings }) => {
if (error) {
console.error(error);
}
if (warnings.length) {
warnings.forEach(warning => console.log(warning));
}
});
viewer.on<Events.SaveXMLStart>('saveXML.start', ({ definitions }) => {
console.log(definitions);
});
viewer.on<Events.SaveXMLDone>('saveXML.done', ({ error, xml }) => {
if (error) {
console.error(error);
} else {
console.log(xml);
}
});
viewer.on<Event>('detach', () => {});
}

15
lib/Modeler.d.ts vendored Normal file
View File

@ -0,0 +1,15 @@
import BaseModeler from "./BaseModeler";
import { ImportXMLResult } from "./BaseViewer";
export default class Modeler extends BaseModeler {
/**
* Create a new diagram to start modeling.
*
* @throws An error thrown during the import of the XML.
*
* @return A promise resolving with warnings that were produced during the import.
*/
createDiagram(): Promise<ImportXMLResult>;
}

View File

@ -62,7 +62,8 @@ var initialDiagram =
/** /**
* @typedef { import('didi').ModuleDeclaration } Module * @typedef {import('./BaseViewer').BaseModelerOptions} BaseModelerOptions
* @typedef {import('./BaseViewer').ImportXMLResult} ImportXMLResult
*/ */
/** /**
@ -129,13 +130,7 @@ var initialDiagram =
* var bpmnModeler = new Modeler({ additionalModules: [ overrideModule ]}); * var bpmnModeler = new Modeler({ additionalModules: [ overrideModule ]});
* ``` * ```
* *
* @param {Object} [options] configuration options to pass to the viewer * @param {BaseModelerOptions} [options] The options to configure the modeler.
* @param {DOMElement} [options.container] the container to render the viewer in, defaults to body.
* @param {string|number} [options.width] the width of the viewer
* @param {string|number} [options.height] the height of the viewer
* @param {Object} [options.moddleExtensions] extension packages to provide
* @param {Module[]} [options.modules] a list of modules to override the default modules
* @param {Module[]} [options.additionalModules] a list of modules to use with the default modules
*/ */
export default function Modeler(options) { export default function Modeler(options) {
BaseModeler.call(this, options); BaseModeler.call(this, options);
@ -147,26 +142,12 @@ inherits(Modeler, BaseModeler);
Modeler.Viewer = Viewer; Modeler.Viewer = Viewer;
Modeler.NavigatedViewer = NavigatedViewer; Modeler.NavigatedViewer = NavigatedViewer;
/**
* The createDiagram result.
*
* @typedef {Object} CreateDiagramResult
*
* @property {Array<string>} warnings
*/
/**
* The createDiagram error.
*
* @typedef {Error} CreateDiagramError
*
* @property {Array<string>} warnings
*/
/** /**
* Create a new diagram to start modeling. * Create a new diagram to start modeling.
* *
* Returns {Promise<CreateDiagramResult, CreateDiagramError>} * @throws {ImportXMLError} An error thrown during the import of the XML.
*
* @return {Promise<ImportXMLResult>} A promise resolving with warnings that were produced during the import.
*/ */
Modeler.prototype.createDiagram = wrapForCompatibility(function createDiagram() { Modeler.prototype.createDiagram = wrapForCompatibility(function createDiagram() {
return this.importXML(initialDiagram); return this.importXML(initialDiagram);

11
lib/Modeler.spec.ts Normal file
View File

@ -0,0 +1,11 @@
import Modeler from './Modeler';
import { testViewer } from './BaseViewer.spec';
const modeler = new Modeler({
container: 'container'
});
testViewer(modeler);
modeler.createDiagram();

3
lib/NavigatedViewer.d.ts vendored Normal file
View File

@ -0,0 +1,3 @@
import Viewer from "./Viewer";
export default class NavigatedViewer extends Viewer {}

View File

@ -6,11 +6,14 @@ import KeyboardMoveModule from 'diagram-js/lib/navigation/keyboard-move';
import MoveCanvasModule from 'diagram-js/lib/navigation/movecanvas'; import MoveCanvasModule from 'diagram-js/lib/navigation/movecanvas';
import ZoomScrollModule from 'diagram-js/lib/navigation/zoomscroll'; import ZoomScrollModule from 'diagram-js/lib/navigation/zoomscroll';
/**
* @typedef { import('./BaseViewer').BaseViewerOptions } BaseViewerOptions
*/
/** /**
* A viewer that includes mouse navigation facilities * A viewer with mouse and keyboard navigation features.
* *
* @param {Object} options * @param {BaseViewerOptions} [options]
*/ */
export default function NavigatedViewer(options) { export default function NavigatedViewer(options) {
Viewer.call(this, options); Viewer.call(this, options);

View File

@ -0,0 +1,9 @@
import NavigatedViewer from './NavigatedViewer';
import { testViewer } from './BaseViewer.spec';
const viewer = new NavigatedViewer({
container: 'container'
});
testViewer(viewer);

3
lib/Viewer.d.ts vendored Normal file
View File

@ -0,0 +1,3 @@
import BaseViewer from "./BaseViewer";
export default class Viewer extends BaseViewer {}

View File

@ -10,7 +10,7 @@ import BaseViewer from './BaseViewer';
/** /**
* @typedef { import('didi').ModuleDeclaration } Module * @typedef { import('./BaseViewer').BaseViewerOptions } BaseViewerOptions
*/ */
/** /**
@ -52,13 +52,7 @@ import BaseViewer from './BaseViewer';
* bpmnViewer.importXML(...); * bpmnViewer.importXML(...);
* ``` * ```
* *
* @param {Object} [options] configuration options to pass to the viewer * @param {BaseViewerOptions} [options] The options to configure the viewer.
* @param {DOMElement} [options.container] the container to render the viewer in, defaults to body.
* @param {string|number} [options.width] the width of the viewer
* @param {string|number} [options.height] the height of the viewer
* @param {Object} [options.moddleExtensions] extension packages to provide
* @param {Module[]} [options.modules] a list of modules to override the default modules
* @param {Module[]} [options.additionalModules] a list of modules to use with the default modules
*/ */
export default function Viewer(options) { export default function Viewer(options) {
BaseViewer.call(this, options); BaseViewer.call(this, options);

9
lib/Viewer.spec.ts Normal file
View File

@ -0,0 +1,9 @@
import Viewer from './Viewer';
import { testViewer } from './BaseViewer.spec';
const viewer = new Viewer({
container: 'container'
});
testViewer(viewer);