diff --git a/lib/sequence-diagram.js b/lib/sequence-diagram.js index 52bfb8d..e0ef09f 100644 --- a/lib/sequence-diagram.js +++ b/lib/sequence-diagram.js @@ -3111,6 +3111,10 @@ define('svg/SVGShapes',['./SVGUtilities', './SVGTextBlock'], (svg, SVGTextBlock) return svg.make('rect', Object.assign({}, position, attrs)); } + function renderLine(attrs, position) { + return svg.make('line', Object.assign({}, position, attrs)); + } + function renderNote(attrs, flickAttrs, position) { const g = svg.make('g'); const x0 = position.x; @@ -3210,6 +3214,7 @@ define('svg/SVGShapes',['./SVGUtilities', './SVGTextBlock'], (svg, SVGTextBlock) return { renderBox, + renderLine, renderNote, renderBoxedText, TextBlock: SVGTextBlock, @@ -3234,6 +3239,7 @@ define('sequence/components/BaseComponent',[],() => { textSizer, addSpacing, addSeparation, + state, components, }*/) { } @@ -3245,6 +3251,7 @@ define('sequence/components/BaseComponent',[],() => { textSizer, addSpacing, addSeparation, + state, components, }*/) { } @@ -3318,7 +3325,8 @@ define('sequence/components/Block',[ class BlockSplit extends BaseComponent { separation({left, right, mode, label}, env) { - const config = env.theme.block.section; + const blockInfo = env.state.blocks.get(left); + const config = env.theme.getBlock(blockInfo.mode).section; const width = ( env.textSizer.measure(config.mode.labelAttrs, mode).width + config.mode.padding.left + @@ -3337,21 +3345,15 @@ define('sequence/components/Block',[ } render({left, right, mode, label}, env, first = false) { - const config = env.theme.block; + const blockInfo = env.state.blocks.get(left); + const config = env.theme.getBlock(blockInfo.mode); const agentInfoL = env.agentInfos.get(left); const agentInfoR = env.agentInfos.get(right); - const {hold} = env.state.blocks.get(left); let y = env.primaryY; if(!first) { y += config.section.padding.bottom; - hold.appendChild(svg.make('line', Object.assign({ - 'x1': agentInfoL.x, - 'y1': y, - 'x2': agentInfoR.x, - 'y2': y, - }, config.separator.attrs))); } const clickable = env.makeRegion(); @@ -3361,8 +3363,9 @@ define('sequence/components/Block',[ y, padding: config.section.mode.padding, boxAttrs: config.section.mode.boxAttrs, + boxRenderer: config.section.mode.boxRenderer, labelAttrs: config.section.mode.labelAttrs, - boxLayer: hold, + boxLayer: blockInfo.hold, labelLayer: clickable, SVGTextBlockClass: env.SVGTextBlockClass, }); @@ -3388,6 +3391,15 @@ define('sequence/components/Block',[ 'fill': 'transparent', }), clickable.firstChild); + if(!first) { + blockInfo.hold.appendChild(config.sepRenderer({ + 'x1': agentInfoL.x, + 'y1': y, + 'x2': agentInfoR.x, + 'y2': y, + })); + } + return y + labelHeight + config.section.padding.top; } } @@ -3401,15 +3413,31 @@ define('sequence/components/Block',[ state.blocks.clear(); } + storeBlockInfo(stage, env) { + env.state.blocks.set(stage.left, { + mode: stage.mode, + hold: null, + startY: null, + }); + } + + separationPre(stage, env) { + this.storeBlockInfo(stage, env); + } + separation(stage, env) { array.mergeSets(env.visibleAgents, [stage.left, stage.right]); super.separation(stage, env); } - renderPre({left, right}, env) { + renderPre(stage, env) { + this.storeBlockInfo(stage, env); + + const config = env.theme.getBlock(stage.mode); + return { - agentNames: [left, right], - topShift: env.theme.block.margin.top, + agentNames: [stage.left, stage.right], + topShift: config.margin.top, }; } @@ -3417,11 +3445,9 @@ define('sequence/components/Block',[ const hold = svg.make('g'); env.blockLayer.appendChild(hold); - env.state.blocks.set(stage.left, { - hold, - mode: stage.mode, - startY: env.primaryY, - }); + const blockInfo = env.state.blocks.get(stage.left); + blockInfo.hold = hold; + blockInfo.startY = env.primaryY; return super.render(stage, env, true); } @@ -3433,25 +3459,27 @@ define('sequence/components/Block',[ } renderPre({left, right}, env) { + const blockInfo = env.state.blocks.get(left); + const config = env.theme.getBlock(blockInfo.mode); + return { agentNames: [left, right], - topShift: env.theme.block.section.padding.bottom, + topShift: config.section.padding.bottom, }; } render({left, right}, env) { - const config = env.theme.block; - + const blockInfo = env.state.blocks.get(left); + const config = env.theme.getBlock(blockInfo.mode); const agentInfoL = env.agentInfos.get(left); const agentInfoR = env.agentInfos.get(right); - const {hold, startY, mode} = env.state.blocks.get(left); - const configMode = config.modes[mode] || config.modes['']; - hold.appendChild(svg.make('rect', Object.assign({ - 'x': agentInfoL.x, - 'y': startY, - 'width': agentInfoR.x - agentInfoL.x, - 'height': env.primaryY - startY, - }, configMode.boxAttrs))); + + blockInfo.hold.appendChild(config.boxRenderer({ + x: agentInfoL.x, + y: blockInfo.startY, + width: agentInfoR.x - agentInfoL.x, + height: env.primaryY - blockInfo.startY, + })); return env.primaryY + config.margin.bottom + env.theme.actionMargin; } @@ -3969,19 +3997,6 @@ define('sequence/components/Connect',[ ) => { 'use strict'; - function drawHorizontalArrowHead({x, y, dx, dy, attrs}) { - return svg.make( - attrs.fill === 'none' ? 'polyline' : 'polygon', - Object.assign({ - 'points': ( - (x + dx) + ' ' + (y - dy) + ' ' + - x + ' ' + y + ' ' + - (x + dx) + ' ' + (y + dy) - ), - }, attrs) - ); - } - class Arrowhead { constructor(propName) { this.propName = propName; @@ -4008,13 +4023,11 @@ define('sequence/components/Connect',[ render(layer, theme, pt, dir) { const config = this.getConfig(theme); - const func = config.render || drawHorizontalArrowHead; - layer.appendChild(func({ + layer.appendChild(config.render(config.attrs, { x: pt.x + this.short(theme) * dir, y: pt.y, dx: config.width * dir, dy: config.height / 2, - attrs: config.attrs, })); } @@ -4821,6 +4834,7 @@ define('sequence/Renderer',[ textSizer: this.sizer, addSpacing, addSeparation: this.addSeparation, + state: this.state, components: this.components, }; const component = this.components.get(stage.type); @@ -4889,13 +4903,13 @@ define('sequence/Renderer',[ return; } - this.theme.drawAgentLine(this.agentLines, { + this.agentLines.appendChild(this.theme.renderAgentLine({ x: agentInfo.x, y0: agentInfo.latestYStart, y1: toY, width: agentInfo.currentRad * 2, className: 'agent-' + agentInfo.index + '-line', - }); + })); } addHighlightObject(line, o) { @@ -5065,6 +5079,13 @@ define('sequence/Renderer',[ this.height = (y1 - y0); } + _resetState() { + this.components.forEach((component) => { + component.resetState(this.state); + }); + this.currentY = 0; + } + _reset() { this.knownDefs.clear(); this.highlights.clear(); @@ -5077,9 +5098,7 @@ define('sequence/Renderer',[ svg.empty(this.actionLabels); this.mask.appendChild(this.maskReveal); this.defs.appendChild(this.mask); - this.components.forEach((component) => { - component.resetState(this.state); - }); + this._resetState(); } setHighlight(line = null) { @@ -5124,7 +5143,7 @@ define('sequence/Renderer',[ this.maxX = 0; this.buildAgentInfos(sequence.agents, sequence.stages); - this.currentY = 0; + this._resetState(); sequence.stages.forEach(this.renderStage); const bottomY = this.checkAgentRange(['[', ']'], this.currentY); @@ -5274,12 +5293,126 @@ define('sequence/Exporter',[],() => { }; }); +define('sequence/themes/BaseTheme',['svg/SVGUtilities'], (svg) => { + 'use strict'; + + function deepCopy(o) { + if(typeof o !== 'object' || !o) { + return o; + } + const r = {}; + for(let k in o) { + if(o.hasOwnProperty(k)) { + r[k] = deepCopy(o[k]); + } + } + return r; + } + + class BaseTheme { + constructor({name, settings, blocks, notes}) { + this.name = name; + this.blocks = deepCopy(blocks); + this.notes = deepCopy(notes); + Object.assign(this, deepCopy(settings)); + } + + reset() { + } + + addDefs() { + } + + getBlock(type) { + return this.blocks[type] || this.blocks['']; + } + + getNote(type) { + return this.notes[type] || this.notes['']; + } + + renderAgentLine({x, y0, y1, width, className}) { + if(width > 0) { + return svg.make('rect', Object.assign({ + 'x': x - width / 2, + 'y': y0, + 'width': width, + 'height': y1 - y0, + 'class': className, + }, this.agentLineAttrs)); + } else { + return svg.make('line', Object.assign({ + 'x1': x, + 'y1': y0, + 'x2': x, + 'y2': y1, + 'class': className, + }, this.agentLineAttrs)); + } + } + } + + BaseTheme.renderHorizArrowHead = (attrs, {x, y, dx, dy}) => { + return svg.make( + attrs.fill === 'none' ? 'polyline' : 'polygon', + Object.assign({ + 'points': ( + (x + dx) + ' ' + (y - dy) + ' ' + + x + ' ' + y + ' ' + + (x + dx) + ' ' + (y + dy) + ), + }, attrs) + ); + }; + + BaseTheme.renderTag = (attrs, {x, y, width, height}) => { + const {rx, ry} = attrs; + const x2 = x + width; + const y2 = y + height; + + const line = ( + 'M' + x2 + ' ' + y + + 'L' + x2 + ' ' + (y2 - ry) + + 'L' + (x2 - rx) + ' ' + y2 + + 'L' + x + ' ' + y2 + ); + + const g = svg.make('g'); + if(attrs.fill !== 'none') { + g.appendChild(svg.make('path', Object.assign({ + 'd': line + 'L' + x + ' ' + y, + }, attrs, {'stroke': 'none'}))); + } + + if(attrs.stroke !== 'none') { + g.appendChild(svg.make('path', Object.assign({ + 'd': line, + }, attrs, {'fill': 'none'}))); + } + + return g; + }; + + BaseTheme.renderCross = (attrs, {x, y, radius}) => { + return svg.make('path', Object.assign({ + 'd': ( + 'M' + (x - radius) + ' ' + (y - radius) + + 'l' + (radius * 2) + ' ' + (radius * 2) + + 'm0 ' + (-radius * 2) + + 'l' + (-radius * 2) + ' ' + (radius * 2) + ), + }, attrs)); + }; + + return BaseTheme; +}); + define('sequence/themes/Basic',[ - 'core/ArrayUtilities', + './BaseTheme', 'svg/SVGUtilities', 'svg/SVGShapes', ], ( - array, + BaseTheme, svg, SVGShapes ) => { @@ -5319,33 +5452,19 @@ define('sequence/themes/Basic',[ }, cross: { size: 20, - render: ({x, y, radius}) => { - return svg.make('path', { - 'd': ( - 'M' + (x - radius) + ' ' + (y - radius) + - 'l' + (radius * 2) + ' ' + (radius * 2) + - 'm0 ' + (-radius * 2) + - 'l' + (-radius * 2) + ' ' + (radius * 2) - ), - 'fill': 'none', - 'stroke': '#000000', - 'stroke-width': 1, - }); - }, + render: BaseTheme.renderCross.bind(null, { + 'fill': 'none', + 'stroke': '#000000', + 'stroke-width': 1, + }), }, bar: { height: 4, - render: ({x, y, width, height}) => { - return svg.make('rect', { - 'x': x, - 'y': y, - 'width': width, - 'height': height, - 'fill': '#000000', - 'stroke': '#000000', - 'stroke-width': 1, - }); - }, + render: SVGShapes.renderBox.bind(null, { + 'fill': '#000000', + 'stroke': '#000000', + 'stroke-width': 1, + }), }, fade: { width: 5, @@ -5390,6 +5509,7 @@ define('sequence/themes/Basic',[ 'single': { width: 5, height: 10, + render: BaseTheme.renderHorizArrowHead, attrs: { 'fill': '#000000', 'stroke-width': 0, @@ -5399,6 +5519,7 @@ define('sequence/themes/Basic',[ 'double': { width: 4, height: 6, + render: BaseTheme.renderHorizArrowHead, attrs: { 'fill': 'none', 'stroke': '#000000', @@ -5432,82 +5553,6 @@ define('sequence/themes/Basic',[ }, }, - block: { - margin: { - top: 0, - bottom: 0, - }, - modes: { - 'ref': { - boxAttrs: { - 'fill': '#FFFFFF', - 'stroke': '#000000', - 'stroke-width': 1.5, - 'rx': 2, - 'ry': 2, - }, - }, - '': { - boxAttrs: { - 'fill': 'none', - 'stroke': '#000000', - 'stroke-width': 1.5, - 'rx': 2, - 'ry': 2, - }, - }, - }, - section: { - padding: { - top: 3, - bottom: 2, - }, - mode: { - padding: { - top: 1, - left: 3, - right: 3, - bottom: 0, - }, - boxAttrs: { - 'fill': '#FFFFFF', - 'stroke': '#000000', - 'stroke-width': 1, - 'rx': 2, - 'ry': 2, - }, - labelAttrs: { - 'font-family': FONT, - 'font-weight': 'bold', - 'font-size': 9, - 'line-height': LINE_HEIGHT, - 'text-anchor': 'left', - }, - }, - label: { - padding: { - top: 1, - left: 5, - right: 3, - bottom: 0, - }, - labelAttrs: { - 'font-family': FONT, - 'font-size': 8, - 'line-height': LINE_HEIGHT, - 'text-anchor': 'left', - }, - }, - }, - separator: { - attrs: { - 'stroke': '#000000', - 'stroke-width': 1.5, - 'stroke-dasharray': '4, 2', - }, - }, - }, - titleAttrs: { 'font-family': FONT, 'font-size': 20, @@ -5523,6 +5568,91 @@ define('sequence/themes/Basic',[ }, }; + const SHARED_BLOCK_SECTION = { + padding: { + top: 3, + bottom: 2, + }, + mode: { + padding: { + top: 1, + left: 3, + right: 3, + bottom: 0, + }, + boxRenderer: BaseTheme.renderTag.bind(null, { + 'fill': '#FFFFFF', + 'stroke': '#000000', + 'stroke-width': 1, + 'rx': 2, + 'ry': 2, + }), + labelAttrs: { + 'font-family': FONT, + 'font-weight': 'bold', + 'font-size': 9, + 'line-height': LINE_HEIGHT, + 'text-anchor': 'left', + }, + }, + label: { + padding: { + top: 1, + left: 5, + right: 3, + bottom: 0, + }, + labelAttrs: { + 'font-family': FONT, + 'font-size': 8, + 'line-height': LINE_HEIGHT, + 'text-anchor': 'left', + }, + }, + }; + + const BLOCKS = { + 'ref': { + margin: { + top: 0, + bottom: 0, + }, + boxRenderer: SVGShapes.renderBox.bind(null, { + 'fill': '#FFFFFF', + 'stroke': '#000000', + 'stroke-width': 1.5, + 'rx': 2, + 'ry': 2, + }), + section: SHARED_BLOCK_SECTION, + }, + '': { + margin: { + top: 0, + bottom: 0, + }, + boxRenderer: SVGShapes.renderBox.bind(null, { + 'fill': 'none', + 'stroke': '#000000', + 'stroke-width': 1.5, + 'rx': 2, + 'ry': 2, + }), + section: SHARED_BLOCK_SECTION, + sepRenderer: SVGShapes.renderLine.bind(null, { + 'stroke': '#000000', + 'stroke-width': 1.5, + 'stroke-dasharray': '4, 2', + }), + }, + }; + + const NOTE_ATTRS = { + 'font-family': FONT, + 'font-size': 8, + 'line-height': LINE_HEIGHT, + }; + const NOTES = { 'text': { margin: {top: 0, left: 2, right: 2, bottom: 0}, @@ -5531,11 +5661,7 @@ define('sequence/themes/Basic',[ boxRenderer: SVGShapes.renderBox.bind(null, { 'fill': '#FFFFFF', }), - labelAttrs: { - 'font-family': FONT, - 'font-size': 8, - 'line-height': LINE_HEIGHT, - }, + labelAttrs: NOTE_ATTRS, }, 'note': { margin: {top: 0, left: 5, right: 5, bottom: 0}, @@ -5550,11 +5676,7 @@ define('sequence/themes/Basic',[ 'stroke': '#000000', 'stroke-width': 1, }), - labelAttrs: { - 'font-family': FONT, - 'font-size': 8, - 'line-height': LINE_HEIGHT, - }, + labelAttrs: NOTE_ATTRS, }, 'state': { margin: {top: 0, left: 5, right: 5, bottom: 0}, @@ -5567,58 +5689,28 @@ define('sequence/themes/Basic',[ 'rx': 10, 'ry': 10, }), - labelAttrs: { - 'font-family': FONT, - 'font-size': 8, - 'line-height': LINE_HEIGHT, - }, + labelAttrs: NOTE_ATTRS, }, }; - return class BasicTheme { + return class BasicTheme extends BaseTheme { constructor() { - this.name = 'basic'; - Object.assign(this, SETTINGS); - } - - reset() { - } - - addDefs() { - } - - getNote(type) { - return NOTES[type]; - } - - drawAgentLine(container, {x, y0, y1, width, className}) { - if(width > 0) { - container.appendChild(svg.make('rect', Object.assign({ - 'x': x - width / 2, - 'y': y0, - 'width': width, - 'height': y1 - y0, - 'class': className, - }, this.agentLineAttrs))); - } else { - container.appendChild(svg.make('line', Object.assign({ - 'x1': x, - 'y1': y0, - 'x2': x, - 'y2': y1, - 'class': className, - }, this.agentLineAttrs))); - } + super({ + name: 'basic', + settings: SETTINGS, + blocks: BLOCKS, + notes: NOTES, + }); } }; }); define('sequence/themes/Chunky',[ - 'core/ArrayUtilities', + './BaseTheme', 'svg/SVGUtilities', 'svg/SVGShapes', ], ( - array, + BaseTheme, svg, SVGShapes ) => { @@ -5661,37 +5753,22 @@ define('sequence/themes/Chunky',[ }, cross: { size: 20, - render: ({x, y, radius}) => { - return svg.make('path', Object.assign({ - 'd': ( - 'M' + (x - radius) + ' ' + (y - radius) + - 'l' + (radius * 2) + ' ' + (radius * 2) + - 'm0 ' + (-radius * 2) + - 'l' + (-radius * 2) + ' ' + (radius * 2) - ), - }, { - 'fill': 'none', - 'stroke': '#000000', - 'stroke-width': 3, - 'stroke-linecap': 'round', - })); - }, + render: BaseTheme.renderCross.bind(null, { + 'fill': 'none', + 'stroke': '#000000', + 'stroke-width': 3, + 'stroke-linecap': 'round', + }), }, bar: { height: 4, - render: ({x, y, width, height}) => { - return svg.make('rect', { - 'x': x, - 'y': y, - 'width': width, - 'height': height, - 'fill': '#000000', - 'stroke': '#000000', - 'stroke-width': 3, - 'rx': 2, - 'ry': 2, - }); - }, + render: SVGShapes.renderBox.bind(null, { + 'fill': '#000000', + 'stroke': '#000000', + 'stroke-width': 3, + 'rx': 2, + 'ry': 2, + }), }, fade: { width: 5, @@ -5736,6 +5813,7 @@ define('sequence/themes/Chunky',[ single: { width: 10, height: 12, + render: BaseTheme.renderHorizArrowHead, attrs: { 'fill': '#000000', 'stroke': '#000000', @@ -5746,6 +5824,7 @@ define('sequence/themes/Chunky',[ double: { width: 10, height: 12, + render: BaseTheme.renderHorizArrowHead, attrs: { 'fill': 'none', 'stroke': '#000000', @@ -5780,82 +5859,6 @@ define('sequence/themes/Chunky',[ }, }, - block: { - margin: { - top: 0, - bottom: 0, - }, - modes: { - 'ref': { - boxAttrs: { - 'fill': '#FFFFFF', - 'stroke': '#000000', - 'stroke-width': 4, - 'rx': 5, - 'ry': 5, - }, - }, - '': { - boxAttrs: { - 'fill': 'none', - 'stroke': '#000000', - 'stroke-width': 4, - 'rx': 5, - 'ry': 5, - }, - }, - }, - section: { - padding: { - top: 3, - bottom: 4, - }, - mode: { - padding: { - top: 2, - left: 5, - right: 5, - bottom: 1, - }, - boxAttrs: { - 'fill': '#FFFFFF', - 'stroke': '#000000', - 'stroke-width': 2, - 'rx': 3, - 'ry': 3, - }, - labelAttrs: { - 'font-family': FONT, - 'font-weight': 'bold', - 'font-size': 9, - 'line-height': LINE_HEIGHT, - 'text-anchor': 'left', - }, - }, - label: { - padding: { - top: 2, - left: 5, - right: 3, - bottom: 0, - }, - labelAttrs: { - 'font-family': FONT, - 'font-size': 8, - 'line-height': LINE_HEIGHT, - 'text-anchor': 'left', - }, - }, - }, - separator: { - attrs: { - 'stroke': '#000000', - 'stroke-width': 2, - 'stroke-dasharray': '5, 3', - }, - }, - }, - titleAttrs: { 'font-family': FONT, 'font-weight': 'bolder', @@ -5872,6 +5875,91 @@ define('sequence/themes/Chunky',[ }, }; + const SHARED_BLOCK_SECTION = { + padding: { + top: 3, + bottom: 4, + }, + mode: { + padding: { + top: 2, + left: 5, + right: 5, + bottom: 1, + }, + boxRenderer: BaseTheme.renderTag.bind(null, { + 'fill': '#FFFFFF', + 'stroke': '#000000', + 'stroke-width': 2, + 'rx': 3, + 'ry': 3, + }), + labelAttrs: { + 'font-family': FONT, + 'font-weight': 'bold', + 'font-size': 9, + 'line-height': LINE_HEIGHT, + 'text-anchor': 'left', + }, + }, + label: { + padding: { + top: 2, + left: 5, + right: 3, + bottom: 0, + }, + labelAttrs: { + 'font-family': FONT, + 'font-size': 8, + 'line-height': LINE_HEIGHT, + 'text-anchor': 'left', + }, + }, + }; + + const BLOCKS = { + 'ref': { + margin: { + top: 0, + bottom: 0, + }, + boxRenderer: SVGShapes.renderBox.bind(null, { + 'fill': '#FFFFFF', + 'stroke': '#000000', + 'stroke-width': 4, + 'rx': 5, + 'ry': 5, + }), + section: SHARED_BLOCK_SECTION, + }, + '': { + margin: { + top: 0, + bottom: 0, + }, + boxRenderer: SVGShapes.renderBox.bind(null, { + 'fill': 'none', + 'stroke': '#000000', + 'stroke-width': 4, + 'rx': 5, + 'ry': 5, + }), + section: SHARED_BLOCK_SECTION, + sepRenderer: SVGShapes.renderLine.bind(null, { + 'stroke': '#000000', + 'stroke-width': 2, + 'stroke-dasharray': '5, 3', + }), + }, + }; + + const NOTE_ATTRS = { + 'font-family': FONT, + 'font-size': 8, + 'line-height': LINE_HEIGHT, + }; + const NOTES = { 'text': { margin: {top: 0, left: 2, right: 2, bottom: 0}, @@ -5880,11 +5968,7 @@ define('sequence/themes/Chunky',[ boxRenderer: SVGShapes.renderBox.bind(null, { 'fill': '#FFFFFF', }), - labelAttrs: { - 'font-family': FONT, - 'font-size': 8, - 'line-height': LINE_HEIGHT, - }, + labelAttrs: NOTE_ATTRS, }, 'note': { margin: {top: 0, left: 5, right: 5, bottom: 0}, @@ -5900,11 +5984,7 @@ define('sequence/themes/Chunky',[ 'stroke': '#000000', 'stroke-width': 1, }), - labelAttrs: { - 'font-family': FONT, - 'font-size': 8, - 'line-height': LINE_HEIGHT, - }, + labelAttrs: NOTE_ATTRS, }, 'state': { margin: {top: 0, left: 5, right: 5, bottom: 0}, @@ -5917,48 +5997,18 @@ define('sequence/themes/Chunky',[ 'rx': 10, 'ry': 10, }), - labelAttrs: { - 'font-family': FONT, - 'font-size': 8, - 'line-height': LINE_HEIGHT, - }, + labelAttrs: NOTE_ATTRS, }, }; - return class ChunkyTheme { + return class ChunkyTheme extends BaseTheme { constructor() { - this.name = 'chunky'; - Object.assign(this, SETTINGS); - } - - reset() { - } - - addDefs() { - } - - getNote(type) { - return NOTES[type]; - } - - drawAgentLine(container, {x, y0, y1, width, className}) { - if(width > 0) { - container.appendChild(svg.make('rect', Object.assign({ - 'x': x - width / 2, - 'y': y0, - 'width': width, - 'height': y1 - y0, - 'class': className, - }, this.agentLineAttrs))); - } else { - container.appendChild(svg.make('line', Object.assign({ - 'x1': x, - 'y1': y0, - 'x2': x, - 'y2': y1, - 'class': className, - }, this.agentLineAttrs))); - } + super({ + name: 'chunky', + settings: SETTINGS, + blocks: BLOCKS, + notes: NOTES, + }); } }; }); @@ -6399,12 +6449,12 @@ define('sequence/themes/HandleeFontData',[],() => { }); define('sequence/themes/Sketch',[ - 'core/ArrayUtilities', + './BaseTheme', 'svg/SVGUtilities', 'svg/SVGShapes', './HandleeFontData', ], ( - array, + BaseTheme, svg, SVGShapes, Handlee @@ -6413,25 +6463,11 @@ define('sequence/themes/Sketch',[ // TODO: // * fade starter/terminator sometimes does not fully cover line - // * blocks (if/else/repeat/ref) const FONT = Handlee.name; const FONT_FAMILY = '"' + FONT + '",cursive'; const LINE_HEIGHT = 1.5; - function deepCopy(o) { - if(typeof o !== 'object' || !o) { - return o; - } - const r = {}; - for(let k in o) { - if(o.hasOwnProperty(k)) { - r[k] = deepCopy(o[k]); - } - } - return r; - } - const PENCIL = { 'stroke': 'rgba(0,0,0,0.7)', 'stroke-width': 0.8, @@ -6439,6 +6475,13 @@ define('sequence/themes/Sketch',[ 'stroke-linecap': 'round', }; + const THICK_PENCIL = { + 'stroke': 'rgba(0,0,0,0.8)', + 'stroke-width': 1.2, + 'stroke-linejoin': 'round', + 'stroke-linecap': 'round', + }; + const SETTINGS = { titleMargin: 10, outerMargin: 5, @@ -6554,82 +6597,6 @@ define('sequence/themes/Sketch',[ }, }, - block: { - margin: { - top: 0, - bottom: 0, - }, - modes: { - 'ref': { - boxAttrs: { - 'fill': '#FFFFFF', - 'stroke': '#000000', - 'stroke-width': 1.5, - 'rx': 2, - 'ry': 2, - }, - }, - '': { - boxAttrs: { - 'fill': 'none', - 'stroke': '#000000', - 'stroke-width': 1.5, - 'rx': 2, - 'ry': 2, - }, - }, - }, - section: { - padding: { - top: 3, - bottom: 2, - }, - mode: { - padding: { - top: 1, - left: 3, - right: 3, - bottom: 0, - }, - boxAttrs: { - 'fill': '#FFFFFF', - 'stroke': '#000000', - 'stroke-width': 1, - 'rx': 2, - 'ry': 2, - }, - labelAttrs: { - 'font-family': FONT_FAMILY, - 'font-weight': 'bold', - 'font-size': 9, - 'line-height': LINE_HEIGHT, - 'text-anchor': 'left', - }, - }, - label: { - padding: { - top: 1, - left: 5, - right: 3, - bottom: 0, - }, - labelAttrs: { - 'font-family': FONT_FAMILY, - 'font-size': 8, - 'line-height': LINE_HEIGHT, - 'text-anchor': 'left', - }, - }, - }, - separator: { - attrs: { - 'stroke': '#000000', - 'stroke-width': 1.5, - 'stroke-dasharray': '4, 2', - }, - }, - }, - titleAttrs: { 'font-family': FONT_FAMILY, 'font-size': 20, @@ -6645,6 +6612,69 @@ define('sequence/themes/Sketch',[ }, }; + const SHARED_BLOCK_SECTION = { + padding: { + top: 3, + bottom: 2, + }, + mode: { + padding: { + top: 2, + left: 3, + right: 5, + bottom: 0, + }, + boxRenderer: null, + labelAttrs: { + 'font-family': FONT_FAMILY, + 'font-weight': 'bold', + 'font-size': 9, + 'line-height': LINE_HEIGHT, + 'text-anchor': 'left', + }, + }, + label: { + padding: { + top: 1, + left: 5, + right: 3, + bottom: 0, + }, + labelAttrs: { + 'font-family': FONT_FAMILY, + 'font-size': 8, + 'line-height': LINE_HEIGHT, + 'text-anchor': 'left', + }, + }, + }; + + const BLOCKS = { + 'ref': { + margin: { + top: 0, + bottom: 0, + }, + boxRenderer: null, + section: SHARED_BLOCK_SECTION, + }, + '': { + margin: { + top: 0, + bottom: 0, + }, + boxRenderer: null, + section: SHARED_BLOCK_SECTION, + sepRenderer: null, + }, + }; + + const NOTE_ATTRS = { + 'font-family': FONT_FAMILY, + 'font-size': 8, + 'line-height': LINE_HEIGHT, + }; + const NOTES = { 'text': { margin: {top: 0, left: 2, right: 2, bottom: 0}, @@ -6653,33 +6683,21 @@ define('sequence/themes/Sketch',[ boxRenderer: SVGShapes.renderBox.bind(null, { 'fill': '#FFFFFF', }), - labelAttrs: { - 'font-family': FONT_FAMILY, - 'font-size': 8, - 'line-height': LINE_HEIGHT, - }, + labelAttrs: NOTE_ATTRS, }, 'note': { margin: {top: 0, left: 5, right: 5, bottom: 0}, padding: {top: 5, left: 5, right: 10, bottom: 5}, overlap: {left: 10, right: 10}, boxRenderer: null, - labelAttrs: { - 'font-family': FONT_FAMILY, - 'font-size': 8, - 'line-height': LINE_HEIGHT, - }, + labelAttrs: NOTE_ATTRS, }, 'state': { margin: {top: 0, left: 5, right: 5, bottom: 0}, padding: {top: 7, left: 7, right: 7, bottom: 7}, overlap: {left: 10, right: 10}, boxRenderer: null, - labelAttrs: { - 'font-family': FONT_FAMILY, - 'font-size': 8, - 'line-height': LINE_HEIGHT, - }, + labelAttrs: NOTE_ATTRS, }, }; @@ -6724,8 +6742,15 @@ define('sequence/themes/Sketch',[ const RIGHT = {}; const LEFT = {}; - class SketchTheme { + class SketchTheme extends BaseTheme { constructor(handedness = RIGHT) { + super({ + name: '', + settings: SETTINGS, + blocks: BLOCKS, + notes: NOTES, + }); + if(handedness === RIGHT) { this.name = 'sketch'; this.handedness = 1; @@ -6734,17 +6759,31 @@ define('sequence/themes/Sketch',[ this.handedness = -1; } this.random = new Random(); - Object.assign(this, deepCopy(SETTINGS)); - this.notes = deepCopy(NOTES); + + this._assignFunctions(); + } + + _assignFunctions() { + this.renderBar = this.renderBar.bind(this); + this.renderBox = this.renderBox.bind(this); + this.renderArrowHead = this.renderArrowHead.bind(this); + this.renderConnect = this.renderConnect.bind(this); + this.renderTag = this.renderTag.bind(this); + this.agentCap.cross.render = this.renderCross.bind(this); - this.agentCap.bar.render = this.renderBar.bind(this); - this.agentCap.box.boxRenderer = this.renderBox.bind(this); - this.connect.arrow.single.render = this.renderArrowHead.bind(this); - this.connect.arrow.double.render = this.renderArrowHead.bind(this); - this.connect.line.solid.render = this.renderConnect.bind(this); - this.connect.line.dash.render = this.renderConnect.bind(this); + this.agentCap.bar.render = this.renderBar; + this.agentCap.box.boxRenderer = this.renderBox; + this.connect.arrow.single.render = this.renderArrowHead; + this.connect.arrow.double.render = this.renderArrowHead; + this.connect.line.solid.render = this.renderConnect; + this.connect.line.dash.render = this.renderConnect; this.notes.note.boxRenderer = this.renderNote.bind(this); this.notes.state.boxRenderer = this.renderState.bind(this); + this.blocks.ref.boxRenderer = this.renderRefBlock.bind(this); + this.blocks[''].boxRenderer = this.renderBlock.bind(this); + this.blocks.ref.section.mode.boxRenderer = this.renderTag; + this.blocks[''].section.mode.boxRenderer = this.renderTag; + this.blocks[''].sepRenderer = this.renderSeparator.bind(this); } reset() { @@ -6834,11 +6873,12 @@ define('sequence/themes/Sketch',[ const shape = svg.make('path', Object.assign({ 'd': line.nodes, 'fill': 'none', - }, PENCIL)); + 'stroke-dasharray': lineOptions.dash ? '6, 5' : 'none', + }, lineOptions.thick ? THICK_PENCIL : PENCIL)); return shape; } - renderBox({x, y, width, height}, {fill = null} = {}) { + renderBox({x, y, width, height}, {fill = null, thick = false} = {}) { const lT = this.lineNodes( {x, y}, {x: x + width, y}, @@ -6863,7 +6903,7 @@ define('sequence/themes/Sketch',[ const shape = svg.make('path', Object.assign({ 'd': lT.nodes + lR.nodes + lB.nodes + lL.nodes, 'fill': fill || '#FFFFFF', - }, PENCIL)); + }, thick ? THICK_PENCIL : PENCIL)); return shape; } @@ -6938,7 +6978,7 @@ define('sequence/themes/Sketch',[ }; } - renderArrowHead({x, y, dx, dy, attrs}) { + renderArrowHead(attrs, {x, y, dx, dy}) { const w = dx * (1 + this.vary(0.2)); const h = dy * (1 + this.vary(0.3)); const l1 = this.lineNodes( @@ -6966,6 +7006,60 @@ define('sequence/themes/Sketch',[ return this.renderBox({x, y, width, height}); } + renderRefBlock({x, y, width, height}) { + return this.renderBox( + {x, y, width, height}, + {fill: '#FFFFFF', thick: true} + ); + } + + renderBlock({x, y, width, height}) { + return this.renderBox( + {x, y, width, height}, + {fill: 'none', thick: true} + ); + } + + renderTag({x, y, width, height}) { + const x2 = x + width; + const y2 = y + height; + + const l1 = this.lineNodes( + {x: x2 + 3, y}, + {x: x2 - 2, y: y2}, + {} + ); + const l2 = this.lineNodes( + l1.p2, + {x, y: y2 + 1}, + {var1: 0, move: false} + ); + + const line = l1.nodes + l2.nodes; + + const g = svg.make('g'); + + g.appendChild(svg.make('path', { + 'd': line + 'L' + x + ' ' + y, + 'fill': '#FFFFFF', + })); + + g.appendChild(svg.make('path', Object.assign({ + 'd': line, + 'fill': '#FFFFFF', + }, PENCIL))); + + return g; + } + + renderSeparator({x1, y1, x2, y2}) { + return this.renderLine( + {x: x1, y: y1}, + {x: x2, y: y2}, + {thick: true, dash: true} + ); + } + renderBar({x, y, width, height}) { return this.renderBox({x, y, width, height}, {fill: '#000000'}); } @@ -6990,11 +7084,7 @@ define('sequence/themes/Sketch',[ }, PENCIL)); } - getNote(type) { - return this.notes[type]; - } - - drawAgentLine(container, {x, y0, y1, width, className}) { + renderAgentLine({x, y0, y1, width, className}) { if(width > 0) { const shape = this.renderBox({ x: x - width / 2, @@ -7003,7 +7093,7 @@ define('sequence/themes/Sketch',[ height: y1 - y0, }, {fill: 'none'}); shape.setAttribute('class', className); - container.appendChild(shape); + return shape; } else { const shape = this.renderLine( {x, y: y0}, @@ -7011,7 +7101,7 @@ define('sequence/themes/Sketch',[ {varY: 0.3} ); shape.setAttribute('class', className); - container.appendChild(shape); + return shape; } } } @@ -7029,6 +7119,7 @@ define('sequence/SequenceDiagram',[ './Generator', './Renderer', './Exporter', + './themes/BaseTheme', './themes/Basic', './themes/Chunky', './themes/Sketch', @@ -7038,6 +7129,7 @@ define('sequence/SequenceDiagram',[ Generator, Renderer, Exporter, + BaseTheme, BasicTheme, ChunkyTheme, SketchTheme @@ -7258,6 +7350,7 @@ define('sequence/SequenceDiagram',[ Generator, Renderer, Exporter, + BaseTheme, themes, addTheme, registerCodeMirrorMode, diff --git a/lib/sequence-diagram.min.js b/lib/sequence-diagram.min.js index ee7b527..f1fce94 100644 --- a/lib/sequence-diagram.min.js +++ b/lib/sequence-diagram.min.js @@ -1 +1 @@ -!function(){var e,t,n;!function(s){function i(e,t){return x.call(e,t)}function r(e,t){var n,s,i,r,a,o,h,l,g,d,c,u=t&&t.split("/"),p=b.map,m=p&&p["*"]||{};if(e){for(a=(e=e.split("/")).length-1,b.nodeIdCompat&&w.test(e[a])&&(e[a]=e[a].replace(w,"")),"."===e[0].charAt(0)&&u&&(e=u.slice(0,u.length-1).concat(e)),g=0;g0&&(e.splice(g-1,2),g-=2)}e=e.join("/")}if((u||m)&&p){for(g=(n=e.split("/")).length;g>0;g-=1){if(s=n.slice(0,g).join("/"),u)for(d=u.length;d>0;d-=1)if((i=p[u.slice(0,d).join("/")])&&(i=i[s])){r=i,o=g;break}if(r)break;!h&&m&&m[s]&&(h=m[s],l=g)}!r&&h&&(r=h,o=l),r&&(n.splice(0,o,r),e=n.join("/"))}return e}function a(e,t){return function(){var n=k.call(arguments,0);return"string"!=typeof n[0]&&1===n.length&&n.push(null),c.apply(s,n.concat([e,t]))}}function o(e){return function(t){m[e]=t}}function h(e){if(i(f,e)){var t=f[e];delete f[e],y[e]=!0,d.apply(s,t)}if(!i(m,e)&&!i(y,e))throw new Error("No "+e);return m[e]}function l(e){var t,n=e?e.indexOf("!"):-1;return n>-1&&(t=e.substring(0,n),e=e.substring(n+1,e.length)),[t,e]}function g(e){return e?l(e):[]}var d,c,u,p,m={},f={},b={},y={},x=Object.prototype.hasOwnProperty,k=[].slice,w=/\.js$/;u=function(e,t){var n,s=l(e),i=s[0],a=t[1];return e=s[1],i&&(n=h(i=r(i,a))),i?e=n&&n.normalize?n.normalize(e,function(e){return function(t){return r(t,e)}}(a)):r(e,a):(i=(s=l(e=r(e,a)))[0],e=s[1],i&&(n=h(i))),{f:i?i+"!"+e:e,n:e,pr:i,p:n}},p={require:function(e){return a(e)},exports:function(e){var t=m[e];return void 0!==t?t:m[e]={}},module:function(e){return{id:e,uri:"",exports:m[e],config:function(e){return function(){return b&&b.config&&b.config[e]||{}}}(e)}}},d=function(e,t,n,r){var l,d,c,b,x,k,w,A=[],v=typeof n;if(r=r||e,k=g(r),"undefined"===v||"function"===v){for(t=!t.length&&n.length?["require","exports","module"]:t,x=0;x{"use strict";return class{constructor(){this.listeners=new Map,this.forwards=new Set}addEventListener(e,t){const n=this.listeners.get(e);n?n.push(t):this.listeners.set(e,[t])}removeEventListener(e,t){const n=this.listeners.get(e);if(!n)return;const s=n.indexOf(t);-1!==s&&n.splice(s,1)}countEventListeners(e){return(this.listeners.get(e)||[]).length}removeAllEventListeners(e){e?this.listeners.delete(e):this.listeners.clear()}addEventForwarding(e){this.forwards.add(e)}removeEventForwarding(e){this.forwards.delete(e)}removeAllEventForwardings(){this.forwards.clear()}trigger(e,t=[]){(this.listeners.get(e)||[]).forEach(e=>e.apply(null,t)),this.forwards.forEach(n=>n.trigger(e,t))}}}),n("core/ArrayUtilities",[],()=>{"use strict";function e(e,t,n=null){if(null===n)return e.indexOf(t);for(let s=0;s=e.length)return void i.push(s.slice());const r=e[n];if(!Array.isArray(r))return s.push(r),t(e,n+1,s,i),void s.pop();for(let a=0;a{n.push(...t(e))}),n}}}),n("sequence/CodeMirrorMode",["core/ArrayUtilities"],e=>{"use strict";function t(e,t,n,s){return""===t?function(e,t,n){return"object"==typeof n.suggest&&n.suggest.global?[n.suggest]:"string"!=typeof n.suggest||t.suggest===n.suggest?null:e["known"+n.suggest]}(e,n,s):!0===s.suggest?[function(e,t){return Object.keys(t.then).length>0?e+" ":e+"\n"}(t,s)]:Array.isArray(s.suggest)?s.suggest:s.suggest?[s.suggest]:null}function n(n,s){const i=[],r=e.last(s);return Object.keys(r.then).forEach(a=>{let o=r.then[a];"number"==typeof o&&(o=s[s.length-o-1]),e.mergeSets(i,t(n,a,r,o))}),i}function s(t,n,s,{suggest:i,override:r}){n.type&&i!==n.type&&(r&&(n.type=r),e.mergeSets(t["known"+n.type],[n.value+" "]),n.type="",n.value=""),"string"==typeof i&&t["known"+i]&&(n.type=i,n.value&&(n.value+=s.s),n.value+=s.v)}function i(t,i,r){const o={type:"",value:""};let h=r;const l=[h];return t.line.forEach((i,r)=>{r===t.line.length-1&&(t.completions=n(t,l));const g=i.q?"":i.v,d=h.then[g]||h.then[""];"number"==typeof d?l.length-=d:l.push(d||a),h=e.last(l),s(t,o,i,h)}),i&&s(t,o,null,{}),t.nextCompletions=n(t,l),t.valid=Boolean(h.then["\n"])||0===Object.keys(h.then).length,h.type}function r(e){const t=e.baseToken||{};return{value:t.v||"",quoted:t.q||!1}}const a={type:"error line-error",then:{"":0}},o=(()=>{function e(e){return{type:"string",then:Object.assign({"":0},e)}}function t(e){return{type:"variable",suggest:"Agent",then:Object.assign({},e,{"":0,",":{type:"operator",suggest:!0,then:{"":1}}})}}function n(e){return{type:"keyword",suggest:[e+" of ",e+": "],then:{of:{type:"keyword",suggest:!0,then:{"":h}},":":{type:"operator",suggest:!0,then:{"":r}},"":h}}}function s(e){const t={type:"operator",suggest:!0,then:{"+":a,"-":a,"*":a,"!":a,"":e}};return{"+":{type:"operator",suggest:!0,then:{"+":a,"-":a,"*":t,"!":a,"":e}},"-":{type:"operator",suggest:!0,then:{"+":a,"-":a,"*":t,"!":{type:"operator",then:{"+":a,"-":a,"*":a,"!":a,"":e}},"":e}},"*":{type:"operator",suggest:!0,then:{"+":t,"-":t,"*":a,"!":a,"":e}},"!":t,"":e}}const i={type:"",suggest:"\n",then:{}},r=e({"\n":i}),o={type:"variable",suggest:"Agent",then:{"":0,"\n":i,",":{type:"operator",suggest:!0,then:{"":1}},as:{type:"keyword",suggest:!0,then:{"":{type:"variable",suggest:"Agent",then:{"":0,",":{type:"operator",suggest:!0,then:{"":3}},"\n":i}}}}}},h=t({":":{type:"operator",suggest:!0,then:{"":r}}}),l={type:"variable",suggest:"Agent",then:{"":0,",":{type:"operator",suggest:!0,then:{"":h}},":":a}},g={type:"variable",suggest:"Agent",then:{"":0,",":a,":":{type:"operator",suggest:!0,then:{"":r}}}},d={type:"variable",suggest:"Agent",then:{"":0,":":{type:"operator",suggest:!0,then:{"":r,"\n":{type:"",then:{}}}},"\n":i}},c={":":{type:"operator",suggest:!0,then:{"":e({as:{type:"keyword",suggest:!0,then:{"":{type:"variable",suggest:"Agent",then:{"":0,"\n":i}}}}})}}},u={type:"keyword",suggest:!0,then:Object.assign({over:{type:"keyword",suggest:!0,then:{"":t(c)}}},c)},p={title:{type:"keyword",suggest:!0,then:{"":r}},theme:{type:"keyword",suggest:!0,then:{"":{type:"string",suggest:{global:"themes",suffix:"\n"},then:{"":0,"\n":i}}}},headers:{type:"keyword",suggest:!0,then:{none:{type:"keyword",suggest:!0,then:{}},cross:{type:"keyword",suggest:!0,then:{}},box:{type:"keyword",suggest:!0,then:{}},fade:{type:"keyword",suggest:!0,then:{}},bar:{type:"keyword",suggest:!0,then:{}}}},terminators:{type:"keyword",suggest:!0,then:{none:{type:"keyword",suggest:!0,then:{}},cross:{type:"keyword",suggest:!0,then:{}},box:{type:"keyword",suggest:!0,then:{}},fade:{type:"keyword",suggest:!0,then:{}},bar:{type:"keyword",suggest:!0,then:{}}}},define:{type:"keyword",suggest:!0,then:{"":o,as:a}},begin:{type:"keyword",suggest:!0,then:{"":o,reference:u,as:a}},end:{type:"keyword",suggest:!0,then:{"":o,as:a,"\n":i}},if:{type:"keyword",suggest:!0,then:{"":r,":":{type:"operator",suggest:!0,then:{"":r}},"\n":i}},else:{type:"keyword",suggest:["else\n","else if: "],then:{if:{type:"keyword",suggest:"if: ",then:{"":r,":":{type:"operator",suggest:!0,then:{"":r}}}},"\n":i}},repeat:{type:"keyword",suggest:!0,then:{"":r,":":{type:"operator",suggest:!0,then:{"":r}},"\n":i}},note:{type:"keyword",suggest:!0,then:{over:{type:"keyword",suggest:!0,then:{"":h}},left:n("left"),right:n("right"),between:{type:"keyword",suggest:!0,then:{"":l}}}},state:{type:"keyword",suggest:"state over ",then:{over:{type:"keyword",suggest:!0,then:{"":g}}}},text:{type:"keyword",suggest:!0,then:{left:n("left"),right:n("right")}},autolabel:{type:"keyword",suggest:!0,then:{off:{type:"keyword",suggest:!0,then:{}},"":r}},simultaneously:{type:"keyword",suggest:!0,then:{":":{type:"operator",suggest:!0,then:{}},with:{type:"keyword",suggest:!0,then:{"":{type:"variable",suggest:"Label",then:{"":0,":":{type:"operator",suggest:!0,then:{}}}}}}}}};return e=>({type:"error line-error",then:Object.assign({},p,function(e){const t={type:"keyword",suggest:!0,then:s(d)},n={"":0};return e.forEach(e=>n[e]=t),n[":"]={type:"operator",suggest:!0,override:"Label",then:{}},s({type:"variable",suggest:"Agent",then:n})}(e))})})();return class{constructor(e,t){this.tokenDefinitions=e,this.commands=o(t),this.lineComment="#"}startState(){return{currentType:-1,current:"",currentSpace:"",currentQuoted:!1,knownAgent:[],knownLabel:[],beginCompletions:n({},[this.commands]),completions:[],nextCompletions:[],valid:!0,line:[],indent:0}}_matchPattern(e,t,n){return t?(t.lastIndex=0,e.match(t,n)):null}_tokenBegin(e,t){t.currentSpace="";let n="";for(;;){if(e.eol())return!1;t.currentSpace+=n;for(let n=0;n{"use strict";function t(e,t,n){return t.lastIndex=n,t.exec(e)}function n(e){return"n"===e[1]?"\n":e[1]}function s(e,n,s){return s?function(e,n,s){if(s.escape){const i=t(e,s.escape,n);if(i)return{newBlock:null,end:!1,appendSpace:"",appendValue:s.escapeWith(i),skip:i[0].length}}const i=t(e,s.end,n);return i?{newBlock:null,end:!0,appendSpace:"",appendValue:"",skip:i[0].length}:{newBlock:null,end:!1,appendSpace:"",appendValue:e[n],skip:1}}(e,n,s):function(e,n){for(let s=0;s,])/y,end:/(?=[ \t\r\n:+\-~*!<>,])|$/y},{start:/(?=[\-~<>])/y,end:/(?=[^\-~<>])|$/y},{start:/,/y,baseToken:{v:","}},{start:/:/y,baseToken:{v:":"}},{start:/!/y,baseToken:{v:"!"}},{start:/\+/y,baseToken:{v:"+"}},{start:/\*/y,baseToken:{v:"*"}},{start:/\n/y,baseToken:{v:"\n"}}];class a{constructor(e){this.src=e,this.block=null,this.token=null,this.pos={i:0,ln:0,ch:0},this.reset()}isOver(){return this.pos.i>this.src.length}reset(){this.token={s:"",v:"",q:!1,b:null,e:null},this.block=null}beginToken(e){this.block=e.newBlock,Object.assign(this.token,this.block.baseToken),this.token.b=i(this.pos)}endToken(){let e=null;return this.block.omit||(this.token.e=i(this.pos),e=this.token),this.reset(),e}advance(){const e=s(this.src,this.pos.i,this.block);return e.newBlock&&this.beginToken(e),this.token.s+=e.appendSpace,this.token.v+=e.appendValue,function(e,t,n){for(let s=0;s{e.q||"\n"!==e.v?n.push(e):n.length>0&&(t.push(n),n=[])}),n.length>0&&t.push(n),t}}}),n("sequence/LabelPatternParser",[],()=>{"use strict";function e(e){const t=s.exec(e);return t&&t[1]?t[1].length:0}function t(t){if("label"===t)return{token:"label"};const n=t.indexOf(" ");let s=null,i=null;return-1===n?(s=t,i=[]):(s=t.substr(0,n),i=t.substr(n+1).split(",")),"inc"===s?function(t){let n=1,s=1,i=0;return t[0]&&(n=Number(t[0]),i=Math.max(i,e(t[0]))),t[1]&&(s=Number(t[1]),i=Math.max(i,e(t[1]))),{start:n,inc:s,dp:i}}(i):"<"+t+">"}const n=/(.*?)<([^<>]*)>/g,s=/\.([0-9]*)/;return function(e){const s=[];let i=null,r=0;for(n.lastIndex=0;i=n.exec(e);)i[1]&&s.push(i[1]),i[2]&&s.push(t(i[2])),r=n.lastIndex;const a=e.substr(r);return a&&s.push(a),s}}),n("sequence/CodeMirrorHints",["core/ArrayUtilities"],e=>{"use strict";function t(e,t){return{text:e,displayText:"\n"===e?"":e.trim(),className:"\n"===e?"pick-virtual":null,from:i.test(e)?t.squashFrom:t.wordFrom,to:r.test(e)?t.squashTo:t.wordTo}}function n({global:e,prefix:t="",suffix:n=""},s){const i=s[e];return i?i.map(e=>t+e+n):[]}const s=/^([ \t]*)(.*)$/,i=/^[ \t\r\n:,]/,r=/[ \t\r\n]$/;return{getHints:function(i,r){const a=i.getCursor(),o=i.getTokenAt(a);let h=o.string;o.end>a.ch&&(h=h.substr(0,a.ch-o.start));const l=s.exec(h);h=l[2];const g=o.start+l[1].length,d=a.ch>0&&o.state.line.length>0;let c=d?o.state.completions:o.state.beginCompletions;d||(c=c.concat(o.state.knownAgent)),function(t,s={}){for(let i=0;i0&&" "===i[n-1]&&r.squashFrom.ch--," "===i[s]&&r.squashTo.ch++,r}(i,a.line,g,o.end);let p=!1;const m=c.filter(e=>e.startsWith(h)).map(e=>e!==h+" "||r.completeSingle?t(e,u):(p=!0,null)).filter(e=>null!==e);return p&&m.length>0&&m.unshift(t(h+" ",u)),{list:m,from:u.wordFrom,to:u.wordTo}}}}),n("sequence/Parser",["core/ArrayUtilities","./Tokeniser","./LabelPatternParser","./CodeMirrorHints"],(e,t,n,s)=>{"use strict";function i(e,t=null){let n="";return t&&(n=" at line "+(t.b.ln+1)+", character "+t.b.ch),new Error(e+n)}function r(e,t=0,n=null){if(null===n&&(n=e.length),n<=t)return"";let s=e[t].v;for(let i=t+1;i=s)&&(o=s),n>=o)throw i("Missing agent name",function(t,n){if(n{const t=e.combine([[{tok:"",type:0},{tok:"<",type:1},{tok:"<<",type:2}],[{tok:"-",type:"solid"},{tok:"--",type:"dash"},{tok:"~",type:"wave"}],[{tok:"",type:0},{tok:">",type:1},{tok:">>",type:2}]]).filter(e=>0!==e[0].type||0!==e[2].type),n=new Map;return t.forEach(e=>{n.set(e.map(e=>e.tok).join(""),{line:e[1].type,left:e[0].type,right:e[2].type})}),n})(),p={"*":"begin","+":"start","-":"stop","!":"end"},m=["none","box","cross","fade","bar"],f={text:{mode:"text",types:{left:{type:"note left",skip:["of"],min:0,max:null},right:{type:"note right",skip:["of"],min:0,max:null}}},note:{mode:"note",types:{over:{type:"note over",skip:[],min:0,max:null},left:{type:"note left",skip:["of"],min:0,max:null},right:{type:"note right",skip:["of"],min:0,max:null},between:{type:"note between",skip:[],min:2,max:null}}},state:{mode:"state",types:{over:{type:"note over",skip:[],min:1,max:1}}}},b={define:{type:"agent define"},begin:{type:"agent begin",mode:"box"},end:{type:"agent end",mode:"cross"}},y=[(e,t)=>"title"!==a(e[0])?null:(t.title=r(e,1),!0),(e,t)=>"theme"!==a(e[0])?null:(t.theme=r(e,1),!0),(e,t)=>{if("terminators"!==a(e[0]))return null;const n=a(e[1]);if(!n)throw i("Unspecified termination",e[0]);if(-1===m.indexOf(n))throw i('Unknown termination "'+n+'"',e[1]);return t.terminators=n,!0},(e,t)=>{if("headers"!==a(e[0]))return null;const n=a(e[1]);if(!n)throw i("Unspecified header",e[0]);if(-1===m.indexOf(n))throw i('Unknown header "'+n+'"',e[1]);return t.headers=n,!0},e=>{if("autolabel"!==a(e[0]))return null;let t=null;return t="off"===a(e[1])?"