diff --git a/README.md b/README.md index 25ea9df..228385d 100644 --- a/README.md +++ b/README.md @@ -146,6 +146,21 @@ state over Foo: 'Newlines here, too!' ``` +### Themes + +Themes preview + +``` +theme sketch + +title Mockup + +A thing -> +Another thing: Something happens +-Another thing --> A thing: With some response +note right of Another thing: Find out what happens here +end Another thing +``` + ### Short-Lived Agents Short Lived Agents preview diff --git a/editor-dev.htm b/editor-dev.htm index 8e4c067..5cb0129 100644 --- a/editor-dev.htm +++ b/editor-dev.htm @@ -5,7 +5,11 @@ base-uri 'self'; default-src 'none'; script-src 'self' https://cdnjs.cloudflare.com https://unpkg.com; - style-src 'self' https://cdnjs.cloudflare.com; + style-src 'self' + https://cdnjs.cloudflare.com + 'sha256-ru2GY2rXeOf7PQX5LzK3ckNo21FCDUoRc2f3i0QcD1g=' + ; + font-src 'self' data:; img-src 'self' blob:; form-action 'none'; "> diff --git a/index.html b/index.html index 6a28767..be4cfa7 100644 --- a/index.html +++ b/index.html @@ -5,7 +5,11 @@ base-uri 'self'; default-src 'none'; script-src 'self' https://cdnjs.cloudflare.com https://unpkg.com; - style-src 'self' https://cdnjs.cloudflare.com; + style-src 'self' + https://cdnjs.cloudflare.com + 'sha256-ru2GY2rXeOf7PQX5LzK3ckNo21FCDUoRc2f3i0QcD1g=' + ; + font-src 'self' data:; img-src 'self' blob:; form-action 'none'; "> diff --git a/lib/sequence-diagram.js b/lib/sequence-diagram.js index 719ed8b..0c82a62 100644 --- a/lib/sequence-diagram.js +++ b/lib/sequence-diagram.js @@ -3630,6 +3630,7 @@ define('sequence/components/AgentCap',[ y, padding: config.padding, boxAttrs: config.boxAttrs, + boxRenderer: config.boxRenderer, labelAttrs: config.labelAttrs, boxLayer: env.shapeLayer, labelLayer: clickable, @@ -3670,14 +3671,7 @@ define('sequence/components/AgentCap',[ const config = env.theme.agentCap.cross; const d = config.size / 2; - env.shapeLayer.appendChild(svg.make('path', Object.assign({ - 'd': ( - 'M ' + (x - d) + ' ' + y + - ' L ' + (x + d) + ' ' + (y + d * 2) + - ' M ' + (x + d) + ' ' + y + - ' L ' + (x - d) + ' ' + (y + d * 2) - ), - }, config.attrs))); + env.shapeLayer.appendChild(config.render({x, y: y + d, radius: d})); env.makeRegion().appendChild(svg.make('rect', { 'x': x - d, @@ -3713,7 +3707,7 @@ define('sequence/components/AgentCap',[ topShift(agentInfo, env) { const config = env.theme.agentCap.bar; - return config.attrs.height / 2; + return config.height / 2; } render(y, {x, label}, env) { @@ -3724,25 +3718,27 @@ define('sequence/components/AgentCap',[ configB.padding.left + configB.padding.right ); + const height = config.height; - env.shapeLayer.appendChild(svg.make('rect', Object.assign({ - 'x': x - width / 2, - 'y': y, - 'width': width, - }, config.attrs))); + env.shapeLayer.appendChild(config.render({ + x: x - width / 2, + y, + width, + height, + })); env.makeRegion().appendChild(svg.make('rect', { 'x': x - width / 2, 'y': y, 'width': width, - 'height': config.attrs.height, + 'height': height, 'fill': 'transparent', })); return { lineTop: 0, - lineBottom: config.attrs.height, - height: config.attrs.height, + lineBottom: height, + height: height, }; } } @@ -4107,10 +4103,10 @@ define('sequence/components/Connect',[ if(!ww || !hh) { container.appendChild(svg.make('path', Object.assign({ 'd': ( - 'M ' + xL1 + ' ' + y1 + - ' L ' + xR + ' ' + y1 + - ' A ' + r + ' ' + r + ' 0 0 1 ' + xR + ' ' + y2 + - ' L ' + xL2 + ' ' + y2 + 'M' + xL1 + ' ' + y1 + + 'L' + xR + ' ' + y1 + + 'A' + r + ' ' + r + ' 0 0 1 ' + xR + ' ' + y2 + + 'L' + xL2 + ' ' + y2 ), }, attrs))); return; @@ -4403,7 +4399,7 @@ define('sequence/components/Note',['./BaseComponent', 'svg/SVGUtilities'], (Base mode, label, }, env) { - const config = env.theme.note[mode]; + const config = env.theme.getNote(mode); const clickable = env.makeRegion(); @@ -4477,7 +4473,7 @@ define('sequence/components/Note',['./BaseComponent', 'svg/SVGUtilities'], (Base class NoteOver extends NoteComponent { separation({agentNames, mode, label}, env) { - const config = env.theme.note[mode]; + const config = env.theme.getNote(mode); const width = ( env.textSizer.measure(config.labelAttrs, label).width + config.padding.left + @@ -4504,7 +4500,7 @@ define('sequence/components/Note',['./BaseComponent', 'svg/SVGUtilities'], (Base } render({agentNames, mode, label}, env) { - const config = env.theme.note[mode]; + const config = env.theme.getNote(mode); const {left, right} = findExtremes(env.agentInfos, agentNames); const infoL = env.agentInfos.get(left); @@ -4536,7 +4532,7 @@ define('sequence/components/Note',['./BaseComponent', 'svg/SVGUtilities'], (Base } separation({agentNames, mode, label}, env) { - const config = env.theme.note[mode]; + const config = env.theme.getNote(mode); const {left, right} = findExtremes(env.agentInfos, agentNames); const width = ( env.textSizer.measure(config.labelAttrs, label).width + @@ -4562,7 +4558,7 @@ define('sequence/components/Note',['./BaseComponent', 'svg/SVGUtilities'], (Base } render({agentNames, mode, label}, env) { - const config = env.theme.note[mode]; + const config = env.theme.getNote(mode); const {left, right} = findExtremes(env.agentInfos, agentNames); if(this.isRight) { const info = env.agentInfos.get(right); @@ -4588,7 +4584,7 @@ define('sequence/components/Note',['./BaseComponent', 'svg/SVGUtilities'], (Base class NoteBetween extends NoteComponent { separation({agentNames, mode, label}, env) { - const config = env.theme.note[mode]; + const config = env.theme.getNote(mode); const {left, right} = findExtremes(env.agentInfos, agentNames); const infoL = env.agentInfos.get(left); const infoR = env.agentInfos.get(right); @@ -4879,25 +4875,13 @@ define('sequence/Renderer',[ return; } - const r = agentInfo.currentRad; - - if(r > 0) { - this.agentLines.appendChild(svg.make('rect', Object.assign({ - 'x': agentInfo.x - r, - 'y': agentInfo.latestYStart, - 'width': r * 2, - 'height': toY - agentInfo.latestYStart, - 'class': 'agent-' + agentInfo.index + '-line', - }, this.theme.agentLineAttrs))); - } else { - this.agentLines.appendChild(svg.make('line', Object.assign({ - 'x1': agentInfo.x, - 'y1': agentInfo.latestYStart, - 'x2': agentInfo.x, - 'y2': toY, - 'class': 'agent-' + agentInfo.index + '-line', - }, this.theme.agentLineAttrs))); - } + this.theme.drawAgentLine(this.agentLines, { + x: agentInfo.x, + y0: agentInfo.latestYStart, + y1: toY, + width: agentInfo.currentRad * 2, + className: 'agent-' + agentInfo.index + '-line', + }); } addHighlightObject(line, o) { @@ -5114,6 +5098,9 @@ define('sequence/Renderer',[ this.theme = this.themes.get(''); } + this.theme.reset(); + this.theme.addDefs(this.addDef); + this.title.set({ attrs: this.theme.titleAttrs, text: sequence.meta.title, @@ -5273,9 +5260,18 @@ define('sequence/Exporter',[],() => { }; }); -define('sequence/themes/Basic',['core/ArrayUtilities', 'svg/SVGShapes'], (array, SVGShapes) => { +define('sequence/themes/Basic',[ + 'core/ArrayUtilities', + 'svg/SVGUtilities', + 'svg/SVGShapes', +], ( + array, + svg, + SVGShapes +) => { 'use strict'; + const FONT = 'sans-serif'; const LINE_HEIGHT = 1.3; const SETTINGS = { @@ -5301,7 +5297,7 @@ define('sequence/themes/Basic',['core/ArrayUtilities', 'svg/SVGShapes'], (array, 'stroke-width': 1, }, labelAttrs: { - 'font-family': 'sans-serif', + 'font-family': FONT, 'font-size': 12, 'line-height': LINE_HEIGHT, 'text-anchor': 'middle', @@ -5309,18 +5305,32 @@ define('sequence/themes/Basic',['core/ArrayUtilities', 'svg/SVGShapes'], (array, }, cross: { size: 20, - attrs: { - 'fill': 'none', - 'stroke': '#000000', - 'stroke-width': 1, + 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, + }); }, }, bar: { - attrs: { - 'fill': '#000000', - 'stroke': '#000000', - 'stroke-width': 1, - 'height': 4, + 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, + }); }, }, fade: { @@ -5381,13 +5391,13 @@ define('sequence/themes/Basic',['core/ArrayUtilities', 'svg/SVGShapes'], (array, padding: 6, margin: {top: 2, bottom: 1}, attrs: { - 'font-family': 'sans-serif', + 'font-family': FONT, 'font-size': 8, 'line-height': LINE_HEIGHT, 'text-anchor': 'middle', }, loopbackAttrs: { - 'font-family': 'sans-serif', + 'font-family': FONT, 'font-size': 8, 'line-height': LINE_HEIGHT, }, @@ -5447,7 +5457,7 @@ define('sequence/themes/Basic',['core/ArrayUtilities', 'svg/SVGShapes'], (array, 'ry': 2, }, labelAttrs: { - 'font-family': 'sans-serif', + 'font-family': FONT, 'font-weight': 'bold', 'font-size': 9, 'line-height': LINE_HEIGHT, @@ -5462,7 +5472,7 @@ define('sequence/themes/Basic',['core/ArrayUtilities', 'svg/SVGShapes'], (array, bottom: 0, }, labelAttrs: { - 'font-family': 'sans-serif', + 'font-family': FONT, 'font-size': 8, 'line-height': LINE_HEIGHT, 'text-anchor': 'left', @@ -5478,60 +5488,8 @@ define('sequence/themes/Basic',['core/ArrayUtilities', 'svg/SVGShapes'], (array, }, }, - note: { - 'text': { - margin: {top: 0, left: 2, right: 2, bottom: 0}, - padding: {top: 2, left: 2, right: 2, bottom: 2}, - overlap: {left: 10, right: 10}, - boxRenderer: SVGShapes.renderBox.bind(null, { - 'fill': '#FFFFFF', - }), - labelAttrs: { - 'font-family': 'sans-serif', - 'font-size': 8, - 'line-height': LINE_HEIGHT, - }, - }, - '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: SVGShapes.renderNote.bind(null, { - 'fill': '#FFFFFF', - 'stroke': '#000000', - 'stroke-width': 1, - }, { - 'fill': 'none', - 'stroke': '#000000', - 'stroke-width': 1, - }), - labelAttrs: { - 'font-family': 'sans-serif', - 'font-size': 8, - 'line-height': LINE_HEIGHT, - }, - }, - '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: SVGShapes.renderBox.bind(null, { - 'fill': '#FFFFFF', - 'stroke': '#000000', - 'stroke-width': 1, - 'rx': 10, - 'ry': 10, - }), - labelAttrs: { - 'font-family': 'sans-serif', - 'font-size': 8, - 'line-height': LINE_HEIGHT, - }, - }, - }, - titleAttrs: { - 'font-family': 'sans-serif', + 'font-family': FONT, 'font-size': 20, 'line-height': LINE_HEIGHT, 'text-anchor': 'middle', @@ -5545,17 +5503,108 @@ define('sequence/themes/Basic',['core/ArrayUtilities', 'svg/SVGShapes'], (array, }, }; + const NOTES = { + 'text': { + margin: {top: 0, left: 2, right: 2, bottom: 0}, + padding: {top: 2, left: 2, right: 2, bottom: 2}, + overlap: {left: 10, right: 10}, + boxRenderer: SVGShapes.renderBox.bind(null, { + 'fill': '#FFFFFF', + }), + labelAttrs: { + 'font-family': FONT, + 'font-size': 8, + 'line-height': LINE_HEIGHT, + }, + }, + '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: SVGShapes.renderNote.bind(null, { + 'fill': '#FFFFFF', + 'stroke': '#000000', + 'stroke-width': 1, + }, { + 'fill': 'none', + 'stroke': '#000000', + 'stroke-width': 1, + }), + labelAttrs: { + 'font-family': FONT, + 'font-size': 8, + 'line-height': LINE_HEIGHT, + }, + }, + '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: SVGShapes.renderBox.bind(null, { + 'fill': '#FFFFFF', + 'stroke': '#000000', + 'stroke-width': 1, + 'rx': 10, + 'ry': 10, + }), + labelAttrs: { + 'font-family': FONT, + 'font-size': 8, + 'line-height': LINE_HEIGHT, + }, + }, + }; + return class BasicTheme { 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))); + } + } }; }); -define('sequence/themes/Chunky',['core/ArrayUtilities', 'svg/SVGShapes'], (array, SVGShapes) => { +define('sequence/themes/Chunky',[ + 'core/ArrayUtilities', + 'svg/SVGUtilities', + 'svg/SVGShapes', +], ( + array, + svg, + SVGShapes +) => { 'use strict'; + const FONT = 'sans-serif'; const LINE_HEIGHT = 1.3; const SETTINGS = { @@ -5583,7 +5632,7 @@ define('sequence/themes/Chunky',['core/ArrayUtilities', 'svg/SVGShapes'], (array 'ry': 4, }, labelAttrs: { - 'font-family': 'sans-serif', + 'font-family': FONT, 'font-weight': 'bold', 'font-size': 14, 'line-height': LINE_HEIGHT, @@ -5592,21 +5641,36 @@ define('sequence/themes/Chunky',['core/ArrayUtilities', 'svg/SVGShapes'], (array }, cross: { size: 20, - attrs: { - 'fill': 'none', - 'stroke': '#000000', - 'stroke-width': 3, - 'stroke-linecap': 'round', + 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', + })); }, }, bar: { - attrs: { - 'fill': '#000000', - 'stroke': '#000000', - 'stroke-width': 3, - 'height': 4, - 'rx': 2, - 'ry': 2, + 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, + }); }, }, fade: { @@ -5669,13 +5733,13 @@ define('sequence/themes/Chunky',['core/ArrayUtilities', 'svg/SVGShapes'], (array padding: 7, margin: {top: 2, bottom: 3}, attrs: { - 'font-family': 'sans-serif', + 'font-family': FONT, 'font-size': 8, 'line-height': LINE_HEIGHT, 'text-anchor': 'middle', }, loopbackAttrs: { - 'font-family': 'sans-serif', + 'font-family': FONT, 'font-size': 8, 'line-height': LINE_HEIGHT, }, @@ -5735,7 +5799,7 @@ define('sequence/themes/Chunky',['core/ArrayUtilities', 'svg/SVGShapes'], (array 'ry': 3, }, labelAttrs: { - 'font-family': 'sans-serif', + 'font-family': FONT, 'font-weight': 'bold', 'font-size': 9, 'line-height': LINE_HEIGHT, @@ -5750,7 +5814,7 @@ define('sequence/themes/Chunky',['core/ArrayUtilities', 'svg/SVGShapes'], (array bottom: 0, }, labelAttrs: { - 'font-family': 'sans-serif', + 'font-family': FONT, 'font-size': 8, 'line-height': LINE_HEIGHT, 'text-anchor': 'left', @@ -5766,61 +5830,8 @@ define('sequence/themes/Chunky',['core/ArrayUtilities', 'svg/SVGShapes'], (array }, }, - note: { - 'text': { - margin: {top: 0, left: 2, right: 2, bottom: 0}, - padding: {top: 2, left: 2, right: 2, bottom: 2}, - overlap: {left: 10, right: 10}, - boxRenderer: SVGShapes.renderBox.bind(null, { - 'fill': '#FFFFFF', - }), - labelAttrs: { - 'font-family': 'sans-serif', - 'font-size': 8, - 'line-height': LINE_HEIGHT, - }, - }, - 'note': { - margin: {top: 0, left: 5, right: 5, bottom: 0}, - padding: {top: 3, left: 3, right: 10, bottom: 3}, - overlap: {left: 10, right: 10}, - boxRenderer: SVGShapes.renderNote.bind(null, { - 'fill': '#FFFFFF', - 'stroke': '#000000', - 'stroke-width': 2, - 'stroke-linejoin': 'round', - }, { - 'fill': 'none', - 'stroke': '#000000', - 'stroke-width': 1, - }), - labelAttrs: { - 'font-family': 'sans-serif', - 'font-size': 8, - 'line-height': LINE_HEIGHT, - }, - }, - 'state': { - margin: {top: 0, left: 5, right: 5, bottom: 0}, - padding: {top: 5, left: 7, right: 7, bottom: 5}, - overlap: {left: 10, right: 10}, - boxRenderer: SVGShapes.renderBox.bind(null, { - 'fill': '#FFFFFF', - 'stroke': '#000000', - 'stroke-width': 3, - 'rx': 10, - 'ry': 10, - }), - labelAttrs: { - 'font-family': 'sans-serif', - 'font-size': 8, - 'line-height': LINE_HEIGHT, - }, - }, - }, - titleAttrs: { - 'font-family': 'sans-serif', + 'font-family': FONT, 'font-weight': 'bolder', 'font-size': 20, 'line-height': LINE_HEIGHT, @@ -5835,14 +5846,1097 @@ define('sequence/themes/Chunky',['core/ArrayUtilities', 'svg/SVGShapes'], (array }, }; + const NOTES = { + 'text': { + margin: {top: 0, left: 2, right: 2, bottom: 0}, + padding: {top: 2, left: 2, right: 2, bottom: 2}, + overlap: {left: 10, right: 10}, + boxRenderer: SVGShapes.renderBox.bind(null, { + 'fill': '#FFFFFF', + }), + labelAttrs: { + 'font-family': FONT, + 'font-size': 8, + 'line-height': LINE_HEIGHT, + }, + }, + 'note': { + margin: {top: 0, left: 5, right: 5, bottom: 0}, + padding: {top: 3, left: 3, right: 10, bottom: 3}, + overlap: {left: 10, right: 10}, + boxRenderer: SVGShapes.renderNote.bind(null, { + 'fill': '#FFFFFF', + 'stroke': '#000000', + 'stroke-width': 2, + 'stroke-linejoin': 'round', + }, { + 'fill': 'none', + 'stroke': '#000000', + 'stroke-width': 1, + }), + labelAttrs: { + 'font-family': FONT, + 'font-size': 8, + 'line-height': LINE_HEIGHT, + }, + }, + 'state': { + margin: {top: 0, left: 5, right: 5, bottom: 0}, + padding: {top: 5, left: 7, right: 7, bottom: 5}, + overlap: {left: 10, right: 10}, + boxRenderer: SVGShapes.renderBox.bind(null, { + 'fill': '#FFFFFF', + 'stroke': '#000000', + 'stroke-width': 3, + 'rx': 10, + 'ry': 10, + }), + labelAttrs: { + 'font-family': FONT, + 'font-size': 8, + 'line-height': LINE_HEIGHT, + }, + }, + }; + return class ChunkyTheme { 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))); + } + } }; }); +define('sequence/themes/HandleeFontData',[],() => { + 'use strict'; + + // Handlee font, by Joe Prince + // Downloaded from Google Fonts and converted to Base64 for embedding in + // generated SVGs + // https://fonts.google.com/specimen/Handlee + + /* License + + SIL OPEN FONT LICENSE + Version 1.1 - 26 February 2007 + + PREAMBLE + The goals of the Open Font License (OFL) are to stimulate worldwide + development of collaborative font projects, to support the font creation + efforts of academic and linguistic communities, and to provide a free and + open framework in which fonts may be shared and improved in partnership + with others. + + The OFL allows the licensed fonts to be used, studied, modified and + redistributed freely as long as they are not sold by themselves. The + fonts, including any derivative works, can be bundled, embedded, + redistributed and/or sold with any software provided that any reserved + names are not used by derivative works. The fonts and derivatives, + however, cannot be released under any other type of license. The + requirement for fonts to remain under this license does not apply + to any document created using the fonts or their derivatives. + + DEFINITIONS + "Font Software" refers to the set of files released by the Copyright + Holder(s) under this license and clearly marked as such. This may + include source files, build scripts and documentation. + + "Reserved Font Name" refers to any names specified as such after the + copyright statement(s). + + "Original Version" refers to the collection of Font Software components as + distributed by the Copyright Holder(s). + + "Modified Version" refers to any derivative made by adding to, deleting, + or substituting — in part or in whole — any of the components of the + Original Version, by changing formats or by porting the Font Software to a + new environment. + + "Author" refers to any designer, engineer, programmer, technical + writer or other person who contributed to the Font Software. + + PERMISSION & CONDITIONS + Permission is hereby granted, free of charge, to any person obtaining + a copy of the Font Software, to use, study, copy, merge, embed, modify, + redistribute, and sell modified and unmodified copies of the Font + Software, subject to the following conditions: + + 1) Neither the Font Software nor any of its individual components, + in Original or Modified Versions, may be sold by itself. + + 2) Original or Modified Versions of the Font Software may be bundled, + redistributed and/or sold with any software, provided that each copy + contains the above copyright notice and this license. These can be + included either as stand-alone text files, human-readable headers or + in the appropriate machine-readable metadata fields within text or + binary files as long as those fields can be easily viewed by the user. + + 3) No Modified Version of the Font Software may use the Reserved Font + Name(s) unless explicit written permission is granted by the corresponding + Copyright Holder. This restriction only applies to the primary font name as + presented to the users. + + 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font + Software shall not be used to promote, endorse or advertise any + Modified Version, except to acknowledge the contribution(s) of the + Copyright Holder(s) and the Author(s) or with their explicit written + permission. + + 5) The Font Software, modified or unmodified, in part or in whole, + must be distributed entirely under this license, and must not be + distributed under any other license. The requirement for fonts to + remain under this license does not apply to any document created + using the Font Software. + + TERMINATION + This license becomes null and void if any of the above conditions are + not met. + + DISCLAIMER + THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT + OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE + COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL + DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM + OTHER DEALINGS IN THE FONT SOFTWARE. + + */ + + return { + name: 'Handlee', + woff2: ( + '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' + + 'jjhu2qURx1x+3R5nnI2W/z0OAAA=' + ), + }; +}); + +define('sequence/themes/Sketch',[ + 'core/ArrayUtilities', + 'svg/SVGUtilities', + 'svg/SVGShapes', + './HandleeFontData', +], ( + array, + svg, + SVGShapes, + Handlee +) => { + 'use strict'; + + // TODO: + // * arrows + // * 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; + + const SETTINGS = { + titleMargin: 10, + outerMargin: 5, + agentMargin: 10, + actionMargin: 10, + minActionMargin: 3, + agentLineHighlightRadius: 4, + + agentCap: { + box: { + padding: { + top: 5, + left: 10, + right: 10, + bottom: 5, + }, + arrowBottom: 5 + 12 * 1.3 / 2, + labelAttrs: { + 'font-family': FONT_FAMILY, + 'font-size': 12, + 'line-height': LINE_HEIGHT, + 'text-anchor': 'middle', + }, + boxRenderer: null, + }, + cross: { + size: 15, + render: null, + }, + bar: { + height: 6, + render: null, + }, + fade: { + width: 8, + height: 6, + }, + none: { + height: 10, + }, + }, + + connect: { + loopbackRadius: 6, + lineAttrs: { + 'solid': { + 'fill': 'none', + 'stroke': '#000000', + 'stroke-width': 1, + }, + 'dash': { + 'fill': 'none', + 'stroke': '#000000', + 'stroke-width': 1, + 'stroke-dasharray': '4, 2', + }, + 'wave': { + 'fill': 'none', + 'stroke': '#000000', + 'stroke-width': 1, + 'stroke-linejoin': 'round', + 'stroke-linecap': 'round', + 'wave-width': 6, + 'wave-height': 0.5, + }, + }, + arrow: { + single: { + width: 5, + height: 10, + attrs: { + 'fill': '#000000', + 'stroke-width': 0, + 'stroke-linejoin': 'miter', + }, + }, + double: { + width: 4, + height: 6, + attrs: { + 'fill': 'none', + 'stroke': '#000000', + 'stroke-width': 1, + 'stroke-linejoin': 'miter', + }, + }, + }, + label: { + padding: 6, + margin: {top: 2, bottom: 1}, + attrs: { + 'font-family': FONT_FAMILY, + 'font-size': 8, + 'line-height': LINE_HEIGHT, + 'text-anchor': 'middle', + }, + loopbackAttrs: { + 'font-family': FONT_FAMILY, + 'font-size': 8, + 'line-height': LINE_HEIGHT, + }, + }, + mask: { + padding: { + top: 0, + left: 3, + right: 3, + bottom: 1, + }, + }, + }, + + 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, + 'line-height': LINE_HEIGHT, + 'text-anchor': 'middle', + 'class': 'title', + }, + + agentLineAttrs: { + 'fill': 'none', + 'stroke': '#000000', + 'stroke-width': 1, + }, + }; + + const NOTES = { + 'text': { + margin: {top: 0, left: 2, right: 2, bottom: 0}, + padding: {top: 2, left: 2, right: 2, bottom: 2}, + overlap: {left: 10, right: 10}, + boxRenderer: SVGShapes.renderBox.bind(null, { + 'fill': '#FFFFFF', + }), + labelAttrs: { + 'font-family': FONT_FAMILY, + 'font-size': 8, + 'line-height': LINE_HEIGHT, + }, + }, + '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, + }, + }, + '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, + }, + }, + }; + + class Random { + // xorshift+ 64-bit random generator + // https://en.wikipedia.org/wiki/Xorshift + + constructor() { + this.s = new Uint32Array(4); + } + + reset() { + // Initial seed: 0x00010203 + for(let i = 0; i < 4; ++ i) { + this.s[i] = i; + } + } + + nextFloat() { + /* jshint -W016 */ // bit-operations are part of the algorithm + const range = 0x100000000; + let x0 = this.s[0]; + let x1 = this.s[1]; + const y0 = this.s[2]; + const y1 = this.s[3]; + this.s[0] = y0; + this.s[1] = y1; + x0 ^= (x0 << 23) | (x1 >>> 9); + x1 ^= (x1 << 23); + this.s[2] = x0 ^ y0 ^ (x0 >>> 17) ^ (y0 >>> 26); + this.s[3] = ( + x1 ^ y1 ^ + (x0 << 15 | x1 >>> 17) ^ + (y0 << 6 | y1 >>> 26) + ); + return (((this.s[3] + y1) >>> 0) % range) / range; + } + } + + const RIGHT = {}; + const LEFT = {}; + + class SketchTheme { + constructor(handedness = RIGHT) { + if(handedness === RIGHT) { + this.name = 'sketch'; + this.handedness = 1; + } else { + this.name = 'sketch left handed'; + this.handedness = -1; + } + this.random = new Random(); + Object.assign(this, SETTINGS); + // TODO: these mutate the global, not our copy + // (fine for now since we're a singleton for all practical purposes) + this.agentCap.cross.render = this.renderCross.bind(this); + this.agentCap.bar.render = this.renderBar.bind(this); + this.agentCap.box.boxRenderer = this.renderBox.bind(this); + NOTES.note.boxRenderer = this.renderNote.bind(this); + NOTES.state.boxRenderer = this.renderState.bind(this); + } + + reset() { + this.random.reset(); + } + + addDefs(builder) { + builder('sketch_font', () => { + const style = document.createElement('style'); + // For some uses, it is fine to load this font externally, + // but this fails when exporting as SVG / PNG (svg tags must + // have no external dependencies). +// const url = 'https://fonts.googleapis.com/css?family=' + FONT; +// style.innerText = '@import url("' + url + '")'; + style.innerText = ( + '@font-face{' + + 'font-family:"' + Handlee.name + '";' + + 'src:url("data:font/woff2;base64,' + Handlee.woff2 + '");' + + '}' + ); + return style; + }); + } + + vary(range) { + if(!range) { + return 0; + } + // cosine distribution [-pi/2 pi/2] scaled to [-range range] + // int(cos(x))dx = sin(x) + // from -pi/2: sin(x) - sin(-pi/2) = sin(x) + 1 + // total: sin(pi/2) + 1 = 2 + // normalise to area 1: /2 + // (sin(x) + 1) / 2 + // inverse: p = (sin(x) + 1) / 2 + // asin(2p - 1) = x + // normalise range + // x = asin(2p - 1) * range / (pi/2) + const rand = this.random.nextFloat(); // [0 1) + return Math.asin(rand * 2 - 1) * 2 * range / Math.PI; + } + + lineNodes(p1, p2, {var1 = 1, var2 = 1, move = true}) { + const length = Math.sqrt( + (p2.x - p1.x) * (p2.x - p1.x) + + (p2.y - p1.y) * (p2.y - p1.y) + ); + const rough = Math.min(Math.sqrt(length) * 0.2, 5); + const x1 = p1.x + this.vary(var1 * rough); + const y1 = p1.y + this.vary(var1 * rough); + const x2 = p2.x + this.vary(var2 * rough); + const y2 = p2.y + this.vary(var2 * rough); + + // -1 = p1 higher, 1 = p2 higher + const upper = Math.max(-1, Math.min(1, + (y1 - y2) / (Math.abs(x1 - x2) + 0.001) + )); + const frac = upper / 6 + 0.5; + + // Line curve is to top / left (simulates right-handed drawing) + // or top / right (left-handed) + const curveX = (0.5 + this.vary(0.5)) * rough; + const curveY = (0.5 + this.vary(0.5)) * rough; + const xc = x1 * (1 - frac) + x2 * frac - curveX * this.handedness; + const yc = y1 * (1 - frac) + y2 * frac - curveY; + const nodes = ( + (move ? ('M' + x1 + ' ' + y1) : '') + + 'C' + xc + ' ' + yc + + ',' + x2 + ' ' + y2 + + ',' + x2 + ' ' + y2 + ); + return { + nodes, + p1: {x: x1, y: y1}, + p2: {x: x2, y: y2}, + }; + } + + renderLine(p1, p2, {var1 = 1, var2 = 1}) { + const line = this.lineNodes(p1, p2, {var1, var2}); + const shape = svg.make('path', { + 'd': line.nodes, + 'stroke': 'rgba(0,0,0,0.7)', + 'stroke-width': 0.8, + 'fill': 'none', + }); + return shape; + } + + renderBox({x, y, width, height}, {fill = null} = {}) { + const lT = this.lineNodes( + {x, y}, + {x: x + width, y}, + {} + ); + const lB = this.lineNodes( + {x: x + width, y: y + height}, + {x, y: y + height}, + {move: false} + ); + const lR = this.lineNodes( + lT.p2, + lB.p1, + {var1: 0, var2: 0, move: false} + ); + const lL = this.lineNodes( + lB.p2, + lT.p1, + {var1: 0, var2: 0.3, move: false} + ); + + const shape = svg.make('path', { + 'd': lT.nodes + lR.nodes + lB.nodes + lL.nodes, + 'stroke': 'rgba(0,0,0,0.7)', + 'stroke-width': 0.8, + 'fill': fill || '#FFFFFF', + }); + + return shape; + } + + renderNote({x, y, width, height}) { + const flickSize = 5; + const lT = this.lineNodes( + {x, y}, + {x: x + width - flickSize, y}, + {} + ); + const lF = this.lineNodes( + lT.p2, + {x: x + width, y: y + flickSize}, + {move: false, var1: 0} + ); + const lB = this.lineNodes( + {x: x + width, y: y + height}, + {x, y: y + height}, + {move: false} + ); + const lR = this.lineNodes( + lF.p2, + lB.p1, + {var1: 0, var2: 0, move: false} + ); + const lL = this.lineNodes( + lB.p2, + lT.p1, + {var1: 0, var2: 0.3, move: false} + ); + const lF1 = this.lineNodes( + lF.p1, + {x: x + width - flickSize, y: y + flickSize}, + {var1: 0.3} + ); + const lF2 = this.lineNodes( + lF1.p2, + lF.p2, + {var1: 0, move: false} + ); + + const g = svg.make('g'); + g.appendChild(svg.make('path', { + 'd': ( + lT.nodes + + lF.nodes + + lR.nodes + + lB.nodes + + lL.nodes + ), + 'stroke': 'rgba(0,0,0,0.7)', + 'stroke-width': 0.8, + 'fill': '#FFFFFF', + })); + g.appendChild(svg.make('path', { + 'd': lF1.nodes + lF2.nodes, + 'stroke': 'rgba(0,0,0,0.7)', + 'stroke-width': 0.8, + 'fill': 'none', + })); + + return g; + } + + renderState({x, y, width, height}) { + // TODO: rounded corners + return this.renderBox({x, y, width, height}); + } + + renderBar({x, y, width, height}) { + return this.renderBox({x, y, width, height}, {fill: '#000000'}); + } + + renderCross({x, y, radius}) { + const r1 = (this.vary(0.2) + 1) * radius; + const l1 = this.lineNodes( + {x: x - r1, y: y - r1}, + {x: x + r1, y: y + r1}, + {} + ); + const r2 = (this.vary(0.2) + 1) * radius; + const l2 = this.lineNodes( + {x: x + r2, y: y - r2}, + {x: x - r2, y: y + r2}, + {} + ); + + return svg.make('path', { + 'd': l1.nodes + l2.nodes, + 'stroke': 'rgba(0,0,0,0.7)', + 'stroke-width': 0.8, + 'fill': 'none', + }); + } + + getNote(type) { + return NOTES[type]; + } + + drawAgentLine(container, {x, y0, y1, width, className}) { + if(width > 0) { + const shape = this.renderBox({ + x: x - width / 2, + y: y0, + width, + height: y1 - y0, + }, {fill: 'none'}); + shape.setAttribute('class', className); + container.appendChild(shape); + } else { + const shape = this.renderLine( + {x, y: y0}, + {x, y: y1}, + {} + ); + shape.setAttribute('class', className); + container.appendChild(shape); + } + } + } + + SketchTheme.RIGHT = RIGHT; + SketchTheme.LEFT = LEFT; + + return SketchTheme; +}); + /* jshint -W072 */ // Allow several required modules define('sequence/SequenceDiagram',[ 'core/EventObject', @@ -5852,6 +6946,7 @@ define('sequence/SequenceDiagram',[ './Exporter', './themes/Basic', './themes/Chunky', + './themes/Sketch', ], ( EventObject, Parser, @@ -5859,7 +6954,8 @@ define('sequence/SequenceDiagram',[ Renderer, Exporter, BasicTheme, - ChunkyTheme + ChunkyTheme, + SketchTheme ) => { /* jshint +W072 */ 'use strict'; @@ -5867,6 +6963,8 @@ define('sequence/SequenceDiagram',[ const themes = [ new BasicTheme(), new ChunkyTheme(), + new SketchTheme(SketchTheme.RIGHT), + new SketchTheme(SketchTheme.LEFT), ]; const SharedParser = new Parser(); diff --git a/lib/sequence-diagram.min.js b/lib/sequence-diagram.min.js index ba7ed38..3a18f0d 100644 --- a/lib/sequence-diagram.min.js +++ b/lib/sequence-diagram.min.js @@ -1 +1 @@ -!function(){var e,t,n;!function(s){function r(e,t){return x.call(e,t)}function i(e,t){var n,s,r,i,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((r=p[u.slice(0,d).join("/")])&&(r=r[s])){i=r,o=g;break}if(i)break;!h&&m&&m[s]&&(h=m[s],l=g)}!i&&h&&(i=h,o=l),i&&(n.splice(0,o,i),e=n.join("/"))}return e}function a(e,t){return function(){var n=y.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(r(f,e)){var t=f[e];delete f[e],k[e]=!0,d.apply(s,t)}if(!r(m,e)&&!r(k,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={},k={},x=Object.prototype.hasOwnProperty,y=[].slice,w=/\.js$/;u=function(e,t){var n,s=l(e),r=s[0],a=t[1];return e=s[1],r&&(n=h(r=i(r,a))),r?e=n&&n.normalize?n.normalize(e,function(e){return function(t){return i(t,e)}}(a)):i(e,a):(r=(s=l(e=i(e,a)))[0],e=s[1],r&&(n=h(r))),{f:r?r+"!"+e:e,n:e,pr:r,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,i){var l,d,c,b,x,y,w,A=[],v=typeof n;if(i=i||e,y=g(i),"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 r.push(s.slice());const i=e[n];if(!Array.isArray(i))return s.push(i),t(e,n+1,s,r),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 r=[],i=e.last(s);return Object.keys(i.then).forEach(a=>{let o=i.then[a];"number"==typeof o&&(o=s[s.length-o-1]),e.mergeSets(r,t(n,a,i,o))}),r}function s(t,n,s,{suggest:r,override:i}){n.type&&r!==n.type&&(i&&(n.type=i),e.mergeSets(t["known"+n.type],[n.value+" "]),n.type="",n.value=""),"string"==typeof r&&t["known"+r]&&(n.type=r,n.value&&(n.value+=s.s),n.value+=s.v)}function r(t,r,i){const o={type:"",value:""};let h=i;const l=[h];return t.line.forEach((r,i)=>{i===t.line.length-1&&(t.completions=n(t,l));const g=r.q?"":r.v,d=h.then[g]||h.then[""];"number"==typeof d?l.length-=d:l.push(d||a),h=e.last(l),s(t,o,r,h)}),r&&s(t,o,null,{}),t.nextCompletions=n(t,l),t.valid=Boolean(h.then["\n"])||0===Object.keys(h.then).length,h.type}function i(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:{"":i}},"":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 r={type:"",suggest:"\n",then:{}},i=e({"\n":r}),o={type:"variable",suggest:"Agent",then:{"":0,"\n":r,",":{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":r}}}}}},h=t({":":{type:"operator",suggest:!0,then:{"":i}}}),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:{"":i}}}},d={type:"variable",suggest:"Agent",then:{"":0,":":{type:"operator",suggest:!0,then:{"":i,"\n":{type:"",then:{}}}},"\n":r}},c={":":{type:"operator",suggest:!0,then:{"":e({as:{type:"keyword",suggest:!0,then:{"":{type:"variable",suggest:"Agent",then:{"":0,"\n":r}}}}})}}},u={type:"keyword",suggest:!0,then:Object.assign({over:{type:"keyword",suggest:!0,then:{"":t(c)}}},c)},p={title:{type:"keyword",suggest:!0,then:{"":i}},theme:{type:"keyword",suggest:!0,then:{"":{type:"string",suggest:{global:"themes",suffix:"\n"},then:{"":0,"\n":r}}}},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":r}},if:{type:"keyword",suggest:!0,then:{"":i,":":{type:"operator",suggest:!0,then:{"":i}},"\n":r}},else:{type:"keyword",suggest:["else\n","else if: "],then:{if:{type:"keyword",suggest:"if: ",then:{"":i,":":{type:"operator",suggest:!0,then:{"":i}}}},"\n":r}},repeat:{type:"keyword",suggest:!0,then:{"":i,":":{type:"operator",suggest:!0,then:{"":i}},"\n":r}},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:{}},"":i}},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 r=t(e,s.escape,n);if(r)return{newBlock:null,end:!1,appendSpace:"",appendValue:s.escapeWith(r),skip:r[0].length}}const r=t(e,s.end,n);return r?{newBlock:null,end:!0,appendSpace:"",appendValue:"",skip:r[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=r(this.pos)}endToken(){let e=null;return this.block.omit||(this.token.e=r(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,r=null;return-1===n?(s=t,r=[]):(s=t.substr(0,n),r=t.substr(n+1).split(",")),"inc"===s?function(t){let n=1,s=1,r=0;return t[0]&&(n=Number(t[0]),r=Math.max(r,e(t[0]))),t[1]&&(s=Number(t[1]),r=Math.max(r,e(t[1]))),{start:n,inc:s,dp:r}}(r):"<"+t+">"}const n=/(.*?)<([^<>]*)>/g,s=/\.([0-9]*)/;return function(e){const s=[];let r=null,i=0;for(n.lastIndex=0;r=n.exec(e);)r[1]&&s.push(r[1]),r[2]&&s.push(t(r[2])),i=n.lastIndex;const a=e.substr(i);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:r.test(e)?t.squashFrom:t.wordFrom,to:i.test(e)?t.squashTo:t.wordTo}}function n({global:e,prefix:t="",suffix:n=""},s){const r=s[e];return r?r.map(e=>t+e+n):[]}const s=/^([ \t]*)(.*)$/,r=/^[ \t\r\n:,]/,i=/[ \t\r\n]$/;return{getHints:function(r,i){const a=r.getCursor(),o=r.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 r=0;r0&&" "===r[n-1]&&i.squashFrom.ch--," "===r[s]&&i.squashTo.ch++,i}(r,a.line,g,o.end);let p=!1;const m=c.filter(e=>e.startsWith(h)).map(e=>e!==h+" "||i.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 r(e,t=null){let n="";return t&&(n=" at line "+(t.b.ln+1)+", character "+t.b.ch),new Error(e+n)}function i(e,t=0,n=null){if(null===n&&(n=e.length),n<=t)return"";let s=e[t].v;for(let r=t+1;r=s)&&(o=s),n>=o)throw r("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"}},k=[(e,t)=>"title"!==a(e[0])?null:(t.title=i(e,1),!0),(e,t)=>"theme"!==a(e[0])?null:(t.theme=i(e,1),!0),(e,t)=>{if("terminators"!==a(e[0]))return null;const n=a(e[1]);if(!n)throw r("Unspecified termination",e[0]);if(-1===m.indexOf(n))throw r('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 r("Unspecified header",e[0]);if(-1===m.indexOf(n))throw r('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])?"