@maxgraph/core
Advanced tools
Comparing version 0.10.2 to 0.10.3
@@ -23,3 +23,3 @@ /* | ||
*/ | ||
Client.VERSION = '0.10.2'; | ||
Client.VERSION = '0.10.3'; | ||
/** | ||
@@ -26,0 +26,0 @@ * Base path for all URLs in the core without trailing slash. |
@@ -17,4 +17,3 @@ import Cell from '../view/cell/Cell'; | ||
* @param node DOM node to return the XML for. | ||
* @param linefeed Optional string that linefeeds are converted into. Default is | ||
* 
 | ||
* @param linefeed Optional string that linefeeds are converted into. Default is `\
`. | ||
*/ | ||
@@ -21,0 +20,0 @@ export declare const getXml: (node: Element, linefeed?: string) => string; |
@@ -89,4 +89,3 @@ /* | ||
* @param node DOM node to return the XML for. | ||
* @param linefeed Optional string that linefeeds are converted into. Default is | ||
* 
 | ||
* @param linefeed Optional string that linefeeds are converted into. Default is `\
`. | ||
*/ | ||
@@ -93,0 +92,0 @@ export const getXml = (node, linefeed = '
') => { |
@@ -16,3 +16,3 @@ import AbstractCanvas2D from './AbstractCanvas2D'; | ||
* - <rect>, <roundrect>, <ellipse>, <image>, <text> | ||
* - <begin>, {@link oveTo}, <lineTo>, <quadTo>, <curveTo> | ||
* - <begin>, {@link moveTo}, <lineTo>, <quadTo>, <curveTo> | ||
* - <stroke>, <fill>, <fillAndStroke> | ||
@@ -28,8 +28,8 @@ * | ||
*/ | ||
declare class mxXmlCanvas2D extends AbstractCanvas2D { | ||
constructor(root: SVGElement); | ||
declare class XmlCanvas2D extends AbstractCanvas2D { | ||
constructor(root: Element); | ||
/** | ||
* Reference to the container for the SVG content. | ||
*/ | ||
root: SVGElement; | ||
root: Element; | ||
/** | ||
@@ -375,2 +375,2 @@ * Specifies if text output should be enabled. | ||
} | ||
export default mxXmlCanvas2D; | ||
export default XmlCanvas2D; |
@@ -34,3 +34,3 @@ /* | ||
* - <rect>, <roundrect>, <ellipse>, <image>, <text> | ||
* - <begin>, {@link oveTo}, <lineTo>, <quadTo>, <curveTo> | ||
* - <begin>, {@link moveTo}, <lineTo>, <quadTo>, <curveTo> | ||
* - <stroke>, <fill>, <fillAndStroke> | ||
@@ -46,3 +46,3 @@ * | ||
*/ | ||
class mxXmlCanvas2D extends AbstractCanvas2D { | ||
class XmlCanvas2D extends AbstractCanvas2D { | ||
constructor(root) { | ||
@@ -843,2 +843,2 @@ super(); | ||
} | ||
export default mxXmlCanvas2D; | ||
export default XmlCanvas2D; |
@@ -10,3 +10,3 @@ import RectangleShape from '../geometry/node/RectangleShape'; | ||
* Renders cells into a document object model. The <defaultShapes> is a global | ||
* map of shapename, constructor pairs that is used in all instances. You can | ||
* map of shape names, constructor pairs that is used in all instances. You can | ||
* get a list of all available shape names using the following code. | ||
@@ -17,3 +17,3 @@ * | ||
* some other graphical objects, namely controls and overlays. The shape | ||
* hieararchy in the display (ie. the hierarchy in which the DOM nodes | ||
* hierarchy in the display (i.e. the hierarchy in which the DOM nodes | ||
* appear in the document) does not reflect the cell hierarchy. The shapes | ||
@@ -31,8 +31,2 @@ * are a (flat) sequence of shapes and labels inside the draw pane of the | ||
* ``` | ||
* | ||
* Constructor: mxCellRenderer | ||
* | ||
* Constructs a new cell renderer with the following built-in shapes: | ||
* arrow, rectangle, ellipse, rhombus, image, line, label, cylinder, | ||
* swimlane, connector, actor and cloud. | ||
*/ | ||
@@ -44,2 +38,5 @@ declare class CellRenderer { | ||
* use the static {@link CellRenderer#registerShape} function. | ||
* | ||
* Built-in shapes: arrow, rectangle, ellipse, rhombus, image, line, label, cylinder, | ||
* swimlane, connector, actor and cloud. | ||
*/ | ||
@@ -50,11 +47,14 @@ static defaultShapes: { | ||
/** | ||
* Defines the default shape for edges. Default is {@link Connector}. | ||
* Defines the default shape for edges. | ||
* @default {@link ConnectorShape} | ||
*/ | ||
defaultEdgeShape: typeof Shape; | ||
/** | ||
* Defines the default shape for vertices. Default is {@link RectangleShape}. | ||
* Defines the default shape for vertices. | ||
* @default {@link RectangleShape}. | ||
*/ | ||
defaultVertexShape: typeof RectangleShape; | ||
/** | ||
* Defines the default shape for labels. Default is {@link Text}. | ||
* Defines the default shape for labels. | ||
* @default {@link Text}. | ||
*/ | ||
@@ -64,3 +64,4 @@ defaultTextShape: typeof TextShape; | ||
* Specifies if the folding icon should ignore the horizontal | ||
* orientation of a swimlane. Default is true. | ||
* orientation of a swimlane. | ||
* @default true. | ||
*/ | ||
@@ -70,7 +71,9 @@ legacyControlPosition: boolean; | ||
* Specifies if spacing and label position should be ignored if overflow is | ||
* fill or width. Default is true for backwards compatiblity. | ||
* fill or width. | ||
* @default true for backwards compatibility. | ||
*/ | ||
legacySpacing: boolean; | ||
/** | ||
* Anti-aliasing option for new shapes. Default is true. | ||
* Antialiasing option for new shapes. | ||
* @default true. | ||
*/ | ||
@@ -84,3 +87,4 @@ antiAlias: boolean; | ||
* Specifies if the enabled state of the graph should be ignored in the control | ||
* click handler (to allow folding in disabled graphs). Default is false. | ||
* click handler (to allow folding in disabled graphs). | ||
* @default false. | ||
*/ | ||
@@ -92,3 +96,3 @@ forceControlClickHandler: boolean; | ||
* ``` | ||
* mxCellRenderer.registerShape(mxConstants.SHAPE_RECTANGLE, mxRectangleShape); | ||
* CellRenderer.registerShape(Constants.SHAPE_RECTANGLE, RectangleShape); | ||
* ``` | ||
@@ -102,3 +106,3 @@ * | ||
* Initializes the shape in the given state by calling its init method with | ||
* the correct container after configuring it using <configureShape>. | ||
* the correct container after configuring it using {@link configureShape}. | ||
* | ||
@@ -111,3 +115,3 @@ * @param state <CellState> for which the shape should be initialized. | ||
* | ||
* @param state <CellState> for which the shape should be created. | ||
* @param state {@link CellState} for which the shape should be created. | ||
*/ | ||
@@ -118,7 +122,7 @@ createShape(state: CellState): Shape; | ||
* | ||
* @param state <CellState> for which the indicator shape should be created. | ||
* @param state {@link CellState} for which the indicator shape should be created. | ||
*/ | ||
createIndicatorShape(state: CellState): void; | ||
/** | ||
* Returns the shape for the given name from <defaultShapes>. | ||
* Returns the shape for the given name from {@link defaultShapes}. | ||
*/ | ||
@@ -144,4 +148,3 @@ getShape(name: string | null): typeof Shape | null; | ||
/** | ||
* Resolves special keywords 'inherit', 'indicated' and 'swimlane' and sets | ||
* the respective color on the shape. | ||
* Check if style properties supporting placeholders requires resolution. | ||
*/ | ||
@@ -148,0 +151,0 @@ checkPlaceholderStyles(state: CellState): boolean; |
@@ -37,5 +37,12 @@ /* | ||
import { isNode } from '../../util/domUtils'; | ||
const placeholderStyleValues = ['inherit', 'swimlane', 'indicated']; | ||
const placeholderStyleProperties = [ | ||
'fillColor', | ||
'strokeColor', | ||
'gradientColor', | ||
'fontColor', | ||
]; | ||
/** | ||
* Renders cells into a document object model. The <defaultShapes> is a global | ||
* map of shapename, constructor pairs that is used in all instances. You can | ||
* map of shape names, constructor pairs that is used in all instances. You can | ||
* get a list of all available shape names using the following code. | ||
@@ -46,3 +53,3 @@ * | ||
* some other graphical objects, namely controls and overlays. The shape | ||
* hieararchy in the display (ie. the hierarchy in which the DOM nodes | ||
* hierarchy in the display (i.e. the hierarchy in which the DOM nodes | ||
* appear in the document) does not reflect the cell hierarchy. The shapes | ||
@@ -60,8 +67,2 @@ * are a (flat) sequence of shapes and labels inside the draw pane of the | ||
* ``` | ||
* | ||
* Constructor: mxCellRenderer | ||
* | ||
* Constructs a new cell renderer with the following built-in shapes: | ||
* arrow, rectangle, ellipse, rhombus, image, line, label, cylinder, | ||
* swimlane, connector, actor and cloud. | ||
*/ | ||
@@ -71,3 +72,4 @@ class CellRenderer { | ||
/** | ||
* Defines the default shape for edges. Default is {@link Connector}. | ||
* Defines the default shape for edges. | ||
* @default {@link ConnectorShape} | ||
*/ | ||
@@ -77,7 +79,9 @@ // @ts-expect-error The constructors for Shape and Connector are different. | ||
/** | ||
* Defines the default shape for vertices. Default is {@link RectangleShape}. | ||
* Defines the default shape for vertices. | ||
* @default {@link RectangleShape}. | ||
*/ | ||
this.defaultVertexShape = RectangleShape; | ||
/** | ||
* Defines the default shape for labels. Default is {@link Text}. | ||
* Defines the default shape for labels. | ||
* @default {@link Text}. | ||
*/ | ||
@@ -87,3 +91,4 @@ this.defaultTextShape = TextShape; | ||
* Specifies if the folding icon should ignore the horizontal | ||
* orientation of a swimlane. Default is true. | ||
* orientation of a swimlane. | ||
* @default true. | ||
*/ | ||
@@ -93,7 +98,9 @@ this.legacyControlPosition = true; | ||
* Specifies if spacing and label position should be ignored if overflow is | ||
* fill or width. Default is true for backwards compatiblity. | ||
* fill or width. | ||
* @default true for backwards compatibility. | ||
*/ | ||
this.legacySpacing = true; | ||
/** | ||
* Anti-aliasing option for new shapes. Default is true. | ||
* Antialiasing option for new shapes. | ||
* @default true. | ||
*/ | ||
@@ -107,3 +114,4 @@ this.antiAlias = true; | ||
* Specifies if the enabled state of the graph should be ignored in the control | ||
* click handler (to allow folding in disabled graphs). Default is false. | ||
* click handler (to allow folding in disabled graphs). | ||
* @default false. | ||
*/ | ||
@@ -116,3 +124,3 @@ this.forceControlClickHandler = false; | ||
* ``` | ||
* mxCellRenderer.registerShape(mxConstants.SHAPE_RECTANGLE, mxRectangleShape); | ||
* CellRenderer.registerShape(Constants.SHAPE_RECTANGLE, RectangleShape); | ||
* ``` | ||
@@ -128,3 +136,3 @@ * | ||
* Initializes the shape in the given state by calling its init method with | ||
* the correct container after configuring it using <configureShape>. | ||
* the correct container after configuring it using {@link configureShape}. | ||
* | ||
@@ -143,3 +151,3 @@ * @param state <CellState> for which the shape should be initialized. | ||
* | ||
* @param state <CellState> for which the shape should be created. | ||
* @param state {@link CellState} for which the shape should be created. | ||
*/ | ||
@@ -163,3 +171,3 @@ createShape(state) { | ||
* | ||
* @param state <CellState> for which the indicator shape should be created. | ||
* @param state {@link CellState} for which the indicator shape should be created. | ||
*/ | ||
@@ -172,3 +180,3 @@ createIndicatorShape(state) { | ||
/** | ||
* Returns the shape for the given name from <defaultShapes>. | ||
* Returns the shape for the given name from {@link defaultShapes}. | ||
*/ | ||
@@ -225,19 +233,9 @@ getShape(name) { | ||
/** | ||
* Resolves special keywords 'inherit', 'indicated' and 'swimlane' and sets | ||
* the respective color on the shape. | ||
* Check if style properties supporting placeholders requires resolution. | ||
*/ | ||
checkPlaceholderStyles(state) { | ||
// LATER: Check if the color has actually changed | ||
if (state.style) { | ||
const values = ['inherit', 'swimlane', 'indicated']; | ||
const styles = [ | ||
'fillColor', | ||
'strokeColor', | ||
'gradientColor', | ||
'fontColor', | ||
]; | ||
for (let i = 0; i < styles.length; i += 1) { | ||
if (values.indexOf(state.style[styles[i]]) >= 0) { | ||
return true; | ||
} | ||
for (const property of placeholderStyleProperties) { | ||
if (placeholderStyleValues.includes(state.style[property])) { | ||
return true; | ||
} | ||
@@ -1190,4 +1188,7 @@ } | ||
* use the static {@link CellRenderer#registerShape} function. | ||
* | ||
* Built-in shapes: arrow, rectangle, ellipse, rhombus, image, line, label, cylinder, | ||
* swimlane, connector, actor and cloud. | ||
*/ | ||
CellRenderer.defaultShapes = {}; | ||
export default CellRenderer; |
@@ -6,5 +6,3 @@ import ConnectionConstraint from '../../other/ConnectionConstraint'; | ||
/** | ||
* Implements a generic shape which is based on a XML node as a description. | ||
* | ||
* @class StencilShape | ||
* Implements a generic shape which is based on an XML node as a description. | ||
*/ | ||
@@ -29,3 +27,3 @@ declare class StencilShape extends Shape { | ||
/** | ||
* Holds an array of {@link ConnectionConstraints} as defined in the shape. | ||
* Holds an array of {@link ConnectionConstraint}s as defined in the shape. | ||
*/ | ||
@@ -62,4 +60,3 @@ constraints: ConnectionConstraint[]; | ||
/** | ||
* Reads the constraints from <desc> into <constraints> using | ||
* <parseConstraint>. | ||
* Reads the constraints from {@link desc} into {@link constraints} using {@link parseConstraint}. | ||
*/ | ||
@@ -66,0 +63,0 @@ parseConstraints(): void; |
@@ -29,5 +29,3 @@ /* | ||
/** | ||
* Implements a generic shape which is based on a XML node as a description. | ||
* | ||
* @class StencilShape | ||
* Implements a generic shape which is based on an XML node as a description. | ||
*/ | ||
@@ -38,3 +36,3 @@ class StencilShape extends Shape { | ||
/** | ||
* Holds an array of {@link ConnectionConstraints} as defined in the shape. | ||
* Holds an array of {@link ConnectionConstraint}s as defined in the shape. | ||
*/ | ||
@@ -93,4 +91,3 @@ this.constraints = []; | ||
/** | ||
* Reads the constraints from <desc> into <constraints> using | ||
* <parseConstraint>. | ||
* Reads the constraints from {@link desc} into {@link constraints} using {@link parseConstraint}. | ||
*/ | ||
@@ -97,0 +94,0 @@ parseConstraints() { |
@@ -40,3 +40,2 @@ import Image from './image/ImageBox'; | ||
paintBackground: Function | null; | ||
foldingEnabled: null | boolean; | ||
isConstrainedMoving: boolean; | ||
@@ -43,0 +42,0 @@ cells: Cell[]; |
@@ -159,3 +159,2 @@ /* | ||
this.paintBackground = null; | ||
this.foldingEnabled = null; | ||
this.isConstrainedMoving = false; | ||
@@ -162,0 +161,0 @@ // =================================================================================================================== |
import AbstractCanvas2D from '../canvas/AbstractCanvas2D'; | ||
import CellState from '../cell/CellState'; | ||
/** | ||
* Creates a new image export instance to be used with an export canvas. Here | ||
* is an example that uses this class to create an image via a backend using | ||
* {@link XmlExportCanvas}. | ||
* Creates a new image export instance to be used with an export canvas. | ||
* | ||
* Here is an example that uses this class to create an image via a backend using {@link XmlCanvas2D}. | ||
* | ||
* ```javascript | ||
* var xmlDoc = mxUtils.createXmlDocument(); | ||
* var root = xmlDoc.createElement('output'); | ||
* const xmlDoc = xmlUtils.createXmlDocument(); | ||
* const root = xmlDoc.createElement('output'); | ||
* xmlDoc.appendChild(root); | ||
* | ||
* var xmlCanvas = new mxXmlCanvas2D(root); | ||
* var imgExport = new mxImageExport(); | ||
* imgExport.drawState(graph.getView().getState(graph.model.root), xmlCanvas); | ||
* const xmlCanvas = new XmlCanvas2D(root); | ||
* const imageExport = new ImageExport(); | ||
* | ||
* var bounds = graph.getGraphBounds(); | ||
* var w = Math.ceil(bounds.x + bounds.width); | ||
* var h = Math.ceil(bounds.y + bounds.height); | ||
* imageExport.drawState(graph.getView().getState(graph.model.root), xmlCanvas); | ||
* const xml = xmlUtils.getXml(root); | ||
* | ||
* var xml = mxUtils.getXml(root); | ||
* const bounds = graph.getGraphBounds(); | ||
* const w = Math.ceil(bounds.x + bounds.width); | ||
* const h = Math.ceil(bounds.y + bounds.height); | ||
* | ||
* new MaxXmlRequest('export', 'format=png&w=' + w + | ||
@@ -26,8 +27,7 @@ * '&h=' + h + '&bg=#F9F7ED&xml=' + encodeURIComponent(xml)) | ||
* ``` | ||
* | ||
* @class ImageExport | ||
*/ | ||
declare class ImageExport { | ||
/** | ||
* Specifies if overlays should be included in the export. Default is false. | ||
* Specifies if overlays should be included in the export. | ||
* @default false | ||
*/ | ||
@@ -42,7 +42,7 @@ includeOverlays: boolean; | ||
*/ | ||
visitStatesRecursive(state: CellState, canvas: AbstractCanvas2D, visitor: Function): void; | ||
visitStatesRecursive(state: CellState, canvas: AbstractCanvas2D, visitor: (state: CellState, canvas: AbstractCanvas2D) => void): void; | ||
/** | ||
* Returns the link for the given cell state and canvas. This returns null. | ||
*/ | ||
getLinkForCellState(state: CellState, canvas: AbstractCanvas2D): any; | ||
getLinkForCellState(_state: CellState, _canvas: AbstractCanvas2D): any; | ||
/** | ||
@@ -49,0 +49,0 @@ * Draws the given state to the given canvas. |
@@ -20,20 +20,21 @@ /* | ||
/** | ||
* Creates a new image export instance to be used with an export canvas. Here | ||
* is an example that uses this class to create an image via a backend using | ||
* {@link XmlExportCanvas}. | ||
* Creates a new image export instance to be used with an export canvas. | ||
* | ||
* Here is an example that uses this class to create an image via a backend using {@link XmlCanvas2D}. | ||
* | ||
* ```javascript | ||
* var xmlDoc = mxUtils.createXmlDocument(); | ||
* var root = xmlDoc.createElement('output'); | ||
* const xmlDoc = xmlUtils.createXmlDocument(); | ||
* const root = xmlDoc.createElement('output'); | ||
* xmlDoc.appendChild(root); | ||
* | ||
* var xmlCanvas = new mxXmlCanvas2D(root); | ||
* var imgExport = new mxImageExport(); | ||
* imgExport.drawState(graph.getView().getState(graph.model.root), xmlCanvas); | ||
* const xmlCanvas = new XmlCanvas2D(root); | ||
* const imageExport = new ImageExport(); | ||
* | ||
* var bounds = graph.getGraphBounds(); | ||
* var w = Math.ceil(bounds.x + bounds.width); | ||
* var h = Math.ceil(bounds.y + bounds.height); | ||
* imageExport.drawState(graph.getView().getState(graph.model.root), xmlCanvas); | ||
* const xml = xmlUtils.getXml(root); | ||
* | ||
* var xml = mxUtils.getXml(root); | ||
* const bounds = graph.getGraphBounds(); | ||
* const w = Math.ceil(bounds.x + bounds.width); | ||
* const h = Math.ceil(bounds.y + bounds.height); | ||
* | ||
* new MaxXmlRequest('export', 'format=png&w=' + w + | ||
@@ -43,4 +44,2 @@ * '&h=' + h + '&bg=#F9F7ED&xml=' + encodeURIComponent(xml)) | ||
* ``` | ||
* | ||
* @class ImageExport | ||
*/ | ||
@@ -50,3 +49,4 @@ class ImageExport { | ||
/** | ||
* Specifies if overlays should be included in the export. Default is false. | ||
* Specifies if overlays should be included in the export. | ||
* @default false | ||
*/ | ||
@@ -60,10 +60,6 @@ this.includeOverlays = false; | ||
if (state) { | ||
this.visitStatesRecursive(state, canvas, () => { | ||
this.drawCellState(state, canvas); | ||
}); | ||
this.visitStatesRecursive(state, canvas, this.drawCellState.bind(this)); | ||
// Paints the overlays | ||
if (this.includeOverlays) { | ||
this.visitStatesRecursive(state, canvas, () => { | ||
this.drawOverlays(state, canvas); | ||
}); | ||
this.visitStatesRecursive(state, canvas, this.drawOverlays.bind(this)); | ||
} | ||
@@ -90,3 +86,3 @@ } | ||
*/ | ||
getLinkForCellState(state, canvas) { | ||
getLinkForCellState(_state, _canvas) { | ||
return null; | ||
@@ -140,3 +136,3 @@ } | ||
if (state.overlays != null) { | ||
state.overlays.visit((id, shape) => { | ||
state.overlays.visit((_id, shape) => { | ||
if (shape instanceof Shape) { | ||
@@ -143,0 +139,0 @@ shape.paint(canvas); |
@@ -13,2 +13,10 @@ import Point from '../geometry/Point'; | ||
getOutlineConstraint: (point: Point, terminalState: CellState, me: InternalMouseEvent) => ConnectionConstraint | null; | ||
/** | ||
* Returns an array of all {@link ConnectionConstraint}s for the given terminal. If | ||
* the shape of the given terminal is a {@link StencilShape} then the constraints | ||
* of the corresponding {@link StencilShape} are returned. | ||
* | ||
* @param terminal {@link CellState} that represents the terminal. | ||
* @param source Boolean that specifies if the terminal is the source or target. | ||
*/ | ||
getAllConnectionConstraints: (terminal: CellState | null, source: boolean) => ConnectionConstraint[] | null; | ||
@@ -15,0 +23,0 @@ getConnectionConstraint: (edge: CellState, terminal: CellState | null, source: boolean) => ConnectionConstraint; |
@@ -104,15 +104,4 @@ /* | ||
}, | ||
/** | ||
* Returns an array of all {@link mxConnectionConstraints} for the given terminal. If | ||
* the shape of the given terminal is a {@link mxStencilShape} then the constraints | ||
* of the corresponding {@link mxStencil} are returned. | ||
* | ||
* @param terminal {@link CellState} that represents the terminal. | ||
* @param source Boolean that specifies if the terminal is the source or target. | ||
*/ | ||
getAllConnectionConstraints(terminal, source) { | ||
if (terminal && terminal.shape && terminal.shape.stencil) { | ||
return terminal.shape.stencil.constraints; | ||
} | ||
return null; | ||
return terminal?.shape?.stencil?.constraints ?? null; | ||
}, | ||
@@ -119,0 +108,0 @@ /** |
import Point from '../geometry/Point'; | ||
/** | ||
* Defines an object that contains the constraints about how to connect one side of an edge to its terminal. | ||
* @class ConnectionConstraint | ||
*/ | ||
@@ -6,0 +5,0 @@ declare class ConnectionConstraint { |
@@ -20,3 +20,2 @@ /* | ||
* Defines an object that contains the constraints about how to connect one side of an edge to its terminal. | ||
* @class ConnectionConstraint | ||
*/ | ||
@@ -23,0 +22,0 @@ class ConnectionConstraint { |
@@ -253,3 +253,3 @@ /* | ||
const graph = new Graph(container, this.source.getDataModel(), defaultPlugins, this.source.getStylesheet()); | ||
graph.foldingEnabled = false; | ||
graph.options.foldingEnabled = false; | ||
graph.autoScroll = false; | ||
@@ -256,0 +256,0 @@ return graph; |
@@ -5,3 +5,3 @@ { | ||
"private": false, | ||
"version": "0.10.2", | ||
"version": "0.10.3", | ||
"type": "module", | ||
@@ -8,0 +8,0 @@ "description": "maxGraph is a fully client side JavaScript diagramming library that uses SVG and HTML for rendering.", |
3340075
87113