From e7a634dd847b0cab7a89abe40f3cc0873d00a82c Mon Sep 17 00:00:00 2001 From: 4902746 Date: Sat, 22 May 2021 19:17:28 +0200 Subject: [PATCH] Version 3.1 --- README.md | 1 - changelog.md | 37 +- dist/g2.chart.html.js | 127 ++- dist/g2.full.js | 57 +- dist/g2.html.js | 476 +++++++++- dist/g2.js | 10 +- docs/subscripts.md | 79 ++ package-lock.json | 1965 +++++++++++++++++++++++++++++++++++++++ package.json | 3 +- sample/g2styleref.html | 25 + src/g2.chart.element.js | 70 +- src/g2.chart.js | 17 +- src/g2.core.js | 4 +- src/g2.element.js | 2 +- src/g2.ext.js | 19 +- src/g2.hdl.canvas.js | 22 +- 16 files changed, 2767 insertions(+), 147 deletions(-) create mode 100644 docs/subscripts.md create mode 100644 package-lock.json create mode 100644 sample/g2styleref.html diff --git a/README.md b/README.md index 76ac24a..b319237 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,6 @@ So the API is minimal and easy to understand. The library is tiny, fast and rend * Fast and lightweight graphics command queue builder. * Addressing HTML canvas 2D context as the default renderer. -* Generating SVG output using an [addon library](https://github.com/goessner/g2-svg). * Method chaining. * Support of cartesian coordinates. * Viewport pan and zoom transformations. diff --git a/changelog.md b/changelog.md index 46e9696..c176083 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,27 @@ # CHANGELOG +## [3.1.0]() on May 2021 + +### `g2.core.js` +* Styles `(fs|ls|lw|lc|lj|ld|ldoff|ml|sh|lsh|font|thal|tval)` can be numbered now from `0-9` as in `{ls2:'red'}`. +This helps to hand over multiple fill styles (for example) to sub- structures (`beg`, `use`). + +### `g2.ext.js` +* Handles `hdl` now have new default fill color `fs:'limegreen'` for better recognition. + +## [3.0.0]() on December 2020 + +### `g2.core.js` +* `g2.mixin` is replaced with `g2.mix`. + +### `g2.ext.js` +* Symbols like `nod`, `origin` etc. are moved from `g2.mec` to `g2.ext`. +* Commands `vec`, `avec`, `dim`, `adim` are also moved. +* `label` is no command anymore, but a property on respective `g2` commands. +* `mark` is no command anymore, but a property on respective `g2` commands. + +### `g2.chart.html.js` +* A new custom HTML element used for easy rendering of `g2.chart` commands. + ## [2.6.0]() on May 2020 ### `g2.core.js` @@ -19,17 +42,3 @@ ### `g2.selector.js` / `canvasinteractor.js` * `interactor.on('pan')`, `interactor.on('drag')` and `interactor.on('wheel')` handling is moved out of the library and is now in the responsibility of the application (s. `g2.drag.html`). * `hdl` elements can be used elegantly to interactively modify geometry. - -## [3.0.0]() on December 2020 - -### `g2.core.js` -* `g2.mixin` is replaced with `g2.mix`. - -### `g2.ext.js` -* Symbols like `nod`, `origin` etc. are moved from `g2.mec` to `g2.ext`. -* Commands `vec`, `avec`, `dim`, `adim` are also moved. -* `label` is no command anymore, but a property on respective `g2` commands. -* `mark` is no command anymore, but a property on respective `g2` commands. - -### `g2.chart.html.js` -* A new custom HTML element used for easy rendering of `g2.chart` commands. diff --git a/dist/g2.chart.html.js b/dist/g2.chart.html.js index 49c964d..37750d3 100644 --- a/dist/g2.chart.html.js +++ b/dist/g2.chart.html.js @@ -2,7 +2,7 @@ "use strict" /** - * g2.core (c) 2013-20 Stefan Goessner + * g2.core (c) 2013-21 Stefan Goessner * @author Stefan Goessner * @license MIT License * @link https://github.com/goessner/g2 @@ -538,6 +538,8 @@ g2.prototype = { // statics g2.defaultStyle = { fs: 'transparent', ls: '#000', lw: 1, lc: "butt", lj: "miter", ld: [], ml: 10, sh: [0, 0], lsh: false, font: '14px serif', thal: 'start', tval: 'alphabetic' }; +g2.styleRex = /^(fs|ls|lw|lc|lj|ld|ldoff|ml|sh|lsh|font|thal|tval)([-0-9].*)?$/, + g2.symbol = { unknown: g2().cir({ r: 12, fs: 'orange' }).txt({ str: '?', thal: 'center', tval: 'middle', font: 'bold 20pt serif' }) }; @@ -955,13 +957,16 @@ g2.canvasHdl.prototype = { let q, prv = {}; for (const key in style) { if (this.get[key]) { // style keys only ... + let keyval = style[key]; if (typeof style[key] === 'string' && style[key][0] === '@') { - let ref = style[key].substr(1); - style[key] = g2.symbol[ref] || this.get[ref] && this.get[ref](this.ctx); + // also check inherited styles ... + const ref = style[key].substr(1); + keyval = g2.symbol[ref] || ref in this.get && this.get[ref](this.ctx) + || ref in this.cur && this.cur[ref]; } - if ((q = this.get[key](this.ctx)) !== style[key]) { + if ((q = this.get[key](this.ctx)) !== keyval) { prv[key] = q; - this.set[key](this.ctx, style[key]); + this.set[key](this.ctx, keyval); } } } @@ -973,14 +978,17 @@ g2.canvasHdl.prototype = { }, pushStyle(style) { let cur = {}; // hold changed properties ... - for (const key in style) - if (this.get[key]) { // style keys only ... + for (const key in style) // allow extended style syntax ('fs-2', ...) + if (g2.styleRex.test(key)) { // (extended) style keys only ... if (typeof style[key] === 'string' && style[key][0] === '@') { let ref = style[key].substr(1); style[key] = g2.symbol[ref] || this.get[ref] && this.get[ref](this.ctx); } - if (this.cur[key] !== style[key]) - this.set[key](this.ctx, (cur[key] = style[key])); + if (this.cur[key] !== style[key]) { + if (key in this.set) + this.set[key](this.ctx, style[key]); + cur[key] = style[key]; + } } this.stack.push(this.cur = Object.assign({}, this.cur, cur)); }, @@ -1052,8 +1060,6 @@ g2.canvasHdl.prototype = { } } -// use it with node.js ... ? -if (typeof module !== 'undefined') module.exports = g2; /** * g2.io (c) 2017-18 Stefan Goessner * @license MIT License @@ -1321,7 +1327,7 @@ g2 = Object.assign(g2, { "use strict" /** - * g2.ext (c) 2015-20 Stefan Goessner + * g2.ext (c) 2015-21 Stefan Goessner * @author Stefan Goessner * @license MIT License * @requires g2.core.js @@ -1346,7 +1352,7 @@ g2.NONE = 0x0; g2.OVER = 0x1; g2.DRAG = 0x2; g2.EDIT = 0x4; * @property {object} [symbol.sqr] Predefined symbol: a little square * @property {string} [symbol.nodcolor=#333] node color. * @property {string} [symbol.nodfill=#dedede] node fill color. - * @property {string} [symbol.nodfill2=#aeaeae] alternate node fill color, somewhat darker. + * @property {string} [symbol.nodfill2=#aeaeae] alternate node fill color, somewhat darker. * @property {string} [symbol.linkcolor=#666] link color. * @property {string} [symbol.linkfill=rgba(225,225,225,0.75)] link fill color, semi-transparent. * @property {string} [symbol.dimcolor=darkslategray] dimension color. @@ -1472,7 +1478,7 @@ g2.markIfc = { } } -g2.prototype.cir.prototype = g2.mix(g2.pointIfc, g2.labelIfc, g2.markIfc, { +g2.prototype.cir.prototype = g2.mix(g2.labelIfc, g2.markIfc, { w: 0, // default start angle (used for dash-dot orgin and editing) lbloc: 'c', get isSolid() { return this.fs && this.fs !== 'transparent' }, @@ -1682,8 +1688,8 @@ g2.prototype.nod.prototype = g2.mix(g2.prototype.cir.prototype, { */ g2.prototype.dblnod = function ({ x = 0, y = 0 }) { return this.addCommand({ c: 'dblnod', a: arguments[0] }); } g2.prototype.dblnod.prototype = g2.mix(g2.prototype.cir.prototype, { - get r() { return 6; }, - get isSolid() { return true; }, + r: 6, + isSolid: true, g2() { return g2() .beg({ x: this.x, y: this.y }) @@ -1709,7 +1715,7 @@ g2.prototype.pol.prototype = g2.mix(g2.prototype.nod.prototype, { g2() { return g2() .beg(g2.flatten(this)) - .cir({ r: 6, fs: g2.symbol.nodfill }) + .cir({ r: 6, fs: '@fs2' }) .cir({ r: 2.5, fs: '@ls', ls: 'transparent' }) .end() .ins((g) => this.label && this.drawLabel(g)); @@ -2188,10 +2194,10 @@ g2.prototype.chart.prototype = { ]; funcs.forEach(f => this.initFunc(f, ...tmp)); } - // if (this.xaxis) - this.xAxis = this.autoAxis(this.get('xmin'), this.get('xmax'), 0, this.b); - // if (this.yaxis) - this.yAxis = this.autoAxis(this.get('ymin'), this.get('ymax'), 0, this.h); + if (this.xaxis) + this.xAxis = this.autoAxis(this.get('xmin'), this.get('xmax'), 0, this.b); + if (this.yaxis) + this.yAxis = this.autoAxis(this.get('ymin'), this.get('ymax'), 0, this.h); // draw background & border ... g.rec({ @@ -2271,15 +2277,14 @@ g2.prototype.chart.prototype = { } }, autoAxis(zmin, zmax, tmin, tmax) { - let base = 2, exp = 1, eps = Math.sqrt(Number.EPSILON), + let base = 1, exp = 1, eps = Math.sqrt(Number.EPSILON), Dz = zmax - zmin || 1, // value range Dt = tmax - tmin || 1, // area range scl = Dz > eps ? Dt / Dz : 1, // scale [usr]->[pix] dz = base * Math.pow(10, exp), // tick size [usr] dt = Math.floor(scl * dz), // tick size [pix] N, // # segments - dt01, // reminder segment - i0, j0, jth, t0, res; + i0, j0, jth, t0; while (dt < 14 || dt > 35) { if (dt < 14) { @@ -2300,8 +2305,6 @@ g2.prototype.chart.prototype = { : Math.floor(zmin / dz) + 1; let z0 = i0 * dz; t0 = Math.round(scl * (z0 - zmin)); - // console.log("Dt="+Dt+",N="+(Dt - t0)/ dt) - // console.log("DT="+Dt+",N="+(Dt - t0)/ dt) N = Math.floor((Dt - t0) / dt) + 1; j0 = base % 2 && i0 % 2 ? i0 + 1 : i0; jth = exp === 0 && N < 11 ? 1 : base === 2 && N > 9 ? 5 : 2; @@ -2345,8 +2348,6 @@ g2.prototype.chart.prototype = { ticklen = showticks ? this.get("xaxis", "ticks", "len") : 0, showorigin = showaxis && this.get("xaxis", "origin"), title = this.xaxis && (this.get("xaxis", "title", "text") || this.xaxis.title) || ''; - // console.log(this.xAxis) - // draw tick/grid lines g.beg(axisstyle); for (let i = 0; i < this.xAxis.N; i++) { tick = this.xAxis.itr(i); @@ -2950,6 +2951,12 @@ class G2ChartElement extends HTMLElement { 'ymin', 'ymax', 'title', + 'xlabels', + 'ylabels', + 'xticks', + 'yticks', + 'xtitle', + 'ytitle' ]; } @@ -2972,33 +2979,52 @@ class G2ChartElement extends HTMLElement { set ymax(q) { return q && +this.setAttribute('ymax', q) } get title() { return this.getAttribute('title') || ''; } set title(q) { return q && this.setAttribute('title', q) } + get xlabels() { return this.getAttribute('xlabels') !== 'false'; } + get ylabels() { return this.getAttribute('ylabels') !== 'false'; } + get xticks() { return this.getAttribute('xticks') !== 'false'; } + get yticks() { return this.getAttribute('yticks') !== 'false'; } + get xtitle() { return this.getAttribute('xtitle'); } + get ytitle() { return this.getAttribute('ytitle'); } connectedCallback() { this._root.innerHTML = G2ChartElement.template({ width: this.width, height: this.height }); - this._ctx = this._root.getElementById('cnv').getContext('2d'); + const xmargin = (this.yticks && 5) + (this.ylabels && 15) + (this.ytitle && 15); + const ymargin = (this.xticks && 5) + (this.xlabels && 15) + (this.xtitle && 15); - const t = 35; this._chart = { - x: t, - y: t, + x: xmargin, + y: ymargin, xmin: this.xmin, xmax: this.xmax, ymin: this.ymin, ymax: this.ymax, title: this.title, - b: this.width - t * 2, - h: this.height - t * 2, - xaxis: () => this.xaxis || {}, - yaxis: () => this.yaxis || {}, + b: this.width - 5 - xmargin, + h: this.height - 5 - ymargin - (this.title && 15), + xaxis: () => this.xaxis || { ticks: this.xticks, labels: this.xlabels, title: this.xtitle }, + yaxis: () => this.yaxis || { ticks: this.yticks, labels: this.ylabels, title: this.ytitle }, title: () => this.title || "", - funcs: () => this.funcs + funcs: [] }; - this._g = g2().del().clr().view({ cartesian: true }).chart(this._chart); + if (this.innerHTML) { + let res; + + try { res = JSON.parse(this.innerHTML); } + catch (e) { + console.error(e); + this._g.txt({ str: e, y: 5 }); + } + + this._chart.funcs.push(...G2ChartElement.validateFunc(res)); + } + this._ctx = this._root.getElementById('cnv').getContext('2d'); + this._g = g2().del().clr().view({ cartesian: true }).chart(this._chart); +/* try { // If not true, the element should be referenced by another module. if (this.innerHTML !== '') { @@ -3028,24 +3054,41 @@ class G2ChartElement extends HTMLElement { }); this.render(); } +*/ + this.render(); } render() { this._g.exe(this._ctx); } - +/* setFuncs(funcs) { this.funcs = funcs; return this; } - +*/ disconnectedCallback() { // TODO } + static validateFunc(obj, funcs) { + funcs = funcs || []; + if (Array.isArray(obj)) // array of functions ... + for (const o of obj) + G2ChartElement.validateFunc(o, funcs); + else if (typeof obj === 'object') { // single function ... + if ('fn' in obj) { + const fnc = Function('"use strict";return (' + obj['fn'] + ')')(); + obj.fn = typeof fnc === 'function' ? fnc : undefined; // todo: error message ... + } + if ('fn' in obj || 'data' in obj) + funcs.push(obj); + } + return funcs; + } + static template({ width, height }) { - return `` + return `` } } customElements.define('g2-chart', G2ChartElement); diff --git a/dist/g2.full.js b/dist/g2.full.js index 7245306..fa2ef73 100644 --- a/dist/g2.full.js +++ b/dist/g2.full.js @@ -2,7 +2,7 @@ "use strict" /** - * g2.core (c) 2013-20 Stefan Goessner + * g2.core (c) 2013-21 Stefan Goessner * @author Stefan Goessner * @license MIT License * @link https://github.com/goessner/g2 @@ -538,6 +538,8 @@ g2.prototype = { // statics g2.defaultStyle = { fs: 'transparent', ls: '#000', lw: 1, lc: "butt", lj: "miter", ld: [], ml: 10, sh: [0, 0], lsh: false, font: '14px serif', thal: 'start', tval: 'alphabetic' }; +g2.styleRex = /^(fs|ls|lw|lc|lj|ld|ldoff|ml|sh|lsh|font|thal|tval)([-0-9].*)?$/, + g2.symbol = { unknown: g2().cir({ r: 12, fs: 'orange' }).txt({ str: '?', thal: 'center', tval: 'middle', font: 'bold 20pt serif' }) }; @@ -955,13 +957,16 @@ g2.canvasHdl.prototype = { let q, prv = {}; for (const key in style) { if (this.get[key]) { // style keys only ... + let keyval = style[key]; if (typeof style[key] === 'string' && style[key][0] === '@') { - let ref = style[key].substr(1); - style[key] = g2.symbol[ref] || this.get[ref] && this.get[ref](this.ctx); + // also check inherited styles ... + const ref = style[key].substr(1); + keyval = g2.symbol[ref] || ref in this.get && this.get[ref](this.ctx) + || ref in this.cur && this.cur[ref]; } - if ((q = this.get[key](this.ctx)) !== style[key]) { + if ((q = this.get[key](this.ctx)) !== keyval) { prv[key] = q; - this.set[key](this.ctx, style[key]); + this.set[key](this.ctx, keyval); } } } @@ -973,14 +978,17 @@ g2.canvasHdl.prototype = { }, pushStyle(style) { let cur = {}; // hold changed properties ... - for (const key in style) - if (this.get[key]) { // style keys only ... + for (const key in style) // allow extended style syntax ('fs-2', ...) + if (g2.styleRex.test(key)) { // (extended) style keys only ... if (typeof style[key] === 'string' && style[key][0] === '@') { let ref = style[key].substr(1); style[key] = g2.symbol[ref] || this.get[ref] && this.get[ref](this.ctx); } - if (this.cur[key] !== style[key]) - this.set[key](this.ctx, (cur[key] = style[key])); + if (this.cur[key] !== style[key]) { + if (key in this.set) + this.set[key](this.ctx, style[key]); + cur[key] = style[key]; + } } this.stack.push(this.cur = Object.assign({}, this.cur, cur)); }, @@ -1052,8 +1060,6 @@ g2.canvasHdl.prototype = { } } -// use it with node.js ... ? -if (typeof module !== 'undefined') module.exports = g2; /** * g2.lib (c) 2013-17 Stefan Goessner * geometric constants and higher functions @@ -1230,7 +1236,7 @@ g2 = Object.assign(g2, { "use strict" /** - * g2.ext (c) 2015-20 Stefan Goessner + * g2.ext (c) 2015-21 Stefan Goessner * @author Stefan Goessner * @license MIT License * @requires g2.core.js @@ -1255,7 +1261,7 @@ g2.NONE = 0x0; g2.OVER = 0x1; g2.DRAG = 0x2; g2.EDIT = 0x4; * @property {object} [symbol.sqr] Predefined symbol: a little square * @property {string} [symbol.nodcolor=#333] node color. * @property {string} [symbol.nodfill=#dedede] node fill color. - * @property {string} [symbol.nodfill2=#aeaeae] alternate node fill color, somewhat darker. + * @property {string} [symbol.nodfill2=#aeaeae] alternate node fill color, somewhat darker. * @property {string} [symbol.linkcolor=#666] link color. * @property {string} [symbol.linkfill=rgba(225,225,225,0.75)] link fill color, semi-transparent. * @property {string} [symbol.dimcolor=darkslategray] dimension color. @@ -1381,7 +1387,7 @@ g2.markIfc = { } } -g2.prototype.cir.prototype = g2.mix(g2.pointIfc, g2.labelIfc, g2.markIfc, { +g2.prototype.cir.prototype = g2.mix(g2.labelIfc, g2.markIfc, { w: 0, // default start angle (used for dash-dot orgin and editing) lbloc: 'c', get isSolid() { return this.fs && this.fs !== 'transparent' }, @@ -1591,8 +1597,8 @@ g2.prototype.nod.prototype = g2.mix(g2.prototype.cir.prototype, { */ g2.prototype.dblnod = function ({ x = 0, y = 0 }) { return this.addCommand({ c: 'dblnod', a: arguments[0] }); } g2.prototype.dblnod.prototype = g2.mix(g2.prototype.cir.prototype, { - get r() { return 6; }, - get isSolid() { return true; }, + r: 6, + isSolid: true, g2() { return g2() .beg({ x: this.x, y: this.y }) @@ -1618,7 +1624,7 @@ g2.prototype.pol.prototype = g2.mix(g2.prototype.nod.prototype, { g2() { return g2() .beg(g2.flatten(this)) - .cir({ r: 6, fs: g2.symbol.nodfill }) + .cir({ r: 6, fs: '@fs2' }) .cir({ r: 2.5, fs: '@ls', ls: 'transparent' }) .end() .ins((g) => this.label && this.drawLabel(g)); @@ -2588,10 +2594,10 @@ g2.prototype.chart.prototype = { ]; funcs.forEach(f => this.initFunc(f, ...tmp)); } - // if (this.xaxis) - this.xAxis = this.autoAxis(this.get('xmin'), this.get('xmax'), 0, this.b); - // if (this.yaxis) - this.yAxis = this.autoAxis(this.get('ymin'), this.get('ymax'), 0, this.h); + if (this.xaxis) + this.xAxis = this.autoAxis(this.get('xmin'), this.get('xmax'), 0, this.b); + if (this.yaxis) + this.yAxis = this.autoAxis(this.get('ymin'), this.get('ymax'), 0, this.h); // draw background & border ... g.rec({ @@ -2671,15 +2677,14 @@ g2.prototype.chart.prototype = { } }, autoAxis(zmin, zmax, tmin, tmax) { - let base = 2, exp = 1, eps = Math.sqrt(Number.EPSILON), + let base = 1, exp = 1, eps = Math.sqrt(Number.EPSILON), Dz = zmax - zmin || 1, // value range Dt = tmax - tmin || 1, // area range scl = Dz > eps ? Dt / Dz : 1, // scale [usr]->[pix] dz = base * Math.pow(10, exp), // tick size [usr] dt = Math.floor(scl * dz), // tick size [pix] N, // # segments - dt01, // reminder segment - i0, j0, jth, t0, res; + i0, j0, jth, t0; while (dt < 14 || dt > 35) { if (dt < 14) { @@ -2700,8 +2705,6 @@ g2.prototype.chart.prototype = { : Math.floor(zmin / dz) + 1; let z0 = i0 * dz; t0 = Math.round(scl * (z0 - zmin)); - // console.log("Dt="+Dt+",N="+(Dt - t0)/ dt) - // console.log("DT="+Dt+",N="+(Dt - t0)/ dt) N = Math.floor((Dt - t0) / dt) + 1; j0 = base % 2 && i0 % 2 ? i0 + 1 : i0; jth = exp === 0 && N < 11 ? 1 : base === 2 && N > 9 ? 5 : 2; @@ -2745,8 +2748,6 @@ g2.prototype.chart.prototype = { ticklen = showticks ? this.get("xaxis", "ticks", "len") : 0, showorigin = showaxis && this.get("xaxis", "origin"), title = this.xaxis && (this.get("xaxis", "title", "text") || this.xaxis.title) || ''; - // console.log(this.xAxis) - // draw tick/grid lines g.beg(axisstyle); for (let i = 0; i < this.xAxis.N; i++) { tick = this.xAxis.itr(i); diff --git a/dist/g2.html.js b/dist/g2.html.js index 0b8ca60..1175774 100644 --- a/dist/g2.html.js +++ b/dist/g2.html.js @@ -2,7 +2,7 @@ "use strict" /** - * g2.core (c) 2013-20 Stefan Goessner + * g2.core (c) 2013-21 Stefan Goessner * @author Stefan Goessner * @license MIT License * @link https://github.com/goessner/g2 @@ -538,6 +538,8 @@ g2.prototype = { // statics g2.defaultStyle = { fs: 'transparent', ls: '#000', lw: 1, lc: "butt", lj: "miter", ld: [], ml: 10, sh: [0, 0], lsh: false, font: '14px serif', thal: 'start', tval: 'alphabetic' }; +g2.styleRex = /^(fs|ls|lw|lc|lj|ld|ldoff|ml|sh|lsh|font|thal|tval)([-0-9].*)?$/, + g2.symbol = { unknown: g2().cir({ r: 12, fs: 'orange' }).txt({ str: '?', thal: 'center', tval: 'middle', font: 'bold 20pt serif' }) }; @@ -607,6 +609,457 @@ g2.mix = function mix(...protos) { */ g2.cpyProp = function (from, fromKey, to, toKey) { Object.defineProperty(to, toKey, Object.getOwnPropertyDescriptor(from, fromKey)); } +// Html canvas handler +g2.canvasHdl = function (ctx) { + if (this instanceof g2.canvasHdl) { + if (ctx instanceof CanvasRenderingContext2D) { + this.ctx = ctx; + this.cur = g2.defaultStyle; + this.stack = [this.cur]; + this.matrix = [[1, 0, 0, 1, 0.5, 0.5]]; + this.gridBase = 2; + this.gridExp = 1; + return this; + } + else + return null; + } + return g2.canvasHdl.apply(Object.create(g2.canvasHdl.prototype), arguments); +}; +g2.handler.factory.push((ctx) => ctx instanceof g2.canvasHdl ? ctx + : ctx instanceof CanvasRenderingContext2D ? g2.canvasHdl(ctx) : false); + +g2.canvasHdl.prototype = { + init(grp, style) { + this.stack.length = 1; + this.matrix.length = 1; + this.initStyle(style ? Object.assign({}, this.cur, style) : this.cur); + return true; + }, + async exe(commands) { + for (let cmd of commands) { + // cmd.a is an object offering a `g2` method, so call it and execute its returned commands array. + if (cmd.a && cmd.a.g2) { + const cmds = cmd.a.g2().commands; + // If false, ext was not applied to this cmd. But the command still renders + if (cmds) { + this.exe(cmds); + continue; + } + } + // cmd.a is a `g2` object, so directly execute its commands array. + else if (cmd.a && cmd.a.commands) { + this.exe(cmd.a.commands); + continue; + } + if (cmd.c && this[cmd.c]) { // explicit command name .. ! + const rx = this[cmd.c](cmd.a); + if (rx && rx instanceof Promise) { + await rx; + } + } + } + }, + view({ x = 0, y = 0, scl = 1, cartesian = false }) { + this.pushTrf(cartesian ? [scl, 0, 0, -scl, x, this.ctx.canvas.height - 1 - y] + : [scl, 0, 0, scl, x, y]); + }, + grid({ color = '#ccc', size } = {}) { + let ctx = this.ctx, b = ctx.canvas.width, h = ctx.canvas.height, + { x, y, scl } = this.uniTrf, + sz = size || this.gridSize(scl), + xoff = x % sz, yoff = y % sz; + ctx.save(); + ctx.setTransform(1, 0, 0, 1, 0, 0); + ctx.strokeStyle = color; + ctx.lineWidth = 1; + ctx.beginPath(); + for (let x = xoff, nx = b + 1; x < nx; x += sz) { ctx.moveTo(x, 0); ctx.lineTo(x, h); } + for (let y = yoff, ny = h + 1; y < ny; y += sz) { ctx.moveTo(0, y); ctx.lineTo(b, y); } + ctx.stroke(); + ctx.restore(); + }, + clr({ b, h } = {}) { + let ctx = this.ctx; + ctx.save(); + ctx.setTransform(1, 0, 0, 1, 0, 0); + ctx.clearRect(0, 0, b || ctx.canvas.width, h || ctx.canvas.height); + ctx.restore(); + }, + cir({ r }) { + const { x = 0, y = 0 } = arguments[0].p !== undefined ? arguments[0].p : arguments[0]; + this.ctx.beginPath(); + this.ctx.arc(x || 0, y || 0, Math.abs(r), 0, 2 * Math.PI, true); + this.drw(arguments[0]); + }, + arc({ r, w = 0, dw = 2 * Math.PI }) { + const { x = 0, y = 0 } = arguments[0].p !== undefined ? arguments[0].p : arguments[0]; + if (Math.abs(dw) > Number.EPSILON && Math.abs(r) > Number.EPSILON) { + this.ctx.beginPath(); + this.ctx.arc(x, y, Math.abs(r), w, w + dw, dw < 0); + this.drw(arguments[0]); + } + else if (Math.abs(dw) < Number.EPSILON && Math.abs(r) > Number.EPSILON) { + const cw = Math.cos(w), sw = Math.sin(w); + this.ctx.beginPath(); + this.ctx.moveTo(x - r * cw, y - r * sw); + this.ctx.lineTo(x + r * cw, y + r * sw); + } + // else // nothing to draw with r === 0 + }, + ell({ rx, ry, w = 0, dw = 2 * Math.PI, rot = 0 }) { + const { x = 0, y = 0 } = arguments[0].p !== undefined ? arguments[0].p : arguments[0]; + this.ctx.beginPath(); + this.ctx.ellipse(x, y, Math.abs(rx), Math.abs(ry), rot, w, w + dw, dw < 0); + this.drw(arguments[0]); + }, + rec({ b, h }) { + const { x = 0, y = 0 } = arguments[0].p !== undefined ? arguments[0].p : arguments[0]; + const tmp = this.setStyle(arguments[0]); + this.ctx.fillRect(x, y, b, h); + this.ctx.strokeRect(x, y, b, h); + this.resetStyle(tmp); + }, + lin(args) { + this.ctx.beginPath(); + this.ctx.moveTo(args.p1 && args.p1.x || args.x1 || 0, args.p1 && args.p1.y || args.y1 || 0); + this.ctx.lineTo(args.p2 && args.p2.x || args.x2 || 0, args.p2 && args.p2.y || args.y2 || 0); + this.stroke(args); + }, + ply({ pts, closed, w = 0, _itr }) { + if (_itr && _itr.len) { + const { x = 0, y = 0 } = arguments[0].p !== undefined ? arguments[0].p : arguments[0]; + let p, i, len = _itr.len, istrf = !!(x || y || w), cw, sw; + if (istrf) this.setTrf([cw = (w ? Math.cos(w) : 1), sw = (w ? Math.sin(w) : 0), -sw, cw, x, y]); + this.ctx.beginPath(); + this.ctx.moveTo((p = _itr(0)).x, p.y); + for (i = 1; i < len; i++) + this.ctx.lineTo((p = _itr(i)).x, p.y); + if (closed) // closed then .. + this.ctx.closePath(); + this.drw(arguments[0]); + if (istrf) this.resetTrf(); + return i - 1; // number of points .. + } + return 0; + }, + txt({ str, w = 0/*,unsizable*/ }) { + const { x = 0, y = 0 } = arguments[0].p !== undefined ? arguments[0].p : arguments[0]; + const tmp = this.setStyle(arguments[0]), + sw = w ? Math.sin(w) : 0, + cw = w ? Math.cos(w) : 1, + trf = this.isCartesian ? [cw, sw, sw, -cw, x, y] + : [cw, sw, -sw, cw, x, y]; + this.setTrf(trf); // this.setTrf(unsizable ? this.concatTrf(this.unscaleTrf({x,y}),trf) : trf); + if (this.ctx.fillStyle === 'rgba(0, 0, 0, 0)') { + this.ctx.fillStyle = this.ctx.strokeStyle; + tmp.fs = 'transparent'; + } + this.ctx.fillText(str, 0, 0); + this.resetTrf(); + this.resetStyle(tmp); + }, + errorImageStr: "data:image/gif;base64,R0lGODlhHgAeAKIAAAAAmWZmmZnM/////8zMzGZmZgAAAAAAACwAAAAAHgAeAEADimi63P5ryAmEqHfqPRWfRQF+nEeeqImum0oJQxUThGaQ7hSs95ezvB4Q+BvihBSAclk6fgKiAkE0kE6RNqwkUBtMa1OpVlI0lsbmFjrdWbMH5Tdcu6wbf7J8YM9H4y0YAE0+dHVKIV0Efm5VGiEpY1A0UVMSBYtPGl1eNZhnEBGEck6jZ6WfoKmgCQA7", + images: Object.create(null), + async loadImage(uri) { + const download = async (xuri) => { + const pimg = new Promise((resolve, reject) => { + let img = new Image(); + img.src = xuri; + function error(err) { + img.removeEventListener('load', load); + img = undefined; + reject(err); + }; + function load() { + img.removeEventListener('error', error); + resolve(img); + img = undefined; + }; + img.addEventListener('error', error, { once: true }); + img.addEventListener('load', load, { once: true }); + }); + + try { + return await pimg; + } catch (err) { + // console.warn(`failed to (pre-)load image; '${xuri}'`, err); + if (xuri === this.errorImageStr) { + throw err; + } else { + return await download(this.errorImageStr); + } + } + } + + let img = this.images[uri]; + if (img !== undefined) { + return img instanceof Promise ? await img : img; + } + img = download(uri); + this.images[uri] = img; + try { + img = await img; + } finally { + this.images[uri] = img; + } + return img; + }, + async img({ uri, x = 0, y = 0, b, h, sx = 0, sy = 0, sb, sh, xoff = 0, yoff = 0, w = 0, scl = 1 }) { + const img_ = await this.loadImage(uri); + this.ctx.save(); + const cart = this.isCartesian ? -1 : 1; + sb = sb || img_.width; + b = b || img_.width; + sh = (sh || img_.height); + h = (h || img_.height) * cart; + yoff *= cart; + w *= cart; + y = this.isCartesian ? -(y / scl) + sy : y / scl; + const [cw, sw] = [Math.cos(w), Math.sin(w)]; + this.ctx.scale(scl, scl * cart); + this.ctx.transform(cw, sw, -sw, cw, x / scl, y); + this.ctx.drawImage(img_, sx, sy, sb, sh, xoff, yoff, b, h); + this.ctx.restore(); + }, + use({ grp }) { + this.beg(arguments[0]); + this.exe(grp.commands); + this.end(); + }, + beg({ w = 0, scl = 1, matrix/*,unsizable*/ } = {}) { + const { x = 0, y = 0 } = arguments[0].p !== undefined ? arguments[0].p : arguments[0]; + let trf = matrix; + if (!trf) { + let ssw, scw; + ssw = w ? Math.sin(w) * scl : 0; + scw = w ? Math.cos(w) * scl : scl; + trf = [scw, ssw, -ssw, scw, x, y]; + } + this.pushStyle(arguments[0]); + this.pushTrf(trf); // this.pushTrf(unsizable ? this.concatTrf(this.unscaleTrf({x,y}),trf) : trf); + }, + end() { + this.popTrf(); + this.popStyle(); + }, + p() { this.ctx.beginPath(); }, + z() { this.ctx.closePath(); }, + m({ x, y }) { this.ctx.moveTo(x, y); }, + l({ x, y }) { this.ctx.lineTo(x, y); }, + q({ x, y, x1, y1 }) { this.ctx.quadraticCurveTo(x1, y1, x, y); }, + c({ x, y, x1, y1, x2, y2 }) { this.ctx.bezierCurveTo(x1, y1, x2, y2, x, y); }, + a({ dw, k, phi, _xp, _yp }) { // todo: fix elliptical arc bug ... + const { x = 0, y = 0 } = arguments[0].p !== undefined ? arguments[0].p : arguments[0]; + if (k === undefined) k = 1; // ratio r1/r2 + if (Math.abs(dw) > Number.EPSILON) { + if (k === 1) { // circular arc ... + let x12 = x - _xp, y12 = y - _yp; + let tdw_2 = Math.tan(dw / 2), + rx = (x12 - y12 / tdw_2) / 2, ry = (y12 + x12 / tdw_2) / 2, + R = Math.hypot(rx, ry), + w = Math.atan2(-ry, -rx); + this.ctx.ellipse(_xp + rx, _yp + ry, R, R, 0, w, w + dw, this.cartesian ? dw > 0 : dw < 0); + } + else { // elliptical arc .. still buggy .. ! + if (phi === undefined) phi = 0; + let x1 = dw > 0 ? _xp : x, + y1 = dw > 0 ? _yp : y, + x2 = dw > 0 ? x : _xp, + y2 = dw > 0 ? y : _yp; + let x12 = x2 - x1, y12 = y2 - y1, + _dw = (dw < 0) ? dw : -dw; + // if (dw < 0) dw = -dw; // test for bugs .. ! + let cp = phi ? Math.cos(phi) : 1, sp = phi ? Math.sin(phi) : 0, + dx = -x12 * cp - y12 * sp, dy = -x12 * sp - y12 * cp, + sdw_2 = Math.sin(_dw / 2), + R = Math.sqrt((dx * dx + dy * dy / (k * k)) / (4 * sdw_2 * sdw_2)), + w = Math.atan2(k * dx, dy) - _dw / 2, + x0 = x1 - R * Math.cos(w), + y0 = y1 - R * k * Math.sin(w); + this.ctx.ellipse(x0, y0, R, R * k, phi, w, w + dw, this.cartesian ? dw > 0 : dw < 0); + } + } + else + this.ctx.lineTo(x, y); + }, + + stroke({ d } = {}) { + let tmp = this.setStyle(arguments[0]); + d ? this.ctx.stroke(new Path2D(d)) : this.ctx.stroke(); // SVG path syntax + this.resetStyle(tmp); + }, + fill({ d } = {}) { + let tmp = this.setStyle(arguments[0]); + d ? this.ctx.fill(new Path2D(d)) : this.ctx.fill(); // SVG path syntax + this.resetStyle(tmp); + }, + drw({ d, lsh } = {}) { + let ctx = this.ctx, + tmp = this.setStyle(arguments[0]), + p = d && new Path2D(d); // SVG path syntax + d ? ctx.fill(p) : ctx.fill(); + if (ctx.shadowColor !== 'rgba(0, 0, 0, 0)' && ctx.fillStyle !== 'rgba(0, 0, 0, 0)' && !lsh) { + let shc = ctx.shadowColor; // usually avoid stroke shadow when filling ... + ctx.shadowColor = 'rgba(0, 0, 0, 0)'; + d ? ctx.stroke(p) : ctx.stroke(); + ctx.shadowColor = shc; + } + else + d ? ctx.stroke(p) : ctx.stroke(); + this.resetStyle(tmp); + }, + + // State management (transform & style) + // getters & setters + get: { + fs: (ctx) => ctx.fillStyle, + ls: (ctx) => ctx.strokeStyle, + lw: (ctx) => ctx.lineWidth, + lc: (ctx) => ctx.lineCap, + lj: (ctx) => ctx.lineJoin, + ld: (ctx) => ctx.getLineDash(), + ldoff: (ctx) => ctx.lineDashOffset, + ml: (ctx) => ctx.miterLimit, + sh: (ctx) => [ctx.shadowOffsetX || 0, ctx.shadowOffsetY || 0, + ctx.shadowBlur || 0, ctx.shadowColor || 'black'], + font: (ctx) => ctx.font, + thal: (ctx) => ctx.textAlign, + tval: (ctx) => ctx.textBaseline, + }, + set: { + fs: (ctx, q) => { ctx.fillStyle = q; }, + ls: (ctx, q) => { ctx.strokeStyle = q; }, + lw: (ctx, q) => { ctx.lineWidth = q; }, + lc: (ctx, q) => { ctx.lineCap = q; }, + lj: (ctx, q) => { ctx.lineJoin = q; }, + ld: (ctx, q) => { ctx.setLineDash(q); }, + ldoff: (ctx, q) => { ctx.lineDashOffset = q; }, + ml: (ctx, q) => { ctx.miterLimit = q; }, + sh: (ctx, q) => { + if (q) { + ctx.shadowOffsetX = q[0] || 0; + ctx.shadowOffsetY = q[1] || 0; + ctx.shadowBlur = q[2] || 0; + ctx.shadowColor = q[3] || 'black'; + } + }, + font: (ctx, q) => { ctx.font = q; }, + thal: (ctx, q) => { ctx.textAlign = q; }, + tval: (ctx, q) => { ctx.textBaseline = q; } + }, + initStyle(style) { + for (const key in style) + if (this.get[key] && this.get[key](this.ctx) !== style[key]) + this.set[key](this.ctx, style[key]); + }, + setStyle(style) { // short circuit style setting + let q, prv = {}; + for (const key in style) { + if (this.get[key]) { // style keys only ... + let keyval = style[key]; + if (typeof style[key] === 'string' && style[key][0] === '@') { + // also check inherited styles ... + const ref = style[key].substr(1); + keyval = g2.symbol[ref] || ref in this.get && this.get[ref](this.ctx) + || ref in this.cur && this.cur[ref]; + } + if ((q = this.get[key](this.ctx)) !== keyval) { + prv[key] = q; + this.set[key](this.ctx, keyval); + } + } + } + return prv; + }, + resetStyle(style) { // short circuit style reset + for (const key in style) + this.set[key](this.ctx, style[key]); + }, + pushStyle(style) { + let cur = {}; // hold changed properties ... + for (const key in style) // allow extended style syntax ('fs-2', ...) + if (g2.styleRex.test(key)) { // (extended) style keys only ... + if (typeof style[key] === 'string' && style[key][0] === '@') { + let ref = style[key].substr(1); + style[key] = g2.symbol[ref] || this.get[ref] && this.get[ref](this.ctx); + } + if (this.cur[key] !== style[key]) { + if (key in this.set) + this.set[key](this.ctx, style[key]); + cur[key] = style[key]; + } + } + this.stack.push(this.cur = Object.assign({}, this.cur, cur)); + }, + popStyle() { + let cur = this.stack.pop(); + this.cur = this.stack[this.stack.length - 1]; + for (const key in this.cur) + if (this.get[key] && this.cur[key] !== cur[key]) + this.set[key](this.ctx, this.cur[key]); + }, + concatTrf(q, t) { + return [ + q[0] * t[0] + q[2] * t[1], + q[1] * t[0] + q[3] * t[1], + q[0] * t[2] + q[2] * t[3], + q[1] * t[2] + q[3] * t[3], + q[0] * t[4] + q[2] * t[5] + q[4], + q[1] * t[4] + q[3] * t[5] + q[5] + ]; + }, + initTrf() { + this.ctx.setTransform(...this.matrix[0]); + }, + setTrf(t) { + this.ctx.setTransform(...this.concatTrf(this.matrix[this.matrix.length - 1], t)); + }, + resetTrf() { + this.ctx.setTransform(...this.matrix[this.matrix.length - 1]); + }, + pushTrf(t) { + let q_t = this.concatTrf(this.matrix[this.matrix.length - 1], t); + this.matrix.push(q_t); + this.ctx.setTransform(...q_t); + }, + popTrf() { + this.matrix.pop(); + this.ctx.setTransform(...this.matrix[this.matrix.length - 1]); + }, + get isCartesian() { // det of mat2x2 < 0 ! + let m = this.matrix[this.matrix.length - 1]; + return m[0] * m[3] - m[1] * m[2] < 0; + }, + get uniTrf() { + let m = this.matrix[this.matrix.length - 1]; + return { x: m[4], y: m[5], scl: Math.hypot(m[0], m[1]), cartesian: m[0] * m[3] - m[1] * m[2] < 0 }; + }, + unscaleTrf({ x, y }) { // remove scaling effect (make unzoomable with respect to (x,y)) + let m = this.matrix[this.matrix.length - 1], + invscl = 1 / Math.hypot(m[0], m[1]); + return [invscl, 0, 0, invscl, (1 - invscl) * x, (1 - invscl) * y]; + }, + gridSize(scl) { + let base = this.gridBase, exp = this.gridExp, sz; + while ((sz = scl * base * Math.pow(10, exp)) < 14 || sz > 35) { + if (sz < 14) { + if (base == 1) base = 2; + else if (base == 2) base = 5; + else if (base == 5) { base = 1; exp++; } + } + else { + if (base == 1) { base = 5; exp--; } + else if (base == 2) base = 1; + else if (base == 5) base = 2; + } + } + this.gridBase = base; + this.gridExp = exp; + return sz; + } +} + /** * g2.io (c) 2017-18 Stefan Goessner * @license MIT License @@ -874,7 +1327,7 @@ g2 = Object.assign(g2, { "use strict" /** - * g2.ext (c) 2015-20 Stefan Goessner + * g2.ext (c) 2015-21 Stefan Goessner * @author Stefan Goessner * @license MIT License * @requires g2.core.js @@ -899,7 +1352,7 @@ g2.NONE = 0x0; g2.OVER = 0x1; g2.DRAG = 0x2; g2.EDIT = 0x4; * @property {object} [symbol.sqr] Predefined symbol: a little square * @property {string} [symbol.nodcolor=#333] node color. * @property {string} [symbol.nodfill=#dedede] node fill color. - * @property {string} [symbol.nodfill2=#aeaeae] alternate node fill color, somewhat darker. + * @property {string} [symbol.nodfill2=#aeaeae] alternate node fill color, somewhat darker. * @property {string} [symbol.linkcolor=#666] link color. * @property {string} [symbol.linkfill=rgba(225,225,225,0.75)] link fill color, semi-transparent. * @property {string} [symbol.dimcolor=darkslategray] dimension color. @@ -972,7 +1425,8 @@ g2.labelIfc = { const font = lbl.font || g2.defaultStyle.font; const h = parseInt(font); // font height (px assumed !) const str = this.getLabelString(); - const rx = (str.length || 1) * 0.75 * h / 2, ry = 1.25 * h / 2; // ellipse semi-axes length + const rx = (str.length || 1) * 0.65 * h / 2, + ry = 1.25 * h / 2; // ellipse semi-axes length const pos = this.pointAt(lbl.loc || this.lbloc || 'se'); const off = this.getLabelOffset(); const p = { @@ -1193,9 +1647,9 @@ g2.prototype.hdl.prototype = g2.mix(g2.prototype.cir.prototype, { get lsh() { return this.state & g2.OVER; }, get sh() { return this.state & g2.OVER ? [0, 0, 5, "black"] : false }, g2() { - const { x, y, r, b = 4, shape = 'cir', ls = 'black', fs = '#ccc', sh } = this; - return shape === 'cir' ? g2().cir({ x, y, r, ls, fs, sh }).ins((g) => this.label && this.drawLabel(g)) - : g2().rec({ x: x - b, y: y - b, b: 2 * b, h: 2 * b, ls, fs, sh }).ins((g) => this.label && this.drawLabel(g)); + const { x, y, r, b = 4, ls = 'black', fs = 'palegreen', sh } = this; + + return g2().cir({ x, y, r, ls, fs, sh }).ins((g) => this.label && this.drawLabel(g)); } }); @@ -1235,8 +1689,8 @@ g2.prototype.nod.prototype = g2.mix(g2.prototype.cir.prototype, { */ g2.prototype.dblnod = function ({ x = 0, y = 0 }) { return this.addCommand({ c: 'dblnod', a: arguments[0] }); } g2.prototype.dblnod.prototype = g2.mix(g2.prototype.cir.prototype, { - get r() { return 6; }, - get isSolid() { return true; }, + r: 6, + isSolid: true, g2() { return g2() .beg({ x: this.x, y: this.y }) @@ -1262,7 +1716,7 @@ g2.prototype.pol.prototype = g2.mix(g2.prototype.nod.prototype, { g2() { return g2() .beg(g2.flatten(this)) - .cir({ r: 6, fs: g2.symbol.nodfill }) + .cir({ r: 6, fs: '@fs2' }) .cir({ r: 2.5, fs: '@ls', ls: 'transparent' }) .end() .ins((g) => this.label && this.drawLabel(g)); @@ -2457,7 +2911,7 @@ const canvasInteractor = { }; /** - * g2.element.js (c) 2019-20 Stefan Goessner + * g2.element.js (c) 2019-21 Stefan Goessner * @license MIT License */ "use strict"; diff --git a/dist/g2.js b/dist/g2.js index 91f63c5..ac5e5eb 100644 --- a/dist/g2.js +++ b/dist/g2.js @@ -1,6 +1,6 @@ "use strict"; /** - * g2.core (c) 2013-20 Stefan Goessner + * g2.core (c) 2013-21 Stefan Goessner * @author Stefan Goessner * @license MIT License * @link https://github.com/goessner/g2 @@ -14,7 +14,7 @@ * .lin({x1:50,y1:50,x2:100,y2:100}) // Append ... * .lin({x1:100,y1:100,x2:200,y2:50}) // ... commands. * .exe(ctx); // Execute commands addressing canvas context. - */function g2(opts){let o=Object.create(g2.prototype);o.commands=[];if(opts)Object.assign(o,opts);return o}g2.prototype={clr(){return this.addCommand({c:"clr"})},view({scl:scl,x:x,y:y,cartesian:cartesian}){return this.addCommand({c:"view",a:arguments[0]})},grid({color:color,size:size}={}){return this.addCommand({c:"grid",a:arguments[0]})},cir({x:x,y:y,r:r,w:w}){return this.addCommand({c:"cir",a:arguments[0]})},ell({x:x,y:y,rx:rx,ry:ry,w:w,dw:dw,rot:rot}){return this.addCommand({c:"ell",a:arguments[0]})},arc({x:x,y:y,r:r,w:w,dw:dw}){return this.addCommand({c:"arc",a:arguments[0]})},rec({x:x,y:y,b:b,h:h}){return this.addCommand({c:"rec",a:arguments[0]})},lin({x1:x1,y1:y1,x2:x2,y2:y2}){return this.addCommand({c:"lin",a:arguments[0]})},ply({pts:pts,format:format,closed:closed,x:x,y:y,w:w}){arguments[0]._itr=format&&g2.pntIterator[format](pts)||g2.pntItrOf(pts);return this.addCommand({c:"ply",a:arguments[0]})},txt({str:str,x:x,y:y,w:w}){return this.addCommand({c:"txt",a:arguments[0]})},use({grp:grp,x:x,y:y,w:w,scl:scl}){if(grp&&grp!==this){if(typeof grp==="string")arguments[0].grp=g2.symbol[grp in g2.symbol?grp:"unknown"];this.addCommand({c:"use",a:arguments[0]})}return this},img({uri:uri,x:x,y:y,b:b,h:h,sx:sx,sy:sy,sb:sb,sh:sh,xoff:xoff,yoff:yoff,w:w,scl:scl}){return this.addCommand({c:"img",a:arguments[0]})},beg({x:x,y:y,w:w,scl:scl,matrix:matrix}={}){return this.addCommand({c:"beg",a:arguments[0]})},end(){let myBeg=1,findMyBeg=cmd=>{if(cmd.c==="beg")myBeg--;else if(cmd.c==="end")myBeg++;return myBeg===0};return g2.cmdIdxBy(this.commands,findMyBeg)!==false?this.addCommand({c:"end"}):this},p(){return this.addCommand({c:"p"})},z(){return this.addCommand({c:"z"})},m({x:x,y:y}){return this.addCommand({c:"m",a:arguments[0]})},l({x:x,y:y}){return this.addCommand({c:"l",a:arguments[0]})},q({x1:x1,y1:y1,x:x,y:y}){return this.addCommand({c:"q",a:arguments[0]})},c({x1:x1,y1:y1,x2:x2,y2:y2,x:x,y:y}){return this.addCommand({c:"c",a:arguments[0]})},a({dw:dw,x:x,y:y}){let prvcmd=this.commands[this.commands.length-1];g2.cpyProp(prvcmd.a,"x",arguments[0],"_xp");g2.cpyProp(prvcmd.a,"y",arguments[0],"_yp");return this.addCommand({c:"a",a:arguments[0]})},stroke({d:d}={}){return this.addCommand({c:"stroke",a:arguments[0]})},fill({d:d}={}){return this.addCommand({c:"fill",a:arguments[0]})},drw({d:d,lsh:lsh}={}){return this.addCommand({c:"drw",a:arguments[0]})},del(idx){this.commands.length=idx||0;return this},ins(arg){return typeof arg==="function"?arg(this)||this:typeof arg==="object"?(this.commands.push({a:arg}),this):this},exe(ctx){let handler=g2.handler(ctx);if(handler&&handler.init(this))handler.exe(this.commands);return this},addCommand({c:c,a:a}){if(a&&Object.getPrototypeOf(a)===Object.prototype){for(const key in a){if(!Object.getOwnPropertyDescriptor(a,key).get&&key[0]!=="_"&&typeof a[key]==="function"){Object.defineProperty(a,key,{get:a[key],enumerable:true,configurable:true,writabel:false})}if(typeof a[key]==="string"&&a[key][0]==="@"){const refidIdx=a[key].indexOf(".");const refid=refidIdx>0?a[key].substr(1,refidIdx-1):"";const refkey=refid?a[key].substr(refidIdx+1):"";const refcmd=refid?()=>this.commands.find(cmd=>cmd.a&&cmd.a.id===refid):undefined;if(refcmd)Object.defineProperty(a,key,{get:function(){const rc=refcmd();return rc&&refkey in rc.a?rc.a[refkey]:0},enumerable:true,configurable:true,writabel:false})}}if(g2.prototype[c].prototype)Object.setPrototypeOf(a,g2.prototype[c].prototype)}this.commands.push(arguments[0]);return this}};g2.defaultStyle={fs:"transparent",ls:"#000",lw:1,lc:"butt",lj:"miter",ld:[],ml:10,sh:[0,0],lsh:false,font:"14px serif",thal:"start",tval:"alphabetic"};g2.symbol={unknown:g2().cir({r:12,fs:"orange"}).txt({str:"?",thal:"center",tval:"middle",font:"bold 20pt serif"})};g2.handler=function(ctx){let hdl;for(let h of g2.handler.factory)if((hdl=h(ctx))!==false)return hdl;return false};g2.handler.factory=[];g2.pntIterator={"x,y":function(pts){function pitr(i){return{x:pts[2*i],y:pts[2*i+1]}}Object.defineProperty(pitr,"len",{get:()=>pts.length/2,enumerable:true,configurable:true,writabel:false});return pitr},"[x,y]":function(pts){function pitr(i){return pts[i]?{x:pts[i][0],y:pts[i][1]}:undefined}Object.defineProperty(pitr,"len",{get:()=>pts.length,enumerable:true,configurable:true,writabel:false});return pitr},"{x,y}":function(pts){function pitr(i){return pts[i]}Object.defineProperty(pitr,"len",{get:()=>pts.length,enumerable:true,configurable:true,writabel:false});return pitr}};g2.pntItrOf=function(pts){return!(pts&&pts.length)?undefined:typeof pts[0]==="number"?g2.pntIterator["x,y"](pts):Array.isArray(pts[0])&&pts[0].length>=2?g2.pntIterator["[x,y]"](pts):typeof pts[0]==="object"&&"x"in pts[0]&&"y"in pts[0]?g2.pntIterator["{x,y}"](pts):undefined};g2.cmdIdxBy=function(cmds,callbk){for(let i=cmds.length-1;i>=0;i--)if(callbk(cmds[i],i,cmds))return i;return false};g2.mix=function mix(...protos){let mixture={};for(const p of protos)mixture=Object.defineProperties(mixture,Object.getOwnPropertyDescriptors(p));return mixture};g2.cpyProp=function(from,fromKey,to,toKey){Object.defineProperty(to,toKey,Object.getOwnPropertyDescriptor(from,fromKey))};g2.canvasHdl=function(ctx){if(this instanceof g2.canvasHdl){if(ctx instanceof CanvasRenderingContext2D){this.ctx=ctx;this.cur=g2.defaultStyle;this.stack=[this.cur];this.matrix=[[1,0,0,1,.5,.5]];this.gridBase=2;this.gridExp=1;return this}else return null}return g2.canvasHdl.apply(Object.create(g2.canvasHdl.prototype),arguments)};g2.handler.factory.push(ctx=>ctx instanceof g2.canvasHdl?ctx:ctx instanceof CanvasRenderingContext2D?g2.canvasHdl(ctx):false);g2.canvasHdl.prototype={init(grp,style){this.stack.length=1;this.matrix.length=1;this.initStyle(style?Object.assign({},this.cur,style):this.cur);return true},async exe(commands){for(let cmd of commands){if(cmd.a&&cmd.a.g2){const cmds=cmd.a.g2().commands;if(cmds){this.exe(cmds);continue}}else if(cmd.a&&cmd.a.commands){this.exe(cmd.a.commands);continue}if(cmd.c&&this[cmd.c]){const rx=this[cmd.c](cmd.a);if(rx&&rx instanceof Promise){await rx}}}},view({x:x=0,y:y=0,scl:scl=1,cartesian:cartesian=false}){this.pushTrf(cartesian?[scl,0,0,-scl,x,this.ctx.canvas.height-1-y]:[scl,0,0,scl,x,y])},grid({color:color="#ccc",size:size}={}){let ctx=this.ctx,b=ctx.canvas.width,h=ctx.canvas.height,{x:x,y:y,scl:scl}=this.uniTrf,sz=size||this.gridSize(scl),xoff=x%sz,yoff=y%sz;ctx.save();ctx.setTransform(1,0,0,1,0,0);ctx.strokeStyle=color;ctx.lineWidth=1;ctx.beginPath();for(let x=xoff,nx=b+1;xNumber.EPSILON&&Math.abs(r)>Number.EPSILON){this.ctx.beginPath();this.ctx.arc(x,y,Math.abs(r),w,w+dw,dw<0);this.drw(arguments[0])}else if(Math.abs(dw)Number.EPSILON){const cw=Math.cos(w),sw=Math.sin(w);this.ctx.beginPath();this.ctx.moveTo(x-r*cw,y-r*sw);this.ctx.lineTo(x+r*cw,y+r*sw)}},ell({rx:rx,ry:ry,w:w=0,dw:dw=2*Math.PI,rot:rot=0}){const{x:x=0,y:y=0}=arguments[0].p!==undefined?arguments[0].p:arguments[0];this.ctx.beginPath();this.ctx.ellipse(x,y,Math.abs(rx),Math.abs(ry),rot,w,w+dw,dw<0);this.drw(arguments[0])},rec({b:b,h:h}){const{x:x=0,y:y=0}=arguments[0].p!==undefined?arguments[0].p:arguments[0];const tmp=this.setStyle(arguments[0]);this.ctx.fillRect(x,y,b,h);this.ctx.strokeRect(x,y,b,h);this.resetStyle(tmp)},lin(args){this.ctx.beginPath();this.ctx.moveTo(args.p1&&args.p1.x||args.x1||0,args.p1&&args.p1.y||args.y1||0);this.ctx.lineTo(args.p2&&args.p2.x||args.x2||0,args.p2&&args.p2.y||args.y2||0);this.stroke(args)},ply({pts:pts,closed:closed,w:w=0,_itr:_itr}){if(_itr&&_itr.len){const{x:x=0,y:y=0}=arguments[0].p!==undefined?arguments[0].p:arguments[0];let p,i,len=_itr.len,istrf=!!(x||y||w),cw,sw;if(istrf)this.setTrf([cw=w?Math.cos(w):1,sw=w?Math.sin(w):0,-sw,cw,x,y]);this.ctx.beginPath();this.ctx.moveTo((p=_itr(0)).x,p.y);for(i=1;i{const pimg=new Promise((resolve,reject)=>{let img=new Image;img.src=xuri;function error(err){img.removeEventListener("load",load);img=undefined;reject(err)}function load(){img.removeEventListener("error",error);resolve(img);img=undefined}img.addEventListener("error",error,{once:true});img.addEventListener("load",load,{once:true})});try{return await pimg}catch(err){if(xuri===this.errorImageStr){throw err}else{return await download(this.errorImageStr)}}};let img=this.images[uri];if(img!==undefined){return img instanceof Promise?await img:img}img=download(uri);this.images[uri]=img;try{img=await img}finally{this.images[uri]=img}return img},async img({uri:uri,x:x=0,y:y=0,b:b,h:h,sx:sx=0,sy:sy=0,sb:sb,sh:sh,xoff:xoff=0,yoff:yoff=0,w:w=0,scl:scl=1}){const img_=await this.loadImage(uri);this.ctx.save();const cart=this.isCartesian?-1:1;sb=sb||img_.width;b=b||img_.width;sh=sh||img_.height;h=(h||img_.height)*cart;yoff*=cart;w*=cart;y=this.isCartesian?-(y/scl)+sy:y/scl;const[cw,sw]=[Math.cos(w),Math.sin(w)];this.ctx.scale(scl,scl*cart);this.ctx.transform(cw,sw,-sw,cw,x/scl,y);this.ctx.drawImage(img_,sx,sy,sb,sh,xoff,yoff,b,h);this.ctx.restore()},use({grp:grp}){this.beg(arguments[0]);this.exe(grp.commands);this.end()},beg({w:w=0,scl:scl=1,matrix:matrix}={}){const{x:x=0,y:y=0}=arguments[0].p!==undefined?arguments[0].p:arguments[0];let trf=matrix;if(!trf){let ssw,scw;ssw=w?Math.sin(w)*scl:0;scw=w?Math.cos(w)*scl:scl;trf=[scw,ssw,-ssw,scw,x,y]}this.pushStyle(arguments[0]);this.pushTrf(trf)},end(){this.popTrf();this.popStyle()},p(){this.ctx.beginPath()},z(){this.ctx.closePath()},m({x:x,y:y}){this.ctx.moveTo(x,y)},l({x:x,y:y}){this.ctx.lineTo(x,y)},q({x:x,y:y,x1:x1,y1:y1}){this.ctx.quadraticCurveTo(x1,y1,x,y)},c({x:x,y:y,x1:x1,y1:y1,x2:x2,y2:y2}){this.ctx.bezierCurveTo(x1,y1,x2,y2,x,y)},a({dw:dw,k:k,phi:phi,_xp:_xp,_yp:_yp}){const{x:x=0,y:y=0}=arguments[0].p!==undefined?arguments[0].p:arguments[0];if(k===undefined)k=1;if(Math.abs(dw)>Number.EPSILON){if(k===1){let x12=x-_xp,y12=y-_yp;let tdw_2=Math.tan(dw/2),rx=(x12-y12/tdw_2)/2,ry=(y12+x12/tdw_2)/2,R=Math.hypot(rx,ry),w=Math.atan2(-ry,-rx);this.ctx.ellipse(_xp+rx,_yp+ry,R,R,0,w,w+dw,this.cartesian?dw>0:dw<0)}else{if(phi===undefined)phi=0;let x1=dw>0?_xp:x,y1=dw>0?_yp:y,x2=dw>0?x:_xp,y2=dw>0?y:_yp;let x12=x2-x1,y12=y2-y1,_dw=dw<0?dw:-dw;let cp=phi?Math.cos(phi):1,sp=phi?Math.sin(phi):0,dx=-x12*cp-y12*sp,dy=-x12*sp-y12*cp,sdw_2=Math.sin(_dw/2),R=Math.sqrt((dx*dx+dy*dy/(k*k))/(4*sdw_2*sdw_2)),w=Math.atan2(k*dx,dy)-_dw/2,x0=x1-R*Math.cos(w),y0=y1-R*k*Math.sin(w);this.ctx.ellipse(x0,y0,R,R*k,phi,w,w+dw,this.cartesian?dw>0:dw<0)}}else this.ctx.lineTo(x,y)},stroke({d:d}={}){let tmp=this.setStyle(arguments[0]);d?this.ctx.stroke(new Path2D(d)):this.ctx.stroke();this.resetStyle(tmp)},fill({d:d}={}){let tmp=this.setStyle(arguments[0]);d?this.ctx.fill(new Path2D(d)):this.ctx.fill();this.resetStyle(tmp)},drw({d:d,lsh:lsh}={}){let ctx=this.ctx,tmp=this.setStyle(arguments[0]),p=d&&new Path2D(d);d?ctx.fill(p):ctx.fill();if(ctx.shadowColor!=="rgba(0, 0, 0, 0)"&&ctx.fillStyle!=="rgba(0, 0, 0, 0)"&&!lsh){let shc=ctx.shadowColor;ctx.shadowColor="rgba(0, 0, 0, 0)";d?ctx.stroke(p):ctx.stroke();ctx.shadowColor=shc}else d?ctx.stroke(p):ctx.stroke();this.resetStyle(tmp)},get:{fs:ctx=>ctx.fillStyle,ls:ctx=>ctx.strokeStyle,lw:ctx=>ctx.lineWidth,lc:ctx=>ctx.lineCap,lj:ctx=>ctx.lineJoin,ld:ctx=>ctx.getLineDash(),ldoff:ctx=>ctx.lineDashOffset,ml:ctx=>ctx.miterLimit,sh:ctx=>[ctx.shadowOffsetX||0,ctx.shadowOffsetY||0,ctx.shadowBlur||0,ctx.shadowColor||"black"],font:ctx=>ctx.font,thal:ctx=>ctx.textAlign,tval:ctx=>ctx.textBaseline},set:{fs:(ctx,q)=>{ctx.fillStyle=q},ls:(ctx,q)=>{ctx.strokeStyle=q},lw:(ctx,q)=>{ctx.lineWidth=q},lc:(ctx,q)=>{ctx.lineCap=q},lj:(ctx,q)=>{ctx.lineJoin=q},ld:(ctx,q)=>{ctx.setLineDash(q)},ldoff:(ctx,q)=>{ctx.lineDashOffset=q},ml:(ctx,q)=>{ctx.miterLimit=q},sh:(ctx,q)=>{if(q){ctx.shadowOffsetX=q[0]||0;ctx.shadowOffsetY=q[1]||0;ctx.shadowBlur=q[2]||0;ctx.shadowColor=q[3]||"black"}},font:(ctx,q)=>{ctx.font=q},thal:(ctx,q)=>{ctx.textAlign=q},tval:(ctx,q)=>{ctx.textBaseline=q}},initStyle(style){for(const key in style)if(this.get[key]&&this.get[key](this.ctx)!==style[key])this.set[key](this.ctx,style[key])},setStyle(style){let q,prv={};for(const key in style){if(this.get[key]){if(typeof style[key]==="string"&&style[key][0]==="@"){let ref=style[key].substr(1);style[key]=g2.symbol[ref]||this.get[ref]&&this.get[ref](this.ctx)}if((q=this.get[key](this.ctx))!==style[key]){prv[key]=q;this.set[key](this.ctx,style[key])}}}return prv},resetStyle(style){for(const key in style)this.set[key](this.ctx,style[key])},pushStyle(style){let cur={};for(const key in style)if(this.get[key]){if(typeof style[key]==="string"&&style[key][0]==="@"){let ref=style[key].substr(1);style[key]=g2.symbol[ref]||this.get[ref]&&this.get[ref](this.ctx)}if(this.cur[key]!==style[key])this.set[key](this.ctx,cur[key]=style[key])}this.stack.push(this.cur=Object.assign({},this.cur,cur))},popStyle(){let cur=this.stack.pop();this.cur=this.stack[this.stack.length-1];for(const key in this.cur)if(this.get[key]&&this.cur[key]!==cur[key])this.set[key](this.ctx,this.cur[key])},concatTrf(q,t){return[q[0]*t[0]+q[2]*t[1],q[1]*t[0]+q[3]*t[1],q[0]*t[2]+q[2]*t[3],q[1]*t[2]+q[3]*t[3],q[0]*t[4]+q[2]*t[5]+q[4],q[1]*t[4]+q[3]*t[5]+q[5]]},initTrf(){this.ctx.setTransform(...this.matrix[0])},setTrf(t){this.ctx.setTransform(...this.concatTrf(this.matrix[this.matrix.length-1],t))},resetTrf(){this.ctx.setTransform(...this.matrix[this.matrix.length-1])},pushTrf(t){let q_t=this.concatTrf(this.matrix[this.matrix.length-1],t);this.matrix.push(q_t);this.ctx.setTransform(...q_t)},popTrf(){this.matrix.pop();this.ctx.setTransform(...this.matrix[this.matrix.length-1])},get isCartesian(){let m=this.matrix[this.matrix.length-1];return m[0]*m[3]-m[1]*m[2]<0},get uniTrf(){let m=this.matrix[this.matrix.length-1];return{x:m[4],y:m[5],scl:Math.hypot(m[0],m[1]),cartesian:m[0]*m[3]-m[1]*m[2]<0}},unscaleTrf({x:x,y:y}){let m=this.matrix[this.matrix.length-1],invscl=1/Math.hypot(m[0],m[1]);return[invscl,0,0,invscl,(1-invscl)*x,(1-invscl)*y]},gridSize(scl){let base=this.gridBase,exp=this.gridExp,sz;while((sz=scl*base*Math.pow(10,exp))<14||sz>35){if(sz<14){if(base==1)base=2;else if(base==2)base=5;else if(base==5){base=1;exp++}}else{if(base==1){base=5;exp--}else if(base==2)base=1;else if(base==5)base=2}}this.gridBase=base;this.gridExp=exp;return sz}};if(typeof module!=="undefined")module.exports=g2; + */function g2(opts){let o=Object.create(g2.prototype);o.commands=[];if(opts)Object.assign(o,opts);return o}g2.prototype={clr(){return this.addCommand({c:"clr"})},view({scl:scl,x:x,y:y,cartesian:cartesian}){return this.addCommand({c:"view",a:arguments[0]})},grid({color:color,size:size}={}){return this.addCommand({c:"grid",a:arguments[0]})},cir({x:x,y:y,r:r,w:w}){return this.addCommand({c:"cir",a:arguments[0]})},ell({x:x,y:y,rx:rx,ry:ry,w:w,dw:dw,rot:rot}){return this.addCommand({c:"ell",a:arguments[0]})},arc({x:x,y:y,r:r,w:w,dw:dw}){return this.addCommand({c:"arc",a:arguments[0]})},rec({x:x,y:y,b:b,h:h}){return this.addCommand({c:"rec",a:arguments[0]})},lin({x1:x1,y1:y1,x2:x2,y2:y2}){return this.addCommand({c:"lin",a:arguments[0]})},ply({pts:pts,format:format,closed:closed,x:x,y:y,w:w}){arguments[0]._itr=format&&g2.pntIterator[format](pts)||g2.pntItrOf(pts);return this.addCommand({c:"ply",a:arguments[0]})},txt({str:str,x:x,y:y,w:w}){return this.addCommand({c:"txt",a:arguments[0]})},use({grp:grp,x:x,y:y,w:w,scl:scl}){if(grp&&grp!==this){if(typeof grp==="string")arguments[0].grp=g2.symbol[grp in g2.symbol?grp:"unknown"];this.addCommand({c:"use",a:arguments[0]})}return this},img({uri:uri,x:x,y:y,b:b,h:h,sx:sx,sy:sy,sb:sb,sh:sh,xoff:xoff,yoff:yoff,w:w,scl:scl}){return this.addCommand({c:"img",a:arguments[0]})},beg({x:x,y:y,w:w,scl:scl,matrix:matrix}={}){return this.addCommand({c:"beg",a:arguments[0]})},end(){let myBeg=1,findMyBeg=cmd=>{if(cmd.c==="beg")myBeg--;else if(cmd.c==="end")myBeg++;return myBeg===0};return g2.cmdIdxBy(this.commands,findMyBeg)!==false?this.addCommand({c:"end"}):this},p(){return this.addCommand({c:"p"})},z(){return this.addCommand({c:"z"})},m({x:x,y:y}){return this.addCommand({c:"m",a:arguments[0]})},l({x:x,y:y}){return this.addCommand({c:"l",a:arguments[0]})},q({x1:x1,y1:y1,x:x,y:y}){return this.addCommand({c:"q",a:arguments[0]})},c({x1:x1,y1:y1,x2:x2,y2:y2,x:x,y:y}){return this.addCommand({c:"c",a:arguments[0]})},a({dw:dw,x:x,y:y}){let prvcmd=this.commands[this.commands.length-1];g2.cpyProp(prvcmd.a,"x",arguments[0],"_xp");g2.cpyProp(prvcmd.a,"y",arguments[0],"_yp");return this.addCommand({c:"a",a:arguments[0]})},stroke({d:d}={}){return this.addCommand({c:"stroke",a:arguments[0]})},fill({d:d}={}){return this.addCommand({c:"fill",a:arguments[0]})},drw({d:d,lsh:lsh}={}){return this.addCommand({c:"drw",a:arguments[0]})},del(idx){this.commands.length=idx||0;return this},ins(arg){return typeof arg==="function"?arg(this)||this:typeof arg==="object"?(this.commands.push({a:arg}),this):this},exe(ctx){let handler=g2.handler(ctx);if(handler&&handler.init(this))handler.exe(this.commands);return this},addCommand({c:c,a:a}){if(a&&Object.getPrototypeOf(a)===Object.prototype){for(const key in a){if(!Object.getOwnPropertyDescriptor(a,key).get&&key[0]!=="_"&&typeof a[key]==="function"){Object.defineProperty(a,key,{get:a[key],enumerable:true,configurable:true,writabel:false})}if(typeof a[key]==="string"&&a[key][0]==="@"){const refidIdx=a[key].indexOf(".");const refid=refidIdx>0?a[key].substr(1,refidIdx-1):"";const refkey=refid?a[key].substr(refidIdx+1):"";const refcmd=refid?()=>this.commands.find(cmd=>cmd.a&&cmd.a.id===refid):undefined;if(refcmd)Object.defineProperty(a,key,{get:function(){const rc=refcmd();return rc&&refkey in rc.a?rc.a[refkey]:0},enumerable:true,configurable:true,writabel:false})}}if(g2.prototype[c].prototype)Object.setPrototypeOf(a,g2.prototype[c].prototype)}this.commands.push(arguments[0]);return this}};g2.defaultStyle={fs:"transparent",ls:"#000",lw:1,lc:"butt",lj:"miter",ld:[],ml:10,sh:[0,0],lsh:false,font:"14px serif",thal:"start",tval:"alphabetic"};g2.styleRex=/^(fs|ls|lw|lc|lj|ld|ldoff|ml|sh|lsh|font|thal|tval)([-0-9].*)?$/,g2.symbol={unknown:g2().cir({r:12,fs:"orange"}).txt({str:"?",thal:"center",tval:"middle",font:"bold 20pt serif"})};g2.handler=function(ctx){let hdl;for(let h of g2.handler.factory)if((hdl=h(ctx))!==false)return hdl;return false};g2.handler.factory=[];g2.pntIterator={"x,y":function(pts){function pitr(i){return{x:pts[2*i],y:pts[2*i+1]}}Object.defineProperty(pitr,"len",{get:()=>pts.length/2,enumerable:true,configurable:true,writabel:false});return pitr},"[x,y]":function(pts){function pitr(i){return pts[i]?{x:pts[i][0],y:pts[i][1]}:undefined}Object.defineProperty(pitr,"len",{get:()=>pts.length,enumerable:true,configurable:true,writabel:false});return pitr},"{x,y}":function(pts){function pitr(i){return pts[i]}Object.defineProperty(pitr,"len",{get:()=>pts.length,enumerable:true,configurable:true,writabel:false});return pitr}};g2.pntItrOf=function(pts){return!(pts&&pts.length)?undefined:typeof pts[0]==="number"?g2.pntIterator["x,y"](pts):Array.isArray(pts[0])&&pts[0].length>=2?g2.pntIterator["[x,y]"](pts):typeof pts[0]==="object"&&"x"in pts[0]&&"y"in pts[0]?g2.pntIterator["{x,y}"](pts):undefined};g2.cmdIdxBy=function(cmds,callbk){for(let i=cmds.length-1;i>=0;i--)if(callbk(cmds[i],i,cmds))return i;return false};g2.mix=function mix(...protos){let mixture={};for(const p of protos)mixture=Object.defineProperties(mixture,Object.getOwnPropertyDescriptors(p));return mixture};g2.cpyProp=function(from,fromKey,to,toKey){Object.defineProperty(to,toKey,Object.getOwnPropertyDescriptor(from,fromKey))};g2.canvasHdl=function(ctx){if(this instanceof g2.canvasHdl){if(ctx instanceof CanvasRenderingContext2D){this.ctx=ctx;this.cur=g2.defaultStyle;this.stack=[this.cur];this.matrix=[[1,0,0,1,.5,.5]];this.gridBase=2;this.gridExp=1;return this}else return null}return g2.canvasHdl.apply(Object.create(g2.canvasHdl.prototype),arguments)};g2.handler.factory.push(ctx=>ctx instanceof g2.canvasHdl?ctx:ctx instanceof CanvasRenderingContext2D?g2.canvasHdl(ctx):false);g2.canvasHdl.prototype={init(grp,style){this.stack.length=1;this.matrix.length=1;this.initStyle(style?Object.assign({},this.cur,style):this.cur);return true},async exe(commands){for(let cmd of commands){if(cmd.a&&cmd.a.g2){const cmds=cmd.a.g2().commands;if(cmds){this.exe(cmds);continue}}else if(cmd.a&&cmd.a.commands){this.exe(cmd.a.commands);continue}if(cmd.c&&this[cmd.c]){const rx=this[cmd.c](cmd.a);if(rx&&rx instanceof Promise){await rx}}}},view({x:x=0,y:y=0,scl:scl=1,cartesian:cartesian=false}){this.pushTrf(cartesian?[scl,0,0,-scl,x,this.ctx.canvas.height-1-y]:[scl,0,0,scl,x,y])},grid({color:color="#ccc",size:size}={}){let ctx=this.ctx,b=ctx.canvas.width,h=ctx.canvas.height,{x:x,y:y,scl:scl}=this.uniTrf,sz=size||this.gridSize(scl),xoff=x%sz,yoff=y%sz;ctx.save();ctx.setTransform(1,0,0,1,0,0);ctx.strokeStyle=color;ctx.lineWidth=1;ctx.beginPath();for(let x=xoff,nx=b+1;xNumber.EPSILON&&Math.abs(r)>Number.EPSILON){this.ctx.beginPath();this.ctx.arc(x,y,Math.abs(r),w,w+dw,dw<0);this.drw(arguments[0])}else if(Math.abs(dw)Number.EPSILON){const cw=Math.cos(w),sw=Math.sin(w);this.ctx.beginPath();this.ctx.moveTo(x-r*cw,y-r*sw);this.ctx.lineTo(x+r*cw,y+r*sw)}},ell({rx:rx,ry:ry,w:w=0,dw:dw=2*Math.PI,rot:rot=0}){const{x:x=0,y:y=0}=arguments[0].p!==undefined?arguments[0].p:arguments[0];this.ctx.beginPath();this.ctx.ellipse(x,y,Math.abs(rx),Math.abs(ry),rot,w,w+dw,dw<0);this.drw(arguments[0])},rec({b:b,h:h}){const{x:x=0,y:y=0}=arguments[0].p!==undefined?arguments[0].p:arguments[0];const tmp=this.setStyle(arguments[0]);this.ctx.fillRect(x,y,b,h);this.ctx.strokeRect(x,y,b,h);this.resetStyle(tmp)},lin(args){this.ctx.beginPath();this.ctx.moveTo(args.p1&&args.p1.x||args.x1||0,args.p1&&args.p1.y||args.y1||0);this.ctx.lineTo(args.p2&&args.p2.x||args.x2||0,args.p2&&args.p2.y||args.y2||0);this.stroke(args)},ply({pts:pts,closed:closed,w:w=0,_itr:_itr}){if(_itr&&_itr.len){const{x:x=0,y:y=0}=arguments[0].p!==undefined?arguments[0].p:arguments[0];let p,i,len=_itr.len,istrf=!!(x||y||w),cw,sw;if(istrf)this.setTrf([cw=w?Math.cos(w):1,sw=w?Math.sin(w):0,-sw,cw,x,y]);this.ctx.beginPath();this.ctx.moveTo((p=_itr(0)).x,p.y);for(i=1;i{const pimg=new Promise((resolve,reject)=>{let img=new Image;img.src=xuri;function error(err){img.removeEventListener("load",load);img=undefined;reject(err)}function load(){img.removeEventListener("error",error);resolve(img);img=undefined}img.addEventListener("error",error,{once:true});img.addEventListener("load",load,{once:true})});try{return await pimg}catch(err){if(xuri===this.errorImageStr){throw err}else{return await download(this.errorImageStr)}}};let img=this.images[uri];if(img!==undefined){return img instanceof Promise?await img:img}img=download(uri);this.images[uri]=img;try{img=await img}finally{this.images[uri]=img}return img},async img({uri:uri,x:x=0,y:y=0,b:b,h:h,sx:sx=0,sy:sy=0,sb:sb,sh:sh,xoff:xoff=0,yoff:yoff=0,w:w=0,scl:scl=1}){const img_=await this.loadImage(uri);this.ctx.save();const cart=this.isCartesian?-1:1;sb=sb||img_.width;b=b||img_.width;sh=sh||img_.height;h=(h||img_.height)*cart;yoff*=cart;w*=cart;y=this.isCartesian?-(y/scl)+sy:y/scl;const[cw,sw]=[Math.cos(w),Math.sin(w)];this.ctx.scale(scl,scl*cart);this.ctx.transform(cw,sw,-sw,cw,x/scl,y);this.ctx.drawImage(img_,sx,sy,sb,sh,xoff,yoff,b,h);this.ctx.restore()},use({grp:grp}){this.beg(arguments[0]);this.exe(grp.commands);this.end()},beg({w:w=0,scl:scl=1,matrix:matrix}={}){const{x:x=0,y:y=0}=arguments[0].p!==undefined?arguments[0].p:arguments[0];let trf=matrix;if(!trf){let ssw,scw;ssw=w?Math.sin(w)*scl:0;scw=w?Math.cos(w)*scl:scl;trf=[scw,ssw,-ssw,scw,x,y]}this.pushStyle(arguments[0]);this.pushTrf(trf)},end(){this.popTrf();this.popStyle()},p(){this.ctx.beginPath()},z(){this.ctx.closePath()},m({x:x,y:y}){this.ctx.moveTo(x,y)},l({x:x,y:y}){this.ctx.lineTo(x,y)},q({x:x,y:y,x1:x1,y1:y1}){this.ctx.quadraticCurveTo(x1,y1,x,y)},c({x:x,y:y,x1:x1,y1:y1,x2:x2,y2:y2}){this.ctx.bezierCurveTo(x1,y1,x2,y2,x,y)},a({dw:dw,k:k,phi:phi,_xp:_xp,_yp:_yp}){const{x:x=0,y:y=0}=arguments[0].p!==undefined?arguments[0].p:arguments[0];if(k===undefined)k=1;if(Math.abs(dw)>Number.EPSILON){if(k===1){let x12=x-_xp,y12=y-_yp;let tdw_2=Math.tan(dw/2),rx=(x12-y12/tdw_2)/2,ry=(y12+x12/tdw_2)/2,R=Math.hypot(rx,ry),w=Math.atan2(-ry,-rx);this.ctx.ellipse(_xp+rx,_yp+ry,R,R,0,w,w+dw,this.cartesian?dw>0:dw<0)}else{if(phi===undefined)phi=0;let x1=dw>0?_xp:x,y1=dw>0?_yp:y,x2=dw>0?x:_xp,y2=dw>0?y:_yp;let x12=x2-x1,y12=y2-y1,_dw=dw<0?dw:-dw;let cp=phi?Math.cos(phi):1,sp=phi?Math.sin(phi):0,dx=-x12*cp-y12*sp,dy=-x12*sp-y12*cp,sdw_2=Math.sin(_dw/2),R=Math.sqrt((dx*dx+dy*dy/(k*k))/(4*sdw_2*sdw_2)),w=Math.atan2(k*dx,dy)-_dw/2,x0=x1-R*Math.cos(w),y0=y1-R*k*Math.sin(w);this.ctx.ellipse(x0,y0,R,R*k,phi,w,w+dw,this.cartesian?dw>0:dw<0)}}else this.ctx.lineTo(x,y)},stroke({d:d}={}){let tmp=this.setStyle(arguments[0]);d?this.ctx.stroke(new Path2D(d)):this.ctx.stroke();this.resetStyle(tmp)},fill({d:d}={}){let tmp=this.setStyle(arguments[0]);d?this.ctx.fill(new Path2D(d)):this.ctx.fill();this.resetStyle(tmp)},drw({d:d,lsh:lsh}={}){let ctx=this.ctx,tmp=this.setStyle(arguments[0]),p=d&&new Path2D(d);d?ctx.fill(p):ctx.fill();if(ctx.shadowColor!=="rgba(0, 0, 0, 0)"&&ctx.fillStyle!=="rgba(0, 0, 0, 0)"&&!lsh){let shc=ctx.shadowColor;ctx.shadowColor="rgba(0, 0, 0, 0)";d?ctx.stroke(p):ctx.stroke();ctx.shadowColor=shc}else d?ctx.stroke(p):ctx.stroke();this.resetStyle(tmp)},get:{fs:ctx=>ctx.fillStyle,ls:ctx=>ctx.strokeStyle,lw:ctx=>ctx.lineWidth,lc:ctx=>ctx.lineCap,lj:ctx=>ctx.lineJoin,ld:ctx=>ctx.getLineDash(),ldoff:ctx=>ctx.lineDashOffset,ml:ctx=>ctx.miterLimit,sh:ctx=>[ctx.shadowOffsetX||0,ctx.shadowOffsetY||0,ctx.shadowBlur||0,ctx.shadowColor||"black"],font:ctx=>ctx.font,thal:ctx=>ctx.textAlign,tval:ctx=>ctx.textBaseline},set:{fs:(ctx,q)=>{ctx.fillStyle=q},ls:(ctx,q)=>{ctx.strokeStyle=q},lw:(ctx,q)=>{ctx.lineWidth=q},lc:(ctx,q)=>{ctx.lineCap=q},lj:(ctx,q)=>{ctx.lineJoin=q},ld:(ctx,q)=>{ctx.setLineDash(q)},ldoff:(ctx,q)=>{ctx.lineDashOffset=q},ml:(ctx,q)=>{ctx.miterLimit=q},sh:(ctx,q)=>{if(q){ctx.shadowOffsetX=q[0]||0;ctx.shadowOffsetY=q[1]||0;ctx.shadowBlur=q[2]||0;ctx.shadowColor=q[3]||"black"}},font:(ctx,q)=>{ctx.font=q},thal:(ctx,q)=>{ctx.textAlign=q},tval:(ctx,q)=>{ctx.textBaseline=q}},initStyle(style){for(const key in style)if(this.get[key]&&this.get[key](this.ctx)!==style[key])this.set[key](this.ctx,style[key])},setStyle(style){let q,prv={};for(const key in style){if(this.get[key]){let keyval=style[key];if(typeof style[key]==="string"&&style[key][0]==="@"){const ref=style[key].substr(1);keyval=g2.symbol[ref]||ref in this.get&&this.get[ref](this.ctx)||ref in this.cur&&this.cur[ref]}if((q=this.get[key](this.ctx))!==keyval){prv[key]=q;this.set[key](this.ctx,keyval)}}}return prv},resetStyle(style){for(const key in style)this.set[key](this.ctx,style[key])},pushStyle(style){let cur={};for(const key in style)if(g2.styleRex.test(key)){if(typeof style[key]==="string"&&style[key][0]==="@"){let ref=style[key].substr(1);style[key]=g2.symbol[ref]||this.get[ref]&&this.get[ref](this.ctx)}if(this.cur[key]!==style[key]){if(key in this.set)this.set[key](this.ctx,style[key]);cur[key]=style[key]}}this.stack.push(this.cur=Object.assign({},this.cur,cur))},popStyle(){let cur=this.stack.pop();this.cur=this.stack[this.stack.length-1];for(const key in this.cur)if(this.get[key]&&this.cur[key]!==cur[key])this.set[key](this.ctx,this.cur[key])},concatTrf(q,t){return[q[0]*t[0]+q[2]*t[1],q[1]*t[0]+q[3]*t[1],q[0]*t[2]+q[2]*t[3],q[1]*t[2]+q[3]*t[3],q[0]*t[4]+q[2]*t[5]+q[4],q[1]*t[4]+q[3]*t[5]+q[5]]},initTrf(){this.ctx.setTransform(...this.matrix[0])},setTrf(t){this.ctx.setTransform(...this.concatTrf(this.matrix[this.matrix.length-1],t))},resetTrf(){this.ctx.setTransform(...this.matrix[this.matrix.length-1])},pushTrf(t){let q_t=this.concatTrf(this.matrix[this.matrix.length-1],t);this.matrix.push(q_t);this.ctx.setTransform(...q_t)},popTrf(){this.matrix.pop();this.ctx.setTransform(...this.matrix[this.matrix.length-1])},get isCartesian(){let m=this.matrix[this.matrix.length-1];return m[0]*m[3]-m[1]*m[2]<0},get uniTrf(){let m=this.matrix[this.matrix.length-1];return{x:m[4],y:m[5],scl:Math.hypot(m[0],m[1]),cartesian:m[0]*m[3]-m[1]*m[2]<0}},unscaleTrf({x:x,y:y}){let m=this.matrix[this.matrix.length-1],invscl=1/Math.hypot(m[0],m[1]);return[invscl,0,0,invscl,(1-invscl)*x,(1-invscl)*y]},gridSize(scl){let base=this.gridBase,exp=this.gridExp,sz;while((sz=scl*base*Math.pow(10,exp))<14||sz>35){if(sz<14){if(base==1)base=2;else if(base==2)base=5;else if(base==5){base=1;exp++}}else{if(base==1){base=5;exp--}else if(base==2)base=1;else if(base==5)base=2}}this.gridBase=base;this.gridExp=exp;return sz}}; /** * g2.lib (c) 2013-17 Stefan Goessner * geometric constants and higher functions @@ -23,14 +23,14 @@ */ "use strict";var g2=g2||{};g2=Object.assign(g2,{EPS:Number.EPSILON,PI:Math.PI,PI2:2*Math.PI,SQRT2:Math.SQRT2,SQRT2_2:Math.SQRT2/2,toPi2(w){return(w%g2.PI2+g2.PI2)%g2.PI2},toPi(w){return(w=(w%g2.PI2+g2.PI2)%g2.PI2)>g2.PI?w-g2.PI2:w},toArc:function(w,w0,dw){if(dw>g2.EPS||dw<-g2.EPS){if(w0>w&&w0+dw>g2.PI2)w0-=g2.PI2;else if(w0eps&&Math.abs(dist-r)=0&&mu<=1},isPntOnPly({x:x,y:y},{pts:pts,closed:closed},eps=Number.EPSILON){for(var i=0,n=pts.length;i<(closed?n:n-1);i++)if(g2.isPntOnLin({x:x,y:y},pts[i],pts[(i+1)%n],eps))return true;return false},isPntOnBox({x:xp,y:yp},{x:x,y:y,b:b,h:h},eps=Number.EPSILON){var dx=x.p-x,dy=yp-y;return dx>=b-eps&&dx<=b+eps&&dy<=h+eps&&dy>=-h-eps||dx>=-b-eps&&dx<=b+eps&&dy<=h+eps&&dy>=h-eps||dx>=-b-eps&&dx<=-b+eps&&dy<=h+eps&&dy>=-h-eps||dx>=-b-eps&&dx<=b+eps&&dy<=-h+eps&&dy>=-h-eps},isPntInCir({x:xp,y:yp},{x:x,y:y,r:r}){return(x-xp)**2+(y-yp)**2pi.y||y>pj.y)&&(y<=pi.y||y<=pj.y)&&(x<=pi.x||x<=pj.x)&&pi.y!==pj.y&&(pi.x===pj.x||x<=pj.x+(y-pj.y)*(pi.x-pj.x)/(pi.y-pj.y)))match++;return match%2!=0},isPntInBox({x:xp,y:yp},{x:x,y:y,b:b,h:h}){var dx=xp-x,dy=yp-y;return dx>=-b&&dx<=b&&dy>=-h&&dy<=h},arc3pts(x1,y1,x2,y2,x3,y3){const dx1=x2-x1,dy1=y2-y1;const dx2=x3-x2,dy2=y3-y2;const den=dx1*dy2-dy1*dx2;const lam=Math.abs(den)>Number.EPSILON?.5*((dx1+dx2)*dx2+(dy1+dy2)*dy2)/den:0;const x0=lam?x1+.5*dx1-lam*dy1:x1+.5*(dx1+dx2);const y0=lam?y1+.5*dy1+lam*dx1:y1+.5*(dy1+dy2);const dx01=x1-x0,dy01=y1-y0;const dx03=x3-x0,dy03=y3-y0;const dw=lam?Math.atan2(dx01*dy03-dy01*dx03,dx01*dx03+dy01*dy03):0;const r=dw?Math.hypot(dy01,dx01):.5*Math.hypot(dy1+dy2,dx1+dx2);return{x:x0,y:y0,r:r,w:Math.atan2(dy01,dx01),dw:dw}}});"use strict"; /** - * g2.ext (c) 2015-20 Stefan Goessner + * g2.ext (c) 2015-21 Stefan Goessner * @author Stefan Goessner * @license MIT License * @requires g2.core.js * @typedef {g2} * @description Additional methods for g2. * @returns {g2} - */var g2=g2||{prototype:{}};g2.NONE=0;g2.OVER=1;g2.DRAG=2;g2.EDIT=4;g2.symbol=g2.symbol||{};g2.symbol.tick=g2().p().m({x:0,y:-2}).l({x:0,y:2}).stroke({lc:"round",lwnosc:true});g2.symbol.dot=g2().cir({x:0,y:0,r:2,ls:"transparent"});g2.symbol.sqr=g2().rec({x:-1.5,y:-1.5,b:3,h:3,ls:"transparent"});g2.symbol.nodcolor="#333";g2.symbol.nodfill="#dedede";g2.symbol.nodfill2="#aeaeae";g2.symbol.linkcolor="#666";g2.symbol.linkfill="rgba(225,225,225,0.75)";g2.symbol.dimcolor="darkslategray";g2.symbol.solid=[];g2.symbol.dash=[15,10];g2.symbol.dot=[4,4];g2.symbol.dashdot=[25,6.5,2,6.5];g2.symbol.labelSignificantDigits=3;g2.flatten=function(obj){const args=Object.create(null);for(let p in obj)if(typeof obj[p]!=="function")args[p]=obj[p];return args};g2.pointIfc={get p(){return{x:this.x,y:this.y}},get x(){return Object.getOwnPropertyDescriptor(this,"p")?this.p.x:0},get y(){return Object.getOwnPropertyDescriptor(this,"p")?this.p.y:0},set x(q){if(Object.getOwnPropertyDescriptor(this,"p"))this.p.x=q},set y(q){if(Object.getOwnPropertyDescriptor(this,"p"))this.p.y=q}};g2.labelIfc={getLabelOffset(){const off=this.label.off!==undefined?+this.label.off:1;return off+Math.sign(off)*(this.lw||2)/2},getLabelString(){let s=typeof this.label==="object"?this.label.str:typeof this.label==="string"?this.label:"?";if(s&&s[0]==="@"&&this[s.substr(1)]){s=s.substr(1);let val=this[s];val=Number.isInteger(val)?val:Number(val).toFixed(Math.max(g2.symbol.labelSignificantDigits-Math.log10(val),0));s=`${val}${s==="angle"?"°":""}`}return s},drawLabel(g){const lbl=this.label;const font=lbl.font||g2.defaultStyle.font;const h=parseInt(font);const str=this.getLabelString();const rx=(str.length||1)*.75*h/2,ry=1.25*h/2;const pos=this.pointAt(lbl.loc||this.lbloc||"se");const off=this.getLabelOffset();const p={x:pos.x+pos.nx*(off+Math.sign(off)*rx),y:pos.y+pos.ny*(off+Math.sign(off)*ry)};if(lbl.border)g.ell({x:p.x,y:p.y,rx:rx,ry:ry,ls:lbl.fs||"black",fs:lbl.fs2||"#ffc"});g.txt({str:str,x:p.x,y:p.y,thal:"center",tval:"middle",fs:lbl.fs||"black",font:lbl.font});return g}};g2.markIfc={markAt(loc){const p=this.pointAt(loc);const w=Math.atan2(p.ny,p.nx)+Math.PI/2;return{grp:this.getMarkSymbol(),x:p.x,y:p.y,w:w,scl:this.lw||1,ls:this.ls||"#000",fs:this.fs||this.ls||"#000"}},getMarkSymbol(){const mrk=this.mark;if(typeof mrk==="number"||!mrk)return g2.symbol.tick;if(typeof mrk.symbol==="object")return mrk.symbol;if(typeof mrk.symbol==="string")return g2.symbol[mrk.symbol]},drawMark(g,closed=false){let loc;if(Array.isArray(this.mark)){loc=this.mark}else{const count=typeof this.mark==="object"?this.mark.count:this.mark;loc=count?Array.from(Array(count)).map((_,i)=>i/(count-!closed)):this.mark.loc}for(let l of loc){g.use(this.markAt(l))}return g}};g2.prototype.cir.prototype=g2.mix(g2.pointIfc,g2.labelIfc,g2.markIfc,{w:0,lbloc:"c",get isSolid(){return this.fs&&this.fs!=="transparent"},get len(){return 2*Math.PI*this.r},get lsh(){return this.state&g2.OVER},get sh(){return this.state&g2.OVER?[0,0,5,"black"]:false},get g2(){const e=g2();this.label&&e.ins(g=>this.drawLabel(g));this.mark&&e.ins(g=>this.drawMark(g,true));return()=>g2().cir(g2.flatten(this)).ins(e)},pointAt(loc){const Q=Math.SQRT2/2;const LOC={c:[0,0],e:[1,0],ne:[Q,Q],n:[0,1],nw:[-Q,Q],w:[-1,0],sw:[-Q,-Q],s:[0,-1],se:[Q,-Q]};const q=loc+0===loc?[Math.cos(loc*2*Math.PI),Math.sin(loc*2*Math.PI)]:LOC[loc||"c"]||[0,0];return{x:this.x+q[0]*this.r,y:this.y+q[1]*this.r,nx:q[0],ny:q[1]}},hit({x:x,y:y,eps:eps}){return this.isSolid?g2.isPntInCir({x:x,y:y},this,eps):g2.isPntOnCir({x:x,y:y},this,eps)},drag({dx:dx,dy:dy}){this.x+=dx;this.y+=dy}});g2.prototype.lin.prototype=g2.mix(g2.labelIfc,g2.markIfc,{get p1(){return{x1:this.x1,y1:this.y1}},get x1(){return Object.getOwnPropertyDescriptor(this,"p1")?this.p1.x:0},get y1(){return Object.getOwnPropertyDescriptor(this,"p1")?this.p1.y:0},set x1(q){if(Object.getOwnPropertyDescriptor(this,"p1"))this.p1.x=q},set y1(q){if(Object.getOwnPropertyDescriptor(this,"p1"))this.p1.y=q},get p2(){return{x2:this.x2,y2:this.y2}},get x2(){return Object.getOwnPropertyDescriptor(this,"p2")?this.p2.x:0},get y2(){return Object.getOwnPropertyDescriptor(this,"p2")?this.p2.y:0},set x2(q){if(Object.getOwnPropertyDescriptor(this,"p2"))this.p2.x=q},set y2(q){if(Object.getOwnPropertyDescriptor(this,"p2"))this.p2.y=q},isSolid:false,get len(){return Math.hypot(this.x2-this.x1,this.y2-this.y1)},get sh(){return this.state&g2.OVER?[0,0,5,"black"]:false},get g2(){const e=g2();this.label&&e.ins(e=>this.drawLabel(e));this.mark&&e.ins(e=>this.drawMark(e));return()=>g2().lin(g2.flatten(this)).ins(e)},pointAt(loc){let t=loc==="beg"?0:loc==="end"?1:loc+0===loc?loc:.5,dx=this.x2-this.x1,dy=this.y2-this.y1,len=Math.hypot(dx,dy);return{x:this.x1+dx*t,y:this.y1+dy*t,nx:len?dy/len:0,ny:len?-dx/len:-1}},hit({x:x,y:y,eps:eps}){return g2.isPntOnLin({x:x,y:y},{x:this.x1,y:this.y1},{x:this.x2,y:this.y2},eps)},drag({dx:dx,dy:dy}){this.x1+=dx;this.x2+=dx;this.y1+=dy;this.y2+=dy}});g2.prototype.rec.prototype=g2.mix(g2.pointIfc,g2.labelIfc,g2.markIfc,{get len(){return 2*(this.b+this.h)},get isSolid(){return this.fs&&this.fs!=="transparent"},get lsh(){return this.state&g2.OVER},get sh(){return this.state&g2.OVER?[0,0,5,"black"]:false},get g2(){const e=g2();this.label&&e.ins(e=>this.drawLabel(e));this.mark&&e.ins(e=>this.drawMark(e,true));return()=>g2().rec(g2.flatten(this)).ins(e)},lbloc:"c",pointAt(loc){const locAt=loc=>{const o={c:[0,0],e:[1,0],ne:[.95,.95],n:[0,1],nw:[-.95,.95],w:[-1,0],sw:[-.95,-.95],s:[0,-1],se:[.95,-.95]};if(o[loc])return o[loc];const w=2*Math.PI*loc+pi/4;if(loc<=.25)return[1/Math.tan(w),1];if(loc<=.5)return[-1,-Math.tan(w)];if(loc<=.75)return[-1/Math.tan(w),-1];if(loc<=1)return[1,Math.tan(w)]};const q=locAt(loc);return{x:this.x+(1+q[0])*this.b/2,y:this.y+(1+q[1])*this.h/2,nx:1-Math.abs(q[0])<.01?q[0]:0,ny:1-Math.abs(q[1])<.01?q[1]:0}},hit({x:x,y:y,eps:eps}){return this.isSolid?g2.isPntInBox({x:x,y:y},{x:this.x+this.b/2,y:this.y+this.h/2,b:this.b/2,h:this.h/2},eps):g2.isPntOnBox({x:x,y:y},{x:this.x+this.b/2,y:this.y+this.h/2,b:this.b/2,h:this.h/2},eps)},drag({dx:dx,dy:dy}){this.x+=dx;this.y+=dy}});g2.prototype.arc.prototype=g2.mix(g2.pointIfc,g2.labelIfc,g2.markIfc,{get len(){return Math.abs(this.r*this.dw)},isSolid:false,get angle(){return this.dw/Math.PI*180},get sh(){return this.state&g2.OVER?[0,0,5,"black"]:false},get g2(){const e=g2();this.label&&e.ins(e=>this.drawLabel(e));this.mark&&e.ins(e=>this.drawMark(e));return()=>g2().arc(g2.flatten(this)).ins(e)},lbloc:"mid",pointAt(loc){let t=loc==="beg"?0:loc==="end"?1:loc==="mid"?.5:loc+0===loc?loc:.5,ang=(this.w||0)+t*(this.dw||Math.PI*2),cang=Math.cos(ang),sang=Math.sin(ang),r=loc==="c"?0:this.r;return{x:this.x+r*cang,y:this.y+r*sang,nx:cang,ny:sang}},hit({x:x,y:y,eps:eps}){return g2.isPntOnArc({x:x,y:y},this,eps)},drag({dx:dx,dy:dy}){this.x+=dx;this.y+=dy}});g2.prototype.hdl=function(args){return this.addCommand({c:"hdl",a:args})};g2.prototype.hdl.prototype=g2.mix(g2.prototype.cir.prototype,{r:5,isSolid:true,draggable:true,lbloc:"se",get lsh(){return this.state&g2.OVER},get sh(){return this.state&g2.OVER?[0,0,5,"black"]:false},g2(){const{x:x,y:y,r:r,b:b=4,shape:shape="cir",ls:ls="black",fs:fs="#ccc",sh:sh}=this;return shape==="cir"?g2().cir({x:x,y:y,r:r,ls:ls,fs:fs,sh:sh}).ins(g=>this.label&&this.drawLabel(g)):g2().rec({x:x-b,y:y-b,b:2*b,h:2*b,ls:ls,fs:fs,sh:sh}).ins(g=>this.label&&this.drawLabel(g))}});g2.prototype.nod=function(args={}){return this.addCommand({c:"nod",a:args})};g2.prototype.nod.prototype=g2.mix(g2.prototype.cir.prototype,{r:5,ls:"@nodcolor",fs:g2.symbol.nodfill,isSolid:true,lbloc:"se",g2(){return g2().cir({...g2.flatten(this),r:this.r*(this.scl!==undefined?this.scl:1)}).ins(g=>this.label&&this.drawLabel(g))}});g2.prototype.dblnod=function({x:x=0,y:y=0}){return this.addCommand({c:"dblnod",a:arguments[0]})};g2.prototype.dblnod.prototype=g2.mix(g2.prototype.cir.prototype,{get r(){return 6},get isSolid(){return true},g2(){return g2().beg({x:this.x,y:this.y}).cir({r:6,ls:"@nodcolor",fs:"@nodfill",sh:this.sh}).cir({r:3,ls:"@nodcolor",fs:"@nodfill2"}).end().ins(g=>this.label&&this.drawLabel(g))}});g2.prototype.pol=function(args={}){return this.addCommand({c:"pol",a:args})};g2.prototype.pol.prototype=g2.mix(g2.prototype.nod.prototype,{g2(){return g2().beg(g2.flatten(this)).cir({r:6,fs:g2.symbol.nodfill}).cir({r:2.5,fs:"@ls",ls:"transparent"}).end().ins(g=>this.label&&this.drawLabel(g))}});g2.prototype.gnd=function(args={}){return this.addCommand({c:"gnd",a:args})};g2.prototype.gnd.prototype=g2.mix(g2.prototype.nod.prototype,{g2(){return g2().beg(g2.flatten(this)).cir({x:0,y:0,r:6}).p().m({x:0,y:6}).a({dw:Math.PI/2,x:-6,y:0}).l({x:6,y:0}).a({dw:-Math.PI/2,x:0,y:-6}).z().fill({fs:g2.symbol.nodcolor}).end().ins(g=>this.label&&this.drawLabel(g))}});g2.prototype.nodfix=function(args={}){return this.addCommand({c:"nodfix",a:args})};g2.prototype.nodfix.prototype=g2.mix(g2.prototype.nod.prototype,{g2(){return g2().beg(g2.flatten(this)).p().m({x:-8,y:-12}).l({x:0,y:0}).l({x:8,y:-12}).drw({fs:g2.symbol.nodfill2}).cir({x:0,y:0,r:this.r}).end().ins(g=>this.label&&this.drawLabel(g))}});g2.prototype.nodflt=function(args={}){return this.addCommand({c:"nodflt",a:args})};g2.prototype.nodflt.prototype=g2.mix(g2.prototype.nod.prototype,{g2(){return g2().beg(g2.flatten(this)).p().m({x:-8,y:-12}).l({x:0,y:0}).l({x:8,y:-12}).drw({ls:g2.symbol.nodcolor,fs:g2.symbol.nodfill2}).cir({x:0,y:0,r:this.r,ls:g2.symbol.nodcolor,fs:g2.symbol.nodfill}).lin({x1:-9,y1:-19,x2:9,y2:-19,ls:g2.symbol.nodfill2,lw:5}).lin({x1:-9,y1:-15.5,x2:9,y2:-15.5,ls:g2.symbol.nodcolor,lw:2}).end().ins(g=>this.label&&this.drawLabel(g))}});g2.prototype.vec=function vec(args){return this.addCommand({c:"vec",a:args})};g2.prototype.vec.prototype=g2.mix(g2.prototype.lin.prototype,{g2(){const{x1:x1,y1:y1,x2:x2,y2:y2,lw:lw=1,ls:ls="#000",ld:ld=[],fs:fs=ls||"#000",lc:lc="round",lj:lj="round"}=this;const dx=x2-x1,dy=y2-y1,r=Math.hypot(dx,dy);const b=3*(1+lw)>r?r/3:1+lw;const arrowHead=()=>g2().p().m({x:0,y:0}).l({x:-5*b,y:b}).a({dw:-Math.PI/3,x:-5*b,y:-b}).z().drw({ls:ls,fs:fs,lc:lc,lj:lj});return g2().beg({x:x1,y:y1,w:Math.atan2(dy,dx),lc:lc,lj:lj}).p().m({x:0,y:0}).l({x:r-3*b,y:0}).stroke({ls:ls,lw:lw,ld:ld}).use({grp:arrowHead,x:r,y:0}).end().ins(g=>this.label&&this.drawLabel(g))}});g2.prototype.avec=function avec(args){return this.addCommand({c:"avec",a:args})};g2.prototype.avec.prototype=g2.mix(g2.prototype.arc.prototype,{g2(){const{x:x,y:y,r:r,w:w,dw:dw=0,lw:lw=1,lc:lc="round",lj:lj="round",ls:ls,fs:fs=ls||"#000",label:label}=this;const b=3*(1+lw)>r?r/3:1+lw,bw=5*b/r;const arrowHead=()=>g2().p().m({x:0,y:2*b}).l({x:0,y:-2*b}).m({x:0,y:0}).l({x:-5*b,y:b}).a({dw:-Math.PI/3,x:-5*b,y:-b}).z().drw({ls:ls,fs:fs});return g2().beg({x:x,y:y,w:w,ls:ls,lw:lw,lc:lc,lj:lj}).arc({r:r,w:0,dw:dw}).use({grp:arrowHead,x:r*Math.cos(dw),y:r*Math.sin(dw),w:dw>=0?dw+Math.PI/2-bw/2:dw-Math.PI/2+bw/2}).end().ins(g=>label&&this.drawLabel(g))}});g2.prototype.dim=function dim(args){return this.addCommand({c:"dim",a:args})};g2.prototype.dim.prototype=g2.mix(g2.prototype.lin.prototype,{pointAt(loc){const pnt=g2.prototype.lin.prototype.pointAt.call(this,loc);if(this.off){pnt.x+=this.off*pnt.nx;pnt.y+=this.off*pnt.ny}return pnt},g2(){const{x1:x1,y1:y1,x2:x2,y2:y2,lw:lw=1,lc:lc="round",lj:lj="round",off:off=0,inside:inside=true,ls:ls,fs:fs=ls||"#000",label:label}=this;const dx=x2-x1,dy=y2-y1,r=Math.hypot(dx,dy);const b=3*(1+lw)>r?r/3:1+lw;const arrowHead=()=>g2().p().m({x:0,y:2*b}).l({x:0,y:-2*b}).m({x:0,y:0}).l({x:-5*b,y:b}).a({dw:-Math.PI/3,x:-5*b,y:-b}).z().drw({ls:ls,fs:fs});return g2().beg({x:x1+off/r*dy,y:y1-off/r*dx,w:Math.atan2(dy,dx),ls:ls,fs:fs,lw:lw,lc:lc,lj:lj}).lin({x1:inside?4*b:0,y1:0,x2:inside?r-4*b:r,y2:0}).use({grp:arrowHead,x:r,y:0,w:inside?0:Math.PI}).use({grp:arrowHead,x:0,y:0,w:inside?Math.PI:0}).lin({x1:0,y1:off,x2:0,y2:0}).lin({x1:r,y1:off,x2:r,y2:0}).end().ins(g=>label&&this.drawLabel(g))}});g2.prototype.adim=function adim(args){return this.addCommand({c:"adim",a:args})};g2.prototype.adim.prototype=g2.mix(g2.prototype.arc.prototype,{g2(){const{x:x,y:y,r:r,w:w,dw:dw,lw:lw=1,lc:lc="round",lj:lj="round",ls:ls,fs:fs=ls||"#000",label:label}=this;const b=3*(1+lw)>r?r/3:1+lw,bw=5*b/r;const arrowHead=()=>g2().p().m({x:0,y:2*b}).l({x:0,y:-2*b}).m({x:0,y:0}).l({x:-5*b,y:b}).a({dw:-Math.PI/3,x:-5*b,y:-b}).z().drw({ls:ls,fs:fs});const outside=this.inside!==undefined&&this.outside===undefined?!this.inside:!!this.outside;return g2().beg({x:x,y:y,w:w,ls:ls,lw:lw,lc:lc,lj:lj}).arc({r:r,w:0,dw:dw}).use({grp:arrowHead,x:r,y:0,w:!outside&&dw>0||outside&&dw<0?-Math.PI/2+bw/2:Math.PI/2-bw/2}).use({grp:arrowHead,x:r*Math.cos(dw),y:r*Math.sin(dw),w:!outside&&dw>0||outside&&dw<0?dw+Math.PI/2-bw/2:dw-Math.PI/2+bw/2}).end().ins(g=>label&&this.drawLabel(g))}});g2.prototype.origin=function(args={}){return this.addCommand({c:"origin",a:args})};g2.prototype.origin.prototype=g2.mix(g2.prototype.nod.prototype,{lbloc:"sw",g2(){const{x:x,y:y,w:w,ls:ls="#000",lw:lw=1}=this;return g2().beg({x:x,y:y,w:w,ls:ls}).vec({x1:0,y1:0,x2:40,y2:0,lw:lw,fs:"#ccc"}).vec({x1:0,y1:0,x2:0,y2:40,lw:lw,fs:"#ccc"}).cir({x:0,y:0,r:lw+1,fs:"#ccc"}).end().ins(g=>this.label&&this.drawLabel(g))}});g2.prototype.ply.prototype=g2.mix(g2.labelIfc,g2.markIfc,{get isSolid(){return this.closed&&this.fs&&this.fs!=="transparent"},get sh(){return this.state&g2.OVER?[0,0,5,"black"]:false},pointAt(loc){const t=loc==="beg"?0:loc==="end"?1:loc+0===loc?loc:.5,pitr=g2.pntItrOf(this.pts),pts=[],len=[];for(let itr=0;itr{const target=t*len.reduce((a,b)=>a+b);for(let itr=0,tmp=0;itr=target){return{t2:1-(tmp-target)/len[itr],x:pts[itr].x,y:pts[itr].y,dx:next.x-pts[itr].x,dy:next.y-pts[itr].y}}}})();const len2=Math.hypot(dx,dy);return{x:(this.x||0)+x+dx*t2,y:(this.y||0)+y+dy*t2,nx:len2?dy/len2:1,ny:len2?dx/len2:0}},hit({x:x,y:y,eps:eps}){return this.isSolid?g2.isPntInPly({x:x-this.x,y:y-this.y},this,eps):g2.isPntOnPly({x:x-this.x,y:y-this.y},this,eps)},drag({dx:dx,dy:dy}){this.x+=dx;this.y+=dy},get g2(){const e=g2();this.label&&e.ins(e=>this.drawLabel(e));this.mark&&e.ins(e=>this.drawMark(e,this.closed));return()=>g2().ply(g2.flatten(this)).ins(e)}});g2.prototype.use.prototype={get p(){return{x:this.x,y:this.y}},get x(){return Object.getOwnPropertyDescriptor(this,"p")?this.p.x:0},get y(){return Object.getOwnPropertyDescriptor(this,"p")?this.p.y:0},set x(q){if(Object.getOwnPropertyDescriptor(this,"p"))this.p.x=q},set y(q){if(Object.getOwnPropertyDescriptor(this,"p"))this.p.y=q},isSolid:false};g2.prototype.spline=function spline({pts:pts,closed:closed,x:x,y:y,w:w}){arguments[0]._itr=g2.pntItrOf(pts);return this.addCommand({c:"spline",a:arguments[0]})};g2.prototype.spline.prototype=g2.mix(g2.prototype.ply.prototype,{g2:function(){let{pts:pts,closed:closed,x:x,y:y,w:w,ls:ls,lw:lw,fs:fs,sh:sh}=this,itr=this._itr,gbez;if(itr){let b=[],i,n=itr.len,p1,p2,p3,p4,d1,d2,d3,d1d2,d2d3,scl2,scl3,den2,den3,istrf=x||y||w;gbez=g2();if(istrf)gbez.beg({x:x,y:y,w:w});gbez.p().m(itr(0));for(let i=0;i<(closed?n:n-1);i++){if(i===0){p1=closed?itr(n-1):{x:2*itr(0).x-itr(1).x,y:2*itr(0).y-itr(1).y};p2=itr(0);p3=itr(1);p4=n===2?closed?itr(0):{x:2*itr(1).x-itr(0).x,y:2*itr(1).y-itr(0).y}:itr(2);d1=Math.max(Math.hypot(p2.x-p1.x,p2.y-p1.y),Number.EPSILON);d2=Math.max(Math.hypot(p3.x-p2.x,p3.y-p2.y),Number.EPSILON)}else{p1=p2;p2=p3;p3=p4;p4=i===n-2?closed?itr(0):{x:2*itr(n-1).x-itr(n-2).x,y:2*itr(n-1).y-itr(n-2).y}:i===n-1?itr(1):itr(i+2);d1=d2;d2=d3}d3=Math.max(Math.hypot(p4.x-p3.x,p4.y-p3.y),Number.EPSILON);d1d2=Math.sqrt(d1*d2),d2d3=Math.sqrt(d2*d3),scl2=2*d1+3*d1d2+d2,scl3=2*d3+3*d2d3+d2,den2=3*(d1+d1d2),den3=3*(d3+d2d3);gbez.c({x:p3.x,y:p3.y,x1:(-d2*p1.x+scl2*p2.x+d1*p3.x)/den2,y1:(-d2*p1.y+scl2*p2.y+d1*p3.y)/den2,x2:(-d2*p4.x+scl3*p3.x+d3*p2.x)/den3,y2:(-d2*p4.y+scl3*p3.y+d3*p2.y)/den3})}gbez.c(closed?{x:itr(0).x,y:itr(0).y}:{x:itr(n-1).x,y:itr(n-1).y});if(closed)gbez.z();gbez.drw({ls:ls,lw:lw,fs:fs,sh:sh});if(istrf)gbez.end()}return gbez}});"use strict"; + */var g2=g2||{prototype:{}};g2.NONE=0;g2.OVER=1;g2.DRAG=2;g2.EDIT=4;g2.symbol=g2.symbol||{};g2.symbol.tick=g2().p().m({x:0,y:-2}).l({x:0,y:2}).stroke({lc:"round",lwnosc:true});g2.symbol.dot=g2().cir({x:0,y:0,r:2,ls:"transparent"});g2.symbol.sqr=g2().rec({x:-1.5,y:-1.5,b:3,h:3,ls:"transparent"});g2.symbol.nodcolor="#333";g2.symbol.nodfill="#dedede";g2.symbol.nodfill2="#aeaeae";g2.symbol.linkcolor="#666";g2.symbol.linkfill="rgba(225,225,225,0.75)";g2.symbol.dimcolor="darkslategray";g2.symbol.solid=[];g2.symbol.dash=[15,10];g2.symbol.dot=[4,4];g2.symbol.dashdot=[25,6.5,2,6.5];g2.symbol.labelSignificantDigits=3;g2.flatten=function(obj){const args=Object.create(null);for(let p in obj)if(typeof obj[p]!=="function")args[p]=obj[p];return args};g2.pointIfc={get p(){return{x:this.x,y:this.y}},get x(){return Object.getOwnPropertyDescriptor(this,"p")?this.p.x:0},get y(){return Object.getOwnPropertyDescriptor(this,"p")?this.p.y:0},set x(q){if(Object.getOwnPropertyDescriptor(this,"p"))this.p.x=q},set y(q){if(Object.getOwnPropertyDescriptor(this,"p"))this.p.y=q}};g2.labelIfc={getLabelOffset(){const off=this.label.off!==undefined?+this.label.off:1;return off+Math.sign(off)*(this.lw||2)/2},getLabelString(){let s=typeof this.label==="object"?this.label.str:typeof this.label==="string"?this.label:"?";if(s&&s[0]==="@"&&this[s.substr(1)]){s=s.substr(1);let val=this[s];val=Number.isInteger(val)?val:Number(val).toFixed(Math.max(g2.symbol.labelSignificantDigits-Math.log10(val),0));s=`${val}${s==="angle"?"°":""}`}return s},drawLabel(g){const lbl=this.label;const font=lbl.font||g2.defaultStyle.font;const h=parseInt(font);const str=this.getLabelString();const rx=(str.length||1)*.75*h/2,ry=1.25*h/2;const pos=this.pointAt(lbl.loc||this.lbloc||"se");const off=this.getLabelOffset();const p={x:pos.x+pos.nx*(off+Math.sign(off)*rx),y:pos.y+pos.ny*(off+Math.sign(off)*ry)};if(lbl.border)g.ell({x:p.x,y:p.y,rx:rx,ry:ry,ls:lbl.fs||"black",fs:lbl.fs2||"#ffc"});g.txt({str:str,x:p.x,y:p.y,thal:"center",tval:"middle",fs:lbl.fs||"black",font:lbl.font});return g}};g2.markIfc={markAt(loc){const p=this.pointAt(loc);const w=Math.atan2(p.ny,p.nx)+Math.PI/2;return{grp:this.getMarkSymbol(),x:p.x,y:p.y,w:w,scl:this.lw||1,ls:this.ls||"#000",fs:this.fs||this.ls||"#000"}},getMarkSymbol(){const mrk=this.mark;if(typeof mrk==="number"||!mrk)return g2.symbol.tick;if(typeof mrk.symbol==="object")return mrk.symbol;if(typeof mrk.symbol==="string")return g2.symbol[mrk.symbol]},drawMark(g,closed=false){let loc;if(Array.isArray(this.mark)){loc=this.mark}else{const count=typeof this.mark==="object"?this.mark.count:this.mark;loc=count?Array.from(Array(count)).map((_,i)=>i/(count-!closed)):this.mark.loc}for(let l of loc){g.use(this.markAt(l))}return g}};g2.prototype.cir.prototype=g2.mix(g2.pointIfc,g2.labelIfc,g2.markIfc,{w:0,lbloc:"c",get isSolid(){return this.fs&&this.fs!=="transparent"},get len(){return 2*Math.PI*this.r},get lsh(){return this.state&g2.OVER},get sh(){return this.state&g2.OVER?[0,0,5,"black"]:false},get g2(){const e=g2();this.label&&e.ins(g=>this.drawLabel(g));this.mark&&e.ins(g=>this.drawMark(g,true));return()=>g2().cir(g2.flatten(this)).ins(e)},pointAt(loc){const Q=Math.SQRT2/2;const LOC={c:[0,0],e:[1,0],ne:[Q,Q],n:[0,1],nw:[-Q,Q],w:[-1,0],sw:[-Q,-Q],s:[0,-1],se:[Q,-Q]};const q=loc+0===loc?[Math.cos(loc*2*Math.PI),Math.sin(loc*2*Math.PI)]:LOC[loc||"c"]||[0,0];return{x:this.x+q[0]*this.r,y:this.y+q[1]*this.r,nx:q[0],ny:q[1]}},hit({x:x,y:y,eps:eps}){return this.isSolid?g2.isPntInCir({x:x,y:y},this,eps):g2.isPntOnCir({x:x,y:y},this,eps)},drag({dx:dx,dy:dy}){this.x+=dx;this.y+=dy}});g2.prototype.lin.prototype=g2.mix(g2.labelIfc,g2.markIfc,{get p1(){return{x1:this.x1,y1:this.y1}},get x1(){return Object.getOwnPropertyDescriptor(this,"p1")?this.p1.x:0},get y1(){return Object.getOwnPropertyDescriptor(this,"p1")?this.p1.y:0},set x1(q){if(Object.getOwnPropertyDescriptor(this,"p1"))this.p1.x=q},set y1(q){if(Object.getOwnPropertyDescriptor(this,"p1"))this.p1.y=q},get p2(){return{x2:this.x2,y2:this.y2}},get x2(){return Object.getOwnPropertyDescriptor(this,"p2")?this.p2.x:0},get y2(){return Object.getOwnPropertyDescriptor(this,"p2")?this.p2.y:0},set x2(q){if(Object.getOwnPropertyDescriptor(this,"p2"))this.p2.x=q},set y2(q){if(Object.getOwnPropertyDescriptor(this,"p2"))this.p2.y=q},isSolid:false,get len(){return Math.hypot(this.x2-this.x1,this.y2-this.y1)},get sh(){return this.state&g2.OVER?[0,0,5,"black"]:false},get g2(){const e=g2();this.label&&e.ins(e=>this.drawLabel(e));this.mark&&e.ins(e=>this.drawMark(e));return()=>g2().lin(g2.flatten(this)).ins(e)},pointAt(loc){let t=loc==="beg"?0:loc==="end"?1:loc+0===loc?loc:.5,dx=this.x2-this.x1,dy=this.y2-this.y1,len=Math.hypot(dx,dy);return{x:this.x1+dx*t,y:this.y1+dy*t,nx:len?dy/len:0,ny:len?-dx/len:-1}},hit({x:x,y:y,eps:eps}){return g2.isPntOnLin({x:x,y:y},{x:this.x1,y:this.y1},{x:this.x2,y:this.y2},eps)},drag({dx:dx,dy:dy}){this.x1+=dx;this.x2+=dx;this.y1+=dy;this.y2+=dy}});g2.prototype.rec.prototype=g2.mix(g2.pointIfc,g2.labelIfc,g2.markIfc,{get len(){return 2*(this.b+this.h)},get isSolid(){return this.fs&&this.fs!=="transparent"},get lsh(){return this.state&g2.OVER},get sh(){return this.state&g2.OVER?[0,0,5,"black"]:false},get g2(){const e=g2();this.label&&e.ins(e=>this.drawLabel(e));this.mark&&e.ins(e=>this.drawMark(e,true));return()=>g2().rec(g2.flatten(this)).ins(e)},lbloc:"c",pointAt(loc){const locAt=loc=>{const o={c:[0,0],e:[1,0],ne:[.95,.95],n:[0,1],nw:[-.95,.95],w:[-1,0],sw:[-.95,-.95],s:[0,-1],se:[.95,-.95]};if(o[loc])return o[loc];const w=2*Math.PI*loc+pi/4;if(loc<=.25)return[1/Math.tan(w),1];if(loc<=.5)return[-1,-Math.tan(w)];if(loc<=.75)return[-1/Math.tan(w),-1];if(loc<=1)return[1,Math.tan(w)]};const q=locAt(loc);return{x:this.x+(1+q[0])*this.b/2,y:this.y+(1+q[1])*this.h/2,nx:1-Math.abs(q[0])<.01?q[0]:0,ny:1-Math.abs(q[1])<.01?q[1]:0}},hit({x:x,y:y,eps:eps}){return this.isSolid?g2.isPntInBox({x:x,y:y},{x:this.x+this.b/2,y:this.y+this.h/2,b:this.b/2,h:this.h/2},eps):g2.isPntOnBox({x:x,y:y},{x:this.x+this.b/2,y:this.y+this.h/2,b:this.b/2,h:this.h/2},eps)},drag({dx:dx,dy:dy}){this.x+=dx;this.y+=dy}});g2.prototype.arc.prototype=g2.mix(g2.pointIfc,g2.labelIfc,g2.markIfc,{get len(){return Math.abs(this.r*this.dw)},isSolid:false,get angle(){return this.dw/Math.PI*180},get sh(){return this.state&g2.OVER?[0,0,5,"black"]:false},get g2(){const e=g2();this.label&&e.ins(e=>this.drawLabel(e));this.mark&&e.ins(e=>this.drawMark(e));return()=>g2().arc(g2.flatten(this)).ins(e)},lbloc:"mid",pointAt(loc){let t=loc==="beg"?0:loc==="end"?1:loc==="mid"?.5:loc+0===loc?loc:.5,ang=(this.w||0)+t*(this.dw||Math.PI*2),cang=Math.cos(ang),sang=Math.sin(ang),r=loc==="c"?0:this.r;return{x:this.x+r*cang,y:this.y+r*sang,nx:cang,ny:sang}},hit({x:x,y:y,eps:eps}){return g2.isPntOnArc({x:x,y:y},this,eps)},drag({dx:dx,dy:dy}){this.x+=dx;this.y+=dy}});g2.prototype.hdl=function(args){return this.addCommand({c:"hdl",a:args})};g2.prototype.hdl.prototype=g2.mix(g2.prototype.cir.prototype,{r:5,isSolid:true,draggable:true,lbloc:"se",get lsh(){return this.state&g2.OVER},get sh(){return this.state&g2.OVER?[0,0,5,"black"]:false},g2(){const{x:x,y:y,r:r,b:b=4,shape:shape="cir",ls:ls="black",fs:fs="#ccc",sh:sh}=this;return shape==="cir"?g2().cir({x:x,y:y,r:r,ls:ls,fs:fs,sh:sh}).ins(g=>this.label&&this.drawLabel(g)):g2().rec({x:x-b,y:y-b,b:2*b,h:2*b,ls:ls,fs:fs,sh:sh}).ins(g=>this.label&&this.drawLabel(g))}});g2.prototype.nod=function(args={}){return this.addCommand({c:"nod",a:args})};g2.prototype.nod.prototype=g2.mix(g2.prototype.cir.prototype,{r:5,ls:"@nodcolor",fs:g2.symbol.nodfill,isSolid:true,lbloc:"se",g2(){return g2().cir({...g2.flatten(this),r:this.r*(this.scl!==undefined?this.scl:1)}).ins(g=>this.label&&this.drawLabel(g))}});g2.prototype.dblnod=function({x:x=0,y:y=0}){return this.addCommand({c:"dblnod",a:arguments[0]})};g2.prototype.dblnod.prototype=g2.mix(g2.prototype.cir.prototype,{r:6,isSolid:true,g2(){return g2().beg({x:this.x,y:this.y}).cir({r:6,ls:"@nodcolor",fs:"@nodfill",sh:this.sh}).cir({r:3,ls:"@nodcolor",fs:"@nodfill2"}).end().ins(g=>this.label&&this.drawLabel(g))}});g2.prototype.pol=function(args={}){return this.addCommand({c:"pol",a:args})};g2.prototype.pol.prototype=g2.mix(g2.prototype.nod.prototype,{g2(){return g2().beg(g2.flatten(this)).cir({r:6,fs:"@fs2"}).cir({r:2.5,fs:"@ls",ls:"transparent"}).end().ins(g=>this.label&&this.drawLabel(g))}});g2.prototype.gnd=function(args={}){return this.addCommand({c:"gnd",a:args})};g2.prototype.gnd.prototype=g2.mix(g2.prototype.nod.prototype,{g2(){return g2().beg(g2.flatten(this)).cir({x:0,y:0,r:6}).p().m({x:0,y:6}).a({dw:Math.PI/2,x:-6,y:0}).l({x:6,y:0}).a({dw:-Math.PI/2,x:0,y:-6}).z().fill({fs:g2.symbol.nodcolor}).end().ins(g=>this.label&&this.drawLabel(g))}});g2.prototype.nodfix=function(args={}){return this.addCommand({c:"nodfix",a:args})};g2.prototype.nodfix.prototype=g2.mix(g2.prototype.nod.prototype,{g2(){return g2().beg(g2.flatten(this)).p().m({x:-8,y:-12}).l({x:0,y:0}).l({x:8,y:-12}).drw({fs:g2.symbol.nodfill2}).cir({x:0,y:0,r:this.r}).end().ins(g=>this.label&&this.drawLabel(g))}});g2.prototype.nodflt=function(args={}){return this.addCommand({c:"nodflt",a:args})};g2.prototype.nodflt.prototype=g2.mix(g2.prototype.nod.prototype,{g2(){return g2().beg(g2.flatten(this)).p().m({x:-8,y:-12}).l({x:0,y:0}).l({x:8,y:-12}).drw({ls:g2.symbol.nodcolor,fs:g2.symbol.nodfill2}).cir({x:0,y:0,r:this.r,ls:g2.symbol.nodcolor,fs:g2.symbol.nodfill}).lin({x1:-9,y1:-19,x2:9,y2:-19,ls:g2.symbol.nodfill2,lw:5}).lin({x1:-9,y1:-15.5,x2:9,y2:-15.5,ls:g2.symbol.nodcolor,lw:2}).end().ins(g=>this.label&&this.drawLabel(g))}});g2.prototype.vec=function vec(args){return this.addCommand({c:"vec",a:args})};g2.prototype.vec.prototype=g2.mix(g2.prototype.lin.prototype,{g2(){const{x1:x1,y1:y1,x2:x2,y2:y2,lw:lw=1,ls:ls="#000",ld:ld=[],fs:fs=ls||"#000",lc:lc="round",lj:lj="round"}=this;const dx=x2-x1,dy=y2-y1,r=Math.hypot(dx,dy);const b=3*(1+lw)>r?r/3:1+lw;const arrowHead=()=>g2().p().m({x:0,y:0}).l({x:-5*b,y:b}).a({dw:-Math.PI/3,x:-5*b,y:-b}).z().drw({ls:ls,fs:fs,lc:lc,lj:lj});return g2().beg({x:x1,y:y1,w:Math.atan2(dy,dx),lc:lc,lj:lj}).p().m({x:0,y:0}).l({x:r-3*b,y:0}).stroke({ls:ls,lw:lw,ld:ld}).use({grp:arrowHead,x:r,y:0}).end().ins(g=>this.label&&this.drawLabel(g))}});g2.prototype.avec=function avec(args){return this.addCommand({c:"avec",a:args})};g2.prototype.avec.prototype=g2.mix(g2.prototype.arc.prototype,{g2(){const{x:x,y:y,r:r,w:w,dw:dw=0,lw:lw=1,lc:lc="round",lj:lj="round",ls:ls,fs:fs=ls||"#000",label:label}=this;const b=3*(1+lw)>r?r/3:1+lw,bw=5*b/r;const arrowHead=()=>g2().p().m({x:0,y:2*b}).l({x:0,y:-2*b}).m({x:0,y:0}).l({x:-5*b,y:b}).a({dw:-Math.PI/3,x:-5*b,y:-b}).z().drw({ls:ls,fs:fs});return g2().beg({x:x,y:y,w:w,ls:ls,lw:lw,lc:lc,lj:lj}).arc({r:r,w:0,dw:dw}).use({grp:arrowHead,x:r*Math.cos(dw),y:r*Math.sin(dw),w:dw>=0?dw+Math.PI/2-bw/2:dw-Math.PI/2+bw/2}).end().ins(g=>label&&this.drawLabel(g))}});g2.prototype.dim=function dim(args){return this.addCommand({c:"dim",a:args})};g2.prototype.dim.prototype=g2.mix(g2.prototype.lin.prototype,{pointAt(loc){const pnt=g2.prototype.lin.prototype.pointAt.call(this,loc);if(this.off){pnt.x+=this.off*pnt.nx;pnt.y+=this.off*pnt.ny}return pnt},g2(){const{x1:x1,y1:y1,x2:x2,y2:y2,lw:lw=1,lc:lc="round",lj:lj="round",off:off=0,inside:inside=true,ls:ls,fs:fs=ls||"#000",label:label}=this;const dx=x2-x1,dy=y2-y1,r=Math.hypot(dx,dy);const b=3*(1+lw)>r?r/3:1+lw;const arrowHead=()=>g2().p().m({x:0,y:2*b}).l({x:0,y:-2*b}).m({x:0,y:0}).l({x:-5*b,y:b}).a({dw:-Math.PI/3,x:-5*b,y:-b}).z().drw({ls:ls,fs:fs});return g2().beg({x:x1+off/r*dy,y:y1-off/r*dx,w:Math.atan2(dy,dx),ls:ls,fs:fs,lw:lw,lc:lc,lj:lj}).lin({x1:inside?4*b:0,y1:0,x2:inside?r-4*b:r,y2:0}).use({grp:arrowHead,x:r,y:0,w:inside?0:Math.PI}).use({grp:arrowHead,x:0,y:0,w:inside?Math.PI:0}).lin({x1:0,y1:off,x2:0,y2:0}).lin({x1:r,y1:off,x2:r,y2:0}).end().ins(g=>label&&this.drawLabel(g))}});g2.prototype.adim=function adim(args){return this.addCommand({c:"adim",a:args})};g2.prototype.adim.prototype=g2.mix(g2.prototype.arc.prototype,{g2(){const{x:x,y:y,r:r,w:w,dw:dw,lw:lw=1,lc:lc="round",lj:lj="round",ls:ls,fs:fs=ls||"#000",label:label}=this;const b=3*(1+lw)>r?r/3:1+lw,bw=5*b/r;const arrowHead=()=>g2().p().m({x:0,y:2*b}).l({x:0,y:-2*b}).m({x:0,y:0}).l({x:-5*b,y:b}).a({dw:-Math.PI/3,x:-5*b,y:-b}).z().drw({ls:ls,fs:fs});const outside=this.inside!==undefined&&this.outside===undefined?!this.inside:!!this.outside;return g2().beg({x:x,y:y,w:w,ls:ls,lw:lw,lc:lc,lj:lj}).arc({r:r,w:0,dw:dw}).use({grp:arrowHead,x:r,y:0,w:!outside&&dw>0||outside&&dw<0?-Math.PI/2+bw/2:Math.PI/2-bw/2}).use({grp:arrowHead,x:r*Math.cos(dw),y:r*Math.sin(dw),w:!outside&&dw>0||outside&&dw<0?dw+Math.PI/2-bw/2:dw-Math.PI/2+bw/2}).end().ins(g=>label&&this.drawLabel(g))}});g2.prototype.origin=function(args={}){return this.addCommand({c:"origin",a:args})};g2.prototype.origin.prototype=g2.mix(g2.prototype.nod.prototype,{lbloc:"sw",g2(){const{x:x,y:y,w:w,ls:ls="#000",lw:lw=1}=this;return g2().beg({x:x,y:y,w:w,ls:ls}).vec({x1:0,y1:0,x2:40,y2:0,lw:lw,fs:"#ccc"}).vec({x1:0,y1:0,x2:0,y2:40,lw:lw,fs:"#ccc"}).cir({x:0,y:0,r:lw+1,fs:"#ccc"}).end().ins(g=>this.label&&this.drawLabel(g))}});g2.prototype.ply.prototype=g2.mix(g2.labelIfc,g2.markIfc,{get isSolid(){return this.closed&&this.fs&&this.fs!=="transparent"},get sh(){return this.state&g2.OVER?[0,0,5,"black"]:false},pointAt(loc){const t=loc==="beg"?0:loc==="end"?1:loc+0===loc?loc:.5,pitr=g2.pntItrOf(this.pts),pts=[],len=[];for(let itr=0;itr{const target=t*len.reduce((a,b)=>a+b);for(let itr=0,tmp=0;itr=target){return{t2:1-(tmp-target)/len[itr],x:pts[itr].x,y:pts[itr].y,dx:next.x-pts[itr].x,dy:next.y-pts[itr].y}}}})();const len2=Math.hypot(dx,dy);return{x:(this.x||0)+x+dx*t2,y:(this.y||0)+y+dy*t2,nx:len2?dy/len2:1,ny:len2?dx/len2:0}},hit({x:x,y:y,eps:eps}){return this.isSolid?g2.isPntInPly({x:x-this.x,y:y-this.y},this,eps):g2.isPntOnPly({x:x-this.x,y:y-this.y},this,eps)},drag({dx:dx,dy:dy}){this.x+=dx;this.y+=dy},get g2(){const e=g2();this.label&&e.ins(e=>this.drawLabel(e));this.mark&&e.ins(e=>this.drawMark(e,this.closed));return()=>g2().ply(g2.flatten(this)).ins(e)}});g2.prototype.use.prototype={get p(){return{x:this.x,y:this.y}},get x(){return Object.getOwnPropertyDescriptor(this,"p")?this.p.x:0},get y(){return Object.getOwnPropertyDescriptor(this,"p")?this.p.y:0},set x(q){if(Object.getOwnPropertyDescriptor(this,"p"))this.p.x=q},set y(q){if(Object.getOwnPropertyDescriptor(this,"p"))this.p.y=q},isSolid:false};g2.prototype.spline=function spline({pts:pts,closed:closed,x:x,y:y,w:w}){arguments[0]._itr=g2.pntItrOf(pts);return this.addCommand({c:"spline",a:arguments[0]})};g2.prototype.spline.prototype=g2.mix(g2.prototype.ply.prototype,{g2:function(){let{pts:pts,closed:closed,x:x,y:y,w:w,ls:ls,lw:lw,fs:fs,sh:sh}=this,itr=this._itr,gbez;if(itr){let b=[],i,n=itr.len,p1,p2,p3,p4,d1,d2,d3,d1d2,d2d3,scl2,scl3,den2,den3,istrf=x||y||w;gbez=g2();if(istrf)gbez.beg({x:x,y:y,w:w});gbez.p().m(itr(0));for(let i=0;i<(closed?n:n-1);i++){if(i===0){p1=closed?itr(n-1):{x:2*itr(0).x-itr(1).x,y:2*itr(0).y-itr(1).y};p2=itr(0);p3=itr(1);p4=n===2?closed?itr(0):{x:2*itr(1).x-itr(0).x,y:2*itr(1).y-itr(0).y}:itr(2);d1=Math.max(Math.hypot(p2.x-p1.x,p2.y-p1.y),Number.EPSILON);d2=Math.max(Math.hypot(p3.x-p2.x,p3.y-p2.y),Number.EPSILON)}else{p1=p2;p2=p3;p3=p4;p4=i===n-2?closed?itr(0):{x:2*itr(n-1).x-itr(n-2).x,y:2*itr(n-1).y-itr(n-2).y}:i===n-1?itr(1):itr(i+2);d1=d2;d2=d3}d3=Math.max(Math.hypot(p4.x-p3.x,p4.y-p3.y),Number.EPSILON);d1d2=Math.sqrt(d1*d2),d2d3=Math.sqrt(d2*d3),scl2=2*d1+3*d1d2+d2,scl3=2*d3+3*d2d3+d2,den2=3*(d1+d1d2),den3=3*(d3+d2d3);gbez.c({x:p3.x,y:p3.y,x1:(-d2*p1.x+scl2*p2.x+d1*p3.x)/den2,y1:(-d2*p1.y+scl2*p2.y+d1*p3.y)/den2,x2:(-d2*p4.x+scl3*p3.x+d3*p2.x)/den3,y2:(-d2*p4.y+scl3*p3.y+d3*p2.y)/den3})}gbez.c(closed?{x:itr(0).x,y:itr(0).y}:{x:itr(n-1).x,y:itr(n-1).y});if(closed)gbez.z();gbez.drw({ls:ls,lw:lw,fs:fs,sh:sh});if(istrf)gbez.end()}return gbez}});"use strict"; /** * g2.mec (c) 2013-18 Stefan Goessner * @author Stefan Goessner @@ -88,4 +88,4 @@ * @property {float} [xmax] - maximal x-axis value. If not given it is calculated from chart data values. * @property {float} [ymin] - minimal y-axis value. If not given it is calculated from chart data values. * @property {float} [ymax] - maximal y-axis value. If not given it is calculated from chart data values. - */g2.prototype.chart=function chart({x:x,y:y,b:b,h:h,style:style,title:title,funcs:funcs,xaxis:xaxis,xmin:xmin,xmax:xmax,yaxis:yaxis,ymin:ymin,ymax:ymax}){return this.addCommand({c:"chart",a:arguments[0]})};g2.prototype.chart.prototype={g2(){const g=g2(),funcs=this.get("funcs"),title=this.title&&this.get("title");if(!this.b)this.b=this.defaults.b;if(!this.h)this.h=this.defaults.h;if(funcs&&funcs.length){const tmp=[this.xmin===undefined,this.xmax===undefined,this.ymin===undefined,this.ymax===undefined];funcs.forEach(f=>this.initFunc(f,...tmp))}this.xAxis=this.autoAxis(this.get("xmin"),this.get("xmax"),0,this.b);this.yAxis=this.autoAxis(this.get("ymin"),this.get("ymax"),0,this.h);g.rec({x:this.x,y:this.y,b:this.b,h:this.h,fs:this.get("fs"),ls:this.get("ls")});g.beg(Object.assign({x:this.x,y:this.y,lw:1},this.defaults.style,this.style));if(title)g.txt(Object.assign({str:this.title&&this.title.text||this.title,x:this.get("b")/2,y:this.get("h")+this.get("title","offset"),w:0},this.defaults.title.style,this.title&&this.title.style||{}));if(this.xaxis)this.drawXAxis(g);if(this.yaxis)this.drawYAxis(g);g.end();if(funcs){funcs.forEach((fnc,i)=>{this.drawFunc(g,fnc,this.defaults.colors[i%this.defaults.colors.length])})}return g},initFunc(fn,setXmin,setXmax,setYmin,setYmax){let itr;if(fn.data&&fn.data.length){itr=fn.itr=g2.pntItrOf(fn.data)}else if(fn.fn&&fn.dx){const xmin=+this.xmin||this.defaults.xmin;const xmax=+this.xmax||this.defaults.xmax;itr=fn.itr=(i=>{let x=xmin+i*fn.dx;return{x:x,y:fn.fn(x)}});itr.len=(xmax-xmin)/fn.dx+1}if(itr&&(setXmin||setXmax||setYmin||setYmax)){const xarr=[];const yarr=[];for(let i=0;ithis.xmax)this.xmax=xmax}if(setYmin){const ymin=Math.min(...yarr);if(!this.ymin||yminthis.ymax)this.ymax=ymax}if(fn.color&&typeof fn.color==="number")fn.color=this.defaults.colors[fn.color%this.defaults.colors.length]}},autoAxis(zmin,zmax,tmin,tmax){let base=2,exp=1,eps=Math.sqrt(Number.EPSILON),Dz=zmax-zmin||1,Dt=tmax-tmin||1,scl=Dz>eps?Dt/Dz:1,dz=base*Math.pow(10,exp),dt=Math.floor(scl*dz),N,dt01,i0,j0,jth,t0,res;while(dt<14||dt>35){if(dt<14){if(base==1)base=2;else if(base==2)base=5;else if(base==5){base=1;exp++}}else{if(base==1){base=5;exp--}else if(base==2)base=1;else if(base==5)base=2}dz=base*Math.pow(10,exp);dt=scl*dz}i0=(scl*Math.abs(zmin)+eps/2)%dt9?5:2;return{zmin:zmin,zmax:zmax,base:base,exp:exp,scl:scl,dt:dt,dz:dz,N:N,t0:t0,z0:z0,i0:i0,j0:j0,jth:jth,itr(i){return{t:this.t0+i*this.dt,z:parseFloat((this.z0+i*this.dz).toFixed(Math.abs(this.exp))),maj:(this.j0-this.i0+i)%this.jth===0}}}},drawXAxis(g){let tick,showgrid=this.xaxis&&this.xaxis.grid,gridstyle=showgrid&&Object.assign({},this.defaults.xaxis.grid,this.xaxis.grid),showaxis=this.xaxis||this.xAxis,axisstyle=showaxis&&Object.assign({},this.defaults.xaxis.style,this.defaults.xaxis.labels.style,this.xaxis&&this.xaxis.style||{}),showline=showaxis&&this.get("xaxis","line"),showlabels=this.xAxis&&showaxis&&this.get("xaxis","labels"),showticks=this.xAxis&&showaxis&&this.get("xaxis","ticks"),ticklen=showticks?this.get("xaxis","ticks","len"):0,showorigin=showaxis&&this.get("xaxis","origin"),title=this.xaxis&&(this.get("xaxis","title","text")||this.xaxis.title)||"";g.beg(axisstyle);for(let i=0;i=0)g.lin({x1:-this.xAxis.zmin*this.xAxis.scl,y1:0,x2:-this.xAxis.zmin*this.xAxis.scl,y2:this.h});if(title)g.txt(Object.assign({str:title.text||title,x:this.b/2,y:-(this.get("xaxis","title","offset")+(showticks&&this.get("xaxis","ticks","len")||0)+(showlabels&&this.get("xaxis","labels","offset")||0)+(showlabels&&parseFloat(this.get("xaxis","labels","style","font"))||0)),w:0},this.get("xaxis","title","style")));g.end()},drawYAxis(g){let tick,showgrid=this.yaxis&&this.yaxis.grid,gridstyle=showgrid&&Object.assign({},this.defaults.yaxis.grid,this.yaxis.grid),showaxis=this.yaxis||this.yAxis,axisstyle=showaxis&&Object.assign({},this.defaults.yaxis.style,this.defaults.yaxis.labels.style,this.yaxis&&this.yaxis.style||{}),showline=showaxis&&this.get("yaxis","line"),showlabels=this.yAxis&&showaxis&&this.get("yaxis","labels"),showticks=this.yAxis&&showaxis&&this.get("yaxis","ticks"),ticklen=showticks?this.get("yaxis","ticks","len"):0,showorigin=showaxis&&this.get("yaxis","origin"),title=this.yaxis&&(this.get("yaxis","title","text")||this.yaxis.title)||"";g.beg(axisstyle);for(let i=0;i=0)g.lin({x1:0,y1:-this.yAxis.zmin*this.yAxis.scl,x2:this.b,y2:-this.yAxis.zmin*this.yAxis.scl});if(title)g.txt(Object.assign({str:title.text||title,x:-(this.get("yaxis","title","offset")+(showticks&&this.get("yaxis","ticks","len")||0)+(showlabels&&this.get("yaxis","labels","offset")||0)+(showlabels&&parseFloat(this.get("yaxis","labels","style","font"))||0)),y:this.h/2,w:Math.PI/2},this.get("yaxis","title","style")));g.end()},drawFunc(g,fn,defaultcolor){let itr=fn.itr;if(itr){let fill=fn.fill||fn.style&&fn.style.fs&&fn.style.fs!=="transparent",color=fn.color=fn.color||fn.style&&fn.style.ls||defaultcolor,plydata=[],args=Object.assign({pts:plydata,closed:false,ls:color,fs:fill?g2.color.rgbaStr(color,.125):"transparent",lw:1},fn.style);if(fill){plydata.push(this.pntOf({x:itr(0).x,y:0}))}const fence=({x:x,y:y})=>({x:Math.max(Math.min(this.xmax,x),this.xmin),y:Math.max(Math.min(this.ymax,y),this.ymin)});plydata.push(this.pntOf(fence(itr(0))));for(let i=1,n=itr.len;ithis.ymax||bfr.ythis.initFunc(f,...tmp))}if(this.xaxis)this.xAxis=this.autoAxis(this.get("xmin"),this.get("xmax"),0,this.b);if(this.yaxis)this.yAxis=this.autoAxis(this.get("ymin"),this.get("ymax"),0,this.h);g.rec({x:this.x,y:this.y,b:this.b,h:this.h,fs:this.get("fs"),ls:this.get("ls")});g.beg(Object.assign({x:this.x,y:this.y,lw:1},this.defaults.style,this.style));if(title)g.txt(Object.assign({str:this.title&&this.title.text||this.title,x:this.get("b")/2,y:this.get("h")+this.get("title","offset"),w:0},this.defaults.title.style,this.title&&this.title.style||{}));if(this.xaxis)this.drawXAxis(g);if(this.yaxis)this.drawYAxis(g);g.end();if(funcs){funcs.forEach((fnc,i)=>{this.drawFunc(g,fnc,this.defaults.colors[i%this.defaults.colors.length])})}return g},initFunc(fn,setXmin,setXmax,setYmin,setYmax){let itr;if(fn.data&&fn.data.length){itr=fn.itr=g2.pntItrOf(fn.data)}else if(fn.fn&&fn.dx){const xmin=+this.xmin||this.defaults.xmin;const xmax=+this.xmax||this.defaults.xmax;itr=fn.itr=(i=>{let x=xmin+i*fn.dx;return{x:x,y:fn.fn(x)}});itr.len=(xmax-xmin)/fn.dx+1}if(itr&&(setXmin||setXmax||setYmin||setYmax)){const xarr=[];const yarr=[];for(let i=0;ithis.xmax)this.xmax=xmax}if(setYmin){const ymin=Math.min(...yarr);if(!this.ymin||yminthis.ymax)this.ymax=ymax}if(fn.color&&typeof fn.color==="number")fn.color=this.defaults.colors[fn.color%this.defaults.colors.length]}},autoAxis(zmin,zmax,tmin,tmax){let base=1,exp=1,eps=Math.sqrt(Number.EPSILON),Dz=zmax-zmin||1,Dt=tmax-tmin||1,scl=Dz>eps?Dt/Dz:1,dz=base*Math.pow(10,exp),dt=Math.floor(scl*dz),N,i0,j0,jth,t0;while(dt<14||dt>35){if(dt<14){if(base==1)base=2;else if(base==2)base=5;else if(base==5){base=1;exp++}}else{if(base==1){base=5;exp--}else if(base==2)base=1;else if(base==5)base=2}dz=base*Math.pow(10,exp);dt=scl*dz}i0=(scl*Math.abs(zmin)+eps/2)%dt9?5:2;return{zmin:zmin,zmax:zmax,base:base,exp:exp,scl:scl,dt:dt,dz:dz,N:N,t0:t0,z0:z0,i0:i0,j0:j0,jth:jth,itr(i){return{t:this.t0+i*this.dt,z:parseFloat((this.z0+i*this.dz).toFixed(Math.abs(this.exp))),maj:(this.j0-this.i0+i)%this.jth===0}}}},drawXAxis(g){let tick,showgrid=this.xaxis&&this.xaxis.grid,gridstyle=showgrid&&Object.assign({},this.defaults.xaxis.grid,this.xaxis.grid),showaxis=this.xaxis||this.xAxis,axisstyle=showaxis&&Object.assign({},this.defaults.xaxis.style,this.defaults.xaxis.labels.style,this.xaxis&&this.xaxis.style||{}),showline=showaxis&&this.get("xaxis","line"),showlabels=this.xAxis&&showaxis&&this.get("xaxis","labels"),showticks=this.xAxis&&showaxis&&this.get("xaxis","ticks"),ticklen=showticks?this.get("xaxis","ticks","len"):0,showorigin=showaxis&&this.get("xaxis","origin"),title=this.xaxis&&(this.get("xaxis","title","text")||this.xaxis.title)||"";g.beg(axisstyle);for(let i=0;i=0)g.lin({x1:-this.xAxis.zmin*this.xAxis.scl,y1:0,x2:-this.xAxis.zmin*this.xAxis.scl,y2:this.h});if(title)g.txt(Object.assign({str:title.text||title,x:this.b/2,y:-(this.get("xaxis","title","offset")+(showticks&&this.get("xaxis","ticks","len")||0)+(showlabels&&this.get("xaxis","labels","offset")||0)+(showlabels&&parseFloat(this.get("xaxis","labels","style","font"))||0)),w:0},this.get("xaxis","title","style")));g.end()},drawYAxis(g){let tick,showgrid=this.yaxis&&this.yaxis.grid,gridstyle=showgrid&&Object.assign({},this.defaults.yaxis.grid,this.yaxis.grid),showaxis=this.yaxis||this.yAxis,axisstyle=showaxis&&Object.assign({},this.defaults.yaxis.style,this.defaults.yaxis.labels.style,this.yaxis&&this.yaxis.style||{}),showline=showaxis&&this.get("yaxis","line"),showlabels=this.yAxis&&showaxis&&this.get("yaxis","labels"),showticks=this.yAxis&&showaxis&&this.get("yaxis","ticks"),ticklen=showticks?this.get("yaxis","ticks","len"):0,showorigin=showaxis&&this.get("yaxis","origin"),title=this.yaxis&&(this.get("yaxis","title","text")||this.yaxis.title)||"";g.beg(axisstyle);for(let i=0;i=0)g.lin({x1:0,y1:-this.yAxis.zmin*this.yAxis.scl,x2:this.b,y2:-this.yAxis.zmin*this.yAxis.scl});if(title)g.txt(Object.assign({str:title.text||title,x:-(this.get("yaxis","title","offset")+(showticks&&this.get("yaxis","ticks","len")||0)+(showlabels&&this.get("yaxis","labels","offset")||0)+(showlabels&&parseFloat(this.get("yaxis","labels","style","font"))||0)),y:this.h/2,w:Math.PI/2},this.get("yaxis","title","style")));g.end()},drawFunc(g,fn,defaultcolor){let itr=fn.itr;if(itr){let fill=fn.fill||fn.style&&fn.style.fs&&fn.style.fs!=="transparent",color=fn.color=fn.color||fn.style&&fn.style.ls||defaultcolor,plydata=[],args=Object.assign({pts:plydata,closed:false,ls:color,fs:fill?g2.color.rgbaStr(color,.125):"transparent",lw:1},fn.style);if(fill){plydata.push(this.pntOf({x:itr(0).x,y:0}))}const fence=({x:x,y:y})=>({x:Math.max(Math.min(this.xmax,x),this.xmin),y:Math.max(Math.min(this.ymax,y),this.ymin)});plydata.push(this.pntOf(fence(itr(0))));for(let i=1,n=itr.len;ithis.ymax||bfr.y\u03f1 = ϱ | +| Zeta | \u0396 = Ζ | \u03b6 = ζ | \| | Sigma | \u03a3 = Σ | \u03c3 = σ | +| Eta | \u0397 = Η | \u03b7 = η | \| | Tau | \u03a4 = Τ | \u03c4 = τ | +| Theta | \u0398 = Θ | \u03b8 = θ
\u03d1 = ϑ | \| | Upsilon | \u03a5 = Υ | \u03c5 = υ | +| Iota | \u0399 = Ι | \u03b9 = ι | \| | Phi | \u03a6 = Φ | \u03c6 = φ
\u03d5 = ϕ | +| Kappa | \u039a = Κ | \u03ba = κ | \| | Chi | \u03a7 = Χ | \u03c7 = χ | +| Lambda | \u039b = Λ | \u03bb = λ | \| | Psi | \u03a8 = Ψ | \u03c8 = ψ | +| Mu | \u039c = Μ | \u03bc = μ | \| | Omega | \u03a9 = Ω | \u03c9 = ω | +

+ + + +| Combining Symbol | Unicode Character | +|:------:|:------:| +| Circumflex | x\u0302 = x̂ | +| Tilde | u\u0303 = ũ | +| Overline | r\u0305 = r̅ | +| Dot | x\u0307 = ẋ | +| Double dot | y\u0308 = ÿ | +

+ +| Symbol | Subscript | Superscript | \| | Symbol | Subscript | Superscript | +|:------:|:------:|:------:| --- |:------:|:------:|:------:| +| 0 | \u2080 = ₀ | \u2070 = ⁰ | \| | α | –| \u1d45 = ᵅ | +| 1 | \u2081 = ₁ | \u00B9 = ¹ | \| |β | \u1d66 = ᵦ |\u1d5d = ᵝ | +| 2 | \u2082 = ₂ | \u00B2 = ² | \| |γ | \u1d67 = ᵧ | \u1d5e = ᵞ | +| 3 | \u2083 = ₃ | \u00B3 = ³ | \| | δ | – | \u1d5f = ᵟ | +| 4 | \u2084 = ₄ | \u2074 = ⁴ | \| | ε | – | \u1d4b = ᵋ | +| 5 | \u2085 = ₅ | \u2075 = ⁵ | \| | θ | – | \u1dbf = ᶿ | +| 6 | \u2086 = ₆ | \u2076 = ⁶ | \| | ι | – | \u1da5 = ᶥ | +| 7 | \u2087 = ₇ | \u2077 = ⁷ | \| | ρ | \u1d68 = ᵨ | – | +| 8 | \u2088 = ₈ | \u2078 = ⁸ | \| | ϕ | – | \u1db2 = ᶲ | +| 9 | \u2089 = ₉ | \u2079 = ⁹ | \| | φ | \u1d69 = ᵩ | \u1d60 = ᵠ | +| + | \u208A = ₊ | \u207A = ⁺ | \| | ψ | – | – | +| - | \u208B = ₋ | \u207B = ⁻ | \| | χ | \u1d6a = ᵪ | \u1d61 = ᵡ | +| = | \u208C = ₌ | \u207C = ⁼ | \| | +| ( | \u208D = ₍ | \u207D = ⁽ | \| | +| ) | \u208E = ₎ | \u207E = ⁾ | \| | +

+| Symbol | Subscript | Superscript | \| | Symbol | Subscript | Superscript +|:------:|:------:|:------:| --- |:------:|:------:|:------:| +| a | \u2090 = ₐ | \u1d43 = ᵃ | \| | A | \u1D00 = ᴀ | \u1d2c = ᴬ | +| b | – | \u1d47 = ᵇ | \| | B | \u0299 = ʙ | \u1d2e = ᴮ | +| c | – | \u1d9c = ᶜ | \| | C |\u1D04 = ᴄ | – | +| d | – | \u1d48 = ᵈ | \| | D | \u1D05 = ᴅ | \u1d30 = ᴰ | +| e | \u2091 = ₑ | \u1d49 = ᵉ | \| | E | \u1D07 = ᴇ | \u1d31 = ᴱ | +| f | – | \u1da0 = ᶠ | \| | F | \ua730 = ꜰ | – | +| g | – | \u1d4d = ᵍ | \| | G | \u0262 = ɢ | \u1d33 = ᴳ | +| h | \u2095 = ₕ | \u02b0 = ʰ | \| | H | \u029c = ʜ | \u1d34 = ᴴ | +| i | \u1d62 = ᵢ | \u2071 = ⁱ | \| | I | \u026a = ɪ | \u1d35 = ᴵ | +| j | \u2c7c = ⱼ | \u02b2 = ʲ | \| | J | \u1D0a = ᴊ | \u1d36 = ᴶ | +| k | \u2096 = ₖ | \u1d4f = ᵏ | \| | K | \u1D0b = ᴋ | \u1d37 = ᴷ | +| l | \u2c7c = ⱼ | \u02b2 = ʲ | \| | L | \u029f = ʟ | \u1d38 = ᴸ | +| m | \u2098 = ₘ | \u1d50 = ᵐ | \| | M | \u1D0d = ᴍ | \u1d39 = ᴹ | +| n | \u2099 = ₙ | \u207f = ⁿ | \| | N | \u0274 = ɴ | \u1d3a = ᴺ | +| o | \u2092 = ₒ | \u1d52 = ᵒ | \| | O | \u1D0f = ᴏ | \u1d3c = ᴼ | +| p | \u209a = ₚ | \u1d56 = ᵖ | \| | P | \u1D18 = ᴘ | \u1d3e = ᴾ | +| q | – | – | \| | Q | \ua7af = ꞯ | – | +| r | \u1d63 = ᵣ | \u02b3 = ʳ | \| | R | \u0280 = ʀ | \u1d3f = ᴿ | +| s | \u209b = ₛ | \u02e2 = ˢ | \| | S | \ua731 = ꜱ | – | +| t | \u209c = ₜ | \u1d57 = ᵗ | \| | T | \u1D1b = ᴛ | \u1d40 = ᵀ | +| u | \u1d64 = ᵤ | \u1d58 = ᵘ | \| | U | \u1D1c = ᴜ | \u1d41 = ᵁ | +| v | \u1d65 = ᵥ | \u1d5b = ᵛ | \| | V | \u1D20 = ᴠ | \u2c7d = ⱽ | +| w | – | \u02b7 = ʷ | \| | W | \u1D21 = ᴡ | \u1d42 = ᵂ | +| x | \u2093 = ₓ | \u02e3 = ˣ | \| | X | \u0078 = x | – | +| y | – | \u02b8 = ʸ | \| | Y | \u028f = ʏ | – | +| z | x\u0302 = x̂ | – | \| | Z | \u1D22 = ᴢ | – | diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..1955a76 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1965 @@ +{ + "name": "g2d", + "version": "3.0.1", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "g2d", + "version": "3.0.1", + "license": "MIT", + "devDependencies": { + "concat": "^1.0.0", + "jsdoc-to-markdown": "^5.0.3", + "uglify-es": "^3.3.9" + } + }, + "node_modules/@babel/parser": { + "version": "7.14.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.3.tgz", + "integrity": "sha512-7MpZDIfI7sUC5zWo2+foJ50CSI5lcqDehZ0lVgIhSi4bFEk94fLAKlF3Q0nzSQQ+ca0lm+O6G9ztKVBeu8PMRQ==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/ansi-escape-sequences": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-4.1.0.tgz", + "integrity": "sha512-dzW9kHxH011uBsidTXd14JXgzye/YLb2LzeKZ4bsgl/Knwx8AtbSFkkGxagdNOoh0DlqHCmfiEjWKBaqjOanVw==", + "dev": true, + "dependencies": { + "array-back": "^3.0.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ansi-escape-sequences/node_modules/array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/cache-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cache-point/-/cache-point-1.0.0.tgz", + "integrity": "sha512-ZqrZp9Hi5Uq7vfSGmNP2bUT/9DzZC2Y/GXjHB8rUJN1a+KLmbV05+vxHipNsg8+CSVgjcVVzLV8VZms6w8ZeRw==", + "dev": true, + "dependencies": { + "array-back": "^4.0.0", + "fs-then-native": "^2.0.0", + "mkdirp2": "^1.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "dev": true, + "dependencies": { + "lodash": "^4.17.15" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/collect-all": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/collect-all/-/collect-all-1.0.4.tgz", + "integrity": "sha512-RKZhRwJtJEP5FWul+gkSMEnaK6H3AGPTTWOiRimCcs+rc/OmQE3Yhy1Q7A7KsdkG3ZXVdZq68Y6ONSdvkeEcKA==", + "dev": true, + "dependencies": { + "stream-connect": "^1.0.2", + "stream-via": "^1.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/command-line-args": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.1.1.tgz", + "integrity": "sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg==", + "dev": true, + "dependencies": { + "array-back": "^3.0.1", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/command-line-args/node_modules/array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/command-line-args/node_modules/typical": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", + "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/command-line-tool": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/command-line-tool/-/command-line-tool-0.8.0.tgz", + "integrity": "sha512-Xw18HVx/QzQV3Sc5k1vy3kgtOeGmsKIqwtFFoyjI4bbcpSgnw2CWVULvtakyw4s6fhyAdI6soQQhXc2OzJy62g==", + "dev": true, + "dependencies": { + "ansi-escape-sequences": "^4.0.0", + "array-back": "^2.0.0", + "command-line-args": "^5.0.0", + "command-line-usage": "^4.1.0", + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/command-line-tool/node_modules/array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "dependencies": { + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/command-line-usage": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-4.1.0.tgz", + "integrity": "sha512-MxS8Ad995KpdAC0Jopo/ovGIroV/m0KHwzKfXxKag6FHOkGsH8/lv5yjgablcRxCJJC0oJeUMuO/gmaq+Wq46g==", + "dev": true, + "dependencies": { + "ansi-escape-sequences": "^4.0.0", + "array-back": "^2.0.0", + "table-layout": "^0.4.2", + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/command-line-usage/node_modules/array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "dependencies": { + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/common-sequence": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/common-sequence/-/common-sequence-2.0.2.tgz", + "integrity": "sha512-jAg09gkdkrDO9EWTdXfv80WWH3yeZl5oT69fGfedBNS9pXUKYInVJ1bJ+/ht2+Moeei48TmSbQDYMc8EOx9G0g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/concat": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/concat/-/concat-1.0.3.tgz", + "integrity": "sha1-QPM1MInWVGdpXLGIa0Xt1jfYzKg=", + "dev": true, + "dependencies": { + "commander": "^2.9.0" + }, + "bin": { + "concat": "bin/concat" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/config-master": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/config-master/-/config-master-3.1.0.tgz", + "integrity": "sha1-ZnZjWQUFooO/JqSE1oSJ10xUhdo=", + "dev": true, + "dependencies": { + "walk-back": "^2.0.1" + } + }, + "node_modules/config-master/node_modules/walk-back": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-2.0.1.tgz", + "integrity": "sha1-VU4qnYdPrEeoywBr9EwvDEmYoKQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/dmd": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/dmd/-/dmd-4.0.6.tgz", + "integrity": "sha512-7ZYAnFQ6jGm4SICArwqNPylJ83PaOdPTAkds3Z/s1ueFqSc5ilJ2F0b7uP+35W1PUbemH++gn5/VlC3KwEgiHQ==", + "dev": true, + "dependencies": { + "array-back": "^4.0.1", + "cache-point": "^1.0.0", + "common-sequence": "^2.0.0", + "file-set": "^3.0.0", + "handlebars": "^4.5.3", + "marked": "^0.7.0", + "object-get": "^2.1.0", + "reduce-flatten": "^3.0.0", + "reduce-unique": "^2.0.1", + "reduce-without": "^1.0.1", + "test-value": "^3.0.0", + "walk-back": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/entities": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", + "dev": true + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/file-set": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/file-set/-/file-set-3.0.0.tgz", + "integrity": "sha512-B/SdeSIeRv7VlOgIjtH3dkxMI+tEy5m+OeCXfAUsirBoVoY+bGtsmvmmTFPm/G23TBY4RiTtjpcgePCfwXRjqA==", + "dev": true, + "dependencies": { + "array-back": "^4.0.0", + "glob": "^7.1.5" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-replace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", + "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "dev": true, + "dependencies": { + "array-back": "^3.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/find-replace/node_modules/array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/fs-then-native": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fs-then-native/-/fs-then-native-2.0.0.tgz", + "integrity": "sha1-GaEk2U2QwiyOBF8ujdbr6jbUjGc=", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "dev": true + }, + "node_modules/handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/js2xmlparser": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.1.tgz", + "integrity": "sha512-KrPTolcw6RocpYjdC7pL7v62e55q7qOMHvLX1UCLc5AAS8qeJ6nukarEJAF2KL2PZxlbGueEbINqZR2bDe/gUw==", + "dev": true, + "dependencies": { + "xmlcreate": "^2.0.3" + } + }, + "node_modules/jsdoc": { + "version": "3.6.7", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.7.tgz", + "integrity": "sha512-sxKt7h0vzCd+3Y81Ey2qinupL6DpRSZJclS04ugHDNmRUXGzqicMJ6iwayhSA0S0DwwX30c5ozyUthr1QKF6uw==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.9.4", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.1", + "klaw": "^3.0.0", + "markdown-it": "^10.0.0", + "markdown-it-anchor": "^5.2.7", + "marked": "^2.0.3", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "taffydb": "2.6.2", + "underscore": "~1.13.1" + }, + "bin": { + "jsdoc": "jsdoc.js" + }, + "engines": { + "node": ">=8.15.0" + } + }, + "node_modules/jsdoc-api": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/jsdoc-api/-/jsdoc-api-5.0.4.tgz", + "integrity": "sha512-1KMwLnfo0FyhF06TQKzqIm8BiY1yoMIGICxRdJHUjzskaHMzHMmpLlmNFgzoa4pAC8t1CDPK5jWuQTvv1pBsEQ==", + "dev": true, + "dependencies": { + "array-back": "^4.0.0", + "cache-point": "^1.0.0", + "collect-all": "^1.0.3", + "file-set": "^2.0.1", + "fs-then-native": "^2.0.0", + "jsdoc": "^3.6.3", + "object-to-spawn-args": "^1.1.1", + "temp-path": "^1.0.0", + "walk-back": "^3.0.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/jsdoc-api/node_modules/file-set": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/file-set/-/file-set-2.0.1.tgz", + "integrity": "sha512-XgOUUpgR6FbbfYcniLw0qm1Am7PnNYIAkd+eXxRt42LiYhjaso0WiuQ+VmrNdtwotyM+cLCfZ56AZrySP3QnKA==", + "dev": true, + "dependencies": { + "array-back": "^2.0.0", + "glob": "^7.1.3" + } + }, + "node_modules/jsdoc-api/node_modules/file-set/node_modules/array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "dependencies": { + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/jsdoc-api/node_modules/walk-back": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-3.0.1.tgz", + "integrity": "sha512-umiNB2qLO731Sxbp6cfZ9pwURJzTnftxE4Gc7hq8n/ehkuXC//s9F65IEIJA2ZytQZ1ZOsm/Fju4IWx0bivkUQ==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/jsdoc-parse": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsdoc-parse/-/jsdoc-parse-4.0.1.tgz", + "integrity": "sha512-qIObw8yqYZjrP2qxWROB5eLQFLTUX2jRGLhW9hjo2CC2fQVlskidCIzjCoctwsDvauBp2a/lR31jkSleczSo8Q==", + "dev": true, + "dependencies": { + "array-back": "^4.0.0", + "lodash.omit": "^4.5.0", + "lodash.pick": "^4.4.0", + "reduce-extract": "^1.0.0", + "sort-array": "^2.0.0", + "test-value": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jsdoc-to-markdown": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/jsdoc-to-markdown/-/jsdoc-to-markdown-5.0.3.tgz", + "integrity": "sha512-tQv5tBV0fTYidRQtE60lJKxE98mmuLcYuITFDKQiDPE9hGccpeEGUNFcVkInq1vigyuPnZmt79bQ8wv2GKjY0Q==", + "dev": true, + "dependencies": { + "array-back": "^4.0.1", + "command-line-tool": "^0.8.0", + "config-master": "^3.1.0", + "dmd": "^4.0.5", + "jsdoc-api": "^5.0.4", + "jsdoc-parse": "^4.0.1", + "walk-back": "^4.0.0" + }, + "bin": { + "jsdoc2md": "bin/cli.js" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/jsdoc/node_modules/marked": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/marked/-/marked-2.0.5.tgz", + "integrity": "sha512-yfCEUXmKhBPLOzEC7c+tc4XZdIeTdGoRCZakFMkCxodr7wDXqoapIME4wjcpBPJLNyUnKJ3e8rb8wlAgnLnaDw==", + "dev": true, + "bin": { + "marked": "bin/marked" + }, + "engines": { + "node": ">= 8.16.2" + } + }, + "node_modules/klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.9" + } + }, + "node_modules/linkify-it": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "dev": true, + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "dev": true + }, + "node_modules/lodash.omit": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", + "integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA=", + "dev": true + }, + "node_modules/lodash.padend": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", + "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=", + "dev": true + }, + "node_modules/lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=", + "dev": true + }, + "node_modules/markdown-it": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", + "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "entities": "~2.0.0", + "linkify-it": "^2.0.0", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/markdown-it-anchor": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz", + "integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==", + "dev": true, + "peerDependencies": { + "markdown-it": "*" + } + }, + "node_modules/marked": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz", + "integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==", + "dev": true, + "bin": { + "marked": "bin/marked" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", + "dev": true + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mkdirp2": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp2/-/mkdirp2-1.0.4.tgz", + "integrity": "sha512-Q2PKB4ZR4UPtjLl76JfzlgSCUZhSV1AXQgAZa1qt5RiaALFjP/CDrGvFBrOz7Ck6McPcwMAxTsJvWOUjOU8XMw==", + "dev": true + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/object-get": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-get/-/object-get-2.1.1.tgz", + "integrity": "sha512-7n4IpLMzGGcLEMiQKsNR7vCe+N5E9LORFrtNUVy4sO3dj9a3HedZCxEL2T7QuLhcHN1NBuBsMOKaOsAYI9IIvg==", + "dev": true + }, + "node_modules/object-to-spawn-args": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-to-spawn-args/-/object-to-spawn-args-1.1.1.tgz", + "integrity": "sha1-d9qIJ/Bz0BHJ4bFz+JV4FHAkZ4U=", + "dev": true + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reduce-extract": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/reduce-extract/-/reduce-extract-1.0.0.tgz", + "integrity": "sha1-Z/I4W+2mUGG19fQxJmLosIDKFSU=", + "dev": true, + "dependencies": { + "test-value": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reduce-extract/node_modules/array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "dependencies": { + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/reduce-extract/node_modules/test-value": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-1.1.0.tgz", + "integrity": "sha1-oJE29y7AQ9J8iTcHwrFZv6196T8=", + "dev": true, + "dependencies": { + "array-back": "^1.0.2", + "typical": "^2.4.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reduce-flatten": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-3.0.1.tgz", + "integrity": "sha512-bYo+97BmUUOzg09XwfkwALt4PQH1M5L0wzKerBt6WLm3Fhdd43mMS89HiT1B9pJIqko/6lWx3OnV4J9f2Kqp5Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/reduce-unique": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/reduce-unique/-/reduce-unique-2.0.1.tgz", + "integrity": "sha512-x4jH/8L1eyZGR785WY+ePtyMNhycl1N2XOLxhCbzZFaqF4AXjLzqSxa2UHgJ2ZVR/HHyPOvl1L7xRnW8ye5MdA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/reduce-without": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/reduce-without/-/reduce-without-1.0.1.tgz", + "integrity": "sha1-aK0OrRGFXJo31OglbBW7+Hly/Iw=", + "dev": true, + "dependencies": { + "test-value": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reduce-without/node_modules/array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "dependencies": { + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/reduce-without/node_modules/test-value": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", + "integrity": "sha1-Edpv9nDzRxpztiXKTz/c97t0gpE=", + "dev": true, + "dependencies": { + "array-back": "^1.0.3", + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requizzle": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", + "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", + "dev": true, + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/sort-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-array/-/sort-array-2.0.0.tgz", + "integrity": "sha1-OKnG2if9fRR7QuYFVPKBGHtN9HI=", + "dev": true, + "dependencies": { + "array-back": "^1.0.4", + "object-get": "^2.1.0", + "typical": "^2.6.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/sort-array/node_modules/array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "dependencies": { + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "node_modules/stream-connect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-connect/-/stream-connect-1.0.2.tgz", + "integrity": "sha1-GLyB8u2zW4tdmoAJIAqYUxRCipc=", + "dev": true, + "dependencies": { + "array-back": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stream-connect/node_modules/array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "dependencies": { + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/stream-via": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/stream-via/-/stream-via-1.0.4.tgz", + "integrity": "sha512-DBp0lSvX5G9KGRDTkR/R+a29H+Wk2xItOF+MpZLLNDWbEV9tGPnqLPxHEYjmiz8xGtJHRIqmI+hCjmNzqoA4nQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/table-layout": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.5.tgz", + "integrity": "sha512-zTvf0mcggrGeTe/2jJ6ECkJHAQPIYEwDoqsiqBjI24mvRmQbInK5jq33fyypaCBxX08hMkfmdOqj6haT33EqWw==", + "dev": true, + "dependencies": { + "array-back": "^2.0.0", + "deep-extend": "~0.6.0", + "lodash.padend": "^4.6.1", + "typical": "^2.6.1", + "wordwrapjs": "^3.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/table-layout/node_modules/array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "dependencies": { + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/taffydb": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", + "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", + "dev": true + }, + "node_modules/temp-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-path/-/temp-path-1.0.0.tgz", + "integrity": "sha1-JLFUOXOrRCiW2a02fdnL2/r+kYs=", + "dev": true + }, + "node_modules/test-value": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-3.0.0.tgz", + "integrity": "sha512-sVACdAWcZkSU9x7AOmJo5TqE+GyNJknHaHsMrR6ZnhjVlVN9Yx6FjHrsKZ3BjIpPCT68zYesPWkakrNupwfOTQ==", + "dev": true, + "dependencies": { + "array-back": "^2.0.0", + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/test-value/node_modules/array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "dependencies": { + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/typical": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", + "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", + "dev": true + }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, + "node_modules/uglify-es": { + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", + "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", + "deprecated": "support for ECMAScript is superseded by `uglify-js` as of v3.13.0", + "dev": true, + "dependencies": { + "commander": "~2.13.0", + "source-map": "~0.6.1" + }, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/uglify-es/node_modules/commander": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", + "dev": true + }, + "node_modules/uglify-js": { + "version": "3.13.7", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.7.tgz", + "integrity": "sha512-1Psi2MmnZJbnEsgJJIlfnd7tFlJfitusmR7zDI8lXlFI0ACD4/Rm/xdrU8bh6zF0i74aiVoBtkRiFulkrmh3AA==", + "dev": true, + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/underscore": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", + "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==", + "dev": true + }, + "node_modules/walk-back": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-4.0.0.tgz", + "integrity": "sha512-kudCA8PXVQfrqv2mFTG72vDBRi8BKWxGgFLwPpzHcpZnSwZk93WMwUDVcLHWNsnm+Y0AC4Vb6MUNRgaHfyV2DQ==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "node_modules/wordwrapjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-3.0.0.tgz", + "integrity": "sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==", + "dev": true, + "dependencies": { + "reduce-flatten": "^1.0.1", + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/wordwrapjs/node_modules/reduce-flatten": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz", + "integrity": "sha1-JYx479FT3fk8tWEjf2EYTzaW4yc=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/xmlcreate": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.3.tgz", + "integrity": "sha512-HgS+X6zAztGa9zIK3Y3LXuJes33Lz9x+YyTxgrkIdabu2vqcGOWwdfCpf1hWLRrd553wd4QCDf6BBO6FfdsRiQ==", + "dev": true + } + }, + "dependencies": { + "@babel/parser": { + "version": "7.14.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.3.tgz", + "integrity": "sha512-7MpZDIfI7sUC5zWo2+foJ50CSI5lcqDehZ0lVgIhSi4bFEk94fLAKlF3Q0nzSQQ+ca0lm+O6G9ztKVBeu8PMRQ==", + "dev": true + }, + "ansi-escape-sequences": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-4.1.0.tgz", + "integrity": "sha512-dzW9kHxH011uBsidTXd14JXgzye/YLb2LzeKZ4bsgl/Knwx8AtbSFkkGxagdNOoh0DlqHCmfiEjWKBaqjOanVw==", + "dev": true, + "requires": { + "array-back": "^3.0.1" + }, + "dependencies": { + "array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true + } + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "cache-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cache-point/-/cache-point-1.0.0.tgz", + "integrity": "sha512-ZqrZp9Hi5Uq7vfSGmNP2bUT/9DzZC2Y/GXjHB8rUJN1a+KLmbV05+vxHipNsg8+CSVgjcVVzLV8VZms6w8ZeRw==", + "dev": true, + "requires": { + "array-back": "^4.0.0", + "fs-then-native": "^2.0.0", + "mkdirp2": "^1.0.4" + } + }, + "catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + }, + "collect-all": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/collect-all/-/collect-all-1.0.4.tgz", + "integrity": "sha512-RKZhRwJtJEP5FWul+gkSMEnaK6H3AGPTTWOiRimCcs+rc/OmQE3Yhy1Q7A7KsdkG3ZXVdZq68Y6ONSdvkeEcKA==", + "dev": true, + "requires": { + "stream-connect": "^1.0.2", + "stream-via": "^1.0.4" + } + }, + "command-line-args": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.1.1.tgz", + "integrity": "sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg==", + "dev": true, + "requires": { + "array-back": "^3.0.1", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" + }, + "dependencies": { + "array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true + }, + "typical": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", + "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", + "dev": true + } + } + }, + "command-line-tool": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/command-line-tool/-/command-line-tool-0.8.0.tgz", + "integrity": "sha512-Xw18HVx/QzQV3Sc5k1vy3kgtOeGmsKIqwtFFoyjI4bbcpSgnw2CWVULvtakyw4s6fhyAdI6soQQhXc2OzJy62g==", + "dev": true, + "requires": { + "ansi-escape-sequences": "^4.0.0", + "array-back": "^2.0.0", + "command-line-args": "^5.0.0", + "command-line-usage": "^4.1.0", + "typical": "^2.6.1" + }, + "dependencies": { + "array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "requires": { + "typical": "^2.6.1" + } + } + } + }, + "command-line-usage": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-4.1.0.tgz", + "integrity": "sha512-MxS8Ad995KpdAC0Jopo/ovGIroV/m0KHwzKfXxKag6FHOkGsH8/lv5yjgablcRxCJJC0oJeUMuO/gmaq+Wq46g==", + "dev": true, + "requires": { + "ansi-escape-sequences": "^4.0.0", + "array-back": "^2.0.0", + "table-layout": "^0.4.2", + "typical": "^2.6.1" + }, + "dependencies": { + "array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "requires": { + "typical": "^2.6.1" + } + } + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "common-sequence": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/common-sequence/-/common-sequence-2.0.2.tgz", + "integrity": "sha512-jAg09gkdkrDO9EWTdXfv80WWH3yeZl5oT69fGfedBNS9pXUKYInVJ1bJ+/ht2+Moeei48TmSbQDYMc8EOx9G0g==", + "dev": true + }, + "concat": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/concat/-/concat-1.0.3.tgz", + "integrity": "sha1-QPM1MInWVGdpXLGIa0Xt1jfYzKg=", + "dev": true, + "requires": { + "commander": "^2.9.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "config-master": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/config-master/-/config-master-3.1.0.tgz", + "integrity": "sha1-ZnZjWQUFooO/JqSE1oSJ10xUhdo=", + "dev": true, + "requires": { + "walk-back": "^2.0.1" + }, + "dependencies": { + "walk-back": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-2.0.1.tgz", + "integrity": "sha1-VU4qnYdPrEeoywBr9EwvDEmYoKQ=", + "dev": true + } + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "dmd": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/dmd/-/dmd-4.0.6.tgz", + "integrity": "sha512-7ZYAnFQ6jGm4SICArwqNPylJ83PaOdPTAkds3Z/s1ueFqSc5ilJ2F0b7uP+35W1PUbemH++gn5/VlC3KwEgiHQ==", + "dev": true, + "requires": { + "array-back": "^4.0.1", + "cache-point": "^1.0.0", + "common-sequence": "^2.0.0", + "file-set": "^3.0.0", + "handlebars": "^4.5.3", + "marked": "^0.7.0", + "object-get": "^2.1.0", + "reduce-flatten": "^3.0.0", + "reduce-unique": "^2.0.1", + "reduce-without": "^1.0.1", + "test-value": "^3.0.0", + "walk-back": "^4.0.0" + } + }, + "entities": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", + "dev": true + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + }, + "file-set": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/file-set/-/file-set-3.0.0.tgz", + "integrity": "sha512-B/SdeSIeRv7VlOgIjtH3dkxMI+tEy5m+OeCXfAUsirBoVoY+bGtsmvmmTFPm/G23TBY4RiTtjpcgePCfwXRjqA==", + "dev": true, + "requires": { + "array-back": "^4.0.0", + "glob": "^7.1.5" + } + }, + "find-replace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", + "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "dev": true, + "requires": { + "array-back": "^3.0.1" + }, + "dependencies": { + "array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true + } + } + }, + "fs-then-native": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fs-then-native/-/fs-then-native-2.0.0.tgz", + "integrity": "sha1-GaEk2U2QwiyOBF8ujdbr6jbUjGc=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "dev": true + }, + "handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "js2xmlparser": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.1.tgz", + "integrity": "sha512-KrPTolcw6RocpYjdC7pL7v62e55q7qOMHvLX1UCLc5AAS8qeJ6nukarEJAF2KL2PZxlbGueEbINqZR2bDe/gUw==", + "dev": true, + "requires": { + "xmlcreate": "^2.0.3" + } + }, + "jsdoc": { + "version": "3.6.7", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.7.tgz", + "integrity": "sha512-sxKt7h0vzCd+3Y81Ey2qinupL6DpRSZJclS04ugHDNmRUXGzqicMJ6iwayhSA0S0DwwX30c5ozyUthr1QKF6uw==", + "dev": true, + "requires": { + "@babel/parser": "^7.9.4", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.1", + "klaw": "^3.0.0", + "markdown-it": "^10.0.0", + "markdown-it-anchor": "^5.2.7", + "marked": "^2.0.3", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "taffydb": "2.6.2", + "underscore": "~1.13.1" + }, + "dependencies": { + "marked": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/marked/-/marked-2.0.5.tgz", + "integrity": "sha512-yfCEUXmKhBPLOzEC7c+tc4XZdIeTdGoRCZakFMkCxodr7wDXqoapIME4wjcpBPJLNyUnKJ3e8rb8wlAgnLnaDw==", + "dev": true + } + } + }, + "jsdoc-api": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/jsdoc-api/-/jsdoc-api-5.0.4.tgz", + "integrity": "sha512-1KMwLnfo0FyhF06TQKzqIm8BiY1yoMIGICxRdJHUjzskaHMzHMmpLlmNFgzoa4pAC8t1CDPK5jWuQTvv1pBsEQ==", + "dev": true, + "requires": { + "array-back": "^4.0.0", + "cache-point": "^1.0.0", + "collect-all": "^1.0.3", + "file-set": "^2.0.1", + "fs-then-native": "^2.0.0", + "jsdoc": "^3.6.3", + "object-to-spawn-args": "^1.1.1", + "temp-path": "^1.0.0", + "walk-back": "^3.0.1" + }, + "dependencies": { + "file-set": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/file-set/-/file-set-2.0.1.tgz", + "integrity": "sha512-XgOUUpgR6FbbfYcniLw0qm1Am7PnNYIAkd+eXxRt42LiYhjaso0WiuQ+VmrNdtwotyM+cLCfZ56AZrySP3QnKA==", + "dev": true, + "requires": { + "array-back": "^2.0.0", + "glob": "^7.1.3" + }, + "dependencies": { + "array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "requires": { + "typical": "^2.6.1" + } + } + } + }, + "walk-back": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-3.0.1.tgz", + "integrity": "sha512-umiNB2qLO731Sxbp6cfZ9pwURJzTnftxE4Gc7hq8n/ehkuXC//s9F65IEIJA2ZytQZ1ZOsm/Fju4IWx0bivkUQ==", + "dev": true + } + } + }, + "jsdoc-parse": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsdoc-parse/-/jsdoc-parse-4.0.1.tgz", + "integrity": "sha512-qIObw8yqYZjrP2qxWROB5eLQFLTUX2jRGLhW9hjo2CC2fQVlskidCIzjCoctwsDvauBp2a/lR31jkSleczSo8Q==", + "dev": true, + "requires": { + "array-back": "^4.0.0", + "lodash.omit": "^4.5.0", + "lodash.pick": "^4.4.0", + "reduce-extract": "^1.0.0", + "sort-array": "^2.0.0", + "test-value": "^3.0.0" + } + }, + "jsdoc-to-markdown": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/jsdoc-to-markdown/-/jsdoc-to-markdown-5.0.3.tgz", + "integrity": "sha512-tQv5tBV0fTYidRQtE60lJKxE98mmuLcYuITFDKQiDPE9hGccpeEGUNFcVkInq1vigyuPnZmt79bQ8wv2GKjY0Q==", + "dev": true, + "requires": { + "array-back": "^4.0.1", + "command-line-tool": "^0.8.0", + "config-master": "^3.1.0", + "dmd": "^4.0.5", + "jsdoc-api": "^5.0.4", + "jsdoc-parse": "^4.0.1", + "walk-back": "^4.0.0" + } + }, + "klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.9" + } + }, + "linkify-it": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "dev": true, + "requires": { + "uc.micro": "^1.0.1" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "dev": true + }, + "lodash.omit": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", + "integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA=", + "dev": true + }, + "lodash.padend": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", + "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=", + "dev": true + }, + "lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=", + "dev": true + }, + "markdown-it": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", + "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "entities": "~2.0.0", + "linkify-it": "^2.0.0", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + } + }, + "markdown-it-anchor": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz", + "integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==", + "dev": true, + "requires": {} + }, + "marked": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz", + "integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==", + "dev": true + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "mkdirp2": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp2/-/mkdirp2-1.0.4.tgz", + "integrity": "sha512-Q2PKB4ZR4UPtjLl76JfzlgSCUZhSV1AXQgAZa1qt5RiaALFjP/CDrGvFBrOz7Ck6McPcwMAxTsJvWOUjOU8XMw==", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "object-get": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-get/-/object-get-2.1.1.tgz", + "integrity": "sha512-7n4IpLMzGGcLEMiQKsNR7vCe+N5E9LORFrtNUVy4sO3dj9a3HedZCxEL2T7QuLhcHN1NBuBsMOKaOsAYI9IIvg==", + "dev": true + }, + "object-to-spawn-args": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-to-spawn-args/-/object-to-spawn-args-1.1.1.tgz", + "integrity": "sha1-d9qIJ/Bz0BHJ4bFz+JV4FHAkZ4U=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "reduce-extract": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/reduce-extract/-/reduce-extract-1.0.0.tgz", + "integrity": "sha1-Z/I4W+2mUGG19fQxJmLosIDKFSU=", + "dev": true, + "requires": { + "test-value": "^1.0.1" + }, + "dependencies": { + "array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "requires": { + "typical": "^2.6.0" + } + }, + "test-value": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-1.1.0.tgz", + "integrity": "sha1-oJE29y7AQ9J8iTcHwrFZv6196T8=", + "dev": true, + "requires": { + "array-back": "^1.0.2", + "typical": "^2.4.2" + } + } + } + }, + "reduce-flatten": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-3.0.1.tgz", + "integrity": "sha512-bYo+97BmUUOzg09XwfkwALt4PQH1M5L0wzKerBt6WLm3Fhdd43mMS89HiT1B9pJIqko/6lWx3OnV4J9f2Kqp5Q==", + "dev": true + }, + "reduce-unique": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/reduce-unique/-/reduce-unique-2.0.1.tgz", + "integrity": "sha512-x4jH/8L1eyZGR785WY+ePtyMNhycl1N2XOLxhCbzZFaqF4AXjLzqSxa2UHgJ2ZVR/HHyPOvl1L7xRnW8ye5MdA==", + "dev": true + }, + "reduce-without": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/reduce-without/-/reduce-without-1.0.1.tgz", + "integrity": "sha1-aK0OrRGFXJo31OglbBW7+Hly/Iw=", + "dev": true, + "requires": { + "test-value": "^2.0.0" + }, + "dependencies": { + "array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "requires": { + "typical": "^2.6.0" + } + }, + "test-value": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", + "integrity": "sha1-Edpv9nDzRxpztiXKTz/c97t0gpE=", + "dev": true, + "requires": { + "array-back": "^1.0.3", + "typical": "^2.6.0" + } + } + } + }, + "requizzle": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", + "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "sort-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-array/-/sort-array-2.0.0.tgz", + "integrity": "sha1-OKnG2if9fRR7QuYFVPKBGHtN9HI=", + "dev": true, + "requires": { + "array-back": "^1.0.4", + "object-get": "^2.1.0", + "typical": "^2.6.0" + }, + "dependencies": { + "array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "requires": { + "typical": "^2.6.0" + } + } + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "stream-connect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-connect/-/stream-connect-1.0.2.tgz", + "integrity": "sha1-GLyB8u2zW4tdmoAJIAqYUxRCipc=", + "dev": true, + "requires": { + "array-back": "^1.0.2" + }, + "dependencies": { + "array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "requires": { + "typical": "^2.6.0" + } + } + } + }, + "stream-via": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/stream-via/-/stream-via-1.0.4.tgz", + "integrity": "sha512-DBp0lSvX5G9KGRDTkR/R+a29H+Wk2xItOF+MpZLLNDWbEV9tGPnqLPxHEYjmiz8xGtJHRIqmI+hCjmNzqoA4nQ==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "table-layout": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.5.tgz", + "integrity": "sha512-zTvf0mcggrGeTe/2jJ6ECkJHAQPIYEwDoqsiqBjI24mvRmQbInK5jq33fyypaCBxX08hMkfmdOqj6haT33EqWw==", + "dev": true, + "requires": { + "array-back": "^2.0.0", + "deep-extend": "~0.6.0", + "lodash.padend": "^4.6.1", + "typical": "^2.6.1", + "wordwrapjs": "^3.0.0" + }, + "dependencies": { + "array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "requires": { + "typical": "^2.6.1" + } + } + } + }, + "taffydb": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", + "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", + "dev": true + }, + "temp-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-path/-/temp-path-1.0.0.tgz", + "integrity": "sha1-JLFUOXOrRCiW2a02fdnL2/r+kYs=", + "dev": true + }, + "test-value": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-3.0.0.tgz", + "integrity": "sha512-sVACdAWcZkSU9x7AOmJo5TqE+GyNJknHaHsMrR6ZnhjVlVN9Yx6FjHrsKZ3BjIpPCT68zYesPWkakrNupwfOTQ==", + "dev": true, + "requires": { + "array-back": "^2.0.0", + "typical": "^2.6.1" + }, + "dependencies": { + "array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "requires": { + "typical": "^2.6.1" + } + } + } + }, + "typical": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", + "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", + "dev": true + }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, + "uglify-es": { + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", + "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", + "dev": true, + "requires": { + "commander": "~2.13.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "commander": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", + "dev": true + } + } + }, + "uglify-js": { + "version": "3.13.7", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.7.tgz", + "integrity": "sha512-1Psi2MmnZJbnEsgJJIlfnd7tFlJfitusmR7zDI8lXlFI0ACD4/Rm/xdrU8bh6zF0i74aiVoBtkRiFulkrmh3AA==", + "dev": true, + "optional": true + }, + "underscore": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", + "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==", + "dev": true + }, + "walk-back": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-4.0.0.tgz", + "integrity": "sha512-kudCA8PXVQfrqv2mFTG72vDBRi8BKWxGgFLwPpzHcpZnSwZk93WMwUDVcLHWNsnm+Y0AC4Vb6MUNRgaHfyV2DQ==", + "dev": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wordwrapjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-3.0.0.tgz", + "integrity": "sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==", + "dev": true, + "requires": { + "reduce-flatten": "^1.0.1", + "typical": "^2.6.1" + }, + "dependencies": { + "reduce-flatten": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz", + "integrity": "sha1-JYx479FT3fk8tWEjf2EYTzaW4yc=", + "dev": true + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xmlcreate": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.3.tgz", + "integrity": "sha512-HgS+X6zAztGa9zIK3Y3LXuJes33Lz9x+YyTxgrkIdabu2vqcGOWwdfCpf1hWLRrd553wd4QCDf6BBO6FfdsRiQ==", + "dev": true + } + } +} diff --git a/package.json b/package.json index ebf7aee..1cf1bea 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "g2d", - "version": "3.0.1", + "version": "3.1.0", "description": "g2 - a tiny 2d graphics command library", "keywords": [ "vector", @@ -12,7 +12,6 @@ "javascript" ], "main": "g2.js", - "microjam": {}, "scripts": { "build": "npm run minify && npm run jsdoc && npm run 7z", "minify": "uglifyjs ./src/g2.core.js ./src/g2.hdl.canvas.js ./src/g2.lib.js ./src/g2.ext.js ./src/g2.mec.js ./src/g2.chart.js -o ./dist/g2.js --comments", diff --git a/sample/g2styleref.html b/sample/g2styleref.html new file mode 100644 index 0000000..dff4215 --- /dev/null +++ b/sample/g2styleref.html @@ -0,0 +1,25 @@ + + +duck + + + + + + + + + diff --git a/src/g2.chart.element.js b/src/g2.chart.element.js index 18a0bc5..6df8f3f 100644 --- a/src/g2.chart.element.js +++ b/src/g2.chart.element.js @@ -10,6 +10,12 @@ class G2ChartElement extends HTMLElement { 'ymin', 'ymax', 'title', + 'xlabels', + 'ylabels', + 'xticks', + 'yticks', + 'xtitle', + 'ytitle' ]; } @@ -32,33 +38,52 @@ class G2ChartElement extends HTMLElement { set ymax(q) { return q && +this.setAttribute('ymax', q) } get title() { return this.getAttribute('title') || ''; } set title(q) { return q && this.setAttribute('title', q) } + get xlabels() { return this.getAttribute('xlabels') !== 'false'; } + get ylabels() { return this.getAttribute('ylabels') !== 'false'; } + get xticks() { return this.getAttribute('xticks') !== 'false'; } + get yticks() { return this.getAttribute('yticks') !== 'false'; } + get xtitle() { return this.getAttribute('xtitle'); } + get ytitle() { return this.getAttribute('ytitle'); } connectedCallback() { this._root.innerHTML = G2ChartElement.template({ width: this.width, height: this.height }); - this._ctx = this._root.getElementById('cnv').getContext('2d'); + const xmargin = (this.yticks && 5) + (this.ylabels && 15) + (this.ytitle && 15); + const ymargin = (this.xticks && 5) + (this.xlabels && 15) + (this.xtitle && 15); - const t = 35; this._chart = { - x: t, - y: t, + x: xmargin, + y: ymargin, xmin: this.xmin, xmax: this.xmax, ymin: this.ymin, ymax: this.ymax, title: this.title, - b: this.width - t * 2, - h: this.height - t * 2, - xaxis: () => this.xaxis || {}, - yaxis: () => this.yaxis || {}, + b: this.width - 5 - xmargin, + h: this.height - 5 - ymargin - (this.title && 15), + xaxis: () => this.xaxis || { ticks: this.xticks, labels: this.xlabels, title: this.xtitle }, + yaxis: () => this.yaxis || { ticks: this.yticks, labels: this.ylabels, title: this.ytitle }, title: () => this.title || "", - funcs: () => this.funcs + funcs: [] }; - this._g = g2().del().clr().view({ cartesian: true }).chart(this._chart); + if (this.innerHTML) { + let res; + + try { res = JSON.parse(this.innerHTML); } + catch (e) { + console.error(e); + this._g.txt({ str: e, y: 5 }); + } + this._chart.funcs.push(...G2ChartElement.validateFunc(res)); + } + + this._ctx = this._root.getElementById('cnv').getContext('2d'); + this._g = g2().del().clr().view({ cartesian: true }).chart(this._chart); +/* try { // If not true, the element should be referenced by another module. if (this.innerHTML !== '') { @@ -88,24 +113,41 @@ class G2ChartElement extends HTMLElement { }); this.render(); } +*/ + this.render(); } render() { this._g.exe(this._ctx); } - +/* setFuncs(funcs) { this.funcs = funcs; return this; } - +*/ disconnectedCallback() { // TODO } + static validateFunc(obj, funcs) { + funcs = funcs || []; + if (Array.isArray(obj)) // array of functions ... + for (const o of obj) + G2ChartElement.validateFunc(o, funcs); + else if (typeof obj === 'object') { // single function ... + if ('fn' in obj) { + const fnc = Function('"use strict";return (' + obj['fn'] + ')')(); + obj.fn = typeof fnc === 'function' ? fnc : undefined; // todo: error message ... + } + if ('fn' in obj || 'data' in obj) + funcs.push(obj); + } + return funcs; + } + static template({ width, height }) { - return `` + return `` } } customElements.define('g2-chart', G2ChartElement); diff --git a/src/g2.chart.js b/src/g2.chart.js index ecba22b..63689ab 100644 --- a/src/g2.chart.js +++ b/src/g2.chart.js @@ -69,10 +69,10 @@ g2.prototype.chart.prototype = { ]; funcs.forEach(f => this.initFunc(f, ...tmp)); } - // if (this.xaxis) - this.xAxis = this.autoAxis(this.get('xmin'), this.get('xmax'), 0, this.b); - // if (this.yaxis) - this.yAxis = this.autoAxis(this.get('ymin'), this.get('ymax'), 0, this.h); + if (this.xaxis) + this.xAxis = this.autoAxis(this.get('xmin'), this.get('xmax'), 0, this.b); + if (this.yaxis) + this.yAxis = this.autoAxis(this.get('ymin'), this.get('ymax'), 0, this.h); // draw background & border ... g.rec({ @@ -152,15 +152,14 @@ g2.prototype.chart.prototype = { } }, autoAxis(zmin, zmax, tmin, tmax) { - let base = 2, exp = 1, eps = Math.sqrt(Number.EPSILON), + let base = 1, exp = 1, eps = Math.sqrt(Number.EPSILON), Dz = zmax - zmin || 1, // value range Dt = tmax - tmin || 1, // area range scl = Dz > eps ? Dt / Dz : 1, // scale [usr]->[pix] dz = base * Math.pow(10, exp), // tick size [usr] dt = Math.floor(scl * dz), // tick size [pix] N, // # segments - dt01, // reminder segment - i0, j0, jth, t0, res; + i0, j0, jth, t0; while (dt < 14 || dt > 35) { if (dt < 14) { @@ -181,8 +180,6 @@ g2.prototype.chart.prototype = { : Math.floor(zmin / dz) + 1; let z0 = i0 * dz; t0 = Math.round(scl * (z0 - zmin)); - // console.log("Dt="+Dt+",N="+(Dt - t0)/ dt) - // console.log("DT="+Dt+",N="+(Dt - t0)/ dt) N = Math.floor((Dt - t0) / dt) + 1; j0 = base % 2 && i0 % 2 ? i0 + 1 : i0; jth = exp === 0 && N < 11 ? 1 : base === 2 && N > 9 ? 5 : 2; @@ -226,8 +223,6 @@ g2.prototype.chart.prototype = { ticklen = showticks ? this.get("xaxis", "ticks", "len") : 0, showorigin = showaxis && this.get("xaxis", "origin"), title = this.xaxis && (this.get("xaxis", "title", "text") || this.xaxis.title) || ''; - // console.log(this.xAxis) - // draw tick/grid lines g.beg(axisstyle); for (let i = 0; i < this.xAxis.N; i++) { tick = this.xAxis.itr(i); diff --git a/src/g2.core.js b/src/g2.core.js index e79b5f8..7620b83 100644 --- a/src/g2.core.js +++ b/src/g2.core.js @@ -2,7 +2,7 @@ "use strict" /** - * g2.core (c) 2013-20 Stefan Goessner + * g2.core (c) 2013-21 Stefan Goessner * @author Stefan Goessner * @license MIT License * @link https://github.com/goessner/g2 @@ -538,6 +538,8 @@ g2.prototype = { // statics g2.defaultStyle = { fs: 'transparent', ls: '#000', lw: 1, lc: "butt", lj: "miter", ld: [], ml: 10, sh: [0, 0], lsh: false, font: '14px serif', thal: 'start', tval: 'alphabetic' }; +g2.styleRex = /^(fs|ls|lw|lc|lj|ld|ldoff|ml|sh|lsh|font|thal|tval)([-0-9].*)?$/, + g2.symbol = { unknown: g2().cir({ r: 12, fs: 'orange' }).txt({ str: '?', thal: 'center', tval: 'middle', font: 'bold 20pt serif' }) }; diff --git a/src/g2.element.js b/src/g2.element.js index 4ad0d26..33551a9 100644 --- a/src/g2.element.js +++ b/src/g2.element.js @@ -1,5 +1,5 @@ /** - * g2.element.js (c) 2019-20 Stefan Goessner + * g2.element.js (c) 2019-21 Stefan Goessner * @license MIT License */ "use strict"; diff --git a/src/g2.ext.js b/src/g2.ext.js index 8a0fcad..5213760 100644 --- a/src/g2.ext.js +++ b/src/g2.ext.js @@ -2,7 +2,7 @@ "use strict" /** - * g2.ext (c) 2015-20 Stefan Goessner + * g2.ext (c) 2015-21 Stefan Goessner * @author Stefan Goessner * @license MIT License * @requires g2.core.js @@ -27,7 +27,7 @@ g2.NONE = 0x0; g2.OVER = 0x1; g2.DRAG = 0x2; g2.EDIT = 0x4; * @property {object} [symbol.sqr] Predefined symbol: a little square * @property {string} [symbol.nodcolor=#333] node color. * @property {string} [symbol.nodfill=#dedede] node fill color. - * @property {string} [symbol.nodfill2=#aeaeae] alternate node fill color, somewhat darker. + * @property {string} [symbol.nodfill2=#aeaeae] alternate node fill color, somewhat darker. * @property {string} [symbol.linkcolor=#666] link color. * @property {string} [symbol.linkfill=rgba(225,225,225,0.75)] link fill color, semi-transparent. * @property {string} [symbol.dimcolor=darkslategray] dimension color. @@ -100,7 +100,8 @@ g2.labelIfc = { const font = lbl.font || g2.defaultStyle.font; const h = parseInt(font); // font height (px assumed !) const str = this.getLabelString(); - const rx = (str.length || 1) * 0.75 * h / 2, ry = 1.25 * h / 2; // ellipse semi-axes length + const rx = (str.length || 1) * 0.65 * h / 2, + ry = 1.25 * h / 2; // ellipse semi-axes length const pos = this.pointAt(lbl.loc || this.lbloc || 'se'); const off = this.getLabelOffset(); const p = { @@ -321,9 +322,9 @@ g2.prototype.hdl.prototype = g2.mix(g2.prototype.cir.prototype, { get lsh() { return this.state & g2.OVER; }, get sh() { return this.state & g2.OVER ? [0, 0, 5, "black"] : false }, g2() { - const { x, y, r, b = 4, shape = 'cir', ls = 'black', fs = '#ccc', sh } = this; - return shape === 'cir' ? g2().cir({ x, y, r, ls, fs, sh }).ins((g) => this.label && this.drawLabel(g)) - : g2().rec({ x: x - b, y: y - b, b: 2 * b, h: 2 * b, ls, fs, sh }).ins((g) => this.label && this.drawLabel(g)); + const { x, y, r, b = 4, ls = 'black', fs = 'palegreen', sh } = this; + + return g2().cir({ x, y, r, ls, fs, sh }).ins((g) => this.label && this.drawLabel(g)); } }); @@ -363,8 +364,8 @@ g2.prototype.nod.prototype = g2.mix(g2.prototype.cir.prototype, { */ g2.prototype.dblnod = function ({ x = 0, y = 0 }) { return this.addCommand({ c: 'dblnod', a: arguments[0] }); } g2.prototype.dblnod.prototype = g2.mix(g2.prototype.cir.prototype, { - get r() { return 6; }, - get isSolid() { return true; }, + r: 6, + isSolid: true, g2() { return g2() .beg({ x: this.x, y: this.y }) @@ -390,7 +391,7 @@ g2.prototype.pol.prototype = g2.mix(g2.prototype.nod.prototype, { g2() { return g2() .beg(g2.flatten(this)) - .cir({ r: 6, fs: g2.symbol.nodfill }) + .cir({ r: 6, fs: '@fs2' }) .cir({ r: 2.5, fs: '@ls', ls: 'transparent' }) .end() .ins((g) => this.label && this.drawLabel(g)); diff --git a/src/g2.hdl.canvas.js b/src/g2.hdl.canvas.js index b7f2dfd..b30751c 100644 --- a/src/g2.hdl.canvas.js +++ b/src/g2.hdl.canvas.js @@ -346,13 +346,16 @@ g2.canvasHdl.prototype = { let q, prv = {}; for (const key in style) { if (this.get[key]) { // style keys only ... + let keyval = style[key]; if (typeof style[key] === 'string' && style[key][0] === '@') { - let ref = style[key].substr(1); - style[key] = g2.symbol[ref] || this.get[ref] && this.get[ref](this.ctx); + // also check inherited styles ... + const ref = style[key].substr(1); + keyval = g2.symbol[ref] || ref in this.get && this.get[ref](this.ctx) + || ref in this.cur && this.cur[ref]; } - if ((q = this.get[key](this.ctx)) !== style[key]) { + if ((q = this.get[key](this.ctx)) !== keyval) { prv[key] = q; - this.set[key](this.ctx, style[key]); + this.set[key](this.ctx, keyval); } } } @@ -364,14 +367,17 @@ g2.canvasHdl.prototype = { }, pushStyle(style) { let cur = {}; // hold changed properties ... - for (const key in style) - if (this.get[key]) { // style keys only ... + for (const key in style) // allow extended style syntax ('fs-2', ...) + if (g2.styleRex.test(key)) { // (extended) style keys only ... if (typeof style[key] === 'string' && style[key][0] === '@') { let ref = style[key].substr(1); style[key] = g2.symbol[ref] || this.get[ref] && this.get[ref](this.ctx); } - if (this.cur[key] !== style[key]) - this.set[key](this.ctx, (cur[key] = style[key])); + if (this.cur[key] !== style[key]) { + if (key in this.set) + this.set[key](this.ctx, style[key]); + cur[key] = style[key]; + } } this.stack.push(this.cur = Object.assign({}, this.cur, cur)); },