From 890298457a8f28b21d98cb776c9c3fdbb4a28fcf Mon Sep 17 00:00:00 2001 From: Neil Cuzon <58763315+NeilCuzon@users.noreply.github.com> Date: Sat, 29 Feb 2020 00:03:42 -0800 Subject: [PATCH 01/34] Update README.md --- docs/README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/README.md b/docs/README.md index 4fb40e62b..a52ae5b36 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,13 +6,14 @@ ![banner](./img/header.png) -Generation of diagrams and flowcharts from text in a similar manner as markdown. +mermaid offers the capacity to generate diagrams and charts from markdown inspired text. -Ever wanted to simplify documentation and avoid heavy tools like Visio when explaining your code? +The reasoning behind it's inception was a need for simplified documentation and frustration with heavy and time consuming tools like Visio, for explaining code? -This is why mermaid was born, a simple markdown-like script language for generating charts from text via javascript. +Thus a simple markdown-inspired, script language for diagramming and charting, via javascript was made. Check out the list of [Integrations and Usages of Mermaid](./integrations.md) +For the uninitiated, you can also try out our [live editor](https://mermaid-js.github.io/mermaid-live-editor/) and look at our [documentation](https://mermaid-js.github.io/mermaid/#/n00b-overview) for a deeper understanding of the tool itself, more importantly don't forget to have fun. **Mermaid was nominated and won the JS Open Source Awards (2019) in the category "The most exciting use of technology"!!! Thanks to all involved, people committing pull requests, people answering questions and special thanks to Tyler Long who is helping me maintain the project.** @@ -41,9 +42,9 @@ mermaidAPI.initialize({ }); ``` -**🖖 Keep a steady pulse: mermaid needs more Collaborators [#866](https://github.com/knsv/mermaid/issues/866)** +**🖖 Keep a steady pulse: mermaid needs more Collaborators [#866](https://github.com/k3nsv/mermaid/issues/866)** -## Diagrams +## The following are examples of Diagrams that mermaid can make. ### Flowchart From cda41a15061d79536466444d2458957f22b751ee Mon Sep 17 00:00:00 2001 From: Neil Cuzon <58763315+NeilCuzon@users.noreply.github.com> Date: Sat, 29 Feb 2020 00:04:38 -0800 Subject: [PATCH 02/34] Update README.md --- docs/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/README.md b/docs/README.md index a52ae5b36..e1c400b9f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -5,7 +5,7 @@ [![Join the chat at https://gitter.im/knsv/mermaid](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/knsv/mermaid?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) ![banner](./img/header.png) - +# What is mermaid? mermaid offers the capacity to generate diagrams and charts from markdown inspired text. The reasoning behind it's inception was a need for simplified documentation and frustration with heavy and time consuming tools like Visio, for explaining code? @@ -44,7 +44,7 @@ mermaidAPI.initialize({ **🖖 Keep a steady pulse: mermaid needs more Collaborators [#866](https://github.com/k3nsv/mermaid/issues/866)** -## The following are examples of Diagrams that mermaid can make. +## The following are examples of Diagrams that mermaid can make: ### Flowchart From 5693c694578dab6ade5a6214543946543eeecf76 Mon Sep 17 00:00:00 2001 From: Neil Cuzon <58763315+NeilCuzon@users.noreply.github.com> Date: Sat, 29 Feb 2020 00:07:47 -0800 Subject: [PATCH 03/34] Update README.md --- docs/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/README.md b/docs/README.md index e1c400b9f..22151a6f2 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,11 +6,12 @@ ![banner](./img/header.png) # What is mermaid? -mermaid offers the capacity to generate diagrams and charts from markdown inspired text. -The reasoning behind it's inception was a need for simplified documentation and frustration with heavy and time consuming tools like Visio, for explaining code? +It is a simple markdown-inspired, script language for diagramming and charting that can be deployed via Javascipt. -Thus a simple markdown-inspired, script language for diagramming and charting, via javascript was made. +The reasoning behind it's inception was a need for simplified documentation and frustration with heavy and time consuming tools like Visio, for explaining code. + +Thus mermaid was created to make the process of diagramming and charting, as simple and as close to markdown, as possible. Check out the list of [Integrations and Usages of Mermaid](./integrations.md) For the uninitiated, you can also try out our [live editor](https://mermaid-js.github.io/mermaid-live-editor/) and look at our [documentation](https://mermaid-js.github.io/mermaid/#/n00b-overview) for a deeper understanding of the tool itself, more importantly don't forget to have fun. From a0b1d16e79c345fce0ba0d243ed803d03358f778 Mon Sep 17 00:00:00 2001 From: Neil Cuzon <58763315+NeilCuzon@users.noreply.github.com> Date: Mon, 2 Mar 2020 16:47:08 -0800 Subject: [PATCH 04/34] Update SUMMARY.md --- docs/SUMMARY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index e4be903f9..f40657a49 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -1,6 +1,6 @@ # Summary -- [mermaid](README.md) +- [mermaid-README](README.md) - [FAQ](faq.md) - [Breaking changes](breakingChanges.md) - [Usage](usage.md) From 25e2d78311cd8bfb83a247609162cd5315e278f4 Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Wed, 4 Mar 2020 20:35:59 +0100 Subject: [PATCH 05/34] #1295 Start renderer --- .gitignore | 3 +- cypress/platform/current.html | 7 +- src/diagrams/flowchart-v2/flowChartShapes.js | 261 +++++++ .../flowchart-v2/flowChartShapes.spec.js | 131 ++++ src/diagrams/flowchart-v2/flowDb.js | 644 ++++++++++++++++++ src/diagrams/flowchart-v2/flowRenderer.js | 488 +++++++++++++ src/diagrams/flowchart/parser/flow.jison | 3 +- src/experimental.js | 42 ++ src/mermaid.js | 1 - src/mermaidAPI.js | 11 + src/utils.js | 3 + 11 files changed, 1586 insertions(+), 8 deletions(-) create mode 100644 src/diagrams/flowchart-v2/flowChartShapes.js create mode 100644 src/diagrams/flowchart-v2/flowChartShapes.spec.js create mode 100644 src/diagrams/flowchart-v2/flowDb.js create mode 100644 src/diagrams/flowchart-v2/flowRenderer.js create mode 100644 src/experimental.js diff --git a/.gitignore b/.gitignore index 69f442484..58579d79b 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,5 @@ dist/classTest.html dist/sequenceTest.html .vscode/ -cypress/platform/current.html \ No newline at end of file +cypress/platform/current.html +cypress/platform/experimental.html \ No newline at end of file diff --git a/cypress/platform/current.html b/cypress/platform/current.html index 3ed964921..2f5ec32b4 100644 --- a/cypress/platform/current.html +++ b/cypress/platform/current.html @@ -20,11 +20,8 @@

info below

- stateDiagram - O --> A : ong line using
should work
should work
should work - A --> B : ong line using
should work - B --> C : Sing line - + flowchart LR + A --> B
diff --git a/src/diagrams/flowchart-v2/flowChartShapes.js b/src/diagrams/flowchart-v2/flowChartShapes.js new file mode 100644 index 000000000..23cb53049 --- /dev/null +++ b/src/diagrams/flowchart-v2/flowChartShapes.js @@ -0,0 +1,261 @@ +import dagreD3 from 'dagre-d3'; + +function question(parent, bbox, node) { + const w = bbox.width; + const h = bbox.height; + const s = (w + h) * 0.9; + const points = [ + { x: s / 2, y: 0 }, + { x: s, y: -s / 2 }, + { x: s / 2, y: -s }, + { x: 0, y: -s / 2 } + ]; + const shapeSvg = insertPolygonShape(parent, s, s, points); + node.intersect = function(point) { + return dagreD3.intersect.polygon(node, points, point); + }; + return shapeSvg; +} + +function hexagon(parent, bbox, node) { + const f = 4; + const h = bbox.height; + const m = h / f; + const w = bbox.width + 2 * m; + const points = [ + { x: m, y: 0 }, + { x: w - m, y: 0 }, + { x: w, y: -h / 2 }, + { x: w - m, y: -h }, + { x: m, y: -h }, + { x: 0, y: -h / 2 } + ]; + const shapeSvg = insertPolygonShape(parent, w, h, points); + node.intersect = function(point) { + return dagreD3.intersect.polygon(node, points, point); + }; + return shapeSvg; +} + +function rect_left_inv_arrow(parent, bbox, node) { + const w = bbox.width; + const h = bbox.height; + const points = [ + { x: -h / 2, y: 0 }, + { x: w, y: 0 }, + { x: w, y: -h }, + { x: -h / 2, y: -h }, + { x: 0, y: -h / 2 } + ]; + const shapeSvg = insertPolygonShape(parent, w, h, points); + node.intersect = function(point) { + return dagreD3.intersect.polygon(node, points, point); + }; + return shapeSvg; +} + +function lean_right(parent, bbox, node) { + const w = bbox.width; + const h = bbox.height; + const points = [ + { x: (-2 * h) / 6, y: 0 }, + { x: w - h / 6, y: 0 }, + { x: w + (2 * h) / 6, y: -h }, + { x: h / 6, y: -h } + ]; + const shapeSvg = insertPolygonShape(parent, w, h, points); + node.intersect = function(point) { + return dagreD3.intersect.polygon(node, points, point); + }; + return shapeSvg; +} + +function lean_left(parent, bbox, node) { + const w = bbox.width; + const h = bbox.height; + const points = [ + { x: (2 * h) / 6, y: 0 }, + { x: w + h / 6, y: 0 }, + { x: w - (2 * h) / 6, y: -h }, + { x: -h / 6, y: -h } + ]; + const shapeSvg = insertPolygonShape(parent, w, h, points); + node.intersect = function(point) { + return dagreD3.intersect.polygon(node, points, point); + }; + return shapeSvg; +} + +function trapezoid(parent, bbox, node) { + const w = bbox.width; + const h = bbox.height; + const points = [ + { x: (-2 * h) / 6, y: 0 }, + { x: w + (2 * h) / 6, y: 0 }, + { x: w - h / 6, y: -h }, + { x: h / 6, y: -h } + ]; + const shapeSvg = insertPolygonShape(parent, w, h, points); + node.intersect = function(point) { + return dagreD3.intersect.polygon(node, points, point); + }; + return shapeSvg; +} + +function inv_trapezoid(parent, bbox, node) { + const w = bbox.width; + const h = bbox.height; + const points = [ + { x: h / 6, y: 0 }, + { x: w - h / 6, y: 0 }, + { x: w + (2 * h) / 6, y: -h }, + { x: (-2 * h) / 6, y: -h } + ]; + const shapeSvg = insertPolygonShape(parent, w, h, points); + node.intersect = function(point) { + return dagreD3.intersect.polygon(node, points, point); + }; + return shapeSvg; +} + +function rect_right_inv_arrow(parent, bbox, node) { + const w = bbox.width; + const h = bbox.height; + const points = [ + { x: 0, y: 0 }, + { x: w + h / 2, y: 0 }, + { x: w, y: -h / 2 }, + { x: w + h / 2, y: -h }, + { x: 0, y: -h } + ]; + const shapeSvg = insertPolygonShape(parent, w, h, points); + node.intersect = function(point) { + return dagreD3.intersect.polygon(node, points, point); + }; + return shapeSvg; +} + +function stadium(parent, bbox, node) { + const h = bbox.height; + const w = bbox.width + h / 4; + + const shapeSvg = parent + .insert('rect', ':first-child') + .attr('rx', h / 2) + .attr('ry', h / 2) + .attr('x', -w / 2) + .attr('y', -h / 2) + .attr('width', w) + .attr('height', h); + + node.intersect = function(point) { + return dagreD3.intersect.rect(node, point); + }; + return shapeSvg; +} + +function cylinder(parent, bbox, node) { + const w = bbox.width; + const rx = w / 2; + const ry = rx / (2.5 + w / 50); + const h = bbox.height + ry; + + const shape = + 'M 0,' + + ry + + ' a ' + + rx + + ',' + + ry + + ' 0,0,0 ' + + w + + ' 0 a ' + + rx + + ',' + + ry + + ' 0,0,0 ' + + -w + + ' 0 l 0,' + + h + + ' a ' + + rx + + ',' + + ry + + ' 0,0,0 ' + + w + + ' 0 l 0,' + + -h; + + const shapeSvg = parent + .attr('label-offset-y', ry) + .insert('path', ':first-child') + .attr('d', shape) + .attr('transform', 'translate(' + -w / 2 + ',' + -(h / 2 + ry) + ')'); + + node.intersect = function(point) { + const pos = dagreD3.intersect.rect(node, point); + const x = pos.x - node.x; + + if ( + rx != 0 && + (Math.abs(x) < node.width / 2 || + (Math.abs(x) == node.width / 2 && Math.abs(pos.y - node.y) > node.height / 2 - ry)) + ) { + // ellipsis equation: x*x / a*a + y*y / b*b = 1 + // solve for y to get adjustion value for pos.y + let y = ry * ry * (1 - (x * x) / (rx * rx)); + if (y != 0) y = Math.sqrt(y); + y = ry - y; + if (point.y - node.y > 0) y = -y; + + pos.y += y; + } + + return pos; + }; + + return shapeSvg; +} + +export function addToRender(render) { + render.shapes().question = question; + render.shapes().hexagon = hexagon; + render.shapes().stadium = stadium; + render.shapes().cylinder = cylinder; + + // Add custom shape for box with inverted arrow on left side + render.shapes().rect_left_inv_arrow = rect_left_inv_arrow; + + // Add custom shape for box with inverted arrow on left side + render.shapes().lean_right = lean_right; + + // Add custom shape for box with inverted arrow on left side + render.shapes().lean_left = lean_left; + + // Add custom shape for box with inverted arrow on left side + render.shapes().trapezoid = trapezoid; + + // Add custom shape for box with inverted arrow on left side + render.shapes().inv_trapezoid = inv_trapezoid; + + // Add custom shape for box with inverted arrow on right side + render.shapes().rect_right_inv_arrow = rect_right_inv_arrow; +} + +function insertPolygonShape(parent, w, h, points) { + return parent + .insert('polygon', ':first-child') + .attr( + 'points', + points + .map(function(d) { + return d.x + ',' + d.y; + }) + .join(' ') + ) + .attr('transform', 'translate(' + -w / 2 + ',' + h / 2 + ')'); +} + +export default { + addToRender +}; diff --git a/src/diagrams/flowchart-v2/flowChartShapes.spec.js b/src/diagrams/flowchart-v2/flowChartShapes.spec.js new file mode 100644 index 000000000..61e876d4b --- /dev/null +++ b/src/diagrams/flowchart-v2/flowChartShapes.spec.js @@ -0,0 +1,131 @@ +import { addToRender } from './flowChartShapes'; + +describe('flowchart shapes', function() { + // rect-based shapes + [ + ['stadium', useWidth, useHeight] + ].forEach(function([shapeType, getW, getH]) { + it(`should add a ${shapeType} shape that renders a properly positioned rect element`, function() { + const mockRender = MockRender(); + const mockSvg = MockSvg(); + addToRender(mockRender); + + [[100, 100], [123, 45], [71, 300]].forEach(function([width, height]) { + const shape = mockRender.shapes()[shapeType](mockSvg, { width, height }, {}); + const w = width + height / 4; + const h = height; + const dx = -getW(w, h) / 2; + const dy = -getH(w, h) / 2; + expect(shape.__tag).toEqual('rect'); + expect(shape.__attrs).toHaveProperty('x', dx); + expect(shape.__attrs).toHaveProperty('y', dy); + }); + }); + }); + + // path-based shapes + [ + ['cylinder', useWidth, useHeight] + ].forEach(function([shapeType, getW, getH]) { + it(`should add a ${shapeType} shape that renders a properly positioned path element`, function() { + const mockRender = MockRender(); + const mockSvg = MockSvg(); + addToRender(mockRender); + + [[100, 100], [123, 45], [71, 300]].forEach(function([width, height]) { + const shape = mockRender.shapes()[shapeType](mockSvg, { width, height }, {}); + expect(shape.__tag).toEqual('path'); + expect(shape.__attrs).toHaveProperty('d'); + }); + }); + }); + + // polygon-based shapes + [ + [ + 'question', + 4, + function(w, h) { + return (w + h) * 0.9; + }, + function(w, h) { + return (w + h) * 0.9; + } + ], + [ + 'hexagon', + 6, + function(w, h) { + return w + h / 2; + }, + useHeight + ], + ['rect_left_inv_arrow', 5, useWidth, useHeight], + ['rect_right_inv_arrow', 5, useWidth, useHeight], + ['lean_right', 4, useWidth, useHeight], + ['lean_left', 4, useWidth, useHeight], + ['trapezoid', 4, useWidth, useHeight], + ['inv_trapezoid', 4, useWidth, useHeight] + ].forEach(function([shapeType, expectedPointCount, getW, getH]) { + it(`should add a ${shapeType} shape that renders a properly translated polygon element`, function() { + const mockRender = MockRender(); + const mockSvg = MockSvg(); + addToRender(mockRender); + + [[100, 100], [123, 45], [71, 300]].forEach(function([width, height]) { + const shape = mockRender.shapes()[shapeType](mockSvg, { width, height }, {}); + const dx = -getW(width, height) / 2; + const dy = getH(width, height) / 2; + const points = shape.__attrs.points.split(' '); + expect(shape.__tag).toEqual('polygon'); + expect(shape.__attrs).toHaveProperty('transform', `translate(${dx},${dy})`); + expect(points).toHaveLength(expectedPointCount); + }); + }); + }); +}); + +function MockRender() { + const shapes = {}; + return { + shapes() { + return shapes; + } + }; +} + +function MockSvg(tag, ...args) { + const children = []; + const attributes = {}; + return { + get __args() { + return args; + }, + get __tag() { + return tag; + }, + get __children() { + return children; + }, + get __attrs() { + return attributes; + }, + insert: function(tag, ...args) { + const child = MockSvg(tag, ...args); + children.push(child); + return child; + }, + attr(name, value) { + this.__attrs[name] = value; + return this; + } + }; +} + +function useWidth(w, h) { + return w; +} + +function useHeight(w, h) { + return h; +} diff --git a/src/diagrams/flowchart-v2/flowDb.js b/src/diagrams/flowchart-v2/flowDb.js new file mode 100644 index 000000000..4917a54a7 --- /dev/null +++ b/src/diagrams/flowchart-v2/flowDb.js @@ -0,0 +1,644 @@ +import * as d3 from 'd3'; +import { logger } from '../../logger'; +import utils from '../../utils'; +import { getConfig } from '../../config'; +import common from '../common/common'; + +// const MERMAID_DOM_ID_PREFIX = 'mermaid-dom-id-'; +const MERMAID_DOM_ID_PREFIX = ''; + +const config = getConfig(); +let vertices = {}; +let edges = []; +let classes = []; +let subGraphs = []; +let subGraphLookup = {}; +let tooltips = {}; +let subCount = 0; +let firstGraphFlag = true; +let direction; +// Functions to be run after graph rendering +let funs = []; + +/** + * Function called by parser when a node definition has been found + * @param id + * @param text + * @param type + * @param style + * @param classes + */ +export const addVertex = function(_id, text, type, style, classes) { + let txt; + let id = _id; + if (typeof id === 'undefined') { + return; + } + if (id.trim().length === 0) { + return; + } + + if (id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id; + + if (typeof vertices[id] === 'undefined') { + vertices[id] = { id: id, styles: [], classes: [] }; + } + if (typeof text !== 'undefined') { + txt = common.sanitizeText(text.trim(), config); + + // strip quotes if string starts and ends with a quote + if (txt[0] === '"' && txt[txt.length - 1] === '"') { + txt = txt.substring(1, txt.length - 1); + } + + vertices[id].text = txt; + } else { + if (typeof vertices[id].text === 'undefined') { + vertices[id].text = _id; + } + } + if (typeof type !== 'undefined') { + vertices[id].type = type; + } + if (typeof style !== 'undefined') { + if (style !== null) { + style.forEach(function(s) { + vertices[id].styles.push(s); + }); + } + } + if (typeof classes !== 'undefined') { + if (classes !== null) { + classes.forEach(function(s) { + vertices[id].classes.push(s); + }); + } + } +}; + +/** + * Function called by parser when a link/edge definition has been found + * @param start + * @param end + * @param type + * @param linktext + */ +export const addSingleLink = function(_start, _end, type, linktext) { + let start = _start; + let end = _end; + if (start[0].match(/\d/)) start = MERMAID_DOM_ID_PREFIX + start; + if (end[0].match(/\d/)) end = MERMAID_DOM_ID_PREFIX + end; + logger.info('Got edge...', start, end); + + const edge = { start: start, end: end, type: undefined, text: '' }; + linktext = type.text; + + if (typeof linktext !== 'undefined') { + edge.text = common.sanitizeText(linktext.trim(), config); + + // strip quotes if string starts and exnds with a quote + if (edge.text[0] === '"' && edge.text[edge.text.length - 1] === '"') { + edge.text = edge.text.substring(1, edge.text.length - 1); + } + } + + if (typeof type !== 'undefined') { + edge.type = type.type; + edge.stroke = type.stroke; + } + edges.push(edge); +}; +export const addLink = function(_start, _end, type, linktext) { + let i, j; + for (i = 0; i < _start.length; i++) { + for (j = 0; j < _end.length; j++) { + addSingleLink(_start[i], _end[j], type, linktext); + } + } +}; + +/** + * Updates a link's line interpolation algorithm + * @param pos + * @param interpolate + */ +export const updateLinkInterpolate = function(positions, interp) { + positions.forEach(function(pos) { + if (pos === 'default') { + edges.defaultInterpolate = interp; + } else { + edges[pos].interpolate = interp; + } + }); +}; + +/** + * Updates a link with a style + * @param pos + * @param style + */ +export const updateLink = function(positions, style) { + positions.forEach(function(pos) { + if (pos === 'default') { + edges.defaultStyle = style; + } else { + if (utils.isSubstringInArray('fill', style) === -1) { + style.push('fill:none'); + } + edges[pos].style = style; + } + }); +}; + +export const addClass = function(id, style) { + if (typeof classes[id] === 'undefined') { + classes[id] = { id: id, styles: [], textStyles: [] }; + } + + if (typeof style !== 'undefined') { + if (style !== null) { + style.forEach(function(s) { + if (s.match('color')) { + const newStyle1 = s.replace('fill', 'bgFill'); + const newStyle2 = newStyle1.replace('color', 'fill'); + classes[id].textStyles.push(newStyle2); + } + classes[id].styles.push(s); + }); + } + } +}; + +/** + * Called by parser when a graph definition is found, stores the direction of the chart. + * @param dir + */ +export const setDirection = function(dir) { + direction = dir; + if (direction.match(/.*/)) { + direction = 'LR'; + } + if (direction.match(/.*v/)) { + direction = 'TB'; + } +}; + +/** + * Called by parser when a special node is found, e.g. a clickable element. + * @param ids Comma separated list of ids + * @param className Class to add + */ +export const setClass = function(ids, className) { + ids.split(',').forEach(function(_id) { + let id = _id; + if (_id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id; + if (typeof vertices[id] !== 'undefined') { + vertices[id].classes.push(className); + } + + if (typeof subGraphLookup[id] !== 'undefined') { + subGraphLookup[id].classes.push(className); + } + }); +}; + +const setTooltip = function(ids, tooltip) { + ids.split(',').forEach(function(id) { + if (typeof tooltip !== 'undefined') { + tooltips[id] = common.sanitizeText(tooltip, config); + } + }); +}; + +const setClickFun = function(_id, functionName) { + let id = _id; + if (_id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id; + if (config.securityLevel !== 'loose') { + return; + } + if (typeof functionName === 'undefined') { + return; + } + if (typeof vertices[id] !== 'undefined') { + funs.push(function() { + const elem = document.querySelector(`[id="${id}"]`); + if (elem !== null) { + elem.addEventListener( + 'click', + function() { + window[functionName](id); + }, + false + ); + } + }); + } +}; + +/** + * Called by parser when a link is found. Adds the URL to the vertex data. + * @param ids Comma separated list of ids + * @param linkStr URL to create a link for + * @param tooltip Tooltip for the clickable element + */ +export const setLink = function(ids, linkStr, tooltip) { + ids.split(',').forEach(function(_id) { + let id = _id; + if (_id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id; + if (typeof vertices[id] !== 'undefined') { + vertices[id].link = utils.formatUrl(linkStr, config); + } + }); + setTooltip(ids, tooltip); + setClass(ids, 'clickable'); +}; +export const getTooltip = function(id) { + return tooltips[id]; +}; + +/** + * Called by parser when a click definition is found. Registers an event handler. + * @param ids Comma separated list of ids + * @param functionName Function to be called on click + * @param tooltip Tooltip for the clickable element + */ +export const setClickEvent = function(ids, functionName, tooltip) { + ids.split(',').forEach(function(id) { + setClickFun(id, functionName); + }); + setTooltip(ids, tooltip); + setClass(ids, 'clickable'); +}; + +export const bindFunctions = function(element) { + funs.forEach(function(fun) { + fun(element); + }); +}; +export const getDirection = function() { + return direction.trim(); +}; +/** + * Retrieval function for fetching the found nodes after parsing has completed. + * @returns {{}|*|vertices} + */ +export const getVertices = function() { + return vertices; +}; + +/** + * Retrieval function for fetching the found links after parsing has completed. + * @returns {{}|*|edges} + */ +export const getEdges = function() { + return edges; +}; + +/** + * Retrieval function for fetching the found class definitions after parsing has completed. + * @returns {{}|*|classes} + */ +export const getClasses = function() { + return classes; +}; + +const setupToolTips = function(element) { + let tooltipElem = d3.select('.mermaidTooltip'); + if ((tooltipElem._groups || tooltipElem)[0][0] === null) { + tooltipElem = d3 + .select('body') + .append('div') + .attr('class', 'mermaidTooltip') + .style('opacity', 0); + } + + const svg = d3.select(element).select('svg'); + + const nodes = svg.selectAll('g.node'); + nodes + .on('mouseover', function() { + const el = d3.select(this); + const title = el.attr('title'); + // Dont try to draw a tooltip if no data is provided + if (title === null) { + return; + } + const rect = this.getBoundingClientRect(); + + tooltipElem + .transition() + .duration(200) + .style('opacity', '.9'); + tooltipElem + .html(el.attr('title')) + .style('left', rect.left + (rect.right - rect.left) / 2 + 'px') + .style('top', rect.top - 14 + document.body.scrollTop + 'px'); + el.classed('hover', true); + }) + .on('mouseout', function() { + tooltipElem + .transition() + .duration(500) + .style('opacity', 0); + const el = d3.select(this); + el.classed('hover', false); + }); +}; +funs.push(setupToolTips); + +/** + * Clears the internal graph db so that a new graph can be parsed. + */ +export const clear = function() { + vertices = {}; + classes = {}; + edges = []; + funs = []; + funs.push(setupToolTips); + subGraphs = []; + subGraphLookup = {}; + subCount = 0; + tooltips = []; + firstGraphFlag = true; +}; +/** + * + * @returns {string} + */ +export const defaultStyle = function() { + return 'fill:#ffa;stroke: #f66; stroke-width: 3px; stroke-dasharray: 5, 5;fill:#ffa;stroke: #666;'; +}; + +/** + * Clears the internal graph db so that a new graph can be parsed. + */ +export const addSubGraph = function(_id, list, _title) { + let id = _id.trim(); + let title = _title; + if (_id === _title && _title.match(/\s/)) { + id = undefined; + } + function uniq(a) { + const prims = { boolean: {}, number: {}, string: {} }; + const objs = []; + + return a.filter(function(item) { + const type = typeof item; + if (item.trim() === '') { + return false; + } + if (type in prims) { + return prims[type].hasOwnProperty(item) ? false : (prims[type][item] = true); // eslint-disable-line + } else { + return objs.indexOf(item) >= 0 ? false : objs.push(item); + } + }); + } + + let nodeList = []; + + nodeList = uniq(nodeList.concat.apply(nodeList, list)); + for (let i = 0; i < nodeList.length; i++) { + if (nodeList[i][0].match(/\d/)) nodeList[i] = MERMAID_DOM_ID_PREFIX + nodeList[i]; + } + + id = id || 'subGraph' + subCount; + if (id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id; + title = title || ''; + title = common.sanitizeText(title, config); + subCount = subCount + 1; + const subGraph = { id: id, nodes: nodeList, title: title.trim(), classes: [] }; + subGraphs.push(subGraph); + subGraphLookup[id] = subGraph; + return id; +}; + +const getPosForId = function(id) { + for (let i = 0; i < subGraphs.length; i++) { + if (subGraphs[i].id === id) { + return i; + } + } + return -1; +}; +let secCount = -1; +const posCrossRef = []; +const indexNodes2 = function(id, pos) { + const nodes = subGraphs[pos].nodes; + secCount = secCount + 1; + if (secCount > 2000) { + return; + } + posCrossRef[secCount] = pos; + // Check if match + if (subGraphs[pos].id === id) { + return { + result: true, + count: 0 + }; + } + + let count = 0; + let posCount = 1; + while (count < nodes.length) { + const childPos = getPosForId(nodes[count]); + // Ignore regular nodes (pos will be -1) + if (childPos >= 0) { + const res = indexNodes2(id, childPos); + if (res.result) { + return { + result: true, + count: posCount + res.count + }; + } else { + posCount = posCount + res.count; + } + } + count = count + 1; + } + + return { + result: false, + count: posCount + }; +}; + +export const getDepthFirstPos = function(pos) { + return posCrossRef[pos]; +}; +export const indexNodes = function() { + secCount = -1; + if (subGraphs.length > 0) { + indexNodes2('none', subGraphs.length - 1, 0); + } +}; + +export const getSubGraphs = function() { + return subGraphs; +}; + +export const firstGraph = () => { + if (firstGraphFlag) { + firstGraphFlag = false; + return true; + } + return false; +}; + +const destructStartLink = _str => { + const str = _str.trim(); + + switch (str) { + case '<--': + return { type: 'arrow', stroke: 'normal' }; + case 'x--': + return { type: 'arrow_cross', stroke: 'normal' }; + case 'o--': + return { type: 'arrow_circle', stroke: 'normal' }; + case '<-.': + return { type: 'arrow', stroke: 'dotted' }; + case 'x-.': + return { type: 'arrow_cross', stroke: 'dotted' }; + case 'o-.': + return { type: 'arrow_circle', stroke: 'dotted' }; + case '<==': + return { type: 'arrow', stroke: 'thick' }; + case 'x==': + return { type: 'arrow_cross', stroke: 'thick' }; + case 'o==': + return { type: 'arrow_circle', stroke: 'thick' }; + case '--': + return { type: 'arrow_open', stroke: 'normal' }; + case '==': + return { type: 'arrow_open', stroke: 'thick' }; + case '-.': + return { type: 'arrow_open', stroke: 'dotted' }; + } +}; + +const destructEndLink = _str => { + const str = _str.trim(); + + switch (str) { + case '--x': + return { type: 'arrow_cross', stroke: 'normal' }; + case '-->': + return { type: 'arrow', stroke: 'normal' }; + case '<-->': + return { type: 'double_arrow_point', stroke: 'normal' }; + case 'x--x': + return { type: 'double_arrow_cross', stroke: 'normal' }; + case 'o--o': + return { type: 'double_arrow_circle', stroke: 'normal' }; + case 'o.-o': + return { type: 'double_arrow_circle', stroke: 'dotted' }; + case '<==>': + return { type: 'double_arrow_point', stroke: 'thick' }; + case 'o==o': + return { type: 'double_arrow_circle', stroke: 'thick' }; + case 'x==x': + return { type: 'double_arrow_cross', stroke: 'thick' }; + case 'x.-x': + return { type: 'double_arrow_cross', stroke: 'dotted' }; + case 'x-.-x': + return { type: 'double_arrow_cross', stroke: 'dotted' }; + case '<.->': + return { type: 'double_arrow_point', stroke: 'dotted' }; + case '<-.->': + return { type: 'double_arrow_point', stroke: 'dotted' }; + case 'o-.-o': + return { type: 'double_arrow_circle', stroke: 'dotted' }; + case '--o': + return { type: 'arrow_circle', stroke: 'normal' }; + case '---': + return { type: 'arrow_open', stroke: 'normal' }; + case '-.-x': + return { type: 'arrow_cross', stroke: 'dotted' }; + case '-.->': + return { type: 'arrow', stroke: 'dotted' }; + case '-.-o': + return { type: 'arrow_circle', stroke: 'dotted' }; + case '-.-': + return { type: 'arrow_open', stroke: 'dotted' }; + case '.-x': + return { type: 'arrow_cross', stroke: 'dotted' }; + case '.->': + return { type: 'arrow', stroke: 'dotted' }; + case '.-o': + return { type: 'arrow_circle', stroke: 'dotted' }; + case '.-': + return { type: 'arrow_open', stroke: 'dotted' }; + case '==x': + return { type: 'arrow_cross', stroke: 'thick' }; + case '==>': + return { type: 'arrow', stroke: 'thick' }; + case '==o': + return { type: 'arrow_circle', stroke: 'thick' }; + case '===': + return { type: 'arrow_open', stroke: 'thick' }; + } +}; + +const destructLink = (_str, _startStr) => { + const info = destructEndLink(_str); + let startInfo; + if (_startStr) { + startInfo = destructStartLink(_startStr); + + if (startInfo.stroke !== info.stroke) { + return { type: 'INVALID', stroke: 'INVALID' }; + } + + if (startInfo.type === 'arrow_open') { + // -- xyz --> - take arrow type form ending + startInfo.type = info.type; + } else { + // x-- xyz --> - not supported + if (startInfo.type !== info.type) return { type: 'INVALID', stroke: 'INVALID' }; + + startInfo.type = 'double_' + startInfo.type; + } + + if (startInfo.type === 'double_arrow') { + startInfo.type = 'double_arrow_point'; + } + + return startInfo; + } + + return info; +}; + +export default { + addVertex, + addLink, + updateLinkInterpolate, + updateLink, + addClass, + setDirection, + setClass, + getTooltip, + setClickEvent, + setLink, + bindFunctions, + getDirection, + getVertices, + getEdges, + getClasses, + clear, + defaultStyle, + addSubGraph, + getDepthFirstPos, + indexNodes, + getSubGraphs, + destructLink, + lex: { + firstGraph + } +}; diff --git a/src/diagrams/flowchart-v2/flowRenderer.js b/src/diagrams/flowchart-v2/flowRenderer.js new file mode 100644 index 000000000..10250a16c --- /dev/null +++ b/src/diagrams/flowchart-v2/flowRenderer.js @@ -0,0 +1,488 @@ +import graphlib from 'graphlib'; +import * as d3 from 'd3'; +import dagre from 'dagre'; + +import flowDb from '../flowchart/flowDb'; +import flow from '../flowchart/parser/flow'; +import { getConfig } from '../../config'; + +import dagreD3 from 'dagre-d3'; +import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js'; +import { logger } from '../../logger'; +import { interpolateToCurve, getStylesFromArray } from '../../utils'; +import flowChartShapes from '../flowchart/flowChartShapes'; + +const conf = {}; +export const setConf = function(cnf) { + const keys = Object.keys(cnf); + for (let i = 0; i < keys.length; i++) { + conf[keys[i]] = cnf[keys[i]]; + } +}; + +/** + * Function that adds the vertices found in the graph definition to the graph to be rendered. + * @param vert Object containing the vertices. + * @param g The graph that is to be drawn. + */ +export const addVertices = function(vert, g, svgId) { + const svg = d3.select(`[id="${svgId}"]`); + const keys = Object.keys(vert); + + // Iterate through each item in the vertex object (containing all the vertices found) in the graph definition + keys.forEach(function(id) { + const vertex = vert[id]; + + /** + * Variable for storing the classes for the vertex + * @type {string} + */ + let classStr = 'default'; + if (vertex.classes.length > 0) { + classStr = vertex.classes.join(' '); + } + + const styles = getStylesFromArray(vertex.styles); + + // Use vertex id as text in the box if no text is provided by the graph definition + let vertexText = vertex.text !== undefined ? vertex.text : vertex.id; + + // We create a SVG label, either by delegating to addHtmlLabel or manually + let vertexNode; + if (getConfig().flowchart.htmlLabels) { + // TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that? + const node = { + label: vertexText.replace( + /fa[lrsb]?:fa-[\w-]+/g, + s => `` + ) + }; + vertexNode = addHtmlLabel(svg, node).node(); + vertexNode.parentNode.removeChild(vertexNode); + } else { + const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text'); + svgLabel.setAttribute('style', styles.labelStyle.replace('color:', 'fill:')); + + const rows = vertexText.split(//gi); + + for (let j = 0; j < rows.length; j++) { + const tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan'); + tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve'); + tspan.setAttribute('dy', '1em'); + tspan.setAttribute('x', '1'); + tspan.textContent = rows[j]; + svgLabel.appendChild(tspan); + } + vertexNode = svgLabel; + } + + let radious = 0; + let _shape = ''; + // Set the shape based parameters + switch (vertex.type) { + case 'round': + radious = 5; + _shape = 'rect'; + break; + case 'square': + _shape = 'rect'; + break; + case 'diamond': + _shape = 'question'; + break; + case 'hexagon': + _shape = 'hexagon'; + break; + case 'odd': + _shape = 'rect_left_inv_arrow'; + break; + case 'lean_right': + _shape = 'lean_right'; + break; + case 'lean_left': + _shape = 'lean_left'; + break; + case 'trapezoid': + _shape = 'trapezoid'; + break; + case 'inv_trapezoid': + _shape = 'inv_trapezoid'; + break; + case 'odd_right': + _shape = 'rect_left_inv_arrow'; + break; + case 'circle': + _shape = 'circle'; + break; + case 'ellipse': + _shape = 'ellipse'; + break; + case 'stadium': + _shape = 'stadium'; + break; + case 'cylinder': + _shape = 'cylinder'; + break; + case 'group': + _shape = 'rect'; + break; + default: + _shape = 'rect'; + } + // Add the node + g.setNode(vertex.id, { + labelType: 'svg', + labelStyle: styles.labelStyle, + shape: _shape, + label: vertexNode, + rx: radious, + ry: radious, + class: classStr, + style: styles.style, + id: vertex.id + }); + }); +}; + +/** + * Add edges to graph based on parsed graph defninition + * @param {Object} edges The edges to add to the graph + * @param {Object} g The graph object + */ +export const addEdges = function(edges, g) { + let cnt = 0; + + let defaultStyle; + let defaultLabelStyle; + + if (typeof edges.defaultStyle !== 'undefined') { + const defaultStyles = getStylesFromArray(edges.defaultStyle); + defaultStyle = defaultStyles.style; + defaultLabelStyle = defaultStyles.labelStyle; + } + + edges.forEach(function(edge) { + cnt++; + const edgeData = {}; + + // Set link type for rendering + if (edge.type === 'arrow_open') { + edgeData.arrowhead = 'none'; + } else { + edgeData.arrowhead = 'normal'; + } + + let style = ''; + let labelStyle = ''; + + if (typeof edge.style !== 'undefined') { + const styles = getStylesFromArray(edge.style); + style = styles.style; + labelStyle = styles.labelStyle; + } else { + switch (edge.stroke) { + case 'normal': + style = 'fill:none'; + if (typeof defaultStyle !== 'undefined') { + style = defaultStyle; + } + if (typeof defaultLabelStyle !== 'undefined') { + labelStyle = defaultLabelStyle; + } + break; + case 'dotted': + style = 'fill:none;stroke-width:2px;stroke-dasharray:3;'; + break; + case 'thick': + style = ' stroke-width: 3.5px;fill:none'; + break; + } + } + + edgeData.style = style; + edgeData.labelStyle = labelStyle; + + if (typeof edge.interpolate !== 'undefined') { + edgeData.curve = interpolateToCurve(edge.interpolate, d3.curveLinear); + } else if (typeof edges.defaultInterpolate !== 'undefined') { + edgeData.curve = interpolateToCurve(edges.defaultInterpolate, d3.curveLinear); + } else { + edgeData.curve = interpolateToCurve(conf.curve, d3.curveLinear); + } + + if (typeof edge.text === 'undefined') { + if (typeof edge.style !== 'undefined') { + edgeData.arrowheadStyle = 'fill: #333'; + } + } else { + edgeData.arrowheadStyle = 'fill: #333'; + edgeData.labelpos = 'c'; + + if (getConfig().flowchart.htmlLabels) { + edgeData.labelType = 'html'; + edgeData.label = '' + edge.text + ''; + } else { + edgeData.labelType = 'text'; + edgeData.label = edge.text.replace(//gi, '\n'); + + if (typeof edge.style === 'undefined') { + edgeData.style = edgeData.style || 'stroke: #333; stroke-width: 1.5px;fill:none'; + } + + edgeData.labelStyle = edgeData.labelStyle.replace('color:', 'fill:'); + } + } + // Add the edge to the graph + g.setEdge(edge.start, edge.end, edgeData, cnt); + }); +}; + +/** + * Returns the all the styles from classDef statements in the graph definition. + * @returns {object} classDef styles + */ +export const getClasses = function(text) { + logger.info('Extracting classes'); + flowDb.clear(); + const parser = flow.parser; + parser.yy = flowDb; + + // Parse the graph definition + parser.parse(text); + return flowDb.getClasses(); +}; + +/** + * Draws a flowchart in the tag with id: id based on the graph definition in text. + * @param text + * @param id + */ +export const draw = function(text, id) { + logger.info('Drawing flowchart'); + flowDb.clear(); + const parser = flow.parser; + parser.yy = flowDb; + + // Parse the graph definition + try { + parser.parse(text); + } catch (err) { + logger.debug('Parsing failed'); + } + + // Fetch the default direction, use TD if none was found + let dir = flowDb.getDirection(); + if (typeof dir === 'undefined') { + dir = 'TD'; + } + + const conf = getConfig().flowchart; + const nodeSpacing = conf.nodeSpacing || 50; + const rankSpacing = conf.rankSpacing || 50; + + // Create the input mermaid.graph + const g = new graphlib.Graph({ + multigraph: true, + compound: true + }) + .setGraph({ + rankdir: dir, + nodesep: nodeSpacing, + ranksep: rankSpacing, + marginx: 8, + marginy: 8 + }) + .setDefaultEdgeLabel(function() { + return {}; + }); + + let subG; + const subGraphs = flowDb.getSubGraphs(); + for (let i = subGraphs.length - 1; i >= 0; i--) { + subG = subGraphs[i]; + flowDb.addVertex(subG.id, subG.title, 'group', undefined, subG.classes); + } + + // Fetch the verices/nodes and edges/links from the parsed graph definition + const vert = flowDb.getVertices(); + + const edges = flowDb.getEdges(); + + let i = 0; + for (i = subGraphs.length - 1; i >= 0; i--) { + subG = subGraphs[i]; + + d3.selectAll('cluster').append('text'); + + for (let j = 0; j < subG.nodes.length; j++) { + g.setParent(subG.nodes[j], subG.id); + } + } + addVertices(vert, g, id); + addEdges(edges, g); + + // Create the renderer + const Render = dagreD3.render; + const render = new Render(); + + // Add custom shapes + flowChartShapes.addToRender(render); + + // Add our custom arrow - an empty arrowhead + render.arrows().none = function normal(parent, id, edge, type) { + const marker = parent + .append('marker') + .attr('id', id) + .attr('viewBox', '0 0 10 10') + .attr('refX', 9) + .attr('refY', 5) + .attr('markerUnits', 'strokeWidth') + .attr('markerWidth', 8) + .attr('markerHeight', 6) + .attr('orient', 'auto'); + + const path = marker.append('path').attr('d', 'M 0 0 L 0 0 L 0 0 z'); + dagreD3.util.applyStyle(path, edge[type + 'Style']); + }; + + // Override normal arrowhead defined in d3. Remove style & add class to allow css styling. + render.arrows().normal = function normal(parent, id) { + const marker = parent + .append('marker') + .attr('id', id) + .attr('viewBox', '0 0 10 10') + .attr('refX', 9) + .attr('refY', 5) + .attr('markerUnits', 'strokeWidth') + .attr('markerWidth', 8) + .attr('markerHeight', 6) + .attr('orient', 'auto'); + + marker + .append('path') + .attr('d', 'M 0 0 L 10 5 L 0 10 z') + .attr('class', 'arrowheadPath') + .style('stroke-width', 1) + .style('stroke-dasharray', '1,0'); + }; + + // Set up an SVG group so that we can translate the final graph. + const svg = d3.select(`[id="${id}"]`); + + // Run the renderer. This is what draws the final graph. + const element = d3.select('#' + id + ' g'); + render(element, g); + + element.selectAll('g.node').attr('title', function() { + return flowDb.getTooltip(this.id); + }); + + const padding = 8; + const svgBounds = svg.node().getBBox(); + const width = svgBounds.width + padding * 2; + const height = svgBounds.height + padding * 2; + logger.debug( + `new ViewBox 0 0 ${width} ${height}`, + `translate(${padding - g._label.marginx}, ${padding - g._label.marginy})` + ); + + if (conf.useMaxWidth) { + svg.attr('width', '100%'); + svg.attr('style', `max-width: ${width}px;`); + } else { + svg.attr('height', height); + svg.attr('width', width); + } + + svg.attr('viewBox', `0 0 ${width} ${height}`); + svg + .select('g') + .attr('transform', `translate(${padding - g._label.marginx}, ${padding - svgBounds.y})`); + + // Index nodes + flowDb.indexNodes('subGraph' + i); + + // reposition labels + for (i = 0; i < subGraphs.length; i++) { + subG = subGraphs[i]; + + if (subG.title !== 'undefined') { + const clusterRects = document.querySelectorAll('#' + id + ' [id="' + subG.id + '"] rect'); + const clusterEl = document.querySelectorAll('#' + id + ' [id="' + subG.id + '"]'); + + const xPos = clusterRects[0].x.baseVal.value; + const yPos = clusterRects[0].y.baseVal.value; + const width = clusterRects[0].width.baseVal.value; + const cluster = d3.select(clusterEl[0]); + const te = cluster.select('.label'); + te.attr('transform', `translate(${xPos + width / 2}, ${yPos + 14})`); + te.attr('id', id + 'Text'); + + for (let j = 0; j < subG.classes.length; j++) { + clusterEl[0].classList.add(subG.classes[j]); + } + } + } + + // Add label rects for non html labels + if (!conf.htmlLabels) { + const labels = document.querySelectorAll('[id="' + id + '"] .edgeLabel .label'); + for (let k = 0; k < labels.length; k++) { + const label = labels[k]; + + // Get dimensions of label + const dim = label.getBBox(); + + const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect'); + rect.setAttribute('rx', 0); + rect.setAttribute('ry', 0); + rect.setAttribute('width', dim.width); + rect.setAttribute('height', dim.height); + rect.setAttribute('style', 'fill:#e8e8e8;'); + + label.insertBefore(rect, label.firstChild); + } + } + + // If node has a link, wrap it in an anchor SVG object. + const keys = Object.keys(vert); + keys.forEach(function(key) { + const vertex = vert[key]; + + if (vertex.link) { + const node = d3.select('#' + id + ' [id="' + key + '"]'); + if (node) { + const link = document.createElementNS('http://www.w3.org/2000/svg', 'a'); + link.setAttributeNS('http://www.w3.org/2000/svg', 'class', vertex.classes.join(' ')); + link.setAttributeNS('http://www.w3.org/2000/svg', 'href', vertex.link); + link.setAttributeNS('http://www.w3.org/2000/svg', 'rel', 'noopener'); + + const linkNode = node.insert(function() { + return link; + }, ':first-child'); + + const shape = node.select('.label-container'); + if (shape) { + linkNode.append(function() { + return shape.node(); + }); + } + + const label = node.select('.label'); + if (label) { + linkNode.append(function() { + return label.node(); + }); + } + } + } + }); +}; + +export default { + setConf, + addVertices, + addEdges, + getClasses, + draw +}; diff --git a/src/diagrams/flowchart/parser/flow.jison b/src/diagrams/flowchart/parser/flow.jison index f867e5713..58e4664a6 100644 --- a/src/diagrams/flowchart/parser/flow.jison +++ b/src/diagrams/flowchart/parser/flow.jison @@ -21,7 +21,8 @@ "classDef" return 'CLASSDEF'; "class" return 'CLASS'; "click" return 'CLICK'; -"graph" {if(yy.lex.firstGraph()){this.begin("dir");} return 'GRAPH';} +"graph" {if(yy.lex.firstGraph()){this.begin("dir");} return 'GRAPH';} +"flowchart" {if(yy.lex.firstGraph()){this.begin("dir");} return 'GRAPH';} "subgraph" return 'subgraph'; "end"\b\s* return 'end'; \s*"LR" { this.popState(); return 'DIR'; } diff --git a/src/experimental.js b/src/experimental.js new file mode 100644 index 000000000..d34de469d --- /dev/null +++ b/src/experimental.js @@ -0,0 +1,42 @@ +import dagre from 'dagre'; +import graphlib from 'graphlib'; + +// Create a new directed graph +var g = new dagre.graphlib.Graph({ compound: true }); + +// Set an object for the graph label +g.setGraph({}); + +// Default to assigning a new object as a label for each new edge. +g.setDefaultEdgeLabel(function() { + return {}; +}); + +// Add nodes to the graph. The first argument is the node id. The second is +// metadata about the node. In this case we're going to add labels to each of +// our nodes. +g.setNode('root', { label: 'Cluster' }); +g.setNode('kspacey', { label: 'Kevin Spacey', width: 144, height: 100, x: 200 }); +// g.setParent('kspacey', 'root'); +g.setNode('swilliams', { label: 'Saul Williams', width: 160, height: 100 }); +// g.setNode('bpitt', { label: 'Brad Pitt', width: 108, height: 100 }); +// g.setNode('hford', { label: 'Harrison Ford', width: 168, height: 100 }); +// g.setNode('lwilson', { label: 'Luke Wilson', width: 144, height: 100 }); +// g.setNode('kbacon', { label: 'Kevin Bacon', width: 121, height: 100 }); + +// Add edges to the graph. +g.setEdge('kspacey', 'swilliams'); +g.setEdge('swilliams'); +// g.setEdge('swilliams', 'kbacon'); +// g.setEdge('bpitt', 'kbacon'); +// g.setEdge('hford', 'lwilson'); +// g.setEdge('lwilson', 'kbacon'); + +dagre.layout(g); + +g.nodes().forEach(function(v) { + console.log('Node ' + v + ': ' + JSON.stringify(g.node(v))); +}); +g.edges().forEach(function(e) { + console.log('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(g.edge(e))); +}); diff --git a/src/mermaid.js b/src/mermaid.js index 0cf24e81f..6f2311390 100644 --- a/src/mermaid.js +++ b/src/mermaid.js @@ -6,7 +6,6 @@ import he from 'he'; import mermaidAPI from './mermaidAPI'; import { logger } from './logger'; - /** * ## init * Function that goes through the document to find the chart definitions in there and render them. diff --git a/src/mermaidAPI.js b/src/mermaidAPI.js index 205254540..600938027 100644 --- a/src/mermaidAPI.js +++ b/src/mermaidAPI.js @@ -17,6 +17,7 @@ import { setConfig, getConfig } from './config'; import { logger, setLogLevel } from './logger'; import utils from './utils'; import flowRenderer from './diagrams/flowchart/flowRenderer'; +import flowRendererV2 from './diagrams/flowchart-v2/flowRenderer'; import flowParser from './diagrams/flowchart/parser/flow'; import flowDb from './diagrams/flowchart/flowDb'; import sequenceRenderer from './diagrams/sequence/sequenceRenderer'; @@ -363,6 +364,11 @@ function parse(text) { parser = flowParser; parser.parser.yy = flowDb; break; + case 'flowchart-v2': + flowDb.clear(); + parser = flowRendererV2; + parser.parser.yy = flowDb; + break; case 'sequence': parser = sequenceParser; parser.parser.yy = sequenceDb; @@ -568,6 +574,11 @@ const render = function(id, _txt, cb, container) { flowRenderer.setConf(config.flowchart); flowRenderer.draw(txt, id, false); break; + case 'flowchart-v2': + config.flowchart.arrowMarkerAbsolute = config.arrowMarkerAbsolute; + flowRendererV2.setConf(config.flowchart); + flowRendererV2.draw(txt, id, false); + break; case 'sequence': config.sequence.arrowMarkerAbsolute = config.arrowMarkerAbsolute; if (config.sequenceDiagram) { diff --git a/src/utils.js b/src/utils.js index 1aec62d4f..c6e37bb9d 100644 --- a/src/utils.js +++ b/src/utils.js @@ -41,6 +41,9 @@ export const detectType = function(text) { if (text.match(/^\s*gitGraph/)) { return 'git'; } + if (text.match(/^\s*flowchart/)) { + return 'flowchart-v2'; + } if (text.match(/^\s*info/)) { return 'info'; From 1570ed4610bbfc9ec1c3a331f2ad1f7038d21f51 Mon Sep 17 00:00:00 2001 From: Neil Cuzon <58763315+NeilCuzon@users.noreply.github.com> Date: Thu, 5 Mar 2020 17:34:06 -0800 Subject: [PATCH 06/34] Update mermaidAPI.md --- docs/mermaidAPI.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/mermaidAPI.md b/docs/mermaidAPI.md index 7b7b68e06..bd4f3787f 100644 --- a/docs/mermaidAPI.md +++ b/docs/mermaidAPI.md @@ -2,14 +2,13 @@ ## mermaidAPI -This is the api to be used when optionally handling the integration with the web page, instead of using the default integration provided by mermaid.js. +This API can be used optionally handle the integration of mermaid to a web page, instead of using the default integration methods provided by mermaid.js. -The core of this api is the [**render**][1] function which, given a graph -definition as text, renders the graph/diagram and returns an svg element for the graph. +The core of this api is the [**render**][1] function which, renders the given text based input to a graph/diagram, that is returned as an svg element. -It is is then up to the user of the API to make use of the svg, either insert it somewhere in the page or do something completely different. +After it is rendered, it is is then up to the user of the API to make use of the svg, which can be either inserted somewhere in the page or something else altogether. -In addition to the render function, a number of behavioral configuration options are available. +In addition to the render function, a number of behavioral configuration options are also available. ## Configuration From 997353ab71620ef2d0691a34b4df180afab3ba36 Mon Sep 17 00:00:00 2001 From: Neil Cuzon <58763315+NeilCuzon@users.noreply.github.com> Date: Sat, 7 Mar 2020 00:59:39 -0800 Subject: [PATCH 07/34] Update gantt.md --- docs/gantt.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/gantt.md b/docs/gantt.md index 9d2124469..70f980bae 100755 --- a/docs/gantt.md +++ b/docs/gantt.md @@ -30,6 +30,11 @@ gantt ``` gantt +## excludes (excludes specified day, i.e, "weekends", saturday, sunday, monday, or specific dates, making it useful for computing the amount of time it will take before a project is finished, not the amount of time and effort spent on a project, by individual contributors. +important note when using exclude function, the graphic will accomodate the exclusion of certain days. however, if the date being excluded is inside the time alloted for a task, by adding an extra day to the duration of the task, rather than creating a gap within the scheduled task. + +## present some screenshots to show for it and the math to back it up. + dateFormat YYYY-MM-DD title Adding GANTT diagram functionality to mermaid From 005defbb5c65f1c225db48476fa5d7ff1a46b799 Mon Sep 17 00:00:00 2001 From: Neil Cuzon <58763315+NeilCuzon@users.noreply.github.com> Date: Sat, 7 Mar 2020 16:17:03 -0800 Subject: [PATCH 08/34] Add files via upload --- docs/img/Gantt-excluded-days-within.png | Bin 0 -> 79453 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/img/Gantt-excluded-days-within.png diff --git a/docs/img/Gantt-excluded-days-within.png b/docs/img/Gantt-excluded-days-within.png new file mode 100644 index 0000000000000000000000000000000000000000..2283bf99d8d6ed1b721541ce1f0f8b38d6e19887 GIT binary patch literal 79453 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

eQe(Y%!Xg7+4bDT&Bc0< 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 Date: Sat, 7 Mar 2020 16:17:11 -0800 Subject: [PATCH 09/34] Update gantt.md --- docs/gantt.md | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/docs/gantt.md b/docs/gantt.md index 70f980bae..7f61578de 100755 --- a/docs/gantt.md +++ b/docs/gantt.md @@ -1,8 +1,19 @@ # Gantt diagrams -> A Gantt chart is a type of bar chart, first developed by Karol Adamiecki in 1896, and independently by Henry Gantt in the 1910s, that illustrates a project schedule. Gantt charts illustrate the start and finish dates of the terminal elements and summary elements of a project. - -Mermaid can render Gantt diagrams. +> A Gantt chart is a type of bar chart, first developed by Karol Adamiecki in 1896, and independently by Henry Gantt in the 1910s, that illustrates a project schedule and the amount of time it would take for any one project to finish. Gantt charts illustrate number of days between the start and finish dates of the terminal elements and summary elements of a project. + + ## A note to users + Gannt Charts will record each scheduled task as one continuous bar that extends from the left to the right. The lower axis represents time and the right records the different tasks and their order. + + It is important to remember that when a date, day or collection of dates are "excluded", the Gannt Chart will accomodate those changes by extending another day, towards the right, not by creating a gap inside the task. + As shown here [excluded dates without](.docs/img/Gantt-excluded-days-within.png) + + However, if the excluded date/s is between two tasks that are set to start consecutively, the excluded dates will be skipped graphically and left blank, and the following task will begin after the end of the excluded date/s. + As shown here [excluded dates between](.docs/img/Gantt-long-weekend-look.png) + + Thus, it is useful for tracking the amount of time it would take before a project is finished, but it can also be used to graphically represent "non-working days. + +Mermaid can render Gantt diagrams as SVG, PNG or a MarkDown link that can be pasted into docs. ``` gantt @@ -30,14 +41,11 @@ gantt ``` gantt -## excludes (excludes specified day, i.e, "weekends", saturday, sunday, monday, or specific dates, making it useful for computing the amount of time it will take before a project is finished, not the amount of time and effort spent on a project, by individual contributors. -important note when using exclude function, the graphic will accomodate the exclusion of certain days. however, if the date being excluded is inside the time alloted for a task, by adding an extra day to the duration of the task, rather than creating a gap within the scheduled task. -## present some screenshots to show for it and the math to back it up. - - dateFormat YYYY-MM-DD - title Adding GANTT diagram functionality to mermaid + dateFormat :YYYY-MM-DD + title :Adding GANTT diagram functionality to mermaid + excludes :excludes the named objects from being charted. Accepts specific dates in YY-MM-DD format, days of the week ("sunday") or "weekends", but not the word "weekdays". section A section Completed task :done, des1, 2014-01-06,2014-01-08 Active task :active, des2, 2014-01-09, 3d @@ -123,7 +131,7 @@ Tbd ### Date format -The default date format is YYYY-MM-DD. You can define your ``dateFormat``. For example: +The default date format is YYYY-MM-DD. You can define your ``dateFormat``. For example: 2020-3-7 ``` dateFormat YYYY MM DD From 5cd54c4831e31940952cd7cd4e3d7c7714350e85 Mon Sep 17 00:00:00 2001 From: Neil Cuzon <58763315+NeilCuzon@users.noreply.github.com> Date: Sat, 7 Mar 2020 16:21:07 -0800 Subject: [PATCH 10/34] Update gantt.md --- docs/gantt.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/gantt.md b/docs/gantt.md index 7f61578de..5fc40436e 100755 --- a/docs/gantt.md +++ b/docs/gantt.md @@ -6,7 +6,7 @@ Gannt Charts will record each scheduled task as one continuous bar that extends from the left to the right. The lower axis represents time and the right records the different tasks and their order. It is important to remember that when a date, day or collection of dates are "excluded", the Gannt Chart will accomodate those changes by extending another day, towards the right, not by creating a gap inside the task. - As shown here [excluded dates without](.docs/img/Gantt-excluded-days-within.png) + As shown here [excluded dates without](https://github.com/NeilCuzon/mermaid/blob/develop/docs/img/Gantt-excluded-days-within.png) However, if the excluded date/s is between two tasks that are set to start consecutively, the excluded dates will be skipped graphically and left blank, and the following task will begin after the end of the excluded date/s. As shown here [excluded dates between](.docs/img/Gantt-long-weekend-look.png) From 5dae0c14d92f76ee19224847912d424c12549a39 Mon Sep 17 00:00:00 2001 From: Neil Cuzon <58763315+NeilCuzon@users.noreply.github.com> Date: Sat, 7 Mar 2020 16:22:55 -0800 Subject: [PATCH 11/34] Add files via upload --- docs/img/Gantt-long-weekend-look.png | Bin 0 -> 79092 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/img/Gantt-long-weekend-look.png diff --git a/docs/img/Gantt-long-weekend-look.png b/docs/img/Gantt-long-weekend-look.png new file mode 100644 index 0000000000000000000000000000000000000000..1b2fc8e17ef9a4adb34de9dc326d41584873292c GIT binary patch literal 79092 zcmeFZ2T+q+_dbfEq9AxIfKsg}!GHpxH$eeGijag7nj$TMP(l$x5fD6}fJ&1NA}tA> zPyzuth)C!Jf|O8%&=aIfzrpjJ^ZjS;%$>P&XZ|zy-rt@9W+!jid%bI~{XEZFFA;|N zTAb{B>?|xSoDa3{8?mskL0MQ>gHN7dexhEl9?1N21ZAY9&QjDVFvsj1bGWB>kAh2@;*;m?s#d*SCSEC)Fc@81JIw_2of*nnwio6Ew539pBq67}lN zeW^73evZP?i1~v83?G0QsfA`<^y|rl-ou4lzW9ZGR_BR}*q{9(FOVN8iL*r#jbah~ zH!2L>#Pm#??Qy0hR_FQ@mV7(yrrV#1NS%6{bbTyFrCq+uw{uN?c6cwe~-L;>L~W#uUOt53x@o+rycSc z@Za9`dp6wv?Y+NTa%jr`w1@w5yF*L-f8Ute#g;U{VvmOMA~=7=5~)JS%p|p-y{H;t z*ifX(KklG5-B$M*j>6l2_}tbG2i2NAq!;!|OLe94$+EH;l*4(VAVCYyH-#H4yo758 zFI}!C+!3f)=&=pnSaNnWq@7_C#cCyJj)Co>yl#NZ|4`9)(c3{=827}-DF1VdS)8Oq z$+l)1reonFz~#~1vY}mbd_qd_kjt?rT$LSd5J~bWZ;+CTUh^4>{FY_=XkKFe&qg}C z`2l217OI;*x}e|K__dVnpX(*vnmmd{k0IZl$G|>f5{)8oGKfi(ZffJqd_~&D)7>u8 zOPI%7ADxnyk5SoK|8v%hP%-9NoG`JGD^9H_e&boLYJE@)A#^C8u1LKnAfTaJ;o%fq zR@k`c-d3@~Ca)jJOWyoz&fLc~{U{~KSGI_}#<4>%CZva~Xojh0T_E445mp6n7YOYT z9_;n+d^(#fhpOQ-V#o^oGtA5Y$=fA-;3jYDwsJ6mb+qm=_k`Je#hjjbk)Q=J4rLiO zuW_Yc75Xu?iMl9$6SlQkWMZ5DcwwodinVq2R)OHow7tUqVaWU41aCGm$3G;541mWK z5OUYQ!KvYrRSPy+TRb7ae-2_{;lj1E;~37}B0k+``$*7Q)=HA<*{9Jdb_KUr`Xf@oZA^f#7e?*Zho?HcqwSAD!A< zP(~a`IMe++jBMh(=wA!OQkKlUJ7I`}Ajp(rA~EjQ9>+g+@)W<+_tdMnasX1>WYkJ8 zkFz~jMC21 zZ0gy8M){kHM&)ouJ2?|;vQ3!igfimhCIZ|#5!j;hQ18f=Q4?_^Hi~=Nl#qlqsVf>a zLC5v=jhs#1tEjqigtM;Xe)*!WeZkaU!O-Yy)lY&oXY?U7ec5d8sF*Ip(KC8&>&~=V zFWEg0gqemzz8g4|{?8L(NsHmP>0n7wfBnj@ux>?Nta9fotGl@{!;BZOY#x@@a234d z`r!HMc6Fg_3S38{#_E#Yt4QIY3qz|(iaicp31x<@ZpEqU!3av&Q~pz55x^Am0>RL> zZ)M}ui_2k9|*JGsw5-j7xW`nrXvj- z^XIb42*30M7sPa#2}6duu&QGHAilM-|rB>ad;_x!`e));s#NzeT~s z97ahe{rI+)^}4WJHaK@Z%WMLg41`q)ePgpB=rZWmP+9IVez7L z#_TVioQKiGma#|$JhX~}jy&+YWOWYn=YV=`*425_7V5!w#Nelia`lC$?2JJT#J>oO z5ZUfj%IDmj+rcRD0L{YWNhyn!QK!X?y$Ypf2X~C(6Kb1$Cs*RAu9=$ElS3n!nm%`M zHJZ9bNpzLsyO|$X*3IwU&OD(!T%(<}`lUcS{gKkue&Hg?l-kN~ft8L`KH8P+_WB&cGo7E7 zjyD4Y=cApiaFLwLFpi~wTnmmmjk`IfVXPxhCNF2i3O+TdvA^Kkb+HnT4$Pr+R27BF zMM;-Sq!l_%j=YopzVpSS<77k3g?#6AN$xe2*4{R^<6ySf1*GiGFHfMZVZ)Q)s|ep5 zQcO+i&PERYUu^oSsBj69&K+4_p__ zPhF+rm>asX$mi-o36kQHG{Xi=8uf=^OR-IyZjASDc?pR88K_Ay;VjR@6BJ--7asx9W1_XWYcj`%*TMPZO;AYn(MN0Vm zQO4E%DIOzgAAJ*Y_-}LWqw&LKUHQfx*^Key4@l*(Ble=hh&^2eNX7x<9t+hUqy_Qv&*!Rv5r zh1|&dGSlY7O5n&y(lcvEdWIs74FDky3vMi$=9RTjCpdJ#e|SX;Orgp+*-89*iQ^Gu z+XoXf(VE!D{ls_U$mKKa!@nj&xGvy~*QFRGc-gR->u4i4>!^}Z*k3}0J>EVgIRbi0 zsyR2${EM;lZ`(34%J8*90ge;TCz70NQ>;@O6vv0)KoskrTe2HE%$Exrv*m@^(;f0LMqkP`xp8_m4@~>{1y}Adfo2rP$Vhh|teYOB{H_sK3I)!Gr z9>&A?{O{%2gO-+7Z^bZDvMf_`?U&kg!OzWI?U?&f#RD-2@d;Xvg>S^XF#b%!f|}=T z{?p-#o(U&zGXAPY%;wZBON}rvIhdUIcedXx3fYT6Gu@W}^><`uzaQ^xr8a7BQu*>1 z^~v0f%XZDKA;aw0dh@-We@Wx)yyUeKW&qMNV7ek`FoL-fE*l)@l?(Nv^<&ESv4LMW zO)U+_y;&Dmd>jzzcp*c#w{8Co3SxsNKV z+WD7vc7yCRZPud*+HF-?O>u(U6K$0550TY<$BKlg`2gAH+;bnxdz01a z=Juop10N_@bazmi$$d&|Q69A%Pd)ui%luE632h^dVIwjxYxsbX`7A9_^cb{bHKZxr zUJQ$pG5eSOuxV=^gYs8Gt2K-|oy>r>vdVX@&r=!D(0j61C5sGw_r*h9j@ZrISFogx zjvvP!C0(K^74+we6&vYI9l==+jM6dauY%CvTs@NVY}Zt~ii_zd-3gm88O9RozG9dF zx5ZMLwHU;&gSmE^wg5HKk8gfvj&U(j(CJFiH>tPeCzG9;KDUC^qF4S>CFC3TBU+CR za$*9no-^gV@J4$mP3m8J4oO}9jB{R~ky;9OxY{#ePl4pZXxV`BN(w_z#`rx;mu^*hxn=4Y>h_C`Ot-Kn(K5B@p|E~20M7|}Qs zpPZlw6>FlN@=JTGACM8Y^$XOez?yMNabNOh6=t`G5M$G?ce_HgaH1?XMBU_Ou z#Qj&xztJMIRwu~D%OO;zCN%f>NalUuZgi({BZ%QPf_!0l(_V|PI8rA%Zx%V2SPZ6F zTImjCVwO_!?`dre{JBh)M)#Zpmi8_pI6yxtgh-?`3=I!S_JjGpPjE}R4GSB15RwW) zY2HGAGu2C(TwHjcWLy|PFU0wu|8@G-AJInrPRm3Z+|faoT+b^GrR{2SG>ntWK?>Mc z+cP}j1Ijx?rF@=7OmzY3^)`CRIckx^6YA`6oeo$^&2Elox}Y@pM-vs|7m?X8_qwqlQ+XF*o)Im09j zF?<~=4w)w`r-Wn?X<;>ckm{iUnrpE@hq-0$)lH={D#{v7AEVb#>*1%}i`eqsgePKF z(svW6vH$LQjGJ*ti4OLpjuLW?U6!A$VtVdDGBQ!DXk>Ewi?J}Ew$Cy>-kvyR{|XdV z8EMoRM$pbhk(I8#X(-G}3>0g{0KV4-m z3FfoPRnGw-y-kfB$;7R!7sZcWKcmm!4u;NSf^fGm7WaHpiIGFELJS9ok%1g&b^axt zGAl8f)dykHshFzDx~Y%zpP~wy-LazUdalHxs~ax?xgS=7yVnjPeJIyGY&u)}9%M+l z=$z_YSC)tmUx{@&__=Gi-~H|R$ZDHoTd8aQN$xX$-Y$PY@C|rv+h0MvEgb;99O!HP zo79T-!1PE1|EiR;046}kKS4(+KD(4!=Y+!iiklP9I1?2I-VErl8=K^8gVZNpfXmqH|h(md5E?$ zFNnyi*<#aaI9mAJB?W*(-5wYiqNdu~6U$F*Aba+_ie0&#+}FMPO$xg`7m|N=B`S{y zEO47w1;oq?i#_JjgZyKY7uZ)3MTDk*q6-Vl3%TBdH~&%#7M5>r|0DArTIYX6?7w~F zf44-xcG7HQqT)Nj3#)kSzg}9vuk^e`(er1H^8cDXNQy3c@sDHw|3O9nuRZ=J;qtdF z{x8!>elKq`+{~S+gnmIL#!$=s?L%=%zmTVXpWMyl=6jeoCvo=MoC?fOJfoLf{Hy+U zx>*&4ZL2>lkNmTR%#l7=>pa34DTNjMT=oGNGWs!#m z8(=))Fh}}c^pbp~$DX*HKd0&%|mU>|6Ek`X{rab`-lhNqnDrOe7wA zjqHbP!guB`@hM(!6Hfs>!`UklT1iopOh{iy^Rw%avdSAZE1)a=VCH5sV;6FQ9WGQi zy>lq#DMEIS4kRKlJH)bs_W5tC2C;#%BUlo)17*zzCRZdv1JsZ-i48(d5Dy>0^)uWzs3yml=E>QcrF@T=NbUCSLrhOKHU2 zy`S|J_qQA#k##oFcKh;8sYpNLZRGbub}pI;00vzZ86UJLj6@gKxl2jA=cn+RFtu=j zEL@$F`Tm->JOXamff)n{NE)6uQ5^0^fV1pP+X}>rp?%5TCI$Xa?Aq2{i=cz{h@h`D z(c%9%_pCU<(Z;JdWJ9mO*-p^K;d*}wJXu7A4{XzSyAWO5>g!E$Kv&F}JYdh)EO)gK zsvqq8Y4gdsc|)0js!RqSm_~eTszyUV!R#F3kIIrrN-og#{NaVjg@MSB08CJub zJh%s9oh$9$Z+h8(`<0$xr>Jsn*|Hx7$WwT$|OALJBB&N~w^#+rBPb`qB)je_Qgm!a5sBU`RoSKi%uc zVsQih@%tF?)=feOC)XS{RrvP6iYUd+B?&{HvG33KkA}z?evFTa$Be_KMUr}S2Wzf< z4613s>WB%S1h}D+0LTvGjR|C+#F&Q(1aa*h6R^I}&no*yuOHB1V&Hy6lw8cl3I0a2FN!|BJ^@7+6bF<$6esU0{}QE>~D z8*o#$%dgP5+>BCm!bLKmKo6iDsL={QD1>u}^A(OVIIFc4jKXrgLizBU*H#ZhRp)i| z^YqA>L?>ISUk9I%;HU*d$;qzS1p}gyd*LuvnZZc5!qofml_YK0cA1;KJPBz z1f?u?CGExC-!oB@B|l)r27vCg9Mix;w%+e>?64M^EG5XcF~9E4;btb}sPo}q>vAhG zq=XUjbK3LFb;;mif2V#O$f8^AgrGU*2M3p@sT3?s^-iI!o*0F$kNqy%3=rtn^)*QZ z1g$W-w2f6LY^Zhs(aC2x?!RES z>J56CafNmYGhG8;02v%1tFOPc(pOubi<)pK67lr>oZM!qO+YvoVu@4f2<60@LU>-G75M|y_X@ix%%t~zkA zJ9D~=>Ld)x_nR=~6fj*pVObvUQ*)}R2;8bC2B{k6td?Ob^k_~-5{zmywS99_#+eVK zW3^bO%dmA_3{p-8?)aAT&C7^l0v2DC0)!k~{z{!ouEc0^PKXDk;C)av_9G^fN-c+C zrlmEyo?j@f_#=!JQ;P~tV9P~pS5p*^ct1ld#vMgGCarrj+DaG}G>cCPDZ)wvp6biT0zkl;EU^1Jhgr#f=#)?EFKH@em%MpxEem7uE zJmZxC^tvAuRbQyX_o49fg#O&3=xh9szg~pI==Yb{`YF=<90qA2!Aih%)t-O^h&6Y+ zsPSVp%+?k->YI0)&=71-!u%XL5|sH74FD@;YPJ;%W$jNmSgcdt$)Cqh<;G*+J?cD% zvodDRia=d9*N~Uh1E=p$K}nx!ujxyTkH<_3`*uD&Nv?JbhpO1B;`{RwHB+sfhX`;= z$LOZjK=;vj3mc;5af`n>0U<+Nz!X#l`PnVfZvr%KtseQw`EhaLIKYfx<#hnTD3OW9 zE}4;H3l)J*5i4x9)Q?Ome~@fvZe3+XHrQPEr4(!1K}Uax?%VNT*GA{OH<6E-nWbjL zF!*kRsc$`PI!dgk3}aTme&}Lth%O(ETE)?)9qGLZl#iX8<1X&K)!lMwM{s?R`bSsN@0X-mr-MN-A^Cu-^PEz$k+O&WFs0?iKJp0L)mI= znIC@xr%j;w$AJHtR!np~Z(lR)e<{uSynpR~rA7a{Dck=Wi?}{&efz=FaRa`kv?Ue^pu* zmj5yOZ_E7ODrH+&8-^79C8XSE>t7Rsgqna+dH5Jgpm@HQl!BT9_=cuhRFnjf}Rb@leIsdNPnym`&c5{hT!-19ZYKhrR5 zOiVAp+UKM~iqxeFZ6Zj#TU7=4y%^UeiVm>a@8vdn*sVtzSXG&&7t(Kj z&Pp>Vs@g9CGv=K)7y=Mpa?WN#?tr#2%Yp)Aed6|vet*c#%9g^Ea0eboI5H@2(dnA> zdMA@h4S@AhD(-`jmcKG)hJU^^nK9$r8TUr}Q9nMJ@ER0Fy!CpMh*j{eLhzcBIUx03 zwIqk={>^jNXfd{)z=39Ok2e4thYQ?-9q5_|GEbL#sg)84M*=4Y-SrA?u zwaP77YiK@cf4$d`2f!|82m3UUlNBXQpxs_SLu&!@egL0^d$!5VYuLpeb#EJTvM_tJ zWr|i`D0(e*(A}J+hdgzypS~RZAf?xBj4&$B!Tm*SGWYW>taB`k@_zRFKq7D0(YvdD zqCWdy-@2YX1?rCr_n2&7y5W#^SVi=%F2v)Y$C16T0Tf7`8pVsk`DK6|x+TP#EW3JR z^6=OXgpNNArT%(h>C**6i%1<6faWSWa_a`u%t|R#I(18efXK$Ol|EI)zy}rG`l>oI69Q zvCCN$T}Yin!u`r0J%E;uXSd;zuVCMLe~wG*`Ag@2&Nst+uWtd4ecEo(iJMGtqI&o5 zjYvD(W>!9>TwTDW2!Vny!;`JVqDLvCsJ42detEd!R`5fyt6L07Ff4bzqjRk!i=4gT z(6zzd!N+ar)^xhViaO4tW3zfr?>4~1?Rf-gej~qic>08cB78c|(RXqCX#luzFtHOF zRR*c^%r35%fiE9NUV4*}WD zi}H5-cm}lGD?#lY^yMnm&UDzQ@`^{ai09MvNY{4b%Wv~~g{QH_DV)Cz%>4CYZ(yAj ztB8T@zghRYR{(AAGRaJgEzCxN{g*trVWFTHu-N18n1L5pJ3ct6r}eWlyjLD&V*T~w zFWl-Owdg>80wrGdAJT?6dNf{KtEMVBGpTPR9O*sjYVhUz$E(bo{OL`FyVka=X%kKZ zJX$Lql0~u$MaC%Sn9@8>^2xFNwLNICP7nl8{sEJR=rec3PtP?|-n9-yY9$spI$9%; zTE&4|fB>6Pe2dpZ)|ZWWiHL`WBx04iSW(-0ze$m1b!p4StRm)qdGTEh&UcfQwzbgY z0pWJa+5|&oQ!xLBd=9Dn1h!K4*2d4N1I(iwUb*$$>}xyU)r+0EsnShc?@ibyJwsDf zdsH+lt&Y&Fr74%{y^|xGwkVQC86vg0Dmpm`YlQq^W#%N438cFn0`b3FH4E3B^Y1}aGji3J1`Cv<`@XY{IHhYmx>e?)dHSJ% z%-D`!4UdJg!mdBqHDgov^055IKf`Cy#v;49-T3{%*~fiZK{&@sDDwNL&L2JfSf3v} zuM6b-Gb0yy!sC+zG_w33;c|%`Tp~HfxYWVg)UK-H%glo zrFEahg}k*TZjNuPecf|?=XlHm;)xEMXJ)P`;e&u*HRXMARWmkd+gL%zzE8o0o~RL% z;J|6Tnw_iS@FiL5s9#V$k?St#alt$x!NtdzjGMQPccewXSXnYJ-d1M1l6yVu3t7yd zJmU^^AL^vZc&9H$9^Iom%)qO?7F%*C1?Apx1#2=3FG_qiJ-E3#K*cfCB ziRU{GUsp@^1fTIrwdXUdkes z{H)=`7_y?_dtRL~TkohQXfb-xzztQCtCwWY27N8j!Qqp(a7-;Hk_6Z^c|(-`md34;m_$gQwH~({depD8K-yJG7Um>KN)dJX^gO8ri8<0X|WWWk;n8ZL1 zg0n%Bb8y7z}Qr9Y-!akhSAZ`iTXvTZ0(9+x37C#<^Fq zZXI2D@cZ7bd5c-Z{)3M)wZjsX5+#nxfZ=!d2c>3BlVy*p# z`R;voEqlj^gs!Rt0bK9m?!9;03icnE!c>A2M6HH*3Rc{ooG{6Fm7>{xmn;TZe!tnG zVHj^RlfU+JaA*oI=`xb*wRyqG=9x(>e=^oA_hX<{{=AAyaB+7EH();@g((ZaxJ8}3gdGD=2!wTWZ@u~x1l4Me)14-* zz3Z5r;yIE#KWKvwf{BVJ)1j{_nN`K<)>$sDuDxZVHACo`rx1pRNP+b`63$M%a)roc zTmFjoH}xE7YNf|>31@{oW~Gl8Jn6DFD{SUfu$~*PP-Y`--AJY>>N88Dr1!G)hW51| zd&+*+$ivR(*a2$plVZgPvF~ zBB5Z7t}8Tn^|NXsUt>&IEYYMz_J zh$(zZJUYhA$`cpx%kQopzX0CS(;X75MpmWKl1od%g+p1Ha+z41J*?8%{ncBjYhoBX zj(l&Dq#lKY`WPMz&t>f%p#-J`xV~G_5F7R6ILZ_emx)nJ3Cw8k;q_WWo-#HiFROos zJEfsR!t^Z0=VlI^tSsL-wyvS8!JjhHF5`$3<%rjB<={MBy~%cBDxAH@OaSw}tOa&nqQ|G&^m z>sj2qa&7H9@hDIF-pOL@W$;F2njj^?_UUjr5bTY*cWZz+bM9iQFu=_Gthu}1XTB~@ zU|7`v?Z?loD?=$-bJ74>G>;**80rJ>CF zdCFQUTE?vDZX3UqjZ2fJ*ucu@*X}aJ3U%+)%M(_n=gc>ZLIRi}?NZ?((v9K4s$E5I zVg}9(I1Quq^atcb=mjQ8R0Z$YklmNR8So3PUfg^O4_4n7P~%<6UQ}9^ZdOF<=89;dFc}5! zoX(G6i_Nq?ZI<40Q5I2b1G$f1*0TT?@X>~7F(Z~av;kiDJnKDfC8ONAyjr^^z6y^O zwWtrww>#1Y4_-uyU%XP@(%7QgHx{Um4E2lhpkz=j3gchr!aY0h$1iy%jGOo@J=I$W zO1QeIapL1CGH<#+zh(z{e>$!qn!{kw7=$|r+D+;9y3b+8l32t{s_4jJ{t{$ zs#*vqrcNlO)TcM2SXe&ad(G6X-3*B)XZv-$x?FWr8@gQA&Bb#wORs{T9av@z zbXw(ayrcjv&kn7nE6!trK7DhF;3J2~jPy#q6*jk+L@fU@3vg_fb1?5D_W1DD`RX7> z-pCn=#%izdU=tGUYIj(X&@$)#Aoh_-D`WWA7IzaUUvpEG&x+;dv$`B}=?b zuW2pq*%)dC@|1Xj3Ab!9oTpTWvNM&tO^Cz&pUaC^ip8LvJ&b%Ybg#4?hbe0p7~5%f zFD?X~;I#d-p7DY9)>&`2(Gy)#RMbe#J?)|G>T{XfMNXtq0itSqA{ViQzO*NJiO)_t+z6NzyDU}nO zHw=SwEfK(_KhR&E0^5@96LMPk7kTQKGl=-ZG;H$ARmcaVo3PmXE&UOfwT{YtIn&(8 zWWOr0aZMMjRhC)e%yzxaZyDi5C{{mSmzm~xs;4wYlL77rhyn0f7-Yl!eR4k`Y6&f&ZHtqv`%^QWf^1nlEy*Wtk3Xl4=9F>@stv9+a`55y=Hy>9G`Z z@vc8n);FKX)mT@C*Mu_XQh4P*>fnnC_^4r4^RyXe;KD755y`S*O$(bLoQ{}@Ne*S6 z%rSZ?qqg|&cKWQ!O;5MFj0D;I`R%hLj||ay#DpR6Co9@$(E0VRxid*J*E-@)RrDC|l)vDK6qDX>x{5 zi`q|eFbhBM9-OxhM%T>`tQR2Ou(lEhYQTBW#tf+U=ec;7!R+o7etOwLRbPQ~DlDIj zI7}`&xH(pqrDnYx@_ckuo>cq!G_LOl8yuJH6)>8)g616tK0+Z$u1(pAIFzk@y}go4 znjmiiJit~v3YNM(?C7FZ0AmX7nc4p+ood^Q`Q0Rl{pI}QzQiSI&iv3jhOck|IyE1dKb(RAG(Uc;!RMUBW$O>yB}i zLb1-=2k4|o93VeQN?j{mMm_t$tKvjjpY?fRPMs!Q{BCkz6NVj%T|7b-s5EU8PR^;D z>OdSC5Ad(?QV2H_+LSCoNdz>uZ^bFU)K7G2-iVgc=#UHlkya0lZC!K$XH#=rvNTWQ zQU1y2yn!QDDMqu#a`BQbMB^*g9amHLCRvT&ci{OuaJ zi>i`I^Cr$@Quh!g8{fXsc)~@tcydMh>c|7nm-xe^xM1Wzum1LC*O+r}CMV<{>A)bF z33PbU1`b7FC&FQqJH?q5sn~zTM!5V{QPup)W%-LBYwF|Sy^~%{X`9kDCNxVBMd!|plh zgl#B+|5z8G{7S|L^h-w({p{W|UX(+Ae)EGoB2~78#2A1(e|aQz+iv_+vJ<`nLKaZG zxeKOx>E`=tX&%V2{HRqFUECAFSj;+$`ow$z6k;JnHlP=IaHmT@j-Mp;{rYfz7Edqg zt+--~AHh9SD_SW-V+*p(eX;6*y&~i5Ig+Q2neYOz-vYwnO04V^i_4Pnr=yg=gUq{a zU)p1tq|_vT_WsQ(mzL}Kq*gP4zqmoO>bC(ktn+65XcMlAKDf4y6#P2IrUfAD;O|Q7)*!{1 zISqfoK#6b1pk$}E1R%q37-v~4v)0UO{Z{gF5<&Z=-&H&H9|AXS=%n(0`rbDrAG{Id zx}cr*g#QT3i#(NzA4ijfcVBrh2B)TP7*@%}*~Z64YH%;r_!c;hTm;nST?gM$8n%jg z7~JTaRVPZ;Xd?~0s%$o+q$l#ciaf!Vy29$A(Y)HGp7N;XjBHqfUMr{FZ}4U8J?Za| zbetBYA3ip0mvyxKjk{eIk1;5TDHEy<@EX~`f4P` zB}+M@<~Z#8MF74{Yom*tVB1>}@F4$-Po1r?4cN(X@|FIep&?XKBwo_eoe+8 zc7H81Or_^fCA~mhh;Tz*h9YK;IhIBupY`3ES;v)ss$KF9Kf>~P-${nbHiKCFs6gAp zSSB?V`0otqe8p2YH^ z5^gxSJBab~57*4-gDLCtXZ0K?m}jGQuq}6+q}O{g%ksdEgBJ)#m_tZ2&f~(pm%Mr7 zT=DIQxac_Ty0TA<_;V2^34O|k`1HjF3F_W2bXX3%ChALqL}4~303ebq2yap1M`;k9vpCbP4AEXFkq$YZt@2Q{qJ^lE-KpX z3cb$-LJ(i83!P>d04;L&x?WJX8-&w%Ayf3`88}*4NLy?kHa_8?C-@lMe26-Trw>eZcfm0QuLapJ$2db9vhp56rP``ak1eCso-RWkapK^SSmIBFeqv z!8Z(UO3V3eL=S zYb+V*rTS`HNot|3+Dlgj8}e6Yhi8Kh&%Q58+bp)k;-{iz z(tSkwRX(*IJjnnr=T%)9oUyO#da#7btN3cNe|xVlxzhVD_xie`ltX`Dw#)C3-A_TQ z{o-c4)O&GfWZ7*bU!@(TN@HH4|2s!@~bXC-Ixn11+9b3 z<0LF;du{%Vx@X=~7Ew!F8H#_8gQfcfb^H=mze!+cjEB4{YSfwGO7PkxnbeowyaRa}aJpOF5`K%nxlbA4;M ztWj2#3BrGb9(mmXw(FEt+?-dwH#vZ#sJm{{eBcz5M{ftr8|zSob;pJU4&B@t(VCAq zS()m+d#sRJWuU4|&RC)Zy9)Den{)VyZp)drFhTB!-4`L%+DD5k@T)B({fK$_T#Hmf zgmUpC-jv67BkQk>+kJUt2el*`?^Z>RMWG5KR%NPZ)OPofd#Ub5Yn8Aa*h1>-(bBR! z*l?{v9qyYuJYcKSoxdShgkVJtaD5yzv1Ozi@kK1y(!#$nU5IO>6v-bwyH8J&y%*uc~_A?*0t9?*)4QkALPLuKHy`cM`b0Mt@C5S=I-P;80m2m{gd^v|q%gO1HVrb*n+j z`*&-5ZO({F`Itw4j1Jyh8bZ=9ekXU{Vkf7~Y!pcY*p=VS?tpC6~(R3K}gkH<= zbQta$-bN5<@q?QQftGS6GlRoI%TrTgIlNR!S~&!sST52Y&`6S^URR_kd^wfvSx}Rt zy7g@HVpT5GXH&_{gj5wH(McXbq30QH*b*On?l%Rl)#T`vP>kD-#dldH`3&eA8X)**eAl1O ze;Fdj#tOw!>@whK#TasDK0QjCmg-bPPn?fH6<2gk+~Q`w1idIIHlw7om#So-==w9k zHEozurq38O-b~wuVpj$Im*6wdg`AR%va~k|oqReaUut-<7GexlA{bCNir1W{;poX6-qkdE8#+K*R z3hIN>){STCDo@Z6b-R)aZypAoeze)Xu@eEx3)rJhSG-o1TjFgg7_(WpF~8c;Rdk3NA$gJL$QL|Z)u^Bj3Kekb!!vELOmFev}OILh)gqU>suzlWN zI01wfKC^cVl~T^`eL2fxvJpbHTQV=)nSSU~SFL$IdXtoz1GB1YvZ81dhkGs#CRS4w z31lBozP`_Fw0!T#fyqLrF_x3!AztJ7DH`9BZCsMoX+C#Dp*f%v(L3dwgSV`@Z(c2= zYLxhae_N3+)!lX2^}{%9rj)tR1~+bk>GX0l!-*yW0K=W1vLyKGg7MX5l88PMd;%7^(#X*c}>Ow8E8L_{FZE&RS85kHlWK@Z!Wb$_NLz$6*Ziiw;7`xZ+(+D^oJecuQUG%QG9%k#@;4>6)*+7z=ev@f(_$w!8#19|u7PUjEDbh%`K{vO z9ZuZtX}KIvOF8}>wOw>?Q|Zo3@>0NOU+ayu8PQMof5hvh;`a2G_u8(bx29FmN_bnF z{qh-(M5lwD2hTZv=#?8a>`#BE)U@;{?=qxk_BOewv#K+Xu+JBW{l3EGU#$baabfb- z_W4)k<9b&LpWP=4r^)xq?>}ytyd5RIFf!Dg3;pN+Fa2SVhb-k=vUjX|HdX_CZmO7) z+;<@!x)YL%lwZ;;r@mi%y1uGcMZVM-1*@&qI=?3Rmf;qf-!o6DBX(?bn=mD`0n;72-f(e-=DjTF; zewXIDH`#>%9`5sB<{nXh^mj$SDpd9waW5KtRh#yr0B^vb?$?VU>q<*b%caT>6$vU{ zv>A8>fnB3d{sH^Cm?tF^6r`8lD$|4?x--U?E@kAP8Gkoe5W%5`6-SS>zs*F}(Qe8W zM+-KX>op{0+FDa>GOT^xs7S#HK1Iq~4iZ1PZzlDd{?IQsu705`gtsh6m10!3q_^pR zrd&X+E*?JYn1?@r0x$>>R@i&V641H8lYd`WWc0=5! z)__PFGOB&M9u(>gHTB}%VLc~n!*5kY{QiAaHJ%1*Jq=qb&U-l{m=QT=gh z+H|g)WQ)^Ov&f$WGQ-1tCL^P_nK!1-%)uJ-S}db`b;-2Nmv%}S;#Qz3GRwDC9Vky} zFu1Xpjwf1Keuoj!DSZYekkPD}j;MX!cHl4lsh6kBCr^la?+=ZQHt23y6t8=FuxjtQ5#OCU^l+o&AS3y-& zw9638+dzG_t=su-H{o(g{@|%{UDMDB>+$ZCh8vq7ZoKo{N_$+kS$uH^b(-tzPS}=G ztjD=J>pDz^?*gA&e0uU~9Wi6Wcfn)YwRNjqS7dADcRG)WI0Xp?CZ9`zrax{tG;aJX z&8w#4cFDvGu%eYyF5hVtZ~;G3DZ5}$Wca)&Xi*X&l=8zLA4wW+wG+UWkSxzXLV~#k1iUOIb zIUp$tDhinc3L+{33IccA>3rY!-rxJ)d-p#T!QT6Mp7pHZvp#D*GrKD03mgG|Iq0!L z?@+saw7G#gWlsz*Aif6eIm^wOO0qIf-xJ{Dld?b@+a|KkS+Tvbs*bPlV=Qkg)Hbxb zw~67lgJ-mAZOZMJ*h<6VIExZpTEGtQZxK%R7u63L&%Qd}I`W6()R+- zEz6Ap63<&DURGPGXA;6$mAzK(4h0wfjBLNRkl9z!yx#B`^A98{+i6(Yax~*|xW$Zb zMRzC+=hUGWkS{h+&-}e7VxIiw@T!}+5?tD?qxDYHar#j>Wv>&tq4uaF%bD2yTgK?k z#E0*@SBmT=6?BdL%1G<&#ag$Bse2HTc6dptPV0Jm$H1n&4GAB|$sfcLPsU*Whz}&V z`8`>5YiUJLu1!C|78pl<*(0ycx|JrArA<6CshQNV!1hR7ZpAjHPSmGWMwI2Rs?K*q zixSWLj}wJaTYtpYa>bwRZvZZG_TDb;lP#7nYPO@}jG9qlY03RTs1GgBgPq3t_|2Oe zxWc!jxBa#9-IqLuuN3`FKMW>+t;@{lN{uqoQA6_9@7KwQ5l+u;?|nFywdZ5(Vy@hY zb-dRxeP_I~RZcuEl4Twge|)?+=5RXfLR|m(8QXBH>2^D}p#t%21fkmb86R-tKtXwv z>AMOOQ&;NuMijIgUp*9XXh6?3S5hL8yt_&w6W}I#s}&ASPlg#gB^Z@%TO|jwfbHh)6jb1;ynkBav1;5 zP~}$iM#~9({kCsorvINK+^HY2$d{2S`N7?X>(p`*ZK5)H8LuY#=*D8lN6>KIn=AB^+Fcvcd_BDGf+tABIsza*KD1$2K4aOK1e%uI zZX0xZLL_mIw;j5EmHfOf`JcKL8JX#CS`MYq9~NBo+IKoJE8!!qvc|9+)ab56lyLBp zy39S#rTTkdrm@0#ENR>fAqCfxi=wVr?Yy1CZQS)}b8i}`j8gn4Vz1{~h=lyUfy`VW znP+>I7w0<6q!Je2Zvh*MrfU8Meu0~TY!EStCp#LBDC=5z?6EYoEsUaeNXEMBw2;65 z6u#8%)FR)Yzs>kPMCW*fZNo7~YmGx~qXYN!Zke?hdfAo6`xS;X#@z3>#)S93x4e3~ zR*n(Bs7%?_HhL>F?8D|>iDTZYhKx&lN)pt{dRyLGzr%i`_Gd73Fd9(tNP^GUpIEGJ8S_xlyri!0;>LWD?*bSNT$ww`HQ(q%z$9nJaAWFV>}~IZzKym&xjc8i6|>v-8`wK?$>a4%AG*bD~w0) zeHHnY0>%#;!3ET*8nUZ=Ver<{dDCdOZmAQI)qVw1ub7_9v2}7FKZY?>!x#_w|R`_za-HgA6k4hyM@zj#V&tZEVte@XP!nN;HH`_5x~Yk%UN8sa zEWbB*hB=@wF#Zh9Xa((UII0=#{?dainD2V$STfX|QIu#g2fiZxS`|aH;=xWhJ!^%G z{6U~)bsS*^62hz?Wk|WTL0tqiQE9?R&bGrkr0bskRUJ?{MZu{9sdutcOSZhj&kY9Mv6IW@iH_+C>crvdct#b(CbZrSt!j^)fOVj2ZmQe>s zBY4(eP8a`+%Hu{*`Hko+j3(oW2&$sxJdyg>5rmEwTC8Nne7o&X zx)KrAZNqEpVYs}znefn2jkyv=m(7?+=bDC&h|5Yo8G;;2TfPe3e{aRy&@fTM zt+$PC;F$QlyXo%_IZ>pg`pYjdbWXgM4)+2oGi@Hr%7?by5Wwjx7gL;}MMlqpp+8=z z2e<6Bt8?!;QH6*JOOzv0OJgO4?_Gbt0ams05u5q1tT`>q3}$$z%oooZMAh6BUx&jU ze7ml%XGm^HRGjXkJLiB3=gvI{_W5tX{H6E^TOtdIpG^pdLcDyqVN*G^4tpI*ABQG&>&TN?DsrRw|CoC4LHQ>Fbd zS*IVgx}Dw*r6=^)nUNvg3U;i%x%zu`7p3>|L!-j0xm{yhErI)7y>dMBUUjH(@S91- zh3?p9d<5#5E$m|zr*@%qYU|}+Yp`AZp-pehDtep64;F3}i#hn7y0J0yLny?IyFl=9 z5pJn+_=O#!4-x##>q~|bOv=+&R;u-z%v%L~ub3!{#Psu7^0w*spet2r@BW*|*%~u; z@#HUL_w?W0|8CG1!OTy^^~;y9z*fCq068x3_(3?wR5_9s&V7vu{ipau=D~Sjnt$C4 z_~Y^%Fgt55ua4?q{-IU4w#}JNpxTGwyjSlHit zd0}@^p)+e_ytUVsOkMK9UO(&lUdd+9Bj_a%bHC2Df8|Xl6?*Jr+~N=5a}MS6E^Y=;^qZcW{*~A~)sWYKU(@Bv zY|1{`8^<~zuG{tc2vEj+tuVUvzwzUP-&u~h@kDef&ghx>qN)_=J&eAUFOfr#6M!zM z?0zT5(wMo2Mi1n4y}EXrh-Rv1Z?y@1vlF2w^?c}70oS?8Bh@XwhKZnq|AQ0t7;{Ox zJQnbxE+G#kyvCg;U3N61Bbj{<`#*m^8@4s=>w1BjdFuCs3%L@x@_!z9!F8u{`^uXb z#)=ChXe2<)7JKQ{x_31Q{FH^urr2=udnmt=H9S1)*_m9n_r&39q+s>|bSm5gy7;ZK zjYkG$#gslcR#+Q|jG&KH?vjpxotUPDk#zb-^rRs>vTZ zF>x_+=^HZ29xE?;X)=60X5Jg2d@I`P>rUuO7V=)unqc_@(JP~c!ZwD>fV*nU?c6qr zJKE&c;^<_=zf!n9>BKt9IpIC6JjI9on*fpVb#XoVu|FjX0M|zoFh`>o{Y^scKPel1 z>oP>9>@q3nvK`gZZ9552OMVW>eiIomtc5>fs%6)@o+j(V-8THhnN;$c5!SUB*R+vcl%B9#N&{nL9;?B^dqij==T#j(%W#oOMN* z`5S{*n?=iQ1Y~_vAfESTwoYslxx{MQS3ugR3Xu=XQwo%z<(5nB@k-)D*t?_VdWxsR z?mQ}%a%01Iqq3HI<5#8P+sdH>ANa?5AHx~Hw6V^1^Ny`QmGEol^|pr$g)ugTrZZ}4 z8NR-^bu435pl{V+q6^W&>B2XCbI;EvSymN{@_03s;o@OxPW8QW{x*lJ11*Vt$2=%@>06n)a6qSm2jUxSV8Mca*{N7MWF zaxCyGE^hp07aVUD+1qRl;qHUIykF{LHS1l`dMM zC|e@2+Icd;k2jdx9Ozh*g$T(o@*;%TS!LGpC{PI9lwD176o!o6&a|t!$iaB}al1)8 z2c{-BuY3kpi?W@r+YCW*E>tgEU1UKaLjM+FkyC3&y6BNjjDIlXQdU?P*7(g1R1= zU!RoqE#C`nk+#5a>d(wnoEtaV5jX>c|I45-9eJam{ z_CnjI86b2_n|+(4F4bL|bt|hdQ!kw56M<`N2z`XoGJrN2@ok}Z0>+~@m(<;`>&Q?o z=nB%Xn$P$JiU2Tn6N%?oI_rCPZJ=1xlBJ@}{s+JwK6a+<88@;2iPG$A4a7AR#qFEl zB>-xMtyK1Smg=5*(y6Z{n>p=_X!nj*-5Z+vjdqP^WGY!qZvT7ncax~ZKsa&Vkx0ni z4BL_>U4c*e`ylu5$TANHR`(l3RI$SuBO>jjPj`I!cbBk6@udT+_(aaQk?V2NBZp}2 zduT7-YBYyj;h31RB8;KqR&n&2gpNjT&76(4w&4b)jBNf9^)Fep6ZLR?#)gsm1u0>r z7oCG&gy2qoY*In?pG(TBK~EHaw5G??|yODIqJn z-@*bjvDNw%fSb-P23e%`CIk$2Rw%BpV{qR~F7uP0cGm3EYqoUuK`HFcJXJzuI@$BIwh~mq3tBh3ybJ!yV zcaHIt)qb^bs`y*;&@?;gea7eRyK@sjO6n;2Pq1ihyISTB<+}lIW}c>cwv5-leYLBt z%Q->O17ux$i_zz+Cv!V8r9r;X*|RnQbt0PkrN}IDClF7r)Qx4;QiXQMUz!lRGkS7$ zsqXH}9ZNikjAbry+5gmL_7=0kHtaLBW{d<7j=>(2_UhiLN?~rrLu)T~r%akkUzjd` z$xC~)>rKHsqnWNBa-thI)AYw)OmYj|&2Hz!@oobB2zMR%sH+fJBKV>^dNiu+Y3sYn zw}DOo0QKOf z9oMqQ2De6#Z4Z5?kJF zH9?kVG2}uXC|qQ|UF$>ZMZIk3$4B0>)+j4$^!9kW3y$~)(m4a-1)aE!WG)+xG##C+ ztG2icMIfY^@X-ix*-;M33=~I@H(JHU5E$ki*3_3f1Zm)8>WFEtMp{l-DDw!=4FNwj z1QonjXGg6HQjCkW)E$>6kPd$YvjjdaLSg9oRomVHN*;rQq~y4qWa{dS z*4LuGzM@W_!v?NJ2FQeTjUSrHE_0&gnbE4b;#PChE9$U?J020M_k9q6RI0g!>YX36 z0T2-cM#C|>{1yv6w|Jv0hFq9fg@j(gh>aUOnU#fGQRKOIh^Rq|+kAhP&pX8j!QA0D zm-ZM%49+gii)WGxjheNr68n$P(FM|b;I7aw1@5|%9$!LPM$U{WC@#Ps;(s;k4L9$R z4MuyI+3Q$_%t-MG%x$1`sPh_;JN?+7uP=OVxz4R?9_@1j{gXsLhPtCto2L`dFWOdn zm3z^-95u?8^JQyUFTM+zDX+=;pajZXCPB+IQVXv~uW%iFC=O0B>ALvIV#DDddQHdU z{OTfCO8xC!l+psUSn89F+>U{EC0?t=6<)>*OJMw`3qvG!A@_;I#S}*AD8_1W7NP8BwC1(V zkPE>Rg!dYm>^k*3C6~wkCY+>3iHs+n)>5wIPWsGlghZ+;XSqRa+U!BPozN@RxE=On zv6y9pXSx}E7oLR>|A?5ZWxTgJ2fRXdC+F#F2Y@rQS1*w!+pwd~C2GxGr-n zs`%dL@b_>oquZEX70P^;Si%m7W!SX&D=8%l4OSVt!7=Vta_{*kS@w}L>-zD6r%=R_ zO?+jW^+f0dD^vgpQygY&Z*X)Wb%gYwVN>HlgqoQ2@A4HY5l=26yv0SsSH1(>C4k&y z!rPQz??e5sa1*~w2n?RiPrUYzZLPxkIAVVu^lOb< z{Bf`Qu)?Q4byR1Cn;{JgD9239*h0#^RC3WFtCd*vuoOM+m|!kBE^>HhCa6G82lG!hZ_vlVRJ#@1CMtn}~^^kfewN=5_mSog3~3P9l|@+~IpfTp}oBW4E+ePBg9q)^CNtq_IZh z!to%Z*FuLD6>L7OLu)we=<}bRgwtg~c&o+{|08e0Jul0i`e|B;$M@dTq5 zP%g|79?SKMsI<@qWqx(?yl;|+)|fBkpI+CiL^X$1qFUa%6kse5x~EM{f??QX+b`3P zMSv!ml4LqKG7`*|PeWj%sDO~pfr%001|wJSV1ec+SarU`u$|>R&|TY!VeUos>HVCL zZ`hul$K>{|jhb%$uVX;;D-1(i`{`#B-$neyGvv&F;TeFLe0X7%_W$p7=@A%sDPMrf zV&D7F;@?kY^zTBS^zM5&2=u-Chjcpo-p;uvLD^{dxJS;KbsMKL&IM>}R z00LQ~2l$1j|2MH%ybNJYiEJ`Yt#Zj9 zB&|%o)ji;%haFm3*kcm_V4mH6aZv z1)}tYn$1E&wrX9y3=D?eBd5jtnfB?OY@m#MdPPYI_!%UvTlJGkA#0hWyO zasAH|a4x{M0LFggK*f+8pKAqk-V8a}bn*4?r6*@ZAF^{mml5=r^9&7}p;K4~=N{X4IQ zK|o#*W=#|`9Qk*pfy!m>RS6ZbYh+Ff8|!&UAvIE!+8j0cY#DWqn`B_r35XJ)m|8P5E|06 z^0iTIKv)9Of86H5@?cGrIlYN+-?sPO)0$Av&Je3tieG{GlBJ@{x*4H#q(JTCZ!)K! z=`Z(vb@>{ItEVWhy>ag6BI;+;DAH4nIV~xfeTKL6 z9^pszQrd=*ZGpBPv>rQ0*nDO-e$cusf`dPcgmR&4?C?#X9-*i@ms|#y>cmh!1N$Od zG_Js?FOKCKe~AI!WSUYfIKb>_jzIhB5Ko&ad0w*nL=SBPMt-6*OR`uXwkddXWh5ubz&B( z_%nmxT3g-KPL>b4<{B7b9Z%YRYs)NNk&=i6w(-<&`j3A0P(ATg9=3GueR49BM{%ir z9H$m?%0({LAeAyUbhivfTZU) z;EK1sd2~PXA_JLXa+JNjKNhqNYB?&QK`Mk%Sn3 zZ|_S3RsCJyf;2MHMcA7%GrCjLw$A#e$MNFTo?b_j#F_l#vr7_Dy4s4q@|nKiGDVrY z`**CKb9d=XbTk&n&EyPd*@_mYbKMgRE(YSoXf-Q@U#+Pw^1_7+LWuy6Bv~2}0;YxE zAImc}U6x;tyzH-mZd<<=BN4LLqkwT9D6{|PdH;r=;SSzwWlqREw3$&13X14T-Ez~` zc5?Cy*nzoKIX&0TIiiKIMkYIGnIn}1Hslxiyzq4>k#yo$;t){gk%kS$KG94I?n;)F z3(M)HOZa+X7G6@4+4ZwST6PHd50!#kzOGMaxpr`0k-cFvp|(L*axb~{4?c;Yw;1+T zR|PSPlH(PO+`UoP!b)v7n;u7yKfN*2C*?T2=2tZg@+RY$0hCgb9s!g!5?^62T~=?g zFF4c#CC+iqbv5>ogg$2zjDY?(<*Y6ENiU$xNDTm)h2HeS^trez+v-B~Ar#OYC;rJ-zpq4dAG^0a6m{0?r`nH9}ZNv#KN; zP&K#dBAOr==$ye~xkxd%l?m;Vii&SB5++Q-fDI9ycnGR*YIa#W;JZe1u!0$Ib*tvj zFxH7g>64~vPm4i%%t2xF5T&|MC|Vb163J2;%Do_jp8UOeQ2U;$TeL+m?W|2)v;J#gdJp7<^vonHf&B0BXI|k!XuT0Ip ztiKkip;uBral+{ZS>(`S8J1=Xt-LHsF#f#xtplseq-RL#KU*UT^Yza(i6b7z2#0CH zuNu`gKi28V%iKM-MgVzQVr#Cv0=(la~Kz@9E>De+t z8M~_W7GL5_Qbxkkr#mRY)2w-nKzE`mYQ7_4*-SP1)d+O*rKZ}`&b09|4xm12+VH%x zhe9z2hUCNuGCtl9-nLa{>hE$a-yt(%GR<&0FKLF@9Cs9RDM`(uiUj1v*t-e}{+xD^ zEGRa-pI%Mn#cAUPVz6v9b!JytEe%@28;q#I8gpOuyC<61GO}PX!_yl!Y#6nz0BX9b zJB6LA`}VZmDK*wLmu&98fnoop{na)uQ|=7C64?aGQ)J3Udn%)r6Lev=0^M>PHyfKd z`-m-5Nh6(e?!2X=RS-FvyRqIgae9okc8|>63Siycy1rYZ_-z{u8^K<+H+9eSD+M;T zt4PL^5_kR<{eiwRc|CGvBE_Zm%L@he9g;?Cu!VO4+@pifq7c(#F5JA^f9%XRp-}ko zezg|?P4P?yFNASoh_mExrJarimubQPyf`#+C0-BBGNLahV6`Oo!CBF0Cpno1=3s~X zbaGKaOR>)dUsG#~WBoOkbj`Pr$OS(ORd0-=4SBLUW(e;9&%$ralZcFS!N4I;0nUoJ z>(lJJTPXbFXKV`li>e#t-5*t}db72MqmXf~6w^qAfR}vGY5zJIIn%WzPER6C;XcYb zKD|4cBMr5gdO)twXv*Hn$v;sE7@c0oSiBy_y{a=k!n}l}M+nWJ2){@9#uBsU)j(lKCPNcg-6R>uFq#wJ7$2hoY`BL z328H?FkR0V6j2X7^JqK(nElCK{;ZO~FEZt0Hia5+qq0%RQBsH_E~_m0;e>fb-6T$4|jpt4;^&dk{1{sGA+^Y79A0hp;`N0;GgE>5hz1q*0 zhN%w0Qp++iKHkCCnKc~MS)JGi={dxycXw9AIKO09QS4)34vQ) zx)A|EQLM8loq)QO4D4|(z!GUtcJyM0!;!`)@E-ZWvOwkT6Z~37H<{BKn@U4>6hu0c zEI8V*<*U5upj72!PBq?@tXFe&T!nf{kAuZYqLX+f4)Mi$Vy;R|5?mlepyAXH6F zU(952M1rqlDiNX+=S9ygdJ1L*pVyEGa8}NvV$06-c#XgRe%?V>jTSCm$H$0oy0~xv>y1&8Tfa7RP7%Nn zre5iESAg1}JZ64Q&OznKnM!_jmj!40MGY-`0%LM!u)2SExK!CFbSg89*7Nnvp%8*D z`isbiCAWnTJ5MvkzhX4M(ujpkA=ni^33e}A*h0qIH&&XDBr#{C~R zm#4#V&+6wJKu&Am;0nau&-0<017rtwIO~+t&PdiqptA0`maPj+9AW~H5JF3AxM`wq z=j5lay4=TE=J&qshg3o*)4)R$Vs50Cy$KDB@hQ8qjzr_-=m=dYLC~|llKArX*z#!0$IqCb0q{~HWX|u3x3hSLJvinp_g;VY`K5F0W z?P`7Sn6-%G?$4gdtE!-8tEx_f6(6EuEPPqjfU|cgB~1s+T%{fWjERC(uSx|c=2O|p zCC}O&F~LQxiK@sFByOlXF67G&vjNWpgUQ_ujj)&`5OmQya$wHkqnD>=&)J_q91vE^ zthY^C>b~4o6fi4a<9_FIoW}xT(R@45eM$|xvT!wB2OOaP&Bvk57;r^Kr}0ZI>-HK3 ze;o0z*xW7bG|$lQQ4yrxOA0IyrDYe{C%~|k+`W~oQ|*rGKV{>z9jTCbfX@PpOlyH7 zl1~fS5aI0)*S@OE_EVQjH{Q75irV7s>)UI@S!oH-g)X$KH`L3KhCE>ox&L54+0h%f zg~nvy1OVcKoIeL-TxIeojxY(_$OF2c#gbc7G`(Zt^MX%R2+MYx%8Gy3R`vwymQzD$ zJPv>qha%LzLjf&Xghrpz0EkmH7vu$~>fe0Y5F8y9DfEVO(mk#}+o&--q!#PNc^k_(#sdQya zrqTk%ro4Z#hW|4rx71AQ_V`5x!OMoq z{(pt$uDU-Dq&|J|Kn3#v05F|*)x~a7^ZXCj>wjX-^u~Si{duVMgI8x=`$!E` zV;?5zigp4FASeGH3?zUplq%z z$5dT%RZMUm>ea^8w}S&#IZ{qp1pyYyKfQugfe*G_Z~Nw&z5QU!hO6Sn?ryu2=@K+eJ`-4F<&{<%(50iUOdLyxgD;HvaJa7>}L zZ-pD{ugbA6chV4G5$PB*Kjsb(cQe&S}l#r_QYNFv=%q0ghG^ zKGFl#+Gp{dEx=2$IMGPZ=Lrj6t55T%L5U~~W=QVYB!f}%;lr6gY(F2W%W?q>Sqv9$ z79wKTHq>^b4fTt-(~3E;`5FiDJxy9UUk<`tw@aKn=! zKFmH%_uhw_o~4W7AQ%EGrNx93ZFz48Q_j0NHnnOhMeb`H2ZegMbS>Af8a?hIe&Z_> znE8ULY;_|iI`9=%-YbG;*vNk6^j{}Hs%$Df`0}Su4ske`zJFAJ6PU1RV&}S$9DIWd za*JzH;9AIh>i*m`Nvjf-m&u80i-{?&{X1!8P20`X?AiR3T~kjK66Cd;Yf>|gjaJ=# zP^Q(j;2hzZyRfhj3@AfQz_k6`EV?0yCj8X34% zILW~MPf(MeZ}v`i=lCZYSZQcz>Vzt3M*&nykW)4c$~GTDu7?$+^yKp@ne zQ2^hrdev$M0}LZ-(Z`RMq$0eOW%-8BrWQ8LVl<6M-szg}u|9Q*e(9vuK~3AzO)0v~ zD$>wp?$~@_B20CqbFNSucNePMzP?QP>LJ?vGJqlkkAzTAUj<*_>N~h&myo6Q1@`Ds z`cYWS!58FdN%lLK&`hp%!f+m{tF zf{6It;2P!8osKUm5b5$;KgZs7d}a}X!cJ31JdV~{swL%lP?L_b4UkkFtAny!hdFI( z){Qb!!Z^s~h6&OUUZ_P+l;fkeN8<7@8Nu_MpqcuVsVJa7(s`buRZf+}eIVI0^$$)s z{KVCiqbQcC0tzkvqMPC&8c7!9pZ6r3pjN*c2>J}tau$2MB=ZmSpuU4HRx*n532ucg zzGZ&JZAAR5fhq}blLpvnGvG8xxp>v6Jb5^%-={5lgmA_z0`OYd6bKSaj?w+?x8G*I zr)<83eoxspSBv9m8EyAji}q*B4ZMqHWa2-%;A5Di!bG@I*5)g4*J^1*ZsnQFiJQ;U zVN(3lb%T@Vng_6vwc_*_Ocrb8L*Ezlr0$s;3f`xh0+60H21g~?D1*=>HK#kW*Revb zPLq|kt6xHM7Jyc* zYaiYe0l-~0*RS7!snPFuYVqZh8$oWW(TmrA`hhh(7Nw-PxI(9*0xg76_s+5`$Z+|JaC_Y0OO_ak4J@iCXIi);D$}LyBfDB9`$>pYLyd`E<3$MpawSM(g=wd2YSq}k7*nB`IeTx^g zF({{uVuLwMjSZ)KUJVY{E$kU_7)0;GdjN0gNHEs{Xin1lRrIOe`ay!3D=MBQ7PVm@ zBbtUd&W;WPgYT0$hf=dsHpir$PE+(d+4$fiC_GsMspJ|MQNZ(XbUYjbs4c$gk(dHr zF22N`y9V(UcpHCNIrlWzN}mhVJ%@*4`BQW}-e~;NAEmmmyJhgPvD|O%;$#yw40#XF&QKTz|-0`f+~8ldI?2wu3nd{ zwg(I4-LSPyHW?l=uI#dq2|5%wGf>G7O?{V?Y?lOXVLCXm}y=QXDd&{L~9&elmBC5DY zP1$0|eQha_(ytACrKhJy9g8U|BMo~WUzM0SrW);jZ@XVm4r_nUvS)&sBjbgMdOW#& zPqm-5{IjrtRN>_>!zV=m8X72@uwrhqGM@v*p@lF{YCZzyAgr~#6b14xeUs^pxY zlHVhrcIRliY>A=JVW|iRdC!)no&_NU^yu0)Ygm zA#z8$XMu2VXegqO%+hdjpvIo3d`6f=%6$a~Lp-VXSANe_IIVWDVrZkt->$M;FV7~HXwJc6V_)mnan~@(+lb2E0?{}4Dr*M~Rdd%2avC&!a zYfR-CJI-=pW|~ivkL0zlrnM|hCmQR4nc(SYK?zk@a>wMBIUp1-7poFRvR8`n*}a?%a;apy8Eyzm9yv#5(~qX)cqZPGR8o@UCq; zxvUwTZvAG$3oo*NKwhen#>E^^uSMrt>9&XFC)a@;Yh2aXHXyT9V#SZF|VtPR)(OFT*E5yEqn64O4zl=Gl5D6q<*en_iP_vA(U zgOcpnEa@{la1VlOI6`^!rlZo5k4V0Z8A7=Ni1iRwBTXgOy!LTgIk1ogu^I~BmEPPb zvl$ztLq7atH@^EL75jK=?b4Rq6T`bgBilgz+Q9 zL%LxcKS~ft47+`(zsg_i$IDWPDY|W!mSaLW8wtv_)}khlDMo7To}3SGw)^zLL3N$- z(@(xHO@{K1q3 zEl}W~vk7l{Y$baXCz|!Qj#i>^9W26{X+rZWi?3W|WVYXNNHG>p<&L^MQFjY)NQEmt zi_oRRR`9PA+CWw(B)g7H8hw6u#Ck>*)gnpN+QW^-v<-Wla9lA2# z##T})+wjVr;X{a3joFR6?3DnIz`YqoJ-PDUo}q`E-`3EeO~Pi@pSf}S_KYRrc9FBJ zgj-_5Jv@f@>Wa@FtOip@%2A;K!G8iaU5Do|N6iw{B#>>88%U3OgO7VVETpNFn`e4d zl|!{s4V`KOoGzkm<3o-ipQ58chJdRuhGYhpiS0$?pXc24~T)=T; z*YA>R1=ryH91~m`gFb)R(0DYC07ebkRufKR0EqbE=HgvQAzsLl`uA16a6joaS2X*s zoUp#J3wciN3->U#+|6RH65A-_6^U7iZ;Ser3Wf+DL)Fr4 z_J`E~u3c)x4TBijF^8$Y%WUNNsBeJzZ7+X%6XdcLse)DAld5{w6RHUfDo-18kE!T) z_|^);6&NP=Bon=n*LOja}H*qY_s+)qQ)o)lin&yf*k&}jT!1^xY zfYw_(IGB#}z#0z;oylZKlXoXL7+B?Z^Zd3If|tZ=PWIWugp01aFJ|}N)NKUYpz|Gv z&o_QTY<`n@PnewI#s_2az-v zQS9tGAl+(5dUStr3Rb!9727kRB#q9}&{GK<*}3yQ-%$P!g{8*%R`_D4i{wTv-PDLV zSlgb;?Tor5O016XdV<$<4Q!CVd2D2#Cifv{!!5!IAjb%q`VBxF4*w9}V~G#UN*|Ny zgm=qh11oO_YHrOtz-vw=E}yG!Y#f$koZ_a!4-{x>!0dw_Q(=c%k2O!G^iS&0hA$lh zWZ|J9*Qt5s3`c6yxXi=gJC7v=V(N5=?hD#_NnebT+Y_uB;TnM9eH*6G53#w!Y@zeA z^s>TcjA`+KTz5R5oLk@Ih7nxhYc2=B3{yUAgdZ}rnpvg-o;|pG3#qCzQj%)G_u5l% z)S;n>JXphP?9PK6uNltg>{Cw6gS z*Hg^(%DjfnxjJjAHf*^9(vReBegi)Zz_5ZwY5Kbp?$#y``oPK-`CBLTdip6a_@m)G{XmKa%RfZ(8|56RkCLZ`~>y z%%&5 z!Q>)%e{fb#lm)ssti|z%AZ$=;V~Eh&kvaU_#MUdVpylt?4EpO^IiLV6T!m;N$S?`$ z@TWBn#&{(xpEIB#5sq;6qXwV9<$*R?RHHknVwyc9SgbuQP) zmt`VfO!{<+ZU8Qq5D=ma{nwQKCNcujG|uMymm~IUGY(1(B)hL|Dp<4a^{Edhsa2kF zJdR?X_!1Q@KE4PPytQOrJQy-r6Df%Nz=`HWeptmBKdb^czC$a^+_U6ZzbPQ|Wj2v? z>2U8utIQF_4|?<{k}?g{EkJjX_n<3vd;$XGv~E@GUnBz1&GqRfS=E|C&PapaN&lgm zyOK!)oV`+9T>NoCE$x0mR8GW?7fyKl@;1C&;Gh&}VzmZY+{hJ6t+pTDuc0!1vc`0~ zTEf|Thxbv><#fHeQ~G;rH*x&;w(~K zwtH)h!Zsc-=b7E@@VtBe^IysA=b&rbAMIa8ascrvotg3AJTd0RI8p9%u;d}us52x` zH%pA=@CQtX94Y9rEUPcicMu4C{1wph3%y)Ua9=VTWi=Ni2Fg|gd}sjiBG!NJ)w@!@ zX(YbVfAEyp(+Qg(5pU<{3vVpWi;`gUFBm*#0l{DLA4jVCL8u52C_H*-Ox3QGk7l%|!V%=6`7m+7f}In>X17bB?EA|pSS&+;DmZkj_q`Im6FxSehb2H8a)pc$;Eeg?%( zp}B<#xXvL`59S5hW$x$y-xW#l_y^fEiQ~1m;^xj}#04t2-Xx)eT@ASaCI^Y^_0(hrY08dk9G2<}jUbZigR00~;X%QkvLPn(l z@Nq0NYvbqRZZZ|pax@JTv!F1oDrtiMQ@JXH15aE%3U;d2Z=WselpCpl;uzxZ_psz? zF&Q;~LD6ZP@E;&_%3ytoj8IF7gUhnFvZ3;bE@ z@$>saqeuPvrox#Zaf@{2eebMxocS~eW*Hbg_oj9uG)eWF+MnBebao7(z23Lj-tjw7 z{Fc_ct-dT?J3k1Pe)`;P0dIsU!WT;bTJ|=hHApuSY@_my6Rc8tjDk!Nt85X zF-9y7Dd-)d7h<*bF9bGsAAl;u>*W6(_wI~Mwqr|71Msv9Y{7{Q{dnwzxFyS}6b~EC z+H5EK#zF?(Se;Xnjh)kk*3&)5-JZLHVIn`^^d64`qd!_e{aC@SqKb-Zprt1HnqZ&H@N6^&<3KbOl{RGlc{RC?=zqYr}PpVDo;g{n9p3^k;EiH;`f#s1MX(hXW$g5w(!E>;0eIXDmI8)GjRr8R5 z{N_+r1NX#<6OO2!5Qe9NI9&)7_{_K4Y4I997EA3 ztnX0b|Ha#TMm4py?ZRvoPyw-Q5UJbk#zGMksS!{tD2ND>(1f5!3xpy~N{E7pBE<$s zmm(zzp?5+AgeXWS0RjmiQbQ7YfB^Ycbi1GDeZF(vG0r>AIO`86kTus_bKd2;uKS)C zPiXpH5Y?g0U>ITX2gP;;om$IVvTFIfz7l9(%Co4u9kFbVoWT8@n%&1NuG|paZKW)V zX(=sI_#7%P@NIUs;xg$=dwX}gI>+X(Pu6A5uRzGD4n7;NW)ZlYQ5ZO-DWobXJzYjq6zwAjxlF#_7Ssqx;* zb4?Wmcz8AjTB65(7_6UrRx8|4LdZNXYr2hIxI z3?oK_R85)-9hW2NY{3i#zHiQ-Js?_VxwbN3kALPSAB<^szvbK(reJrcG)Jq1D@LEu z*?61^CR<&YQj*aQ^vRaD77*TAQ4ka2YYy3cL=ei>TduY~j3eoE$7T85B#Dx!kT}=7 zrOW8n_N4)Sttk(%z*_RXLAP7j2NY8G~fyqipqFE@ql#4Vk#{N8a9u2DzFt#5+G8(C^YWuYyzM zJ1kJBpiw(l(pIPWyp-oFb;y!V_a3hDDrhu>`Xn@xt`y4HTFpBSmDukofm_RFfR*?V zTQsPvh_cnmDntC3-uACow1-b&VbzH6m;z}MKo;6dSs@YTZl4JG#p*fQc?e;-4H zGhkrYMB&)_bYEfE`xhfVsXX}p`3dPC25zT718j%F1;j*zCVAyn21r|ZNzP`ai_>#R zf;vyqK&+2H-FTxL;_O7H;)W3EINd63fm`;^8Kw`nHhc^8KmrvCqmj+4#6t=L<&V@K zZj#zPk#-sR;JlFKZhiLwmkcKb(c{)}v+{*?-}v6rc{4<_t=?}8jck)_lptMh%yMNS zsn~bRJt7Q~q^fbX(5T_%`OkW$XwmIteBu$!)1dU}E{dMHfIVl`1Aj;pYp3C1BgM~h zx{W!VY5#oRgnjYph(ngYn)>hvD(nL4k+-sSiC=Z`mkaUi$JXtEH6^!*p-pz5XJTc@ zmXJXg<`O|u=q5y4+{PwAE-*8)FZAQ)rZwdP>+`G5V+8l{yw$^^H>^Ge5W$IbzMPht z!DwtxwBzFszOioon5dT# zZnecRN=f013mt0y+I!Ps+*%FquLE{8_alD})OxmcAo7MuoMMwieXos7e0= z!?vnf71VD^`_TbQP@0p&16O)rZ zt}E!yP=`z5CzRdVM1Dh)>)KBE?-gXRvq&pVA9TUo#g zJ*vh$>QoyeBO`}-mP*==SJ5m_)&QpSOzn;eWv{`KgRB5gNw5U7XW#)XhKTwti(pw^ zgi>*{j@8+C#t#1expWvlpjMFN)17&RvB_{eYGpb2#yxLRrqWk)7(o8I;ZARS3!=80 z^t?Fa0pAju1jWc}x$2`#$eMno{PaVL$gdsq=<$jC!7**-A&}o(SN8RhdD{$madB~< zh33Px;0!<_St}b5yAxdMM-Mc1adDy2umT+ap}&}5&bj@7fbqvg$*SatUjFw3BtKpJ z`?!Q3Klj@IZwIYjkOacJf3E%f4RZhdgXe$#XOSUe)7@DcW5Uc^rak-plg?|}0OU|i zWm%AdO-&yqf-Zpb00J}Z2R8hXquTE9SI>HJ?HftuwdKgne!v0zxRk4ag$xw~!kx5$ zNf%Z1^gbXGTAbXWk-A|2^BhA!=!n!SB478%ZCZbzKy#AQ^GRd&(1+fSx7!QrXkQ{n z8~&=nh2Azt9}d%%u9`)m>#D;9SV#W8ft~U(3;L545Ve<#MD_>q3JQwuvh^F>MG5kF zB{4f_W?p#(4Jqj1sv8QzEii#(4;7?1CSyAPo6fKICFr*cy{BZh?=Tc;sKVJi=&vPZ zaqA$auhd-=A^P?Xaw|$r#D(6jE+QgQP~lVvYNOf@3G=CL>tt0P#^IY^AZHa_6km-; zVn4mmdAi+NbIYcBQFd#TU-#C{n=$I@ceJaWyZ_{dEeu)=S@|KBw6EXBAIElPg^frT z*SJQzm!b>PCV|hWl1dI`B_f4eYK~XfLT&kxU(G-<)80bT9-eOCG`qn1N+9SZw`Z7|TZ>VqN z>ay1n4r06bSIEjI3ivF`yc%Y2Q=r}Cj7fpx<4bqPg6YG9qmVTE2&Y&Lh)DKaP&gSd zR}8J{G%v84&`HWo3pB{Mb&Z?2)GYTHQUXGXih~1O?gyzwi>sn2k7mpUy?~DW1Ul2> z%j@(Y;O2!+1Si4~!8>ze9`)-?EAY3$YR;@VevvfI0jdD9j_JodEWFtc$Zo&$-5e*x z`VTddJ1U@7R)TWA7L_i&v;sXj zfx@|vx>?j$wG11N()mt?aP8FA5;u-~HLuXU5XOHgS@uDCGbn^j9jM1qZ5-1rK?%q7 zbz(6da2Gh)asm4W(UEJ+acxgSxZa2QxtZVb3a=e@qHO`ZQY^-vpawL#pO_k%ttc)p zfZNkZ1%aF`7S2DMNFvSF(6HXvB?qeH-|O+?1-+uAN0mBj*Ocn&DMDa;V233T=Cn2b zCLp1BZMn%rKtNPc&Tr>_UBPk((H)j{cgLO>tqxDFGgXEv;NF*>+6}l8B zFmo=1A(KbHyJ~}^K^`EaD}O1H6T(_(l`r&>i7xPGQT&4nH&EFkR*&HHKpGE;^0#u{EOi>(WJri0!I$1b`4=vSeA9;%u@^4UI2+c=R4a65veR5 zV27n|jaFMrNN{SuwX2T+BT7w9%_~V! z$6aBURe(5))h#R@&HI-qpJl=awdTD~F$QfrUI0Ss&&j=|3SX~Xzy91>ghUO5ARMQd z>A6TMggzP3y7Re>Fd9|bsw+^RRePGg7p>tI8y+A!>sxkHA9GOcB;*>=n)Q~_OZQ!$ zEoD1=|NM%I_Ux()*{ZoVpYp7s%Q5#s`V|?Z@$|ITdPXj9kLX*!c!d5gdFz7cf`Tw` z6CF|bD<|gL2c(uH=0ju7h74y0f{qan$x-+BEZuur!n~_SR_Lh#Jz8DEgL=MlvF&(} z^!<4h*zPauNo z9*HLHBas?VcLgfwNoyjdf3Lkqk0b2Lcgi4EtEKPMT2|UQ*tg%{)y)w@NddMwN zMr_?)Zr?e-t+^EXZ~=R;zUDN^kMz_J&r9eEp7{_*6<5T(?iJ48WI&7wUUK}V$;~yL zTHc#maR3kz{&1dshGc;ukyh;m(c%?L6?U~~kuSf-yZsm#?+Pw{T^~xDorS5_tq*pFpw^cJRsaK7vlOcEQ4r$pt1b|& zFuiQ)d}ywddh`t0b|Md~ZzVD&jC`n%7g!qdt|_y0iWwR3k0}50>X?3==EC553kt)0 z=6k?xgdfr@T?QkfAVZ5gdoIfv7ZlLX(^c+|-$?FVApHG^Jj(BYym@rvIud0gEK-r^ zxVpC{;&2*^YW=;QutQ(M-gkYm2g0lc z>Uk(#)7aXOIle>nfLyviRl2mVQCPrnbMJZ3(`jrF&=Ex7N))|!RZ0rB)^K~->k2wA z&y#iN{>3uCz%QYZxue3-sbqeAf5 z?5u^Kh@X~$4>*2q5>Hq3cW8)K5 zR}|&KpBia1V@(mqz|acD_b)SyU;zWg?0J?HCbM*&R3lXG>o(Z)K^7>CVy%S9Y<{$H zcS8bVF9G$xihXkcGtXKPQs0cOy!tNul$vxluT}Rr#%f@^t+UfV?EUBi8hM~2AI~rA z7c83RaQ}XVR*1knCK=*tY!5GXvwSX56fGGL53=mKA6IQ-VrJGi8)(h53dk1%44dZ2 z331x_KtLd_dD^-V=YCf)yX0kC`j_80nQ zXJ-iWd)UeT1k_}obLmm9GoOxp`jpQmcmYuViYQxHUT}Ggur4eB#u!tkE}FWv|TaYIVScqVCd2g zWP4mR!|V{-?>2V>EiDMSM!08FYIP-hP7Ue4 z{I$*|UbPgZp?3-WP~9fFdw-2`jCqFUK(`~JjZA9ss9=O|VPF0VO?FB&$UO={XJ$4^ z5qgBTwf5#IoWFw)Nli*NP9t3ug_9~b&-lUxArkn(7Bq11%8yHMUsSQyZe?y$Iqm0X zAc&~HJN7-=&gRC_MOwSLF>}`&KK-J=AAYlTl4uT<{Ts-r4pv`aWykEbG)cg0id|Bnc4Zb6Po8fBhfn^HRHejdU`kf*Pwa2 ze0QOz&Erqopk%h^_ep67_9cfsbp9tpdz7YMBu>yzM_}=5>3CD}mIFKo2zHl%6FF*u z_^TWdgadYU?oy}jNb(R%;rk5(@q>wTzQ}Iq(9cdYz;oFB@rQ*`mkn}D5x^yjh(18> zyAuD+$BCE;QLPDB66MBvz|7X%2IM|~VzI9LpD9qj1w`*QqPttr^~*c2Af+UldRrEw zWCMdjMyF%9T$V(Yw)43a`oNZe+{f9eS2p-&C0u#ozgba0!`4y}f{-M?57rd;P(?KX z2dn@ztP72;F#uu{Dq5NRuK|u8icnirDoEl_Vge8d_5*wfPL->Wy{t}smjx7V zy1w#d;3}_iZ9ze(p6<0MDmBj}Yj|bzGz?DV0;a+t^E;(97X$9&oYDfUj$MuNtQ5hy zD{OB=u)(KHwPCRkBXKDnF6>Y<$7j?R3`cIFT;Z{TR$K?Vjo{C5TU`V#}g9i_WSp@(VnS2O4ISh14umv{R z@XJnCC6ZlPVC#Pv$+bQ&uC3&0TdC%Q{m6@d2uN(9Os$zH^w|{va&!|p-lF2r`n&ot zH)fTByzg=R=MC&U)Bux&YELO_(TwYdU~XUu58sgHK<(l&A&-Iv0_uR`ty(rC=-yKY zH4lIRpj>Dd{uTwkZl&s|d>>s<06)~T`qvQDz#x(1!DrB;HU z*Kcne=K{p;S8{z{(flc{|F-%bzW~Y!Chs7^x7p41D;u>k)APkjK>qate9Y>am}ISr z26Ynfi^E0jEv#k2;PQ#&snYjdJ1zG*z zTCPj5)_1BDK9J#;5ZJ<;T>%Qk7A8L<>I0VIA(UP&nkqDIU}#9`r&n{G_5z4mLn9Pa ztOE*5D{k)0lKU#Bg#^fGXP~r_n$nSc)*%w4!!4Bh^Pn9$B;mB8iMxBuY231@zpZ~s zu^E5~&*Ao#A^?Q@^^k0l)SHaftg4n+v`)V?MXnltup!= zO%f0q8`(KggsoZCYHIoTG~KKD#XP;~9yW*g36IJhT4FeW_|Pkz-F8n3>0ffj1&|{j zBZv;?jx-nk``B`_9V1wE#(-k*(wpOmrl4@Fv$Jy-aFE(u%oxC5)mZ=U+>Kw<&j-{% zEKiQ0cSHDp3+6oi-`w?s3r7dJ3B3&BN@PeaP^$(`alft(fa%jH1+llr# z(LA6qyD-f=o=vXV9m2%#d+7bI`wBvUL1k}!384Ptws?4Q(f_doh#btwLK>qGMdZ}b zK{ekR3j@7BoKUOFAbO}duSiw9^SVM|KNkrGFe!oF05HV5z9`L)a-@@2(t3J&>iTUC zZ!;^dQ_OJw-)-fVEC-Mqd@uz0D>6wztEPB)GXTDK-b$YeP!l zl9bceccJSaAH=M(?0@zTxWJmG<9WM9JSDlPGwe8Lj=Ps~hI6+orCZx)4`=)fO5?iX zBpv~C==$9lKW#IyL~QzUF4gp(spSci`o9Cb{p$_zc>Sdcs+&UGBg9B0otu%M%KJ3q zw}zO$W8sHk01?kc9lC6|i5zqA0uf_VOTBGnmBgx{HF79wUxJ9bLQnq7bDI2n6XXAY z5Pf*h@7@J8&STbfQ}1v)O1-WlJdXU)g#ma(WeuRckY{9!wDylUMG-&%fzBU@7fji| zpI>ZkH>6vh8Zaegl$L^RPgV~CUf|!?qsL*uqH7lByto>T2Th*yA|J$+(vEqwHxLSo z3=G8e;zao3MsYSKCS&b%&23=;H{=iUPB9S2rF(%8;FGnuV{#^fPy z1)jR4j@so`c~17^#a!Mu2{vjMxoI2L`}^l9adr2U#U+pE;MKWq zTO}(q$w88#Qb8X;r@D$@$$ng*$;KD#7{R{rL`HAO|Ks+SOzlwM){0RLm-!6s03sy0 z5~XA}3YT1C)G}v$M&Etb0V;`1;Ul&qFaWUu5IWm_3`W5pm*xr7Y+Q+HOXs4i{wc11 zKkvuUD@9~p$cGI)l#+w50ge`U@F@{Mp{4+o#ta5Sm6VoJ`a%8-9~n?np+@P)X`m?m z!Or(~apuZ`i%oAw7wtU9X$G>k^V-D~&$m1APo=KMHW9g~q4%L)B0?O5fBW{WZEd~O9>{PEkePAAQIDSz32x;3rv*JUa#nqr zSeTNPh}8a)tg>d&W&c}WnTt6MC~feR9|>(R$`nO)0-MRkONZ5tj=Av&3k#8S zKl}=zRSzTsDx8)x6fmQw&`SrXTT<;EL^*AGsl<6>0eQs%n%hb>f}!{lH=X&SPIC-l z@zI4qij%qX33w{9_AM}&&Q}xi$I#(9t3hENE{MlKOpnBJ`TsiAUmI)Zfd<%#bt1~! z{Y%&SRO$pbXmWo9fU^dy6`&{yB=y;cMDZV?pimxMoMZn1!MIiCNa3xMeR7XVc$#+% zTii{=d5ksQV+CAkHbjV5jP_aZW`Z5B^1JKQ`p-!(4sO}~W^Ejf%xz@Yqem-7`;l;N zAgLpc_A3h-srkmpo9*S?7;rkbMjojsmN}tdW0eWC2O(9pZEiK&r^^WN~2+ zb)b{Z!X;MVKymXu8W8A{XI?IutyZ_9A?0$^wEL{ScW0o_&9bhVo3KSHS1-M?82RNp zA3c6%(Q zCpO(TY$!4Eb}cl}UXs{RBy+;zv&(OHfnKrjYTvtV7xPnTmQLlIo%;lqq!G)98QvWI z{TC~S_3)Hh|62HALHF9m9b|z1Dz=sl0a}3sd0SiXz-+v&2b?L$p(<>y)lq4W^m-}^ zQogi+&V(-#UgH*8Qa%eC-vbZ-gB|LG5^rkQpumbz#Rk=O&F^@3iT-Y3p3=~YVf-%W zu<5e!Ej`e%NkQ4NG>2Spe}&)*_lP1+v?bKqq+3l;0ahJXE%r6k-irJ^mOccvn0K@} zG!*-L=y=4&T!a85u^PyyhA;H!M65RbR!eAWO>+a&;TSn$qYmxhfLx9JLRde5EBsE= z7YN}kKx~r*PSeFIJPKo<#2nvPIzsc7))vJoy+Uk2R!qxb=Rl`xZMTZgivKd0xZM!Y zm`^@rg%DJBt5;a(YRvgIAy2Zz$fB9$zymRMK{DNtXEfF6%Yt2c-yAHW`J(!V6wS`ESwcodtnj&yfB)Me%HL2-$7cvFG*1TrXuSjE{1z?`0# z(-B#Ko9U#agFmt}o6M6jNhIN$wI#;vIo8AgD#XDj$maK76b~Oiz;&daCZbyO_6uCX zylAsq8;f|?@bWK{kbz#?`B4vV0Q+XxXDVbD|IzwMT)ijW`kBLTZ+T6`sy0tQ$Rd=U ztN7Z&Q(>ngW|1a`uPMPrwqE8%8$ywY+vq>~)PP<;V#mb|s1 z1wcyNs6-95oLU_`W3iH}NV~D-JbuL5S!`=?8GquQuTwBetG4qp8oU+hNVBa1t&cz( z&g9c;PivgUM%Tjnf1OOhO=^x$1FwUAGI*g$##&m+t=XRF2XSz;*+bZy=a%R@ILrTg z1wx=J6JR?}8)RKNz|js7u{|eHtnjD=?(6?Plxk1GSd}|rP%fP9lKnk+{G6>O5&K9H zQ^^_%=`Vyb+vzC}Gf>4{eJDk`^h)hmIm1IR9j zS>hneSmH7qGxr9BUv19!?%0c`-4!qZo_Y1sDbALf<+YN#O-wC}Ss71jg~L##-QJzC z;8V8#6kqpI$D_zw7d4^na0ZtuU#ez$vk0Gxh~k zPN95H#RjhdYtrw_b|6^C21RazOs^-K)+PQXis?A{ijm(<4(g4YYyXK|U0`x>kpMX6 z907i2Ma%_*4x#o18*8t;9lF8O5gAQzvEQ`vZ&34_1km6*S+QrB7x!te`)e-6^uslH z{>oe+K8Q2!FzF~is%UM44x|3))XT#o=>B*33XF|H0|K?BG$At|-eKHq`JaeLx%yfo zaMlae?TTX5##+Ec)Pg9#l$%+5tB717#$<(b^^`+siQ{+lD4Vx6IVrQ|!}ZoXa|IH& zO#3n6w=bbmR3Yo=rlkjRto+${JM#v9Fza%$fi=ALf`H7O_n40`2H+3Nn6LJr5JlHy znh7_rTJZJihY6U5y*#1(P# z@NAj&w#db~cbbj~%^0M{XSv0pH;Gq0Tt243+P5Yjw%3&^NCqd}3WGrvAlt9YBNt+B zI-5=SpEz0CUh(1_!YwBr9zB~jkeI&S{=60Ho`GuLoj*oA+iuipK4I%GG-DSXiTwgD zmOzO+rAAMnd`TzFehvUouyMaR_~4eRe8MRocv=aDM?=w2QzbizfCkIhHry^0sr-%# zHjgY31<%l9lO0k&os-di504Wt3-qWrO)Wnws_F`Lh+*$TU-Rwv$_c*>zZtm*(JZ7H z3{PB)R_ZX{ZhdKrwahD*krcu+t4it6Nlhl|_5#JhgwUIpb;zKs0m_rPlOBG#+@3O(Lc@kp^?uxjN9>2(_K&n2E3o!GsX3A}L-x9X!D5c#q?UJf*QGer zAQP);Cku_w?I9z`l{prPY;)&H*+b{HGHR~b{ls8BYkn?)ZyHrt(>9D?xy=OXp<-R* z^qH|p63S>O@Q=4QOj^r3npXK#EA~9NgbFGk1$;GaeK((iy_T4i8;F?~~3NYF=5tb4b))vX{mwqLZva&+YZ>J<+uyhFpBk~MB4HU568>^!tun21^^f;V}6 zdoNB>yxnbJ-KKJG5Rqp)UZM?^c@Tx9iXT zxtVsrUUloSc(`eaS#zB!UE#T0x-qd$1>&WmNQ9 zL&GF`?|YVNz8^T>&4<`1QTjXR-VKvgMcxj3oPjy9hQc{+Y?CLnBC-5kO0#tyt>1h0 zt+#$YO1cBSM@Q+i$$HCP#dl+!*TF4gJ7=q|`h@O9(aOgb^c;*!%t)`!UL5p4Kf~~D zh#Qj|xasBhF6C900y4-?(%ZnSyx43ox2xbs3qhWbc6xu49dpplH>Mp@9{|p@rgxIf zv1RLMV?qye9BxIRMRm9|<)Bk~_hh?uUgM|tDu6tLIXL=_bMjlaJ~AUii24$P;b&=%Txt(oe7Y*Hu0OI?SKCp~Uz+0o5SZ&V zv$%>nn(vWKhA3FO{DS5iYmXD_CFkQvbNdQ=>#VIqtn++45_3-bOqo-@@u#I_oNC?Z zeq+Usm@igk23fnN%b7v?U`JjwvTZep$zwqCq`H&GHUoWXf-n-B^g*w>qFb5?zDKiv zT3)eiK;V{#)XlzRMDQ6Rnm_dZ0kXN*JP4J*hJ?&jsr%1!tNP=Tl2CJQ5(Gmspz>o+ zm!39NtQ)NLFC20}K}|%_G&B5z4(N#i8+Xq^u2vlAwu63ktTPfLfp)dSCqs~_7VNTO z(X9!!E9Mlw+Q4Yre%ljr4;3n@TGre?;pZH`n*TYpHx2#V{l%)>ycVo zc+Hd5aEzy7hwpek25^wu<>lqn9#PTI?e>x3_XKHnI3{y$rC+`JqM5RC$%Pp}=a+|> zyY4TQ>=x9U%PE(Lyc0O{fefg8QawamxXH2)fXKY^Rg~PzcS_XHCUC~Vsw@wfDE6KD zx;{#L=c=WJ1{CD4Rz(}oNP_rENL@GrqJA(m{L>y@zuaTM!Zpx+Kh?ap!H3v<#{se} z8?+Y)o;X6mgu4Nz>@vy%)k zJ=n!~!F{50L* z;}|lVE>12lbDag)oly-8E+Bo~E#1=6^3`}T!g^F}I2Rnu7wfHD)M*58Jl?5T*5s2* z^l7FjTj!^D0Mv#j_G4PSe(7D8n6hLcM-E@1noqe8_m}`ccGEb%QVx&CQ zlX*<{r2yaP^Jz5u>yF-0r!TAUu}wP$c8J_VKBsXUyS3It9tnv$GZ1q5*F;RGbK&d( z#Szk*^?n+_?b!mBvYN895Dzl`p_7SjATap`go_k*0c9EP7eww~OyISpFQ5gp2qk5n zpHL880EMCZ(a33+S6v9=g0k)J&e#tVrh%?m0KbF&qbF1j{hnS>)DqJcI`#+0B1_)V ze!Y;hp;Rf?OMY1N6xG5wBA}Zk{|1 z)u)93zMyC?7;RDR>C5hP_pjxtpUvQiDMo?+8H)gb@LN2rSsfYiy#%I-4%BRO<>2nD zkATR{=0~N?B36h4I>wwB0ZWcHBob(j-tZUswIS_+>|9 z?`j3SP4P~tC$Vv;;d5c%CZLCPzO70hF;*kx=~8F%OFoWZr+}WQIL(5UX2hg_0i2k; zRjxHCcjJWdO^?dP8Wk-7Ct9s!iXzWD*|WmI#9#St*CD|Azw=s8ula3Ops>=1zTWMW z?z)mJv_YOOjSDfM6`$eP(%mdwFwP1S#Dnat)13W3RtO1PiC0pBt3sx48*5MKTs6;b364dolBrfa#X2E#MGZTCO5i&|&_YzcA?w zBLF+qRKqEEe^dY(1sJm7FD>Tfdr3($oYZ=*NHQrbY(&Tt&>*PihVvRh?ve)?j}+%? zS=3C3y-CR0m`pifN|NVEg>_}`KSR|a;rGr1J|0%uiFHS-D7eYX2bF-;TN_$&K3fe?ZLqitP!MT*K3!=1L(++c<6p>Ax*fuI#)FCP%&f_1HdgS{+2%iL#8a?u5E ziBb}|ZAT@55#;uXcrLG$oEpI55b4b|cuXs(M&1r|65Y}1zXF7R!#OAn_cGIPu zaa%8trmfXkWwZ=E|G<;#hSkPf9t8l$SSkAJnE|>};XkDKE4o~vc{mVGE@~pPOqx1< zrYw0~0p|0YjxhH;qA-*H1y1rq3H6`UG-#AR4^prJIF!}Nr(8isK}hLEH1jjjyi>C+ zS%8O!PbL&Ra$ygI%|7$*Z*O{U)lSHBSOyA=vHC1dztwxj|Cg8@$Qpl8z(*1|`P(C$ z;aotH-j;j}x6+^=IJQEk%K!6VT(S`+$>oo=6OlM+ppkW)A2Jc7UFBEmi15zrxGBwm zl>J(Rz@!ZWzRzxK78|kmSg*Y9SCi@9PSw?66D`*@WsiUAEr6#7sMN#3%Y#!WASl%Y z=;fHEf3cBvo`BRon=7>k`rIi|d?t2PzW&9q0lCvCSE*zTbkSN)*X@S|6WduFT*$et zWa=+a85letw^kEdHIGJdX6UaLz?_v6BR}TL`d_yh^||o>xYFTY_vZNzQuP1MqUL(5 zE{}8h4@kes%1W6{*m{U|wH{D3ED8FqLJaWU_(bYVvGTc}*wf=WB54~3p=ATuHDW^Uu-_{R&({`B%X{65j*>? z8eYHo#POy^=8Uk^9;EtOMMyqx?A7)cQsn_!)jfBQOnil!e3XBeS7Ad$7N zm#V8}H}N?Wg;FmLq@Bz6Gb&wrm)$6F^@)?F9$NU63Nu?gb)7dhJ)gqgv08z^#z>20 zC=#7e^W?i!G9|oo%`Wb?X6DM)QsaJy59iQxAS0^^fOA}ami!c!&OvxOXH&77mj*i$ z^yoVYW(QY}y{Ks>m@UK1R9$P6%n(B+6Zq-#saltfNikiIv!(+3f#YzUC9x=CQ=FFIZu zOXbQ}_G+7Q6S-0ws?W-A&sTr@MtR}(^tsV1vQ%b+#v{gK!oqg5A z_J*I}Vc_UVZ7AZ;vuO^?1Kvg;Vb?@&$wP#v2}1*ZSCmdDQ&V(19Q-ij8kr(99cTRo zzaF!iWDX^gqk12Hdk0HjGgDDwk*Ytns0hYH3}!F7S+C}!SV5)1wfj!79(N9zsY(a0 z-1fI_ru)cBjO_nFeUKA*+%O{--xqIZKgYS_@c7I|i!DQvx!5TZIX7z-%j#pkDjJ7b zEG14lmPa|j?Ds$z&-R|&q=~(olYSNzAl{DcUyNU>^fj+@6v^Hr7MESTy2iM!>eoki zT--fDwKu+rdSF9Cm9-c_Q7r)qRa;-L-GbTdObE|jj_B-b%%|AIkz=IUQ8MO~o_US* z^@SEM#!Tl!{$Ve3Cn?jWm`iez;!6I_Eyu%cJ+xyOUjrh{Mqp9aOi-h>`x`|3r0#)D zh4q`Wqsb9g6;mmMuK~dBZz8B7<9n$M3-IxfbRV0=zA?EHcT{CaKAAoiaF<{;7)g8VdO;g|7owrtQJEcG1O$#rxJQRZ-(A-z~y6dj}P{C){o+l3*=v9&A&gm*&g*r!g z*Rc>8#l1SWQzbEo57Di~zGGDI!|#-_+2^-ZC^e(A%5PH}qQ*y`YPB53M9DURL)!AqyHk6d&ZiMioLg8t zWOYE**4>0;GPTqdC`n1mHFj=|YI+4NW!iR zT(YffxD=-tuQd{DEp{A|IN!Gr1biFn>E&< z34KCUeQSv{_5gGcfA}C?ZEVTE-gVImSVA@nAFmUiLepM{t=z2Dik-=_l8Jq~&!i#j zW^KKn-a63d!m*{xM{fwzh*&(*n)Efjj%zlz)(UR`U*CgnXzRDPA2aiM!_u<4W>D>t zSAlS&rRGk?cA9-LbJ|{20+;8f%C%`noMVv>p(LFsN74@A7h7V+!ZOBS>7xU_FY4y= zXT0MquF=jbKD=ACPqK1iYId5xsjN#gzRN)123er~hK9mt&$KwKmiX?`m~iO#DMYY%z^CK$}Ue?TddpW9{gYLr|Kbb}Hx9MwewnLQ!byIfC{h_`w=n{YoueU+V zHcgP619225z%=+cj0)3g>u;^UFx}8@dh2UY{dNhjAF_}YbUn#Tr_%*F#Zw|G)T@Jx zs*jDJtq*p5D}cfpyvN3;+FQ^3IAzcadvTSJczY zLN*RWcW#?aSlbUfz3DU?6P#LTK7?Ahlm$4M>W+XqmY_rIp3agNhsgG^*Tp3g`x^_E z12x=`m?|8`-=3>TXf^0 zc{J5`4L z(dzo(r5|DVa^zp_c&6KjSj}Ub558KqCLi9nSDZ!IZG$;Ti$5ec5|}z8>yR+|&_f@&`e@*O{g(@4!8b_eftt4JFul+kohInsFW7IBR+gtB&-@nF$wc|Ph zjX`X@|2q^z7jW)%71yM(%R~BkUu%YgyJ=7R3sH9{i~3tF=BcZmW~}+csFfWT z@aTa}SL0J)c$@Hwqabm~@am~%nJka5*F?^r{VHTi3-LWKnd#HE;I}CKTq8q~)@TDg zy*Xhi_bkdm%j}d&2V}6Rqqpliv9DaJRC!J?y8gIjv;V-7WB4Ymrt-Q&TPh*nDQ`C1 z`>ogG1Z5#9Y?MptI`qqZ2i>z)>{TK2=7UqgDfX$!cSVp9S*R0lRJ|)wJ-oA93%$k@ z+(m{Pk9=9UM9}H4ruo~^?oM=S<+mh1Mg95emg;Ym#Uruyj%mo4F?z?>eVysLO3J!) zHxXbDkNm!8HYfho2D7;ubErVA*W_RTa?@k9LX%sIo;^Y(Mos+(k?Cc>) zFuhH*=y?A3gef`DeB!e?m4nBF!0(Svff{I;!-aF5-i)QL-VA4x|D{6rDRWmF;b7N(ysA6{W&@zq{(A0-vWa(Z_6KxpDjj=AS=UQ@9J2xo4fw6Po2xm^8?Sdv?mpx zyyIKhT=NIRo^Ffx#|!!|&~jTMrYs#{O4}2{FHMlRX%A_f$JmQN0`yf18854E zkDRcn^f0b6%FQO5sLC%VEsX}}D1H z`#NgvQk8tSgYGOePV-B@20`_b9FifR8fasYqjW@c8dVUnM8xKAw;w`zPCAX8n|n)0CvK0UEN9N&l+N6NzFbRChdYT z2L>N^e|gTUxyMk`P(VhfNyx7i`U3T?v=y3LFzgi!J;JOXJjM6cmGN*r5sC_Km*{ z#;3w-W#JE2?-CQm6Z&%GTPv=fWcf`YWl5>G*274Y`>*$UTz@Zr+leEZ^FiSVBf9Od zt9U`(wY)?O=KNH{pz*f$36Ug~8@%o-6Ut88M+`HI0mog0X;n zdra`+6ByFP=0?!Csq}n{yHAdqNLt6NpF2^)IK{NT_>622%QAWPOGazT-8j5yH=G0^ zIh3e}IA54m9W(ft1f-YMxj}L@LBw*Wyw&hh)v;LuntPU0YtwbyrJ03eJO*tcdMu%+ zg=QtQGD?8fl%PXR^kguVVzA<UF%zpBLDvwo-E3Glh0^^SMJ zPxpG1je0&a_3-KFPSoYJ%(HHGD=_P7t~)WppA<$zjW%IxrGvRW9X)S47Km6u^T`Ua z42<<$RWi8lySHkEHUfB^qi=uWsastES-6EAC;ZPoT;R;pV^#(?lv=;^K84+lG((OY zmb2~8KJLGepjEZ?GLo^6lX1SgSV6yYw}Zq|MxRjEY$b@G2CA0bpLG6Cvv>AYi7d~Kd>_O04@s+%CWG*F z*A3IDi9QuGzlg)%H3`X1ao$SO=40OaK1E-4w7!9n+12swpfSHoNeIKD|Bt-)j%sr2 z-bLNIm8~dlbpz65TTlrgBArmIARt8`p%Vomv=CY-2@o5wRf>foU6h(a?*tGKkQQnZ zAS8eY0YV79g>r-Lubl7x&K={7d+r_QjI;hp2ua>|%~dkjGv|Ds#S-Nx%Gkw92xf+x ze@DB1Ixrbl<$0H!lxw*mM65YA9)c-&;?BYL=&E(Wkc`wyRD~YUG=Z+4wlF6!#6;wxIurDa zgeEnQt0B*M8bylaH8kC_0s){ZX-UUcpi=PUHE4t(I_*N+Mg&_6Gt(3v6KJi{fwxfa zx^BO76?g4@N+K=^5gEYw;3>5EkpIoq6k;W635J_&2(Mv3ZzZA# zSE{Se4RTJKgT%pKff>YM-oucj82MPY@vk1cCZYakOl-ebPgZapspn*ei)$rk^=c$6 z9gAz?f5|O>jzay0S5NPNqcMy4oekhDhdD8B#jM$@JyCo0qipG}F@k;{zEzv!0*>(F zN)laq79aDl4YAujjH`?nU5r}z0Dv7OelIpNb9s2DIL=X=^w-0(S^1RskeiOynf|KHoF;dgR{IrEqTL{UkLY!Zh5O)&40)4nT+!gV&$G70a5#milUSVL2YPne#^3$>*)YIK3twp!WYIjLHo+q(L&2yN(`Vk@SCl2Esj;gofT zFO7PYIkc1kjDpsiHpWhzaV@&$G{8wx)S}gCHJD}{EFf+H{39&nO+vwPEOl()XvM{l zCTsNbVp?Dih#MwV!<0rVU@up6g-h~6UcOK!l z-}qcfcf$YWr8TGl8&}HmJNLz-QugD;{1jC4Z!%N&9Fg$g=4#7L(io>sx}_3+00vZ& z4U#2ok(sOJm&|rw`$Usc(q}#~v@w^;37%0!CIs>1imLhG-Y0Qve}?={?8S*IFz{sw z-ApFY^{|gvu1^?qL!=>{7V{PQEhkHB6kqq~HWQ^ZxG`&aI^o)FUaMg4@#yzYpwXd& z)A9{zeVY?4ihcvou|gEkOZGwt7bt`-7*D85Q8c`6CcI%MHVW^iybCsNO2j2+hq*iv z3wn*<-&(xNZ&gvXkTL1B&S2kL-JS@R&7%J?>&2Zv`|ck72|2P67Xu2l6vA&Q?M8EQ zO*0SJeZIPxSPWVUe+Wo8Ws{omcIFWb_0TMP=W8;u(U|{sRkcBPMe)j(NGrzbZ3a%4 zt`5z%R6f@8P7&Ii^Zg!IvD~jkVtI1?ZN5<6Taoa~QsaL-{rI)^9pXV>WgFkGm-E_* zV-CqAc9A?=1uD};ve1Xwrv_?SLW~5*an9k zNoKN&0d*Ly>4ewC{SN$kJoy_UAsIK@(nYSVN}t=Fg@~^u5`{i8 zu;FfyM&}6$69XDW4U|AfaW{^bpw7#%T)yFQ7hQnGwR>>%RU0F<7NqC27l>VY@KP!J znbY+2xG*z(fv%uA{vi&}8+5>LlXF2%h@!>JyzfKp}1=n z*uY=Pn-{SYbR0y+$;SkDU1hf%`^AOm&)L>(OCa|Ir|x6y;PS`Q>I2MnJyR?7%|imAWl?HveWKV#6)bZui~>Nf%HhZz(iR zc-fQXfI%(iToZQ&(=l%_6)qJ(D!_7FHDpWuSmc{VZjH_jG0ov@^vN4qSN-QaHP(`q z%l5$IL&@|V6#vh3SZ)I4w;aHkEfZ4oq2~D#moF!j%|JuHPe4xb{m4uBQ2wKut@|th z9GvaIt;qjyJXs~HiqvAZGaPSKegBARvAby3EFsbd+go*Mje_x#?u=4bnVL2>%8FZutY{`7zL)z1G{ zGftO2{@<%M{4(uA!hrS)LDiJp$kOb+$mX|cZi(fIJ-hq<^?;;PaKty|Aa*NVbl>mC zcWb%-pW=@C4=UTgjmD(oB_?TNprDg9xhUaHx&0C3e!wKka>-02iO_wU&yhiYTqLLaz(Mb5u?4N^3f_lfNCRv9iwxKF$3|5qNtKB#$2|U#6Y|ku@x0rYhJFP ztE>CO#U-WuLK|Ig!mnib1X8tprOXMWJ?8*9$1DM5I})q#fHyVcs(Yq2oq)8B5w}X&a!pLF3VDh> zkT;^$Q#GE-bx^LOZ~wr5E`0D#H6z^DtGqGPeOXaCJo~_k$(Wg>&(m^yw4br-@SM7) z4D7`l99eT>>-+`9*~4|(T3)81tE$S@#Rjjg5fTa~GBS}}L#7{PcFMpLl1)iW{mM)L zp(CM8dcn!>Ys0g9{J<8A(ICF6i=rLc;nF<~>FjGz){aa`t{%yY`pK~LRSMS2i0a1W z)hl$P3s!V}Yqj_uEFNN*;jMcXJYHOR8f z>kOyH)+BbV#OdAImvWlrgnEM=Uo73)n6QrFsKJd8o(bu^!X* zuh#iD#b)yjR)T>{iHy#j{ifCY#Na?9?)ZPW^kW6=^XkXNP!%8cXqa>$KYPI#%B+|; z+C>9V>NNqkp7#5;^K-G@FdSJl*Sj(%P&a^97_YyS=D8Z!VBK|}<=!3#Vy`*~M{U=J8WBG0&PMI+7j8;$y$armHGZLmqh(T_)9`HB^#?0bokZNC~%%J}8YDCJZL?x+rIFQ+?61IOQfw^yI6tc!Yk+8jyNam6Puq)mWEzDrH+=&Mmq@H5bw^pR z+vZ|=>tskkj`CnJen&z(GxyV^BSW0nfKx$_z}$b+x>7;i&@uD>Om&YKNJ@63sBv)c z!w(ELBZ)gTj4RNGkxM(%(^qKaO#Nr4#(Ov3trhA1x$oPN_?bXI%1bPVb zQRZrhz5X4`td}ViQlNu1*(b}B@_EeTDQjhb;L1Q0UOT`nnGqhq19-zPvRLvT4Gvmy zY>$SQ$KE}C%4Fg^F+p0=gnp2YvnY#`LL;I8lfP;ej4hmIC2u?Uca4ar6?g7f4@s;p z@HF#As!{I7x4&6kEaxZr^{@m~1<W?sa2kZ zg0QQ^_YSmmFxJ&nM<@0p0VTa0S#C$UqY1=kMQL)gb@rY9>*t;tHM`bOub)vk7on1v z@m7S@wO~@u+xujEtk5Dl8=k7L7i-ERBxtOz8J+MnbV~WHokxYAD1F=>j^BlBh zk@4~AU=0yvu0OqY*RqvP@FT#`$$n*Tc4?kpPak&i*Nx5BRV8{ctnN;VI$(n{blqwk ze6l~8G`T}VF57GjH48J|C$AzokNq`|>wT)Zb3yKY7s z*~dqEq7-Bfh&WO%0`VobRJr&KLGgXfa|^0WILA@tuPe1c(brWB*1eTzF5ZwoETU7= zZ>jZG9!M!@vo!KaUiBnuOilgj@~lq0PE2&7aOj~iZ#3<6emnJB#05v!SABM1TIn4L z>=J0|po+|RrP@*oMKzW~po~cl8#spvAoHnaFDp%bOL3r#QW|66L5^d3XXpmeKzv|? zCl?Som*iDM!J>S^@KwnqBJUrA?Tp+}xel5G&_DHIw)`OLUT-JN}k7L}xAG;A4lStdgL(y!z8Awy`^jcsb-(YTizPSa20?m9 zDIlE#LKY92wDyf%m#-4Bu6OEi-Ydbps3RaTge;K3QWsEzJvfWVIM&xdli(pC>x-#&A&*CKX(81< zA%+|`Y;hFD&V!@cQcY%Ft85LFM#N2Y`Z)n9S#3Z@mRjzxW&UVb*^~J#p8k_&7Qi5_ zEd?jwQKuJv=&DEhAFv%q9c8@cD2k;i7(Zr7POyN*pVbv*68na!Q$bE2qiC2>d%tNR zO((|O3shdZ0qC&VeAu(0wdG;E2+!U#l$h==?hu=cPj1_uqgtpX2@Z z5+t0XcJ$Q|dX`h=lfg1=G&eI8LN|fAa7IqLgu5zkJ_IMNE?{?Gf~a<+hd?fm4EyW- zCLS49!ZjI6!YP#&Fz#C4aS)X~qsINUFT9;sSuM`6ILB;)?efhP*T_}P`{ltC4ps+F z&>3H<+0W8Mbg1J~zYyzAd22aWLL1M*OBW##M*^P>cli=Nml(ER!zqOnM8UX~PLJt( z36fkl^id2KqBmBXAx;h4fFCu(s=1n8M<&ELMibTSj@Pk@fA2X%8Aw}iG=aZ9lHAgJ zy~&N`$`F^&NY2qCD*34~)s9=nKaZAzrY;@N2aZ}n#mUDC4u<90d0Mg&BD28tEUQSN zq?kF-)8=cPmaVL9^C#ai4FYO;N8yn~0T0FEG-I({`@i-xd8Z zJ~jg2cp$sba&Dl~kQ%ElA#?9d8%}I%gUD2eTH4r6p{fomdid<9-pLJlK#2+R zrb*^1ZO)cmzx#gXkn4-6($jf2U)k~xd^DU0BzZ|~+?0*4dT3i+Z-`yE>SJF5N5wYe z>LD~6Lw*2`jg zjaPo9&+Y0V=4I8@O)(lYL`Aqpdei5v7tGg_s_$^1ywY$CWsP=rXYdG#9n7lFYm^7M zYgJ9nC+>N_3qQRdF(H{u>(6V6X4L!qQ26Qd6ExY-RPU&!w>Ov#{wXoR@3yBa9eA{U z<4G4f)sSzRe>j|==$0YlL5Tt%m^jUtZ4AsAdMMj4bLQ>EAX9vEga$vtI`gf;n1?U6 zj+xwe27V*vgjbc)T!}*NgQ&g`VxYShF@Knwt3q>mb)Pu?)>FA&k+>xc4S88?=j6|> z6I?bEjDPkLsO?aJ1u>OWM5{`)nq6-WAE5`t28}%cWEXv4))VR4mKkCiXJ9684?YVRMMFCOR)a_YN}{p~f`uyvYZd7ie%!?B9(s|`%GKrhMh6t1O4WB&FNAJI;R zNZZ+$-YXPS7Yz~BxVTl}2wj)UaY0qM_BXUEIYenM0q!YQBb*Zz_4SU29w2R+H!>~a zOBWQ7H>PjzM$fy9z3eEWCbtF(P3x)LNxWvs&DWo+oO`Qx#?#Iy7BG|fi5`&MDQ-Iwrn^qs^XBj8%q&*qY$t;hhbjjL2*m&v^IX`k`GNim zRaLOV{Vf0p|4=zV+q}+euDD;J+BIbKw8lZHV$&FegTC_6m`C&}{3gpV-Bb2Ze71H9 zcEq;WM+vb2XfsVlj|^-JXX`)YPQpKb`8#)#eC%PXnPiDcqNYCPn3;u=YFB))PU2Nr zQND{ty#7+w=rl6|(K6&5fnLut>7k8bdP3zt-mHH1k zUh7iqPFrAbcntq5_3=`MwKKtM!s{;1ML3zLFo)r;7dh^Y2vAW1oMR+s3d z;~$I~M$JAige;`0a7(l9n}UI`al|qAB0@p&SJm=GybR14R>Pvr`=p5@1?l4@_>nN8 z7e(`e%zTwD@rds!^`StPop^R+G5curDW-Q+=KMoOG9EDKGA<1jwrIF9)^OSuz4}~< z#!P+dS5+9}-*!YlO58}7eTXowk}ldh9|GGpFC920vk5FGM8x%<1aA5IOtO&`@&$no^?lmR!T}gPA`4(k$ zGpD<~(rR+p`i948e)*$|H=Fo~q+l{V??@MthSgACF3$X^<*~w8cNQ2xw&E) zAZY7Xhsc$BPGC$d%jV0L>p5;E{4xhy!cEv3@uhRW03(4kL8wR69f* zy5OBwX}e{mJn+KI8G5;WgHML|TeK>*j5_`r5Pt}ZY#b;0K_v2vw^0o+TY*7;!J8nX z3Vlb+9&X|3`Zs(L@h%m8%ZgJGb87vTN3%iiyVBk;37N6)Q*IfFT6ZOUtZvqrF*GDd zy=8*K_wq~KGDH3Eo+2D9o7)eq34`1TeVW=cZKq5iZd$(BT0zEdS5hs5Z}!*rWdt$S zi?ajsH5_U%;BqyE!JPn>XxA|rcBdy1+ooCvGqipr8m9+Y5%9fV*5}t_yPu)Ts2h6- z<%E>xa!YPMT$!(y=DX}Ugm~s74ZhFxE{kQAFv5_~ZK;~TU&txms~SWHUq~HMQ(%}~ z0y9JX8Rt3LYx~f=`JBiBIh9G5h$DCEUV3^tJxZ}~_#^-=aX&BVkVFlJT@BK$%+#~Y zKS=h<>d-QChWOy*gc}(yX%z#u*sy1H-0jUn83VWvzI5}0pJgbEho2aJ0hvtV!?+sh zatq-H-a z8M)9H5#feUq@IwMMwCr#aXwrvioC~f?FbXB&hT3!&8Vl8RSyr^6{t~IGb&ppBq%NA zThO5)GyKqLJRMadex$@*ex7!+qN~};Q*=vunH+7&U8dde3yRj_*Mgn@NkYc;q;@X0 zqC|5NOWi0aJ^iJ=+&u|{q%@l!e6iMpQWI7a41?ZU(CVd`Us+!Ccz~j&G_0DEL;-2FxK~_-V1~0XO0n+2 zpMj~8DL8we1h{fq!Kno%oL7LYDoiUmWoU4dLI7H>$LD@a8VV7hb>#q8@sV;vx7HF+ zwM{8`d@N%~5Sa6n>bE)`72xo>j7&m9xV=iw`|`RDF|atqsD@yO?IV%72s!T}PT>etGvj>#TIv?JB406V#Y3jv+g zeRS=?oXkSNBh$Y9ij5k+X`wCdEV@T@V{EA^O_|S4ixeU_&b{2}uRj;kFZPxu?eFu1 z^fMY->H9xKm-vn)eGQ0wW>BF|s-UG>QEECOo30ZJAs6tFst4a?dWC^4YFU-PD0!#7 z(vU(ftJL(}}d@{*s-)?Rp*cVqpGe_7l$t6^%WjSJa_>*IS%A6DKsd1ytA7 zYqrb(+=HPW^PRwL{xCE5V%=$b@s&ND&wsZ6S)ys&;oSEo;!xneeF_7*w{MvJyukmC z(S`qKak#yH{vXh{sQ)0!yzx7P|@J{$YOs=`Nu0vzk1Omu z^c!=B0s!&c`XJo-U;bOflvK4VhMOIp73G}&`@Z%*`rvWF!d)JRQcTzX?K}UQh~}Zh zn%Fi2J(FIXUK2|J!Mr9hSf$S-2u&TIiBqF|sl2jRfY#0ac{1Jm;>RJa$5YSs4ZKLy zbgKmuY_g5tm7nZ}_hY5qaLrD5<6v~9mR6vCEPNQFnj}lXC*_-uiEt}Z^7tT|5XH?6 z5yi~`)Zm-*;^e7ZG{+iVhsJW~I5IU2$;)%~Umdu5^|`QFb=AE)feFH>4I2=9Ve)`8 z^X{{q1uYLyryzW~0yusvc(dsg60;DG~Hf&$px@~PZ zySiF!jaFYZ)mS&QPj^Sh_0P_yuDuWga=G)l-RT}NNK|O$ZtL83y{q^osiVn6*S1)| zuvFDRts>hF6fNC7d}$^_sLRdY;E4&X)JUGpKOee*sm;B~`4Q6+d&i}|zb`E__;K=% z5dGeAY1x{;J(;~5y5rs9Ut=ydu%zF)F@HExohc!c<{PS=s-D4ukEHi@Y4w*vMsnDZ zOXOFKFX2f14tRT9kdygv*EBjr${MmD(6l&BOv{;nH^O|oWY=qSDa2N7Gu_p17}F+O zo5{A_)IzXM!<+cFMz-sER~$lSYi6`I)qkYo?)7HhUzyvZxi=g~Qgb%)Cvv_$15DVC zc50^lj^hi^ID-qrAVyGHq$xS;<f$IifRr5VC&e~OGw};oj%2^5)9pT7o0!h8 zU4IdRU$388SWE3*yOre23dP3w-w&XR`*)Cn)9li#d(j#2sH0uXyXa%!>3{v~9ld%= zK|<}XAxL&nU}YQOg8CWeKzp{^+@e*eVL&^Hn?G-@WKQDLSk~H3v;}_v_cYp{2}0Bs z?^y7|-7UR6bxPxCak&d~75NT|3&15%nH;jaO-;rpUe=WMLK`%qYBNvl*2YLePT^eDcx)i`8i=hjC38$ICoKMz!qQ?P5$We44=V9ak}rR!Nzc;TwXhfC z?6`K8I#lA-n#;IMPfEaWdy=0*NKR;lZY5^8=l22gQRHkXv;P`8Xf-IdPH6m|;d3+2 zm#wd=mu%nWR_bF(zn5aP_}E2wBEQ{ud5=YBP~KTl%}WMed5}*tab1zaB4zkt4uDip zeuJcMJsDl24rwPVBCWXsxF_E?Lpw-CipTInmzTXg+SQ5yB&XAT#(41UIgx6zlo{tq zIW9Y+qkkj~5lW|{%Tsrwk0ZYKm78rWXt`P}t}UA%4#o6l?-t%{k7i6m-_>UJ&<|ddYbD>>bBYrL=idHhwh^gJ9RIcu_!qEy~Fp9_MvXD=r)<@>`Rln5k=#nhp^9TL^IFx6A3_#K4%8}?{ z$;`_6v}bGKBNt(m&HzvA44GBXWQp{vs*5@)O0B;UWRb2Yw7)y8C0a?`W#>ZS^jDG2 z-HH{rPSt!=ANf+!h^Bx;jYXf1R1(@`&3Gv(ZIJ1oh~9=1IlC~&C3LfuGID4aohUvu zTr^@mvZZC1^u;1SrIovXfBct~kN&RI?3&W%(GKeIlbnchcZ~8d+aLsi!c1aHo$;$; zu(FTW6ww5Ot}eqjWdd&XJ}Yz8I!5i_CrcJP-Uj-2#&%q}B{uEtpsH(xR5$b3Hb_h_ zyA=d3T0(M;OfWzIg;Hbw6&~OI)vBmUG_tGnA5?9aumf)p{`p7XSW^$A z2~~4-)qnYM8At%o=<;HSXUo9|OvasqR!;!XrHBb9XVX|rio~7bqU6$(qot++5KhTz zNIvhk7k$TqhQvX?HNZ+LG$ZzpSLUTWXcl|$hH@U@FCdi zb(#x^NRfqLgEN~5DE-;yhIL(E%NxBpKT)LqZUtu-;Ip-+C^!7d^V?3H0dh7a5cz2X z?Y#JvJ^eOAPOZ1ZLJP%|5nBKY<^03r=l*omfs@Dl8`W+yGM!v^UPYQ%J!zY3Cr{aO zr8yZmg-^G;WLv>6(>5b@&FjxQdc3w;!&+4q(%!pI(9+J~^SXy@m2SBPmD)^rPj(ra z(;7i>7naI<-&FRU@Bnw>p7WnPL9V3BgYy&_{wauz`nZIvDD2t~_W zp#;4ZJBisvNj?AQ`ZwxU)8*>9iLO*gjUEKg+m)95sX@r3bDT7$cgean0A-^`D5xpTKIAVaTf_wsp9wA1C{@bK#GaiGx@ z1;Q0D4`ERN35)0Xx1(2(%SN@?4II~pNZ8@54muIa^^^M$F zs3@LYH}YMZgv_w!6XitvL{I|E$VvBL_FD!h#x5f*gqa5No_iD=wBE7_VT&!1Mc)5w z=s)j!^YJj{d(Qkq>CkrbQkxK?V@TWtzw|nU6;pO&{JpQE4O86%zWB80k)xgUsC%Y1 zDG7J3*p3uUxjaEX2!Pn+%ywS`(?xSKqigaBgYQu%!c*89}&!r_~0=KnR1nt(5N==OVM>D)2E8 ztXY+Y?VUhNJ;Qd&QILK*?)@=ikm70gdqCFqYZe@Gm7vJs$bdMW~@cYWETS(xtERvFX zsnX|=^uIZ>o{_ruBr!B4DX z6K6YQO*Y9U6Lb>{l0Rqkkk(yM{2$mTP!vFO{ucdo-^bgVeu$_hjI*g;i3C}RkUJy5 z_$&Nk_yLl6`L9(IEIR{sEnbG`ptt!vPDzhwGN&Q5gXL!Px$Mcb|{m;U2$W;Mb&Ls^qBu)R{meA+exJ-f&ar{*%ASlm{r-mMov`Tgz zBpmc8FB&Z8RwWwL6&ep>%(qwnkV#I#-(6sS-_PH5IM>VkZsI$!sSst$1XT$=|FW_N z^lPNqqY?Fi757WqUztru4hlmsPQ=zXH=C?Hp_MbMCBEXrC3W2TQoM1BmXw5krBc?^ z>N);H6pfyY=1tg)@Ah}`vfL2#0}<(_29IwsiX%TSwCN%EYl+{Z?%oVVwQG!}{0xwNS zp@Pq60$XZFWxyqBo4 z!X=y{x(V$r%`PN{j2wy0(CnWZ? zS=yu%{wTHcANVbDm-v!sUYM7fF9|v9e%>LZLU?K68h;h2`WKfUYLXQLAP`Z7`;C zAkG}yCWb9P@QxQ$cH!0$QjQABzI}VzhPk0c_Bamo-&$M#+z(;iDF=?M065?`c{QW% z@LZu!b(@n&=-^VD2!)$yXYJt2Do=(5?H#ZtOLpmF!piA)C4|a4Ryl4Oo1JVI?{*QM ze_y@@w%`w?Kj<$96GvB|N!KK;L!;rw+i=0lH3sPq_x4xgdR8T@+1Q{q>$-%pz-6iP zn+C0I6(fUotaku{7v~ESqMz^7?IG2{2U{OB7|ir?`$O zKKb3pCKZtEBb9P$INK*8TH3R^!(gD_1h#Q2R_`2@%dly{yBuU&L*BWp(R@1ZQ|z2* zv~I$?%#PDdi5gBeQK{&07)Zt|ukpg}Q$u62K`64w>EVaB6^u+`Zg*J=Z_F6t+3bip zhi;2KsC=(Gjt$0KA>@b=gNt*t;pSJ2{YGty*a0RI<>3(f(Yvl?Q6K(^!aaW699t>8 zOVf@e!~332y#y~OtZ>ljb)rkQY|`j5dTm#a61`ElhS~k_FW+~cjQbWTlDmj%U0u9u zi+%%fV)rnWM@#W^Y<KJg>__U8%4D!}1!9t=ln$gNSW0G#x?znI3iuGIZY&pg-UFc{&sFD|YJ%9~aKs9j~MQeAQF!)BmzUNB`YU{x6H^lKM#8?CFaV zk}lxPn{?bS4(Jr{cY}Tl#(ImLrl})bDUkQ?VdMHAsd8VRk+fscsFz^(H9KvWAg`<} zb?%u{c%3gVDSttCT+!da=uRdNslbU#rxJRr^8!>j?G1LL9ZT};w$98J%QIalO#mP( z>yJIZ1$>LJ(<@q<{opz$nxCORi9zO9PyTuJbk{$0O7=Z?AUs?@Q-6q52hM*PS=i9` zdWKBOsjc-I1-Y+=HX^Lz6mOjJc?qhO6Ln2&#*+ZmvgS=pWH!HudA#$WpQJK`}pc~l|i z8L7LP+VEs%^$1BD!4p&v@(M$PB9N$f&aW($^_e3w7D6U%vqxYXjLp7)i)4io8#w&Ed`RWYR#n&CgZ+wUX>Zdmwl475Wr&J#*dk8?LMmX?!S^0s%@zDtslsBIPfWlL+6Tz9*? zYqE#M`~D3RvpowU>h;DbF8N4_~c9QUlAUxp~Hs-R>X*Dzz+8UFdT&!!*>TKGjp>Y0>hkYp+l)$AMHB)^p|?qPr@?#DTM31lQ{_g&jwU8 zPDzY6dq2OLELSon>b)?8NO|7w1KP4r5!4LrpLgZX(n!!`uUcuYk9y%9DW`iqL0qNB zVg<*T>f2T+`7h!bZcW&oiVR{IS83wwAbG%L2_%p(l9QOtaBYj=muZ>4yXO_seav&} zE#b9U*$nK^&87-r&<5>r;`{QOT>Y%`1NT4iAIBNvIe@6F^3u+#d#TC!xZ7BhH8a5O z;=N9El@-EH(bHK6-^NawOJ2H0665PyB5A$FzL@R<{o%saCe>Krrj^y0srL6>womoN zCfMQ@@pMHxD0{KV2SiZ2WyB@7KU%k5#w(0gge0hjR7Zix%9m84r`sxvN&G(4>RIBn zULAg@nw*{G!o22aP{1h$AEO_F;i&w9rxeGkW9>vXXF$ll+nG@QJEir$6U|le|D4mm z_l+I{CkdCrBA4F3$!rkewMOs^m*i?o#eCdQ4Q(UbKT^}veNuZ*I)b1Vnk9hwxbrxw z%Hf3)(|O!VCK*8D!aQ5kcYZ?Z~8Dxn0;E&Xdsv?L(^Xl-$e3-Li z0(p~W2zkxTBw&o+!!9NR`+DfAiX_Z;E;=;DMTZ)c#8l>3jn(-#r39Uuuz0sOx2jEI ztOtwco(!F2M7^02G~YKf}eg067r* zX=AOlUbAt^~{%@vk-93 zqcD+YYAwUw`L})YS;2Gsrq1X9JM+Ql{c)=C8WTH=mG8;Ek!OTc;cKAvouj$#v^cWu z{t*R8Q+WvvxS6QlS=W=Qn7X*|4+HK?zH$gwfGkL-bH(R_hb>%uk=L}#PPZPn zH9sCiG+wxG>~qQE+W~$VhoVxafhhrZ67uzXGbdB+Gi79l(F;%8lLJ0T-HsU7d;a~c zXC2&VH|&=~$mfBN?D8>X)pfMGxt(D2cFP}dtr7OODx53a9dTq{k5%25&G&`QFtwCq zX{L?K!h@*qChL*n&U;;OyX-l2-K`EHKhZzxcN=!EE~|tdQgXE$_x09iACoHWGbq1T zLTKMA=PHTBot?aj%sh4U+=uszp@!S`p;mmQ;6Y-F=0yLW{`N3|(=F+7Pj~QNH-GA} zJSGC++#1f#B>ml#Q>M+?>n@%h6;75+&(9-+qD(%s=3X}wobY|s5Ir+(Q+KMV+4i7F zRC63EFKR|B72Ob&$Q~Mf*#|Zi5VjI4l{~uLv*|2-+<^+|zZV@UX&LMb8ZKANA5*VV zCetg=@uH#T(Hfi()s#l-Z+TTS@2|n{sIPWSZ2T;2;gVF3DEubgS5PP7u(AA*yCLz97pX!WhA^=dg2w4tNt)*FQJIrh_paq++3t>bUc^~K?bP|)ysdJ%Ob1f``Otl>9{yeHOcvT zyVR_N_GTYyiBQGrwUAqinz)R3G*+0I20>YvZF|NIRph$V{bb-h8Eqq2>;`a{Z*45! zsS65Li$%z-W%VLCix!KOE%xp08|53FJpsDNOPV%TXsE7qV2PyFqG@!ki5h&N$fQfVW9O0WS_gaRNxi9H zTuA%i{S>y2Bch`gf7Wh&C*B@Oo$utAlSV1dy;2;J)L4S|uJ$+&?pO?a_u0B+_wfKW22yJwt^xd{gsuEtao{y{FNnp%|n6RoOZ|66Ond=u)RN3F#BS#>IqJ!Cu)?z!_R^Hqx`(A2lsPn?;@aa|5hEK*s z?}p`dAtTsdG81||e8(bHAs&APX1cit&d0r%EBm;zRA+u-ToValU@c@XYqX5yzX}EA zp7RN`v8^?9$vuri-~s^O7Ug2)q=A9%(pyRJrrEXwg{xiJUkYAs5%l{4c|I;;NQE=+ zH2AS+{#sF{G-G(dU&_2o*>195!gl3kF-DiCaS>I__($xv&8AE!akJ`N7>RyTgijp( zOzqR^OIb&XrTnG**PZdN7>;!o?ptGVeoJZKmf5b%8AetG^Hxh2WWk-uz4^RX6K?TM z%L6C8A zFw9c0UDJf`ua@TJBydv|1M&)XTsmSpoc)qy#NY8v)yYmlVOs?}(!WzJ9RWfYON$hh z_ceFCfNwMP3&);F$U&{BvG$uQ`rp!$}sy>+95hZav zW^*OH{bN~+cOAu^y~JbRF6dNp@HM`@$!kL=zS*HmEdQj~<{MH^MF^+^>k>R##;~nc zpt5oG=J=PL%y>us<^;@i=9-f&p#W{IZnk;M3Y-_Ul3#L0k8QwUsrcnkt|3=`zB~EJgV-g?K}6wZOyEPQPn(#~LRZ$L^XAywsd}M*Y`HCmhDEul zbjf1q@;%S->g(KpWC2|MS>MEc@qeRdSEnp=YiUy4p-6!Lvaj2m)ZhOIU7o49XOW|~ zgU?y49QWO~FF5TdSaSO7(Stv=jP@D-lRo-?qh}Ag3*QD+o6inc%DcL{F4pArVj;OB zsHM)hAl`kOb>(!V6jylj9ed?CwG8&E=aUWt1%AzhwxzAJS4VbM z%V7-l?d3j8PS`P#Zw#&7Kmu3Byb#)zI$J!gvS;|KSA~weH!TrA5-?DZz9F!0+5Fie z;?XbDQDQ)QN}lb)E6CP4`daPUo#5bL!uBfFiz`&@#25}CFiE_JZB?{P3wF zzkO58RTfqJlXhg=+9uCWEO1#PY=2gFmO;`tI?B9-tHxl@S-qGJ*te}`YHC`$$9J*M zbM;qj&G(e^bx}!Ly8$*==g8~T==FF)DcsfFJ)+Ww@tfH%Q}LRsh0zn%d+*-|H7Xe5 zHF>SJatrb*I%q1|p34KdNUojcDswK(V0Tm5KhI~MKVPt5J?z?P-+hthzF8hH7mntS zhxmEX|K3xU9iNiU_%)$9*Mm4By!LmS*o?mk*RMk^{o4wih~V~0(7N0svZ|`;2So?> z9uA$U2Z*_H4J4IMxK_Kf0{;>xljJbjk+5;%$35;l9q=pGHwS|Oa0P%9Dptr{Ez8sL z_I+6f|Ne&Lo}Bxi?1xHRdIkpGm;e0W=g&WhYq@`MHwD&1Stap^cC7&D55we(Z(7Zw zRyr-V;z!z7O;KuGTyn21%W(UmlDL{X10|SFv3JAF(wSt1z4!(u|a(!3XeV`x+yX*X4Oq{(X@T2|P z+W&0)IeBk($|0AhPG5U;m%e}B_TYyg8v69lG^Ncm{QpQnKKM_<_y6YE@?Qo?N=+Yb zuwTSVnKyIQ$?bbSb~$l!w`qEmyJ<$0X*XeE;UYE{7$+=f+n`wC4vXK1e)Lwp3S24M zzIJ)d2fBGF1(nworfc8yZ(44^Ej@Yt2pU({pS4WRPrlI zh>e9KU70dJ3ZvgU8OkZg#^ernNU5e8CbvdrHibj6sqR{dt)`Zdxx+T*HY_$~ZTHNk z>yLZA?)mHU$Md{i-|y$g`~7}B-_P@W+REcRJf_n}iuVq|DjwM4e;7h>r&3g%*jngv zR>*Go?C@YWb$KU&Pm~iH4RPHjn3kUvsL*KzQ<9R$tx= zbAy}WdFzZS3WXxh9E$|z!a=INLFLK2aguAioavQVx?g1HCcA}bzeh@C!PY zpg3UY+i%Zu>{CTf1Q?q3Og-cv2(+nBw^xj`7QqH-b&X6-fbmT**skin^gWC`wWZ7#-+m%dp zp?U@rTaYJ+HG9iJTS0tHbKP^!)ucyuLTTPZZSBh>CS4pn!=UD=o z#L8wgxSr~~jG^Me(ha z&uuEYI16FXgZtF?J;4t&K#an!5se`~10dGu*pv!31yHT4$oS-o8&0gHG}-q!w_UqN z_JV8-8ciU|Zij>5H0H~OnpJgF>gE2#sLW1qZNa(>w^|k03|0;8e$1FIv{n8MtqF#0 zL9{xt>**%ovzW}run5@^L&95f+BTY!Pi=%-54<0#%<7TT)T*SDKIxt|1I@I|KWv4> z`RZZ6+%|WMw2|V~l!tLWRZ4QW`2eVUrmy_31r@7zR%Mn#-aIH-3rdv~;&3=LwRTz* zA(CGZ_pK%Dz0Azz8)T`H4$>qLTxlr*Ao;;@&;#Mb!VC9NOWmKW^z_zz?EU{=D>+{z z5@|S)raKn;*nVO7-tBGg!=SY^ns<@;JRIN|YXOUX zs71@Z9a%u799yOyzHyF^Q9r!(R&$UHcH= z2HE{5bj5iMCPcd>{}8=H#Ri1l#vRAM2@MYyptMgoPc9Ef`53|=Qy^Sm7Hc$Wk#iZA>cp=+k~b$UNJ)UH{WRJzOY!@!9tH`>z5W%6{t% zH%)i&eAEi4%X;&9lK`>#<$yQh_`Z@|pH0fBnVx34F{gT?sLyJ>kZhtgVa&dw2%zgm z$6yB>Aw<_0tZ-g*^`0e<>~ipE>GQi}a^WwlZ3H^$>Ri7({NL0#Kh9x%kYlWKO)T-2 zT5!v{=wII%_vY Date: Sat, 7 Mar 2020 16:23:51 -0800 Subject: [PATCH 12/34] Update gantt.md --- docs/gantt.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/gantt.md b/docs/gantt.md index 5fc40436e..3cae0f4ac 100755 --- a/docs/gantt.md +++ b/docs/gantt.md @@ -6,10 +6,10 @@ Gannt Charts will record each scheduled task as one continuous bar that extends from the left to the right. The lower axis represents time and the right records the different tasks and their order. It is important to remember that when a date, day or collection of dates are "excluded", the Gannt Chart will accomodate those changes by extending another day, towards the right, not by creating a gap inside the task. - As shown here [excluded dates without](https://github.com/NeilCuzon/mermaid/blob/develop/docs/img/Gantt-excluded-days-within.png) + As shown here ![](https://github.com/NeilCuzon/mermaid/blob/develop/docs/img/Gantt-excluded-days-within.png) However, if the excluded date/s is between two tasks that are set to start consecutively, the excluded dates will be skipped graphically and left blank, and the following task will begin after the end of the excluded date/s. - As shown here [excluded dates between](.docs/img/Gantt-long-weekend-look.png) + As shown here ![](https://github.com/NeilCuzon/mermaid/blob/develop/docs/img/Gantt-long-weekend-look.png) Thus, it is useful for tracking the amount of time it would take before a project is finished, but it can also be used to graphically represent "non-working days. From fdaf13bdc4b80545a2b87ca87bebb5370ea91ce2 Mon Sep 17 00:00:00 2001 From: Neil Cuzon <58763315+NeilCuzon@users.noreply.github.com> Date: Sat, 7 Mar 2020 16:26:22 -0800 Subject: [PATCH 13/34] Update gantt.md --- docs/gantt.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/gantt.md b/docs/gantt.md index 3cae0f4ac..b57b933c6 100755 --- a/docs/gantt.md +++ b/docs/gantt.md @@ -3,7 +3,7 @@ > A Gantt chart is a type of bar chart, first developed by Karol Adamiecki in 1896, and independently by Henry Gantt in the 1910s, that illustrates a project schedule and the amount of time it would take for any one project to finish. Gantt charts illustrate number of days between the start and finish dates of the terminal elements and summary elements of a project. ## A note to users - Gannt Charts will record each scheduled task as one continuous bar that extends from the left to the right. The lower axis represents time and the right records the different tasks and their order. + Gannt Charts will record each scheduled task as one continuous bar that extends from the left to the right. The x axis represents time and the y records the different tasks and the order in which they are to be completed. It is important to remember that when a date, day or collection of dates are "excluded", the Gannt Chart will accomodate those changes by extending another day, towards the right, not by creating a gap inside the task. As shown here ![](https://github.com/NeilCuzon/mermaid/blob/develop/docs/img/Gantt-excluded-days-within.png) From e90ed7a85329168f610d18f06ec2cddbfbb8e7fd Mon Sep 17 00:00:00 2001 From: Neil Cuzon <58763315+NeilCuzon@users.noreply.github.com> Date: Sat, 7 Mar 2020 16:46:59 -0800 Subject: [PATCH 14/34] Update gantt.md --- docs/gantt.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/gantt.md b/docs/gantt.md index b57b933c6..321bb5712 100755 --- a/docs/gantt.md +++ b/docs/gantt.md @@ -5,13 +5,13 @@ ## A note to users Gannt Charts will record each scheduled task as one continuous bar that extends from the left to the right. The x axis represents time and the y records the different tasks and the order in which they are to be completed. - It is important to remember that when a date, day or collection of dates are "excluded", the Gannt Chart will accomodate those changes by extending another day, towards the right, not by creating a gap inside the task. + It is important to remember that when a date, day or collection of dates specific to a task are "excluded", the Gannt Chart will accomodate those changes by extending an equal number of day, towards the right, not by creating a gap inside the task. As shown here ![](https://github.com/NeilCuzon/mermaid/blob/develop/docs/img/Gantt-excluded-days-within.png) However, if the excluded date/s is between two tasks that are set to start consecutively, the excluded dates will be skipped graphically and left blank, and the following task will begin after the end of the excluded date/s. As shown here ![](https://github.com/NeilCuzon/mermaid/blob/develop/docs/img/Gantt-long-weekend-look.png) - Thus, it is useful for tracking the amount of time it would take before a project is finished, but it can also be used to graphically represent "non-working days. + A Gantt chart is useful for tracking the amount of time it would take before a project is finished, but it can also be used to graphically represent "non-working days, with a few tweaks. Mermaid can render Gantt diagrams as SVG, PNG or a MarkDown link that can be pasted into docs. From df88300e6e9c25179893c40b4b3f7fbcd0d415f2 Mon Sep 17 00:00:00 2001 From: Neil Cuzon <58763315+NeilCuzon@users.noreply.github.com> Date: Sat, 7 Mar 2020 16:50:39 -0800 Subject: [PATCH 15/34] Update README.md --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 22151a6f2..4e3f71c02 100644 --- a/docs/README.md +++ b/docs/README.md @@ -9,7 +9,7 @@ It is a simple markdown-inspired, script language for diagramming and charting that can be deployed via Javascipt. -The reasoning behind it's inception was a need for simplified documentation and frustration with heavy and time consuming tools like Visio, for explaining code. +The reasoning behind it's inception was a need for simplified documentation and frustration with heavy and time consuming tools for explaining code, like Visio. Thus mermaid was created to make the process of diagramming and charting, as simple and as close to markdown, as possible. From d3b69abd87941bf9f53bff70fadca0c02ea1e0f5 Mon Sep 17 00:00:00 2001 From: Neil Cuzon <58763315+NeilCuzon@users.noreply.github.com> Date: Sat, 7 Mar 2020 16:54:49 -0800 Subject: [PATCH 16/34] Update gantt.md --- docs/gantt.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/gantt.md b/docs/gantt.md index 321bb5712..542f3a43e 100755 --- a/docs/gantt.md +++ b/docs/gantt.md @@ -45,7 +45,8 @@ gantt dateFormat :YYYY-MM-DD title :Adding GANTT diagram functionality to mermaid - excludes :excludes the named objects from being charted. Accepts specific dates in YY-MM-DD format, days of the week ("sunday") or "weekends", but not the word "weekdays". + excludes :excludes the named dates/days from being included in a charted task.. + (Accepts specific dates in YYYY-MM-DD format, days of the week ("sunday") or "weekends", but not the word "weekdays".) section A section Completed task :done, des1, 2014-01-06,2014-01-08 Active task :active, des2, 2014-01-09, 3d From b0852222530fc441ca9402399ad4ac5147ed4540 Mon Sep 17 00:00:00 2001 From: Neil Cuzon <58763315+NeilCuzon@users.noreply.github.com> Date: Mon, 9 Mar 2020 22:55:03 -0700 Subject: [PATCH 17/34] Delete README.md --- docs/README.md | 239 ------------------------------------------------- 1 file changed, 239 deletions(-) delete mode 100644 docs/README.md diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 4e3f71c02..000000000 --- a/docs/README.md +++ /dev/null @@ -1,239 +0,0 @@ -# Mermaid - -[![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid) -[![Coverage Status](https://coveralls.io/repos/github/knsv/mermaid/badge.svg?branch=master)](https://coveralls.io/github/knsv/mermaid?branch=master) -[![Join the chat at https://gitter.im/knsv/mermaid](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/knsv/mermaid?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - -![banner](./img/header.png) -# What is mermaid? - -It is a simple markdown-inspired, script language for diagramming and charting that can be deployed via Javascipt. - -The reasoning behind it's inception was a need for simplified documentation and frustration with heavy and time consuming tools for explaining code, like Visio. - -Thus mermaid was created to make the process of diagramming and charting, as simple and as close to markdown, as possible. - -Check out the list of [Integrations and Usages of Mermaid](./integrations.md) -For the uninitiated, you can also try out our [live editor](https://mermaid-js.github.io/mermaid-live-editor/) and look at our [documentation](https://mermaid-js.github.io/mermaid/#/n00b-overview) for a deeper understanding of the tool itself, more importantly don't forget to have fun. - -**Mermaid was nominated and won the JS Open Source Awards (2019) in the category "The most exciting use of technology"!!! Thanks to all involved, people committing pull requests, people answering questions and special thanks to Tyler Long who is helping me maintain the project.** - -## New diagrams in 8.4 - -With version 8.4 class diagrams have got some new features, bug fixes and documentation. Another new feature in 8.4 is the new diagram type, state diagrams. - -![Image show the two new diagram types](./img/new-diagrams.png) - -## Special note regarding version 8.2 - -In version 8.2 a security improvement was introduced. A securityLevel configuration was introduced which sets the level of trust to be used on the parsed diagrams. - -- **true**: (default) tags in text are encoded, click functionality is disabled -- false: tags in text are allowed, click functionality is enabled - -Closed issues: - -⚠️ **Note** : This changes the default behaviour of mermaid so that after upgrade to 8.2, if the securityLevel is not configured, tags in flowcharts are encoded as tags and clicking is prohibited. - -If your application is taking resposibility for the diagram source security you can set the securityLevel accordingly. By doing this clicks and tags are again allowed. - -```javascript -mermaidAPI.initialize({ - securityLevel: 'loose' -}); -``` - -**🖖 Keep a steady pulse: mermaid needs more Collaborators [#866](https://github.com/k3nsv/mermaid/issues/866)** - -## The following are examples of Diagrams that mermaid can make: - -### Flowchart - -``` -graph TD; - A-->B; - A-->C; - B-->D; - C-->D; -``` - -![Flowchart](./img/flow.png) - -### Sequence diagram - -``` -sequenceDiagram - participant Alice - participant Bob - Alice->>John: Hello John, how are you? - loop Healthcheck - John->>John: Fight against hypochondria - end - Note right of John: Rational thoughts
prevail! - John-->>Alice: Great! - John->>Bob: How about you? - Bob-->>John: Jolly good! -``` - -![Sequence diagram](./img/sequence.png) - -### Gantt diagram - -``` -gantt -dateFormat YYYY-MM-DD -title Adding GANTT diagram to mermaid -excludes weekdays 2014-01-10 - -section A section -Completed task :done, des1, 2014-01-06,2014-01-08 -Active task :active, des2, 2014-01-09, 3d -Future task : des3, after des2, 5d -Future task2 : des4, after des3, 5d -``` - -![Gantt diagram](./img/gantt.png) - -### Class diagram - :exclamation: experimental - -``` -classDiagram -Class01 <|-- AveryLongClass : Cool -Class03 *-- Class04 -Class05 o-- Class06 -Class07 .. Class08 -Class09 --> C2 : Where am i? -Class09 --* C3 -Class09 --|> Class07 -Class07 : equals() -Class07 : Object[] elementData -Class01 : size() -Class01 : int chimp -Class01 : int gorilla -Class08 <--> C2: Cool label -``` - -![Class diagram](./img/class.png) - -### Git graph - :exclamation: experimental - -``` -gitGraph: -options -{ - "nodeSpacing": 150, - "nodeRadius": 10 -} -end -commit -branch newbranch -checkout newbranch -commit -commit -checkout master -commit -commit -merge newbranch - -``` - -![Git graph](./img/git.png) - -## Installation - -### CDN - -``` -https://unpkg.com/mermaid@/dist/ -``` - -Replace `` with expected version number. - -Example: https://unpkg.com/mermaid@7.1.0/dist/ - -### Node.js - -``` -yarn add mermaid -``` - -## Documentation - -https://mermaidjs.github.io - -## Sibling projects - -- [mermaid CLI](https://github.com/mermaidjs/mermaid.cli) -- [mermaid live editor](https://github.com/mermaidjs/mermaid-live-editor) -- [mermaid webpack demo](https://github.com/mermaidjs/mermaid-webpack-demo) -- [mermaid Parcel demo](https://github.com/mermaidjs/mermaid-parcel-demo) - -## Request for assistance - -Things are piling up and I have a hard time keeping up. To remedy this -it would be great if we could form a core team of developers to cooperate -with the future development of mermaid. - -As part of this team you would get write access to the repository and would -represent the project when answering questions and issues. - -Together we could continue the work with things like: - -- Adding more types of diagrams like mindmaps, ert diagrams, etc. -- Improving existing diagrams - -Don't hesitate to contact me if you want to get involved. - -## For contributors - -### Setup - -``` -yarn install -``` - -### Build - -``` -yarn build:watch -``` - -### Lint - -``` -yarn lint -``` - -We use [eslint](https://eslint.org/). -We recommend you installing [editor plugins](https://eslint.org/docs/user-guide/integrations) so you can get real time lint result. - -### Test - -``` -yarn test -``` -Manual test in browser: open `dist/index.html` - -### Release - -For those who have the permission to do so: - -Update version number in `package.json`. - -``` -npm publish -``` - -Command above generates files into the `dist` folder and publishes them to npmjs.org. - -## Credits - -Many thanks to the [d3](http://d3js.org/) and [dagre-d3](https://github.com/cpettitt/dagre-d3) projects for providing the graphical layout and drawing libraries! - -Thanks also to the [js-sequence-diagram](http://bramp.github.io/js-sequence-diagrams) project for usage of the grammar for the sequence diagrams. Thanks to Jessica Peter for inspiration and starting point for gantt rendering. - -_Mermaid was created by Knut Sveidqvist for easier documentation._ - -_[Tyler Long](https://github.com/tylerlong) has became a collaborator since April 2017._ - -Here is the full list of the projects [contributors](https://github.com/knsv/mermaid/graphs/contributors). From 71cfec91afbfdf1223a28d029a82568c841201df Mon Sep 17 00:00:00 2001 From: Neil Cuzon <58763315+NeilCuzon@users.noreply.github.com> Date: Mon, 9 Mar 2020 23:02:14 -0700 Subject: [PATCH 18/34] Update README.md --- README.md | 344 +++++++++++++++++++++++++++++------------------------- 1 file changed, 187 insertions(+), 157 deletions(-) diff --git a/README.md b/README.md index 781cee7e1..791ac115c 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,29 @@ - -| :mega: :mega: :mega: | -| :----: | -| * If you're upgrading from a version __< v8.2.0__, there are [non-backward-compatible changes](http://mermaid-js.github.io/mermaid/#/usage?id=to-enable-click-event-and-tags-in-nodes) related to security issues. Default behaviour of the library might have changed for your implementation.| - -# mermaid [![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid) [![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid) [![Coverage Status](https://coveralls.io/repos/github/mermaid-js/mermaid/badge.svg?branch=master)](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) [![This project is using Percy.io for visual regression testing.](https://percy.io/static/images/percy-badge.svg)](https://percy.io/Mermaid/mermaid) +# Mermaid - -__mermaid is a Javascript based diagramming and charting tool. It generates diagrams flowcharts and more, using markdown-inspired text for ease and speed.__ +[![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid) +[![Coverage Status](https://coveralls.io/repos/github/knsv/mermaid/badge.svg?branch=master)](https://coveralls.io/github/knsv/mermaid?branch=master) +[![Join the chat at https://gitter.im/knsv/mermaid](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/knsv/mermaid?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -Check out the list of [Integrations and Usages of Mermaid](https://github.com/mermaid-js/mermaid/blob/develop/docs/integrations.md) +![banner](./img/header.png) +# What is mermaid? -For more information and help in getting started, please view our [documentation](http://mermaid-js.github.io/mermaid/) and start simplifying yours. Alternatively, you can also play with our [live editor](https://mermaidjs.github.io/mermaid-live-editor/). - +It is a simple markdown-inspired, script language for diagramming and charting that can be deployed via Javascipt. -:trophy: **Mermaid was nominated and won the [JS Open Source Awards (2019)](https://osawards.com/javascript/#nominees) in the category "The most exciting use of technology"!!! Thanks to all involved, people committing pull requests, people answering questions and special thanks to Tyler Long who is helping me maintain the project.** +The reasoning behind it's inception was a need for simplified documentation and frustration with heavy and time consuming tools for explaining code, like Visio. + +Thus mermaid was created to make the process of diagramming and charting, as simple and as close to markdown, as possible. + +Check out the list of [Integrations and Usages of Mermaid](./integrations.md) +For the uninitiated, you can also try out our [live editor](https://mermaid-js.github.io/mermaid-live-editor/) and look at our [documentation](https://mermaid-js.github.io/mermaid/#/n00b-overview) for a deeper understanding of the tool itself, more importantly don't forget to have fun. + +**Mermaid was nominated and won the JS Open Source Awards (2019) in the category "The most exciting use of technology"!!! Thanks to all involved, people committing pull requests, people answering questions and special thanks to Tyler Long who is helping me maintain the project.** ## New diagrams in 8.4 With version 8.4 class diagrams have got some new features, bug fixes and documentation. Another new feature in 8.4 is the new diagram type, state diagrams. -![Image show the two new diagram types](.docs/img/new-diagrams.png) +![Image show the two new diagram types](./img/new-diagrams.png) ## Special note regarding version 8.2 @@ -41,82 +44,64 @@ mermaidAPI.initialize({ }); ``` -For more information and help in getting started, please view our [documentation](http://mermaid-js.github.io/mermaid/) and start simplifying yours. Play with our [live editor](https://mermaidjs.github.io/mermaid-live-editor/) or jump straight to the [installation and usage](http://mermaid-js.github.io/mermaid/#/usage). - +**🖖 Keep a steady pulse: mermaid needs more Collaborators [#866](https://github.com/k3nsv/mermaid/issues/866)** -__The following are some examples of the diagrams, charts and graphs that can be made using mermaid and the Markdown-inspired text specific to it. Click here jump into the [text syntax](https://mermaid-js.github.io/mermaid/#/n00b-syntaxReference).__ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Flow
- [docs - live editor] -
-graph TD
-A[Hard] -->|Text| B(Round)
-B --> C{Decision}
-C -->|One| D[Result 1]
-C -->|Two| E[Result 2]
-    
- -
- Sequence
- [docs - live editor] -
+## The following are examples of Diagrams that mermaid can make:
+
+### Flowchart
+
+```
+graph TD;
+    A-->B;
+    A-->C;
+    B-->D;
+    C-->D;
+```
+
+![Flowchart](./img/flow.png)
+
+### Sequence diagram
+
+```
 sequenceDiagram
-Alice->>John: Hello John, how are you?
-loop Healthcheck
-    John->>John: Fight against hypochondria
-end
-Note right of John: Rational thoughts!
-John-->>Alice: Great!
-John->>Bob: How about you?
-Bob-->>John: Jolly good!
-    
- -
- Gantt
- [docs - live editor] -
+    participant Alice
+    participant Bob
+    Alice->>John: Hello John, how are you?
+    loop Healthcheck
+        John->>John: Fight against hypochondria
+    end
+    Note right of John: Rational thoughts 
prevail! + John-->>Alice: Great! + John->>Bob: How about you? + Bob-->>John: Jolly good! +``` + +![Sequence diagram](./img/sequence.png) + +### Gantt diagram + +``` gantt -section Section -Completed :done, des1, 2014-01-06,2014-01-08 -Active :active, des2, 2014-01-07, 3d -Parallel 1 : des3, after des1, 1d -Parallel 2 : des4, after des1, 1d -Parallel 3 : des5, after des3, 1d -Parallel 4 : des6, after des4, 1d -
- -
- Class
- [docs - live editor] -
+dateFormat  YYYY-MM-DD
+title Adding GANTT diagram to mermaid
+excludes weekdays 2014-01-10
+section A section
+Completed task            :done,    des1, 2014-01-06,2014-01-08
+Active task               :active,  des2, 2014-01-09, 3d
+Future task               :         des3, after des2, 5d
+Future task2               :         des4, after des3, 5d
+```
+
+![Gantt diagram](./img/gantt.png)
+
+### Class diagram - :exclamation: experimental
+
+```
 classDiagram
-Class01 <|-- AveryLongClass : Cool
-<<interface>> Class01
+Class01 <|-- AveryLongClass : Cool
+Class03 *-- Class04
+Class05 o-- Class06
+Class07 .. Class08
 Class09 --> C2 : Where am i?
 Class09 --* C3
 Class09 --|> Class07
@@ -125,84 +110,129 @@ Class07 : Object[] elementData
 Class01 : size()
 Class01 : int chimp
 Class01 : int gorilla
-class Class10 {
-  <<service>>
-  int id
-  size()
+Class08 <--> C2: Cool label
+```
+
+![Class diagram](./img/class.png)
+
+### Git graph - :exclamation: experimental
+
+```
+gitGraph:
+options
+{
+    "nodeSpacing": 150,
+    "nodeRadius": 10
 }
-
- -
- State
- [docs - live editor] -
-stateDiagram
-[*] --> Still
-Still --> [*]
-Still --> Moving
-Moving --> Still
-Moving --> Crash
-Crash --> [*]
-
- -
- Pie
- [docs - live editor] -
-pie
-"Dogs" : 386
-"Cats" : 85
-"Rats" : 15 
-
- -
- Git
- [experimental - live editor] -
Coming soon!
+end +commit +branch newbranch +checkout newbranch +commit +commit +checkout master +commit +commit +merge newbranch +``` -## Related projects +![Git graph](./img/git.png) -- [Command Line Interface](https://github.com/mermaid-js/mermaid.cli) -- [Live Editor](https://github.com/mermaid-js/mermaid-live-editor) +## Installation -# Contributors [![Help wanted](https://img.shields.io/github/labels/mermaid-js/mermaid/Help%20wanted!)](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue+is%3Aopen+label%3A%22Help+wanted%21%22) [![Contributors](https://img.shields.io/github/contributors/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors) [![Commits](https://img.shields.io/github/commit-activity/m/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors) +### CDN -Mermaid is a growing community and is always accepting new contributors. There's a lot of different ways to help out and we're always looking for extra hands! Look at [this issue](https://github.com/mermaid-js/mermaid/issues/866) if you want to know where to start helping out. +``` +https://unpkg.com/mermaid@/dist/ +``` -Detailed information about how to contribute can be found in the [contribution guide](CONTRIBUTING.md) +Replace `` with expected version number. -# Appreciation -A quick note from Knut Sveidqvist: ->*Many thanks to the [d3](http://d3js.org/) and [dagre-d3](https://github.com/cpettitt/dagre-d3) projects for providing the graphical layout and drawing libraries!* ->*Thanks also to the [js-sequence-diagram](http://bramp.github.io/js-sequence-diagrams) project for usage of the grammar for the sequence diagrams. Thanks to Jessica Peter for inspiration and starting point for gantt rendering.* ->*Thank you to [Tyler Long](https://github.com/tylerlong) who has been a collaborator since April 2017.* -> ->*Thank you to the ever-growing list of [contributors](https://github.com/knsv/mermaid/graphs/contributors) that brought the project this far!* +Example: https://unpkg.com/mermaid@7.1.0/dist/ ---- +### Node.js -*Mermaid was created by Knut Sveidqvist for easier documentation.* +``` +yarn add mermaid +``` + +## Documentation + +https://mermaidjs.github.io + +## Sibling projects + +- [mermaid CLI](https://github.com/mermaidjs/mermaid.cli) +- [mermaid live editor](https://github.com/mermaidjs/mermaid-live-editor) +- [mermaid webpack demo](https://github.com/mermaidjs/mermaid-webpack-demo) +- [mermaid Parcel demo](https://github.com/mermaidjs/mermaid-parcel-demo) + +## Request for assistance + +Things are piling up and I have a hard time keeping up. To remedy this +it would be great if we could form a core team of developers to cooperate +with the future development of mermaid. + +As part of this team you would get write access to the repository and would +represent the project when answering questions and issues. + +Together we could continue the work with things like: + +- Adding more types of diagrams like mindmaps, ert diagrams, etc. +- Improving existing diagrams + +Don't hesitate to contact me if you want to get involved. + +## For contributors + +### Setup + +``` +yarn install +``` + +### Build + +``` +yarn build:watch +``` + +### Lint + +``` +yarn lint +``` + +We use [eslint](https://eslint.org/). +We recommend you installing [editor plugins](https://eslint.org/docs/user-guide/integrations) so you can get real time lint result. + +### Test + +``` +yarn test +``` +Manual test in browser: open `dist/index.html` + +### Release + +For those who have the permission to do so: + +Update version number in `package.json`. + +``` +npm publish +``` + +Command above generates files into the `dist` folder and publishes them to npmjs.org. + +## Credits + +Many thanks to the [d3](http://d3js.org/) and [dagre-d3](https://github.com/cpettitt/dagre-d3) projects for providing the graphical layout and drawing libraries! + +Thanks also to the [js-sequence-diagram](http://bramp.github.io/js-sequence-diagrams) project for usage of the grammar for the sequence diagrams. Thanks to Jessica Peter for inspiration and starting point for gantt rendering. + +_Mermaid was created by Knut Sveidqvist for easier documentation._ + +_[Tyler Long](https://github.com/tylerlong) has became a collaborator since April 2017._ + +Here is the full list of the projects [contributors](https://github.com/knsv/mermaid/graphs/contributors). From c3e9ae0ca055eef0f1f944f616dd34bc7ae445f9 Mon Sep 17 00:00:00 2001 From: NeilCuzon Date: Mon, 9 Mar 2020 23:23:27 -0700 Subject: [PATCH 19/34] Revert "Delete README.md" This reverts commit b0852222530fc441ca9402399ad4ac5147ed4540. --- docs/README.md | 239 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100644 docs/README.md diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..4e3f71c02 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,239 @@ +# Mermaid + +[![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid) +[![Coverage Status](https://coveralls.io/repos/github/knsv/mermaid/badge.svg?branch=master)](https://coveralls.io/github/knsv/mermaid?branch=master) +[![Join the chat at https://gitter.im/knsv/mermaid](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/knsv/mermaid?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +![banner](./img/header.png) +# What is mermaid? + +It is a simple markdown-inspired, script language for diagramming and charting that can be deployed via Javascipt. + +The reasoning behind it's inception was a need for simplified documentation and frustration with heavy and time consuming tools for explaining code, like Visio. + +Thus mermaid was created to make the process of diagramming and charting, as simple and as close to markdown, as possible. + +Check out the list of [Integrations and Usages of Mermaid](./integrations.md) +For the uninitiated, you can also try out our [live editor](https://mermaid-js.github.io/mermaid-live-editor/) and look at our [documentation](https://mermaid-js.github.io/mermaid/#/n00b-overview) for a deeper understanding of the tool itself, more importantly don't forget to have fun. + +**Mermaid was nominated and won the JS Open Source Awards (2019) in the category "The most exciting use of technology"!!! Thanks to all involved, people committing pull requests, people answering questions and special thanks to Tyler Long who is helping me maintain the project.** + +## New diagrams in 8.4 + +With version 8.4 class diagrams have got some new features, bug fixes and documentation. Another new feature in 8.4 is the new diagram type, state diagrams. + +![Image show the two new diagram types](./img/new-diagrams.png) + +## Special note regarding version 8.2 + +In version 8.2 a security improvement was introduced. A securityLevel configuration was introduced which sets the level of trust to be used on the parsed diagrams. + +- **true**: (default) tags in text are encoded, click functionality is disabled +- false: tags in text are allowed, click functionality is enabled + +Closed issues: + +⚠️ **Note** : This changes the default behaviour of mermaid so that after upgrade to 8.2, if the securityLevel is not configured, tags in flowcharts are encoded as tags and clicking is prohibited. + +If your application is taking resposibility for the diagram source security you can set the securityLevel accordingly. By doing this clicks and tags are again allowed. + +```javascript +mermaidAPI.initialize({ + securityLevel: 'loose' +}); +``` + +**🖖 Keep a steady pulse: mermaid needs more Collaborators [#866](https://github.com/k3nsv/mermaid/issues/866)** + +## The following are examples of Diagrams that mermaid can make: + +### Flowchart + +``` +graph TD; + A-->B; + A-->C; + B-->D; + C-->D; +``` + +![Flowchart](./img/flow.png) + +### Sequence diagram + +``` +sequenceDiagram + participant Alice + participant Bob + Alice->>John: Hello John, how are you? + loop Healthcheck + John->>John: Fight against hypochondria + end + Note right of John: Rational thoughts
prevail! + John-->>Alice: Great! + John->>Bob: How about you? + Bob-->>John: Jolly good! +``` + +![Sequence diagram](./img/sequence.png) + +### Gantt diagram + +``` +gantt +dateFormat YYYY-MM-DD +title Adding GANTT diagram to mermaid +excludes weekdays 2014-01-10 + +section A section +Completed task :done, des1, 2014-01-06,2014-01-08 +Active task :active, des2, 2014-01-09, 3d +Future task : des3, after des2, 5d +Future task2 : des4, after des3, 5d +``` + +![Gantt diagram](./img/gantt.png) + +### Class diagram - :exclamation: experimental + +``` +classDiagram +Class01 <|-- AveryLongClass : Cool +Class03 *-- Class04 +Class05 o-- Class06 +Class07 .. Class08 +Class09 --> C2 : Where am i? +Class09 --* C3 +Class09 --|> Class07 +Class07 : equals() +Class07 : Object[] elementData +Class01 : size() +Class01 : int chimp +Class01 : int gorilla +Class08 <--> C2: Cool label +``` + +![Class diagram](./img/class.png) + +### Git graph - :exclamation: experimental + +``` +gitGraph: +options +{ + "nodeSpacing": 150, + "nodeRadius": 10 +} +end +commit +branch newbranch +checkout newbranch +commit +commit +checkout master +commit +commit +merge newbranch + +``` + +![Git graph](./img/git.png) + +## Installation + +### CDN + +``` +https://unpkg.com/mermaid@/dist/ +``` + +Replace `` with expected version number. + +Example: https://unpkg.com/mermaid@7.1.0/dist/ + +### Node.js + +``` +yarn add mermaid +``` + +## Documentation + +https://mermaidjs.github.io + +## Sibling projects + +- [mermaid CLI](https://github.com/mermaidjs/mermaid.cli) +- [mermaid live editor](https://github.com/mermaidjs/mermaid-live-editor) +- [mermaid webpack demo](https://github.com/mermaidjs/mermaid-webpack-demo) +- [mermaid Parcel demo](https://github.com/mermaidjs/mermaid-parcel-demo) + +## Request for assistance + +Things are piling up and I have a hard time keeping up. To remedy this +it would be great if we could form a core team of developers to cooperate +with the future development of mermaid. + +As part of this team you would get write access to the repository and would +represent the project when answering questions and issues. + +Together we could continue the work with things like: + +- Adding more types of diagrams like mindmaps, ert diagrams, etc. +- Improving existing diagrams + +Don't hesitate to contact me if you want to get involved. + +## For contributors + +### Setup + +``` +yarn install +``` + +### Build + +``` +yarn build:watch +``` + +### Lint + +``` +yarn lint +``` + +We use [eslint](https://eslint.org/). +We recommend you installing [editor plugins](https://eslint.org/docs/user-guide/integrations) so you can get real time lint result. + +### Test + +``` +yarn test +``` +Manual test in browser: open `dist/index.html` + +### Release + +For those who have the permission to do so: + +Update version number in `package.json`. + +``` +npm publish +``` + +Command above generates files into the `dist` folder and publishes them to npmjs.org. + +## Credits + +Many thanks to the [d3](http://d3js.org/) and [dagre-d3](https://github.com/cpettitt/dagre-d3) projects for providing the graphical layout and drawing libraries! + +Thanks also to the [js-sequence-diagram](http://bramp.github.io/js-sequence-diagrams) project for usage of the grammar for the sequence diagrams. Thanks to Jessica Peter for inspiration and starting point for gantt rendering. + +_Mermaid was created by Knut Sveidqvist for easier documentation._ + +_[Tyler Long](https://github.com/tylerlong) has became a collaborator since April 2017._ + +Here is the full list of the projects [contributors](https://github.com/knsv/mermaid/graphs/contributors). From d28e3374c77798b1f83330c977265311bd393ce6 Mon Sep 17 00:00:00 2001 From: NeilCuzon Date: Mon, 9 Mar 2020 23:23:44 -0700 Subject: [PATCH 20/34] Revert "Update README.md" This reverts commit 71cfec91afbfdf1223a28d029a82568c841201df. --- README.md | 344 +++++++++++++++++++++++++----------------------------- 1 file changed, 157 insertions(+), 187 deletions(-) diff --git a/README.md b/README.md index 791ac115c..781cee7e1 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,26 @@ + +| :mega: :mega: :mega: | +| :----: | +| * If you're upgrading from a version __< v8.2.0__, there are [non-backward-compatible changes](http://mermaid-js.github.io/mermaid/#/usage?id=to-enable-click-event-and-tags-in-nodes) related to security issues. Default behaviour of the library might have changed for your implementation.| + -# Mermaid +# mermaid [![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid) [![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid) [![Coverage Status](https://coveralls.io/repos/github/mermaid-js/mermaid/badge.svg?branch=master)](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) [![This project is using Percy.io for visual regression testing.](https://percy.io/static/images/percy-badge.svg)](https://percy.io/Mermaid/mermaid) -[![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid) -[![Coverage Status](https://coveralls.io/repos/github/knsv/mermaid/badge.svg?branch=master)](https://coveralls.io/github/knsv/mermaid?branch=master) -[![Join the chat at https://gitter.im/knsv/mermaid](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/knsv/mermaid?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +__mermaid is a Javascript based diagramming and charting tool. It generates diagrams flowcharts and more, using markdown-inspired text for ease and speed.__ -![banner](./img/header.png) -# What is mermaid? +Check out the list of [Integrations and Usages of Mermaid](https://github.com/mermaid-js/mermaid/blob/develop/docs/integrations.md) -It is a simple markdown-inspired, script language for diagramming and charting that can be deployed via Javascipt. +For more information and help in getting started, please view our [documentation](http://mermaid-js.github.io/mermaid/) and start simplifying yours. Alternatively, you can also play with our [live editor](https://mermaidjs.github.io/mermaid-live-editor/). + -The reasoning behind it's inception was a need for simplified documentation and frustration with heavy and time consuming tools for explaining code, like Visio. - -Thus mermaid was created to make the process of diagramming and charting, as simple and as close to markdown, as possible. - -Check out the list of [Integrations and Usages of Mermaid](./integrations.md) -For the uninitiated, you can also try out our [live editor](https://mermaid-js.github.io/mermaid-live-editor/) and look at our [documentation](https://mermaid-js.github.io/mermaid/#/n00b-overview) for a deeper understanding of the tool itself, more importantly don't forget to have fun. - -**Mermaid was nominated and won the JS Open Source Awards (2019) in the category "The most exciting use of technology"!!! Thanks to all involved, people committing pull requests, people answering questions and special thanks to Tyler Long who is helping me maintain the project.** +:trophy: **Mermaid was nominated and won the [JS Open Source Awards (2019)](https://osawards.com/javascript/#nominees) in the category "The most exciting use of technology"!!! Thanks to all involved, people committing pull requests, people answering questions and special thanks to Tyler Long who is helping me maintain the project.** ## New diagrams in 8.4 With version 8.4 class diagrams have got some new features, bug fixes and documentation. Another new feature in 8.4 is the new diagram type, state diagrams. -![Image show the two new diagram types](./img/new-diagrams.png) +![Image show the two new diagram types](.docs/img/new-diagrams.png) ## Special note regarding version 8.2 @@ -44,64 +41,82 @@ mermaidAPI.initialize({ }); ``` -**🖖 Keep a steady pulse: mermaid needs more Collaborators [#866](https://github.com/k3nsv/mermaid/issues/866)** +For more information and help in getting started, please view our [documentation](http://mermaid-js.github.io/mermaid/) and start simplifying yours. Play with our [live editor](https://mermaidjs.github.io/mermaid-live-editor/) or jump straight to the [installation and usage](http://mermaid-js.github.io/mermaid/#/usage). + -## The following are examples of Diagrams that mermaid can make: - -### Flowchart - -``` -graph TD; - A-->B; - A-->C; - B-->D; - C-->D; -``` - -![Flowchart](./img/flow.png) - -### Sequence diagram - -``` +__The following are some examples of the diagrams, charts and graphs that can be made using mermaid and the Markdown-inspired text specific to it. Click here jump into the [text syntax](https://mermaid-js.github.io/mermaid/#/n00b-syntaxReference).__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Flow
+ [docs - live editor] +
+graph TD
+A[Hard] -->|Text| B(Round)
+B --> C{Decision}
+C -->|One| D[Result 1]
+C -->|Two| E[Result 2]
+    
+ +
+ Sequence
+ [docs - live editor] +
 sequenceDiagram
-    participant Alice
-    participant Bob
-    Alice->>John: Hello John, how are you?
-    loop Healthcheck
-        John->>John: Fight against hypochondria
-    end
-    Note right of John: Rational thoughts 
prevail! - John-->>Alice: Great! - John->>Bob: How about you? - Bob-->>John: Jolly good! -``` - -![Sequence diagram](./img/sequence.png) - -### Gantt diagram - -``` +Alice->>John: Hello John, how are you? +loop Healthcheck + John->>John: Fight against hypochondria +end +Note right of John: Rational thoughts! +John-->>Alice: Great! +John->>Bob: How about you? +Bob-->>John: Jolly good! +
+ +
+ Gantt
+ [docs - live editor] +
 gantt
-dateFormat  YYYY-MM-DD
-title Adding GANTT diagram to mermaid
-excludes weekdays 2014-01-10
-section A section
-Completed task            :done,    des1, 2014-01-06,2014-01-08
-Active task               :active,  des2, 2014-01-09, 3d
-Future task               :         des3, after des2, 5d
-Future task2               :         des4, after des3, 5d
-```
-
-![Gantt diagram](./img/gantt.png)
-
-### Class diagram - :exclamation: experimental
-
-```
+section Section
+Completed :done,    des1, 2014-01-06,2014-01-08
+Active        :active,  des2, 2014-01-07, 3d
+Parallel 1   :         des3, after des1, 1d
+Parallel 2   :         des4, after des1, 1d
+Parallel 3   :         des5, after des3, 1d
+Parallel 4   :         des6, after des4, 1d
+    
+ +
+ Class
+ [docs - live editor] +
 classDiagram
-Class01 <|-- AveryLongClass : Cool
-Class03 *-- Class04
-Class05 o-- Class06
-Class07 .. Class08
+Class01 <|-- AveryLongClass : Cool
+<<interface>> Class01
 Class09 --> C2 : Where am i?
 Class09 --* C3
 Class09 --|> Class07
@@ -110,129 +125,84 @@ Class07 : Object[] elementData
 Class01 : size()
 Class01 : int chimp
 Class01 : int gorilla
-Class08 <--> C2: Cool label
-```
-
-![Class diagram](./img/class.png)
-
-### Git graph - :exclamation: experimental
-
-```
-gitGraph:
-options
-{
-    "nodeSpacing": 150,
-    "nodeRadius": 10
+class Class10 {
+  <<service>>
+  int id
+  size()
 }
-end
-commit
-branch newbranch
-checkout newbranch
-commit
-commit
-checkout master
-commit
-commit
-merge newbranch
-```
+
+ +
+ State
+ [docs - live editor] +
+stateDiagram
+[*] --> Still
+Still --> [*]
+Still --> Moving
+Moving --> Still
+Moving --> Crash
+Crash --> [*]
+
+ +
+ Pie
+ [docs - live editor] +
+pie
+"Dogs" : 386
+"Cats" : 85
+"Rats" : 15 
+
+ +
+ Git
+ [experimental - live editor] +
Coming soon!
-![Git graph](./img/git.png) +## Related projects -## Installation +- [Command Line Interface](https://github.com/mermaid-js/mermaid.cli) +- [Live Editor](https://github.com/mermaid-js/mermaid-live-editor) -### CDN +# Contributors [![Help wanted](https://img.shields.io/github/labels/mermaid-js/mermaid/Help%20wanted!)](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue+is%3Aopen+label%3A%22Help+wanted%21%22) [![Contributors](https://img.shields.io/github/contributors/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors) [![Commits](https://img.shields.io/github/commit-activity/m/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors) -``` -https://unpkg.com/mermaid@/dist/ -``` +Mermaid is a growing community and is always accepting new contributors. There's a lot of different ways to help out and we're always looking for extra hands! Look at [this issue](https://github.com/mermaid-js/mermaid/issues/866) if you want to know where to start helping out. -Replace `` with expected version number. +Detailed information about how to contribute can be found in the [contribution guide](CONTRIBUTING.md) -Example: https://unpkg.com/mermaid@7.1.0/dist/ +# Appreciation +A quick note from Knut Sveidqvist: +>*Many thanks to the [d3](http://d3js.org/) and [dagre-d3](https://github.com/cpettitt/dagre-d3) projects for providing the graphical layout and drawing libraries!* +>*Thanks also to the [js-sequence-diagram](http://bramp.github.io/js-sequence-diagrams) project for usage of the grammar for the sequence diagrams. Thanks to Jessica Peter for inspiration and starting point for gantt rendering.* +>*Thank you to [Tyler Long](https://github.com/tylerlong) who has been a collaborator since April 2017.* +> +>*Thank you to the ever-growing list of [contributors](https://github.com/knsv/mermaid/graphs/contributors) that brought the project this far!* -### Node.js +--- -``` -yarn add mermaid -``` - -## Documentation - -https://mermaidjs.github.io - -## Sibling projects - -- [mermaid CLI](https://github.com/mermaidjs/mermaid.cli) -- [mermaid live editor](https://github.com/mermaidjs/mermaid-live-editor) -- [mermaid webpack demo](https://github.com/mermaidjs/mermaid-webpack-demo) -- [mermaid Parcel demo](https://github.com/mermaidjs/mermaid-parcel-demo) - -## Request for assistance - -Things are piling up and I have a hard time keeping up. To remedy this -it would be great if we could form a core team of developers to cooperate -with the future development of mermaid. - -As part of this team you would get write access to the repository and would -represent the project when answering questions and issues. - -Together we could continue the work with things like: - -- Adding more types of diagrams like mindmaps, ert diagrams, etc. -- Improving existing diagrams - -Don't hesitate to contact me if you want to get involved. - -## For contributors - -### Setup - -``` -yarn install -``` - -### Build - -``` -yarn build:watch -``` - -### Lint - -``` -yarn lint -``` - -We use [eslint](https://eslint.org/). -We recommend you installing [editor plugins](https://eslint.org/docs/user-guide/integrations) so you can get real time lint result. - -### Test - -``` -yarn test -``` -Manual test in browser: open `dist/index.html` - -### Release - -For those who have the permission to do so: - -Update version number in `package.json`. - -``` -npm publish -``` - -Command above generates files into the `dist` folder and publishes them to npmjs.org. - -## Credits - -Many thanks to the [d3](http://d3js.org/) and [dagre-d3](https://github.com/cpettitt/dagre-d3) projects for providing the graphical layout and drawing libraries! - -Thanks also to the [js-sequence-diagram](http://bramp.github.io/js-sequence-diagrams) project for usage of the grammar for the sequence diagrams. Thanks to Jessica Peter for inspiration and starting point for gantt rendering. - -_Mermaid was created by Knut Sveidqvist for easier documentation._ - -_[Tyler Long](https://github.com/tylerlong) has became a collaborator since April 2017._ - -Here is the full list of the projects [contributors](https://github.com/knsv/mermaid/graphs/contributors). +*Mermaid was created by Knut Sveidqvist for easier documentation.* From a8eeb7f76a082097b6c14a504a9ae9d6095cc780 Mon Sep 17 00:00:00 2001 From: NeilCuzon Date: Mon, 9 Mar 2020 23:25:19 -0700 Subject: [PATCH 21/34] Revert "Revert "Delete README.md"" This reverts commit c3e9ae0ca055eef0f1f944f616dd34bc7ae445f9. --- docs/README.md | 239 ------------------------------------------------- 1 file changed, 239 deletions(-) delete mode 100644 docs/README.md diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 4e3f71c02..000000000 --- a/docs/README.md +++ /dev/null @@ -1,239 +0,0 @@ -# Mermaid - -[![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid) -[![Coverage Status](https://coveralls.io/repos/github/knsv/mermaid/badge.svg?branch=master)](https://coveralls.io/github/knsv/mermaid?branch=master) -[![Join the chat at https://gitter.im/knsv/mermaid](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/knsv/mermaid?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - -![banner](./img/header.png) -# What is mermaid? - -It is a simple markdown-inspired, script language for diagramming and charting that can be deployed via Javascipt. - -The reasoning behind it's inception was a need for simplified documentation and frustration with heavy and time consuming tools for explaining code, like Visio. - -Thus mermaid was created to make the process of diagramming and charting, as simple and as close to markdown, as possible. - -Check out the list of [Integrations and Usages of Mermaid](./integrations.md) -For the uninitiated, you can also try out our [live editor](https://mermaid-js.github.io/mermaid-live-editor/) and look at our [documentation](https://mermaid-js.github.io/mermaid/#/n00b-overview) for a deeper understanding of the tool itself, more importantly don't forget to have fun. - -**Mermaid was nominated and won the JS Open Source Awards (2019) in the category "The most exciting use of technology"!!! Thanks to all involved, people committing pull requests, people answering questions and special thanks to Tyler Long who is helping me maintain the project.** - -## New diagrams in 8.4 - -With version 8.4 class diagrams have got some new features, bug fixes and documentation. Another new feature in 8.4 is the new diagram type, state diagrams. - -![Image show the two new diagram types](./img/new-diagrams.png) - -## Special note regarding version 8.2 - -In version 8.2 a security improvement was introduced. A securityLevel configuration was introduced which sets the level of trust to be used on the parsed diagrams. - -- **true**: (default) tags in text are encoded, click functionality is disabled -- false: tags in text are allowed, click functionality is enabled - -Closed issues: - -⚠️ **Note** : This changes the default behaviour of mermaid so that after upgrade to 8.2, if the securityLevel is not configured, tags in flowcharts are encoded as tags and clicking is prohibited. - -If your application is taking resposibility for the diagram source security you can set the securityLevel accordingly. By doing this clicks and tags are again allowed. - -```javascript -mermaidAPI.initialize({ - securityLevel: 'loose' -}); -``` - -**🖖 Keep a steady pulse: mermaid needs more Collaborators [#866](https://github.com/k3nsv/mermaid/issues/866)** - -## The following are examples of Diagrams that mermaid can make: - -### Flowchart - -``` -graph TD; - A-->B; - A-->C; - B-->D; - C-->D; -``` - -![Flowchart](./img/flow.png) - -### Sequence diagram - -``` -sequenceDiagram - participant Alice - participant Bob - Alice->>John: Hello John, how are you? - loop Healthcheck - John->>John: Fight against hypochondria - end - Note right of John: Rational thoughts
prevail! - John-->>Alice: Great! - John->>Bob: How about you? - Bob-->>John: Jolly good! -``` - -![Sequence diagram](./img/sequence.png) - -### Gantt diagram - -``` -gantt -dateFormat YYYY-MM-DD -title Adding GANTT diagram to mermaid -excludes weekdays 2014-01-10 - -section A section -Completed task :done, des1, 2014-01-06,2014-01-08 -Active task :active, des2, 2014-01-09, 3d -Future task : des3, after des2, 5d -Future task2 : des4, after des3, 5d -``` - -![Gantt diagram](./img/gantt.png) - -### Class diagram - :exclamation: experimental - -``` -classDiagram -Class01 <|-- AveryLongClass : Cool -Class03 *-- Class04 -Class05 o-- Class06 -Class07 .. Class08 -Class09 --> C2 : Where am i? -Class09 --* C3 -Class09 --|> Class07 -Class07 : equals() -Class07 : Object[] elementData -Class01 : size() -Class01 : int chimp -Class01 : int gorilla -Class08 <--> C2: Cool label -``` - -![Class diagram](./img/class.png) - -### Git graph - :exclamation: experimental - -``` -gitGraph: -options -{ - "nodeSpacing": 150, - "nodeRadius": 10 -} -end -commit -branch newbranch -checkout newbranch -commit -commit -checkout master -commit -commit -merge newbranch - -``` - -![Git graph](./img/git.png) - -## Installation - -### CDN - -``` -https://unpkg.com/mermaid@/dist/ -``` - -Replace `` with expected version number. - -Example: https://unpkg.com/mermaid@7.1.0/dist/ - -### Node.js - -``` -yarn add mermaid -``` - -## Documentation - -https://mermaidjs.github.io - -## Sibling projects - -- [mermaid CLI](https://github.com/mermaidjs/mermaid.cli) -- [mermaid live editor](https://github.com/mermaidjs/mermaid-live-editor) -- [mermaid webpack demo](https://github.com/mermaidjs/mermaid-webpack-demo) -- [mermaid Parcel demo](https://github.com/mermaidjs/mermaid-parcel-demo) - -## Request for assistance - -Things are piling up and I have a hard time keeping up. To remedy this -it would be great if we could form a core team of developers to cooperate -with the future development of mermaid. - -As part of this team you would get write access to the repository and would -represent the project when answering questions and issues. - -Together we could continue the work with things like: - -- Adding more types of diagrams like mindmaps, ert diagrams, etc. -- Improving existing diagrams - -Don't hesitate to contact me if you want to get involved. - -## For contributors - -### Setup - -``` -yarn install -``` - -### Build - -``` -yarn build:watch -``` - -### Lint - -``` -yarn lint -``` - -We use [eslint](https://eslint.org/). -We recommend you installing [editor plugins](https://eslint.org/docs/user-guide/integrations) so you can get real time lint result. - -### Test - -``` -yarn test -``` -Manual test in browser: open `dist/index.html` - -### Release - -For those who have the permission to do so: - -Update version number in `package.json`. - -``` -npm publish -``` - -Command above generates files into the `dist` folder and publishes them to npmjs.org. - -## Credits - -Many thanks to the [d3](http://d3js.org/) and [dagre-d3](https://github.com/cpettitt/dagre-d3) projects for providing the graphical layout and drawing libraries! - -Thanks also to the [js-sequence-diagram](http://bramp.github.io/js-sequence-diagrams) project for usage of the grammar for the sequence diagrams. Thanks to Jessica Peter for inspiration and starting point for gantt rendering. - -_Mermaid was created by Knut Sveidqvist for easier documentation._ - -_[Tyler Long](https://github.com/tylerlong) has became a collaborator since April 2017._ - -Here is the full list of the projects [contributors](https://github.com/knsv/mermaid/graphs/contributors). From c598fd9ec4a14f38c789f741232f6d40fdb031b0 Mon Sep 17 00:00:00 2001 From: NeilCuzon Date: Mon, 9 Mar 2020 23:25:24 -0700 Subject: [PATCH 22/34] Revert "Revert "Update README.md"" This reverts commit d28e3374c77798b1f83330c977265311bd393ce6. --- README.md | 344 +++++++++++++++++++++++++++++------------------------- 1 file changed, 187 insertions(+), 157 deletions(-) diff --git a/README.md b/README.md index 781cee7e1..791ac115c 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,29 @@ - -| :mega: :mega: :mega: | -| :----: | -| * If you're upgrading from a version __< v8.2.0__, there are [non-backward-compatible changes](http://mermaid-js.github.io/mermaid/#/usage?id=to-enable-click-event-and-tags-in-nodes) related to security issues. Default behaviour of the library might have changed for your implementation.| - -# mermaid [![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid) [![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid) [![Coverage Status](https://coveralls.io/repos/github/mermaid-js/mermaid/badge.svg?branch=master)](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) [![This project is using Percy.io for visual regression testing.](https://percy.io/static/images/percy-badge.svg)](https://percy.io/Mermaid/mermaid) +# Mermaid - -__mermaid is a Javascript based diagramming and charting tool. It generates diagrams flowcharts and more, using markdown-inspired text for ease and speed.__ +[![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid) +[![Coverage Status](https://coveralls.io/repos/github/knsv/mermaid/badge.svg?branch=master)](https://coveralls.io/github/knsv/mermaid?branch=master) +[![Join the chat at https://gitter.im/knsv/mermaid](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/knsv/mermaid?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -Check out the list of [Integrations and Usages of Mermaid](https://github.com/mermaid-js/mermaid/blob/develop/docs/integrations.md) +![banner](./img/header.png) +# What is mermaid? -For more information and help in getting started, please view our [documentation](http://mermaid-js.github.io/mermaid/) and start simplifying yours. Alternatively, you can also play with our [live editor](https://mermaidjs.github.io/mermaid-live-editor/). - +It is a simple markdown-inspired, script language for diagramming and charting that can be deployed via Javascipt. -:trophy: **Mermaid was nominated and won the [JS Open Source Awards (2019)](https://osawards.com/javascript/#nominees) in the category "The most exciting use of technology"!!! Thanks to all involved, people committing pull requests, people answering questions and special thanks to Tyler Long who is helping me maintain the project.** +The reasoning behind it's inception was a need for simplified documentation and frustration with heavy and time consuming tools for explaining code, like Visio. + +Thus mermaid was created to make the process of diagramming and charting, as simple and as close to markdown, as possible. + +Check out the list of [Integrations and Usages of Mermaid](./integrations.md) +For the uninitiated, you can also try out our [live editor](https://mermaid-js.github.io/mermaid-live-editor/) and look at our [documentation](https://mermaid-js.github.io/mermaid/#/n00b-overview) for a deeper understanding of the tool itself, more importantly don't forget to have fun. + +**Mermaid was nominated and won the JS Open Source Awards (2019) in the category "The most exciting use of technology"!!! Thanks to all involved, people committing pull requests, people answering questions and special thanks to Tyler Long who is helping me maintain the project.** ## New diagrams in 8.4 With version 8.4 class diagrams have got some new features, bug fixes and documentation. Another new feature in 8.4 is the new diagram type, state diagrams. -![Image show the two new diagram types](.docs/img/new-diagrams.png) +![Image show the two new diagram types](./img/new-diagrams.png) ## Special note regarding version 8.2 @@ -41,82 +44,64 @@ mermaidAPI.initialize({ }); ``` -For more information and help in getting started, please view our [documentation](http://mermaid-js.github.io/mermaid/) and start simplifying yours. Play with our [live editor](https://mermaidjs.github.io/mermaid-live-editor/) or jump straight to the [installation and usage](http://mermaid-js.github.io/mermaid/#/usage). - +**🖖 Keep a steady pulse: mermaid needs more Collaborators [#866](https://github.com/k3nsv/mermaid/issues/866)** -__The following are some examples of the diagrams, charts and graphs that can be made using mermaid and the Markdown-inspired text specific to it. Click here jump into the [text syntax](https://mermaid-js.github.io/mermaid/#/n00b-syntaxReference).__ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Flow
- [docs - live editor] -
-graph TD
-A[Hard] -->|Text| B(Round)
-B --> C{Decision}
-C -->|One| D[Result 1]
-C -->|Two| E[Result 2]
-    
- -
- Sequence
- [docs - live editor] -
+## The following are examples of Diagrams that mermaid can make:
+
+### Flowchart
+
+```
+graph TD;
+    A-->B;
+    A-->C;
+    B-->D;
+    C-->D;
+```
+
+![Flowchart](./img/flow.png)
+
+### Sequence diagram
+
+```
 sequenceDiagram
-Alice->>John: Hello John, how are you?
-loop Healthcheck
-    John->>John: Fight against hypochondria
-end
-Note right of John: Rational thoughts!
-John-->>Alice: Great!
-John->>Bob: How about you?
-Bob-->>John: Jolly good!
-    
- -
- Gantt
- [docs - live editor] -
+    participant Alice
+    participant Bob
+    Alice->>John: Hello John, how are you?
+    loop Healthcheck
+        John->>John: Fight against hypochondria
+    end
+    Note right of John: Rational thoughts 
prevail! + John-->>Alice: Great! + John->>Bob: How about you? + Bob-->>John: Jolly good! +``` + +![Sequence diagram](./img/sequence.png) + +### Gantt diagram + +``` gantt -section Section -Completed :done, des1, 2014-01-06,2014-01-08 -Active :active, des2, 2014-01-07, 3d -Parallel 1 : des3, after des1, 1d -Parallel 2 : des4, after des1, 1d -Parallel 3 : des5, after des3, 1d -Parallel 4 : des6, after des4, 1d -
- -
- Class
- [docs - live editor] -
+dateFormat  YYYY-MM-DD
+title Adding GANTT diagram to mermaid
+excludes weekdays 2014-01-10
+section A section
+Completed task            :done,    des1, 2014-01-06,2014-01-08
+Active task               :active,  des2, 2014-01-09, 3d
+Future task               :         des3, after des2, 5d
+Future task2               :         des4, after des3, 5d
+```
+
+![Gantt diagram](./img/gantt.png)
+
+### Class diagram - :exclamation: experimental
+
+```
 classDiagram
-Class01 <|-- AveryLongClass : Cool
-<<interface>> Class01
+Class01 <|-- AveryLongClass : Cool
+Class03 *-- Class04
+Class05 o-- Class06
+Class07 .. Class08
 Class09 --> C2 : Where am i?
 Class09 --* C3
 Class09 --|> Class07
@@ -125,84 +110,129 @@ Class07 : Object[] elementData
 Class01 : size()
 Class01 : int chimp
 Class01 : int gorilla
-class Class10 {
-  <<service>>
-  int id
-  size()
+Class08 <--> C2: Cool label
+```
+
+![Class diagram](./img/class.png)
+
+### Git graph - :exclamation: experimental
+
+```
+gitGraph:
+options
+{
+    "nodeSpacing": 150,
+    "nodeRadius": 10
 }
-
- -
- State
- [docs - live editor] -
-stateDiagram
-[*] --> Still
-Still --> [*]
-Still --> Moving
-Moving --> Still
-Moving --> Crash
-Crash --> [*]
-
- -
- Pie
- [docs - live editor] -
-pie
-"Dogs" : 386
-"Cats" : 85
-"Rats" : 15 
-
- -
- Git
- [experimental - live editor] -
Coming soon!
+end +commit +branch newbranch +checkout newbranch +commit +commit +checkout master +commit +commit +merge newbranch +``` -## Related projects +![Git graph](./img/git.png) -- [Command Line Interface](https://github.com/mermaid-js/mermaid.cli) -- [Live Editor](https://github.com/mermaid-js/mermaid-live-editor) +## Installation -# Contributors [![Help wanted](https://img.shields.io/github/labels/mermaid-js/mermaid/Help%20wanted!)](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue+is%3Aopen+label%3A%22Help+wanted%21%22) [![Contributors](https://img.shields.io/github/contributors/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors) [![Commits](https://img.shields.io/github/commit-activity/m/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors) +### CDN -Mermaid is a growing community and is always accepting new contributors. There's a lot of different ways to help out and we're always looking for extra hands! Look at [this issue](https://github.com/mermaid-js/mermaid/issues/866) if you want to know where to start helping out. +``` +https://unpkg.com/mermaid@/dist/ +``` -Detailed information about how to contribute can be found in the [contribution guide](CONTRIBUTING.md) +Replace `` with expected version number. -# Appreciation -A quick note from Knut Sveidqvist: ->*Many thanks to the [d3](http://d3js.org/) and [dagre-d3](https://github.com/cpettitt/dagre-d3) projects for providing the graphical layout and drawing libraries!* ->*Thanks also to the [js-sequence-diagram](http://bramp.github.io/js-sequence-diagrams) project for usage of the grammar for the sequence diagrams. Thanks to Jessica Peter for inspiration and starting point for gantt rendering.* ->*Thank you to [Tyler Long](https://github.com/tylerlong) who has been a collaborator since April 2017.* -> ->*Thank you to the ever-growing list of [contributors](https://github.com/knsv/mermaid/graphs/contributors) that brought the project this far!* +Example: https://unpkg.com/mermaid@7.1.0/dist/ ---- +### Node.js -*Mermaid was created by Knut Sveidqvist for easier documentation.* +``` +yarn add mermaid +``` + +## Documentation + +https://mermaidjs.github.io + +## Sibling projects + +- [mermaid CLI](https://github.com/mermaidjs/mermaid.cli) +- [mermaid live editor](https://github.com/mermaidjs/mermaid-live-editor) +- [mermaid webpack demo](https://github.com/mermaidjs/mermaid-webpack-demo) +- [mermaid Parcel demo](https://github.com/mermaidjs/mermaid-parcel-demo) + +## Request for assistance + +Things are piling up and I have a hard time keeping up. To remedy this +it would be great if we could form a core team of developers to cooperate +with the future development of mermaid. + +As part of this team you would get write access to the repository and would +represent the project when answering questions and issues. + +Together we could continue the work with things like: + +- Adding more types of diagrams like mindmaps, ert diagrams, etc. +- Improving existing diagrams + +Don't hesitate to contact me if you want to get involved. + +## For contributors + +### Setup + +``` +yarn install +``` + +### Build + +``` +yarn build:watch +``` + +### Lint + +``` +yarn lint +``` + +We use [eslint](https://eslint.org/). +We recommend you installing [editor plugins](https://eslint.org/docs/user-guide/integrations) so you can get real time lint result. + +### Test + +``` +yarn test +``` +Manual test in browser: open `dist/index.html` + +### Release + +For those who have the permission to do so: + +Update version number in `package.json`. + +``` +npm publish +``` + +Command above generates files into the `dist` folder and publishes them to npmjs.org. + +## Credits + +Many thanks to the [d3](http://d3js.org/) and [dagre-d3](https://github.com/cpettitt/dagre-d3) projects for providing the graphical layout and drawing libraries! + +Thanks also to the [js-sequence-diagram](http://bramp.github.io/js-sequence-diagrams) project for usage of the grammar for the sequence diagrams. Thanks to Jessica Peter for inspiration and starting point for gantt rendering. + +_Mermaid was created by Knut Sveidqvist for easier documentation._ + +_[Tyler Long](https://github.com/tylerlong) has became a collaborator since April 2017._ + +Here is the full list of the projects [contributors](https://github.com/knsv/mermaid/graphs/contributors). From a414aa27b6d6bd2b483b00f122e6483991043f04 Mon Sep 17 00:00:00 2001 From: NeilCuzon Date: Mon, 9 Mar 2020 23:25:28 -0700 Subject: [PATCH 23/34] Revert "Revert "Revert "Update README.md""" This reverts commit c598fd9ec4a14f38c789f741232f6d40fdb031b0. --- README.md | 344 +++++++++++++++++++++++++----------------------------- 1 file changed, 157 insertions(+), 187 deletions(-) diff --git a/README.md b/README.md index 791ac115c..781cee7e1 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,26 @@ + +| :mega: :mega: :mega: | +| :----: | +| * If you're upgrading from a version __< v8.2.0__, there are [non-backward-compatible changes](http://mermaid-js.github.io/mermaid/#/usage?id=to-enable-click-event-and-tags-in-nodes) related to security issues. Default behaviour of the library might have changed for your implementation.| + -# Mermaid +# mermaid [![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid) [![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid) [![Coverage Status](https://coveralls.io/repos/github/mermaid-js/mermaid/badge.svg?branch=master)](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) [![This project is using Percy.io for visual regression testing.](https://percy.io/static/images/percy-badge.svg)](https://percy.io/Mermaid/mermaid) -[![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid) -[![Coverage Status](https://coveralls.io/repos/github/knsv/mermaid/badge.svg?branch=master)](https://coveralls.io/github/knsv/mermaid?branch=master) -[![Join the chat at https://gitter.im/knsv/mermaid](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/knsv/mermaid?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +__mermaid is a Javascript based diagramming and charting tool. It generates diagrams flowcharts and more, using markdown-inspired text for ease and speed.__ -![banner](./img/header.png) -# What is mermaid? +Check out the list of [Integrations and Usages of Mermaid](https://github.com/mermaid-js/mermaid/blob/develop/docs/integrations.md) -It is a simple markdown-inspired, script language for diagramming and charting that can be deployed via Javascipt. +For more information and help in getting started, please view our [documentation](http://mermaid-js.github.io/mermaid/) and start simplifying yours. Alternatively, you can also play with our [live editor](https://mermaidjs.github.io/mermaid-live-editor/). + -The reasoning behind it's inception was a need for simplified documentation and frustration with heavy and time consuming tools for explaining code, like Visio. - -Thus mermaid was created to make the process of diagramming and charting, as simple and as close to markdown, as possible. - -Check out the list of [Integrations and Usages of Mermaid](./integrations.md) -For the uninitiated, you can also try out our [live editor](https://mermaid-js.github.io/mermaid-live-editor/) and look at our [documentation](https://mermaid-js.github.io/mermaid/#/n00b-overview) for a deeper understanding of the tool itself, more importantly don't forget to have fun. - -**Mermaid was nominated and won the JS Open Source Awards (2019) in the category "The most exciting use of technology"!!! Thanks to all involved, people committing pull requests, people answering questions and special thanks to Tyler Long who is helping me maintain the project.** +:trophy: **Mermaid was nominated and won the [JS Open Source Awards (2019)](https://osawards.com/javascript/#nominees) in the category "The most exciting use of technology"!!! Thanks to all involved, people committing pull requests, people answering questions and special thanks to Tyler Long who is helping me maintain the project.** ## New diagrams in 8.4 With version 8.4 class diagrams have got some new features, bug fixes and documentation. Another new feature in 8.4 is the new diagram type, state diagrams. -![Image show the two new diagram types](./img/new-diagrams.png) +![Image show the two new diagram types](.docs/img/new-diagrams.png) ## Special note regarding version 8.2 @@ -44,64 +41,82 @@ mermaidAPI.initialize({ }); ``` -**🖖 Keep a steady pulse: mermaid needs more Collaborators [#866](https://github.com/k3nsv/mermaid/issues/866)** +For more information and help in getting started, please view our [documentation](http://mermaid-js.github.io/mermaid/) and start simplifying yours. Play with our [live editor](https://mermaidjs.github.io/mermaid-live-editor/) or jump straight to the [installation and usage](http://mermaid-js.github.io/mermaid/#/usage). + -## The following are examples of Diagrams that mermaid can make: - -### Flowchart - -``` -graph TD; - A-->B; - A-->C; - B-->D; - C-->D; -``` - -![Flowchart](./img/flow.png) - -### Sequence diagram - -``` +__The following are some examples of the diagrams, charts and graphs that can be made using mermaid and the Markdown-inspired text specific to it. Click here jump into the [text syntax](https://mermaid-js.github.io/mermaid/#/n00b-syntaxReference).__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Flow
+ [docs - live editor] +
+graph TD
+A[Hard] -->|Text| B(Round)
+B --> C{Decision}
+C -->|One| D[Result 1]
+C -->|Two| E[Result 2]
+    
+ +
+ Sequence
+ [docs - live editor] +
 sequenceDiagram
-    participant Alice
-    participant Bob
-    Alice->>John: Hello John, how are you?
-    loop Healthcheck
-        John->>John: Fight against hypochondria
-    end
-    Note right of John: Rational thoughts 
prevail! - John-->>Alice: Great! - John->>Bob: How about you? - Bob-->>John: Jolly good! -``` - -![Sequence diagram](./img/sequence.png) - -### Gantt diagram - -``` +Alice->>John: Hello John, how are you? +loop Healthcheck + John->>John: Fight against hypochondria +end +Note right of John: Rational thoughts! +John-->>Alice: Great! +John->>Bob: How about you? +Bob-->>John: Jolly good! +
+ +
+ Gantt
+ [docs - live editor] +
 gantt
-dateFormat  YYYY-MM-DD
-title Adding GANTT diagram to mermaid
-excludes weekdays 2014-01-10
-section A section
-Completed task            :done,    des1, 2014-01-06,2014-01-08
-Active task               :active,  des2, 2014-01-09, 3d
-Future task               :         des3, after des2, 5d
-Future task2               :         des4, after des3, 5d
-```
-
-![Gantt diagram](./img/gantt.png)
-
-### Class diagram - :exclamation: experimental
-
-```
+section Section
+Completed :done,    des1, 2014-01-06,2014-01-08
+Active        :active,  des2, 2014-01-07, 3d
+Parallel 1   :         des3, after des1, 1d
+Parallel 2   :         des4, after des1, 1d
+Parallel 3   :         des5, after des3, 1d
+Parallel 4   :         des6, after des4, 1d
+    
+ +
+ Class
+ [docs - live editor] +
 classDiagram
-Class01 <|-- AveryLongClass : Cool
-Class03 *-- Class04
-Class05 o-- Class06
-Class07 .. Class08
+Class01 <|-- AveryLongClass : Cool
+<<interface>> Class01
 Class09 --> C2 : Where am i?
 Class09 --* C3
 Class09 --|> Class07
@@ -110,129 +125,84 @@ Class07 : Object[] elementData
 Class01 : size()
 Class01 : int chimp
 Class01 : int gorilla
-Class08 <--> C2: Cool label
-```
-
-![Class diagram](./img/class.png)
-
-### Git graph - :exclamation: experimental
-
-```
-gitGraph:
-options
-{
-    "nodeSpacing": 150,
-    "nodeRadius": 10
+class Class10 {
+  <<service>>
+  int id
+  size()
 }
-end
-commit
-branch newbranch
-checkout newbranch
-commit
-commit
-checkout master
-commit
-commit
-merge newbranch
-```
+
+ +
+ State
+ [docs - live editor] +
+stateDiagram
+[*] --> Still
+Still --> [*]
+Still --> Moving
+Moving --> Still
+Moving --> Crash
+Crash --> [*]
+
+ +
+ Pie
+ [docs - live editor] +
+pie
+"Dogs" : 386
+"Cats" : 85
+"Rats" : 15 
+
+ +
+ Git
+ [experimental - live editor] +
Coming soon!
-![Git graph](./img/git.png) +## Related projects -## Installation +- [Command Line Interface](https://github.com/mermaid-js/mermaid.cli) +- [Live Editor](https://github.com/mermaid-js/mermaid-live-editor) -### CDN +# Contributors [![Help wanted](https://img.shields.io/github/labels/mermaid-js/mermaid/Help%20wanted!)](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue+is%3Aopen+label%3A%22Help+wanted%21%22) [![Contributors](https://img.shields.io/github/contributors/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors) [![Commits](https://img.shields.io/github/commit-activity/m/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors) -``` -https://unpkg.com/mermaid@/dist/ -``` +Mermaid is a growing community and is always accepting new contributors. There's a lot of different ways to help out and we're always looking for extra hands! Look at [this issue](https://github.com/mermaid-js/mermaid/issues/866) if you want to know where to start helping out. -Replace `` with expected version number. +Detailed information about how to contribute can be found in the [contribution guide](CONTRIBUTING.md) -Example: https://unpkg.com/mermaid@7.1.0/dist/ +# Appreciation +A quick note from Knut Sveidqvist: +>*Many thanks to the [d3](http://d3js.org/) and [dagre-d3](https://github.com/cpettitt/dagre-d3) projects for providing the graphical layout and drawing libraries!* +>*Thanks also to the [js-sequence-diagram](http://bramp.github.io/js-sequence-diagrams) project for usage of the grammar for the sequence diagrams. Thanks to Jessica Peter for inspiration and starting point for gantt rendering.* +>*Thank you to [Tyler Long](https://github.com/tylerlong) who has been a collaborator since April 2017.* +> +>*Thank you to the ever-growing list of [contributors](https://github.com/knsv/mermaid/graphs/contributors) that brought the project this far!* -### Node.js +--- -``` -yarn add mermaid -``` - -## Documentation - -https://mermaidjs.github.io - -## Sibling projects - -- [mermaid CLI](https://github.com/mermaidjs/mermaid.cli) -- [mermaid live editor](https://github.com/mermaidjs/mermaid-live-editor) -- [mermaid webpack demo](https://github.com/mermaidjs/mermaid-webpack-demo) -- [mermaid Parcel demo](https://github.com/mermaidjs/mermaid-parcel-demo) - -## Request for assistance - -Things are piling up and I have a hard time keeping up. To remedy this -it would be great if we could form a core team of developers to cooperate -with the future development of mermaid. - -As part of this team you would get write access to the repository and would -represent the project when answering questions and issues. - -Together we could continue the work with things like: - -- Adding more types of diagrams like mindmaps, ert diagrams, etc. -- Improving existing diagrams - -Don't hesitate to contact me if you want to get involved. - -## For contributors - -### Setup - -``` -yarn install -``` - -### Build - -``` -yarn build:watch -``` - -### Lint - -``` -yarn lint -``` - -We use [eslint](https://eslint.org/). -We recommend you installing [editor plugins](https://eslint.org/docs/user-guide/integrations) so you can get real time lint result. - -### Test - -``` -yarn test -``` -Manual test in browser: open `dist/index.html` - -### Release - -For those who have the permission to do so: - -Update version number in `package.json`. - -``` -npm publish -``` - -Command above generates files into the `dist` folder and publishes them to npmjs.org. - -## Credits - -Many thanks to the [d3](http://d3js.org/) and [dagre-d3](https://github.com/cpettitt/dagre-d3) projects for providing the graphical layout and drawing libraries! - -Thanks also to the [js-sequence-diagram](http://bramp.github.io/js-sequence-diagrams) project for usage of the grammar for the sequence diagrams. Thanks to Jessica Peter for inspiration and starting point for gantt rendering. - -_Mermaid was created by Knut Sveidqvist for easier documentation._ - -_[Tyler Long](https://github.com/tylerlong) has became a collaborator since April 2017._ - -Here is the full list of the projects [contributors](https://github.com/knsv/mermaid/graphs/contributors). +*Mermaid was created by Knut Sveidqvist for easier documentation.* From 09e6804761aa7bd8acd1bd3392120f58fa3703b5 Mon Sep 17 00:00:00 2001 From: NeilCuzon Date: Mon, 9 Mar 2020 23:25:55 -0700 Subject: [PATCH 24/34] Revert "Revert "Revert "Revert "Update README.md"""" This reverts commit a414aa27b6d6bd2b483b00f122e6483991043f04. --- README.md | 344 +++++++++++++++++++++++++++++------------------------- 1 file changed, 187 insertions(+), 157 deletions(-) diff --git a/README.md b/README.md index 781cee7e1..791ac115c 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,29 @@ - -| :mega: :mega: :mega: | -| :----: | -| * If you're upgrading from a version __< v8.2.0__, there are [non-backward-compatible changes](http://mermaid-js.github.io/mermaid/#/usage?id=to-enable-click-event-and-tags-in-nodes) related to security issues. Default behaviour of the library might have changed for your implementation.| - -# mermaid [![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid) [![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid) [![Coverage Status](https://coveralls.io/repos/github/mermaid-js/mermaid/badge.svg?branch=master)](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) [![This project is using Percy.io for visual regression testing.](https://percy.io/static/images/percy-badge.svg)](https://percy.io/Mermaid/mermaid) +# Mermaid - -__mermaid is a Javascript based diagramming and charting tool. It generates diagrams flowcharts and more, using markdown-inspired text for ease and speed.__ +[![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid) +[![Coverage Status](https://coveralls.io/repos/github/knsv/mermaid/badge.svg?branch=master)](https://coveralls.io/github/knsv/mermaid?branch=master) +[![Join the chat at https://gitter.im/knsv/mermaid](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/knsv/mermaid?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -Check out the list of [Integrations and Usages of Mermaid](https://github.com/mermaid-js/mermaid/blob/develop/docs/integrations.md) +![banner](./img/header.png) +# What is mermaid? -For more information and help in getting started, please view our [documentation](http://mermaid-js.github.io/mermaid/) and start simplifying yours. Alternatively, you can also play with our [live editor](https://mermaidjs.github.io/mermaid-live-editor/). - +It is a simple markdown-inspired, script language for diagramming and charting that can be deployed via Javascipt. -:trophy: **Mermaid was nominated and won the [JS Open Source Awards (2019)](https://osawards.com/javascript/#nominees) in the category "The most exciting use of technology"!!! Thanks to all involved, people committing pull requests, people answering questions and special thanks to Tyler Long who is helping me maintain the project.** +The reasoning behind it's inception was a need for simplified documentation and frustration with heavy and time consuming tools for explaining code, like Visio. + +Thus mermaid was created to make the process of diagramming and charting, as simple and as close to markdown, as possible. + +Check out the list of [Integrations and Usages of Mermaid](./integrations.md) +For the uninitiated, you can also try out our [live editor](https://mermaid-js.github.io/mermaid-live-editor/) and look at our [documentation](https://mermaid-js.github.io/mermaid/#/n00b-overview) for a deeper understanding of the tool itself, more importantly don't forget to have fun. + +**Mermaid was nominated and won the JS Open Source Awards (2019) in the category "The most exciting use of technology"!!! Thanks to all involved, people committing pull requests, people answering questions and special thanks to Tyler Long who is helping me maintain the project.** ## New diagrams in 8.4 With version 8.4 class diagrams have got some new features, bug fixes and documentation. Another new feature in 8.4 is the new diagram type, state diagrams. -![Image show the two new diagram types](.docs/img/new-diagrams.png) +![Image show the two new diagram types](./img/new-diagrams.png) ## Special note regarding version 8.2 @@ -41,82 +44,64 @@ mermaidAPI.initialize({ }); ``` -For more information and help in getting started, please view our [documentation](http://mermaid-js.github.io/mermaid/) and start simplifying yours. Play with our [live editor](https://mermaidjs.github.io/mermaid-live-editor/) or jump straight to the [installation and usage](http://mermaid-js.github.io/mermaid/#/usage). - +**🖖 Keep a steady pulse: mermaid needs more Collaborators [#866](https://github.com/k3nsv/mermaid/issues/866)** -__The following are some examples of the diagrams, charts and graphs that can be made using mermaid and the Markdown-inspired text specific to it. Click here jump into the [text syntax](https://mermaid-js.github.io/mermaid/#/n00b-syntaxReference).__ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Flow
- [docs - live editor] -
-graph TD
-A[Hard] -->|Text| B(Round)
-B --> C{Decision}
-C -->|One| D[Result 1]
-C -->|Two| E[Result 2]
-    
- -
- Sequence
- [docs - live editor] -
+## The following are examples of Diagrams that mermaid can make:
+
+### Flowchart
+
+```
+graph TD;
+    A-->B;
+    A-->C;
+    B-->D;
+    C-->D;
+```
+
+![Flowchart](./img/flow.png)
+
+### Sequence diagram
+
+```
 sequenceDiagram
-Alice->>John: Hello John, how are you?
-loop Healthcheck
-    John->>John: Fight against hypochondria
-end
-Note right of John: Rational thoughts!
-John-->>Alice: Great!
-John->>Bob: How about you?
-Bob-->>John: Jolly good!
-    
- -
- Gantt
- [docs - live editor] -
+    participant Alice
+    participant Bob
+    Alice->>John: Hello John, how are you?
+    loop Healthcheck
+        John->>John: Fight against hypochondria
+    end
+    Note right of John: Rational thoughts 
prevail! + John-->>Alice: Great! + John->>Bob: How about you? + Bob-->>John: Jolly good! +``` + +![Sequence diagram](./img/sequence.png) + +### Gantt diagram + +``` gantt -section Section -Completed :done, des1, 2014-01-06,2014-01-08 -Active :active, des2, 2014-01-07, 3d -Parallel 1 : des3, after des1, 1d -Parallel 2 : des4, after des1, 1d -Parallel 3 : des5, after des3, 1d -Parallel 4 : des6, after des4, 1d -
- -
- Class
- [docs - live editor] -
+dateFormat  YYYY-MM-DD
+title Adding GANTT diagram to mermaid
+excludes weekdays 2014-01-10
+section A section
+Completed task            :done,    des1, 2014-01-06,2014-01-08
+Active task               :active,  des2, 2014-01-09, 3d
+Future task               :         des3, after des2, 5d
+Future task2               :         des4, after des3, 5d
+```
+
+![Gantt diagram](./img/gantt.png)
+
+### Class diagram - :exclamation: experimental
+
+```
 classDiagram
-Class01 <|-- AveryLongClass : Cool
-<<interface>> Class01
+Class01 <|-- AveryLongClass : Cool
+Class03 *-- Class04
+Class05 o-- Class06
+Class07 .. Class08
 Class09 --> C2 : Where am i?
 Class09 --* C3
 Class09 --|> Class07
@@ -125,84 +110,129 @@ Class07 : Object[] elementData
 Class01 : size()
 Class01 : int chimp
 Class01 : int gorilla
-class Class10 {
-  <<service>>
-  int id
-  size()
+Class08 <--> C2: Cool label
+```
+
+![Class diagram](./img/class.png)
+
+### Git graph - :exclamation: experimental
+
+```
+gitGraph:
+options
+{
+    "nodeSpacing": 150,
+    "nodeRadius": 10
 }
-
- -
- State
- [docs - live editor] -
-stateDiagram
-[*] --> Still
-Still --> [*]
-Still --> Moving
-Moving --> Still
-Moving --> Crash
-Crash --> [*]
-
- -
- Pie
- [docs - live editor] -
-pie
-"Dogs" : 386
-"Cats" : 85
-"Rats" : 15 
-
- -
- Git
- [experimental - live editor] -
Coming soon!
+end +commit +branch newbranch +checkout newbranch +commit +commit +checkout master +commit +commit +merge newbranch +``` -## Related projects +![Git graph](./img/git.png) -- [Command Line Interface](https://github.com/mermaid-js/mermaid.cli) -- [Live Editor](https://github.com/mermaid-js/mermaid-live-editor) +## Installation -# Contributors [![Help wanted](https://img.shields.io/github/labels/mermaid-js/mermaid/Help%20wanted!)](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue+is%3Aopen+label%3A%22Help+wanted%21%22) [![Contributors](https://img.shields.io/github/contributors/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors) [![Commits](https://img.shields.io/github/commit-activity/m/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors) +### CDN -Mermaid is a growing community and is always accepting new contributors. There's a lot of different ways to help out and we're always looking for extra hands! Look at [this issue](https://github.com/mermaid-js/mermaid/issues/866) if you want to know where to start helping out. +``` +https://unpkg.com/mermaid@/dist/ +``` -Detailed information about how to contribute can be found in the [contribution guide](CONTRIBUTING.md) +Replace `` with expected version number. -# Appreciation -A quick note from Knut Sveidqvist: ->*Many thanks to the [d3](http://d3js.org/) and [dagre-d3](https://github.com/cpettitt/dagre-d3) projects for providing the graphical layout and drawing libraries!* ->*Thanks also to the [js-sequence-diagram](http://bramp.github.io/js-sequence-diagrams) project for usage of the grammar for the sequence diagrams. Thanks to Jessica Peter for inspiration and starting point for gantt rendering.* ->*Thank you to [Tyler Long](https://github.com/tylerlong) who has been a collaborator since April 2017.* -> ->*Thank you to the ever-growing list of [contributors](https://github.com/knsv/mermaid/graphs/contributors) that brought the project this far!* +Example: https://unpkg.com/mermaid@7.1.0/dist/ ---- +### Node.js -*Mermaid was created by Knut Sveidqvist for easier documentation.* +``` +yarn add mermaid +``` + +## Documentation + +https://mermaidjs.github.io + +## Sibling projects + +- [mermaid CLI](https://github.com/mermaidjs/mermaid.cli) +- [mermaid live editor](https://github.com/mermaidjs/mermaid-live-editor) +- [mermaid webpack demo](https://github.com/mermaidjs/mermaid-webpack-demo) +- [mermaid Parcel demo](https://github.com/mermaidjs/mermaid-parcel-demo) + +## Request for assistance + +Things are piling up and I have a hard time keeping up. To remedy this +it would be great if we could form a core team of developers to cooperate +with the future development of mermaid. + +As part of this team you would get write access to the repository and would +represent the project when answering questions and issues. + +Together we could continue the work with things like: + +- Adding more types of diagrams like mindmaps, ert diagrams, etc. +- Improving existing diagrams + +Don't hesitate to contact me if you want to get involved. + +## For contributors + +### Setup + +``` +yarn install +``` + +### Build + +``` +yarn build:watch +``` + +### Lint + +``` +yarn lint +``` + +We use [eslint](https://eslint.org/). +We recommend you installing [editor plugins](https://eslint.org/docs/user-guide/integrations) so you can get real time lint result. + +### Test + +``` +yarn test +``` +Manual test in browser: open `dist/index.html` + +### Release + +For those who have the permission to do so: + +Update version number in `package.json`. + +``` +npm publish +``` + +Command above generates files into the `dist` folder and publishes them to npmjs.org. + +## Credits + +Many thanks to the [d3](http://d3js.org/) and [dagre-d3](https://github.com/cpettitt/dagre-d3) projects for providing the graphical layout and drawing libraries! + +Thanks also to the [js-sequence-diagram](http://bramp.github.io/js-sequence-diagrams) project for usage of the grammar for the sequence diagrams. Thanks to Jessica Peter for inspiration and starting point for gantt rendering. + +_Mermaid was created by Knut Sveidqvist for easier documentation._ + +_[Tyler Long](https://github.com/tylerlong) has became a collaborator since April 2017._ + +Here is the full list of the projects [contributors](https://github.com/knsv/mermaid/graphs/contributors). From 5a763230e5945a37ad72b5ffd546f9ea0b8392b9 Mon Sep 17 00:00:00 2001 From: NeilCuzon Date: Mon, 9 Mar 2020 23:26:00 -0700 Subject: [PATCH 25/34] Revert "Revert "Revert "Revert "Revert "Update README.md""""" This reverts commit 09e6804761aa7bd8acd1bd3392120f58fa3703b5. --- README.md | 344 +++++++++++++++++++++++++----------------------------- 1 file changed, 157 insertions(+), 187 deletions(-) diff --git a/README.md b/README.md index 791ac115c..781cee7e1 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,26 @@ + +| :mega: :mega: :mega: | +| :----: | +| * If you're upgrading from a version __< v8.2.0__, there are [non-backward-compatible changes](http://mermaid-js.github.io/mermaid/#/usage?id=to-enable-click-event-and-tags-in-nodes) related to security issues. Default behaviour of the library might have changed for your implementation.| + -# Mermaid +# mermaid [![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid) [![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid) [![Coverage Status](https://coveralls.io/repos/github/mermaid-js/mermaid/badge.svg?branch=master)](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) [![This project is using Percy.io for visual regression testing.](https://percy.io/static/images/percy-badge.svg)](https://percy.io/Mermaid/mermaid) -[![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid) -[![Coverage Status](https://coveralls.io/repos/github/knsv/mermaid/badge.svg?branch=master)](https://coveralls.io/github/knsv/mermaid?branch=master) -[![Join the chat at https://gitter.im/knsv/mermaid](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/knsv/mermaid?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +__mermaid is a Javascript based diagramming and charting tool. It generates diagrams flowcharts and more, using markdown-inspired text for ease and speed.__ -![banner](./img/header.png) -# What is mermaid? +Check out the list of [Integrations and Usages of Mermaid](https://github.com/mermaid-js/mermaid/blob/develop/docs/integrations.md) -It is a simple markdown-inspired, script language for diagramming and charting that can be deployed via Javascipt. +For more information and help in getting started, please view our [documentation](http://mermaid-js.github.io/mermaid/) and start simplifying yours. Alternatively, you can also play with our [live editor](https://mermaidjs.github.io/mermaid-live-editor/). + -The reasoning behind it's inception was a need for simplified documentation and frustration with heavy and time consuming tools for explaining code, like Visio. - -Thus mermaid was created to make the process of diagramming and charting, as simple and as close to markdown, as possible. - -Check out the list of [Integrations and Usages of Mermaid](./integrations.md) -For the uninitiated, you can also try out our [live editor](https://mermaid-js.github.io/mermaid-live-editor/) and look at our [documentation](https://mermaid-js.github.io/mermaid/#/n00b-overview) for a deeper understanding of the tool itself, more importantly don't forget to have fun. - -**Mermaid was nominated and won the JS Open Source Awards (2019) in the category "The most exciting use of technology"!!! Thanks to all involved, people committing pull requests, people answering questions and special thanks to Tyler Long who is helping me maintain the project.** +:trophy: **Mermaid was nominated and won the [JS Open Source Awards (2019)](https://osawards.com/javascript/#nominees) in the category "The most exciting use of technology"!!! Thanks to all involved, people committing pull requests, people answering questions and special thanks to Tyler Long who is helping me maintain the project.** ## New diagrams in 8.4 With version 8.4 class diagrams have got some new features, bug fixes and documentation. Another new feature in 8.4 is the new diagram type, state diagrams. -![Image show the two new diagram types](./img/new-diagrams.png) +![Image show the two new diagram types](.docs/img/new-diagrams.png) ## Special note regarding version 8.2 @@ -44,64 +41,82 @@ mermaidAPI.initialize({ }); ``` -**🖖 Keep a steady pulse: mermaid needs more Collaborators [#866](https://github.com/k3nsv/mermaid/issues/866)** +For more information and help in getting started, please view our [documentation](http://mermaid-js.github.io/mermaid/) and start simplifying yours. Play with our [live editor](https://mermaidjs.github.io/mermaid-live-editor/) or jump straight to the [installation and usage](http://mermaid-js.github.io/mermaid/#/usage). + -## The following are examples of Diagrams that mermaid can make: - -### Flowchart - -``` -graph TD; - A-->B; - A-->C; - B-->D; - C-->D; -``` - -![Flowchart](./img/flow.png) - -### Sequence diagram - -``` +__The following are some examples of the diagrams, charts and graphs that can be made using mermaid and the Markdown-inspired text specific to it. Click here jump into the [text syntax](https://mermaid-js.github.io/mermaid/#/n00b-syntaxReference).__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Flow
+ [docs - live editor] +
+graph TD
+A[Hard] -->|Text| B(Round)
+B --> C{Decision}
+C -->|One| D[Result 1]
+C -->|Two| E[Result 2]
+    
+ +
+ Sequence
+ [docs - live editor] +
 sequenceDiagram
-    participant Alice
-    participant Bob
-    Alice->>John: Hello John, how are you?
-    loop Healthcheck
-        John->>John: Fight against hypochondria
-    end
-    Note right of John: Rational thoughts 
prevail! - John-->>Alice: Great! - John->>Bob: How about you? - Bob-->>John: Jolly good! -``` - -![Sequence diagram](./img/sequence.png) - -### Gantt diagram - -``` +Alice->>John: Hello John, how are you? +loop Healthcheck + John->>John: Fight against hypochondria +end +Note right of John: Rational thoughts! +John-->>Alice: Great! +John->>Bob: How about you? +Bob-->>John: Jolly good! +
+ +
+ Gantt
+ [docs - live editor] +
 gantt
-dateFormat  YYYY-MM-DD
-title Adding GANTT diagram to mermaid
-excludes weekdays 2014-01-10
-section A section
-Completed task            :done,    des1, 2014-01-06,2014-01-08
-Active task               :active,  des2, 2014-01-09, 3d
-Future task               :         des3, after des2, 5d
-Future task2               :         des4, after des3, 5d
-```
-
-![Gantt diagram](./img/gantt.png)
-
-### Class diagram - :exclamation: experimental
-
-```
+section Section
+Completed :done,    des1, 2014-01-06,2014-01-08
+Active        :active,  des2, 2014-01-07, 3d
+Parallel 1   :         des3, after des1, 1d
+Parallel 2   :         des4, after des1, 1d
+Parallel 3   :         des5, after des3, 1d
+Parallel 4   :         des6, after des4, 1d
+    
+ +
+ Class
+ [docs - live editor] +
 classDiagram
-Class01 <|-- AveryLongClass : Cool
-Class03 *-- Class04
-Class05 o-- Class06
-Class07 .. Class08
+Class01 <|-- AveryLongClass : Cool
+<<interface>> Class01
 Class09 --> C2 : Where am i?
 Class09 --* C3
 Class09 --|> Class07
@@ -110,129 +125,84 @@ Class07 : Object[] elementData
 Class01 : size()
 Class01 : int chimp
 Class01 : int gorilla
-Class08 <--> C2: Cool label
-```
-
-![Class diagram](./img/class.png)
-
-### Git graph - :exclamation: experimental
-
-```
-gitGraph:
-options
-{
-    "nodeSpacing": 150,
-    "nodeRadius": 10
+class Class10 {
+  <<service>>
+  int id
+  size()
 }
-end
-commit
-branch newbranch
-checkout newbranch
-commit
-commit
-checkout master
-commit
-commit
-merge newbranch
-```
+
+ +
+ State
+ [docs - live editor] +
+stateDiagram
+[*] --> Still
+Still --> [*]
+Still --> Moving
+Moving --> Still
+Moving --> Crash
+Crash --> [*]
+
+ +
+ Pie
+ [docs - live editor] +
+pie
+"Dogs" : 386
+"Cats" : 85
+"Rats" : 15 
+
+ +
+ Git
+ [experimental - live editor] +
Coming soon!
-![Git graph](./img/git.png) +## Related projects -## Installation +- [Command Line Interface](https://github.com/mermaid-js/mermaid.cli) +- [Live Editor](https://github.com/mermaid-js/mermaid-live-editor) -### CDN +# Contributors [![Help wanted](https://img.shields.io/github/labels/mermaid-js/mermaid/Help%20wanted!)](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue+is%3Aopen+label%3A%22Help+wanted%21%22) [![Contributors](https://img.shields.io/github/contributors/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors) [![Commits](https://img.shields.io/github/commit-activity/m/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors) -``` -https://unpkg.com/mermaid@/dist/ -``` +Mermaid is a growing community and is always accepting new contributors. There's a lot of different ways to help out and we're always looking for extra hands! Look at [this issue](https://github.com/mermaid-js/mermaid/issues/866) if you want to know where to start helping out. -Replace `` with expected version number. +Detailed information about how to contribute can be found in the [contribution guide](CONTRIBUTING.md) -Example: https://unpkg.com/mermaid@7.1.0/dist/ +# Appreciation +A quick note from Knut Sveidqvist: +>*Many thanks to the [d3](http://d3js.org/) and [dagre-d3](https://github.com/cpettitt/dagre-d3) projects for providing the graphical layout and drawing libraries!* +>*Thanks also to the [js-sequence-diagram](http://bramp.github.io/js-sequence-diagrams) project for usage of the grammar for the sequence diagrams. Thanks to Jessica Peter for inspiration and starting point for gantt rendering.* +>*Thank you to [Tyler Long](https://github.com/tylerlong) who has been a collaborator since April 2017.* +> +>*Thank you to the ever-growing list of [contributors](https://github.com/knsv/mermaid/graphs/contributors) that brought the project this far!* -### Node.js +--- -``` -yarn add mermaid -``` - -## Documentation - -https://mermaidjs.github.io - -## Sibling projects - -- [mermaid CLI](https://github.com/mermaidjs/mermaid.cli) -- [mermaid live editor](https://github.com/mermaidjs/mermaid-live-editor) -- [mermaid webpack demo](https://github.com/mermaidjs/mermaid-webpack-demo) -- [mermaid Parcel demo](https://github.com/mermaidjs/mermaid-parcel-demo) - -## Request for assistance - -Things are piling up and I have a hard time keeping up. To remedy this -it would be great if we could form a core team of developers to cooperate -with the future development of mermaid. - -As part of this team you would get write access to the repository and would -represent the project when answering questions and issues. - -Together we could continue the work with things like: - -- Adding more types of diagrams like mindmaps, ert diagrams, etc. -- Improving existing diagrams - -Don't hesitate to contact me if you want to get involved. - -## For contributors - -### Setup - -``` -yarn install -``` - -### Build - -``` -yarn build:watch -``` - -### Lint - -``` -yarn lint -``` - -We use [eslint](https://eslint.org/). -We recommend you installing [editor plugins](https://eslint.org/docs/user-guide/integrations) so you can get real time lint result. - -### Test - -``` -yarn test -``` -Manual test in browser: open `dist/index.html` - -### Release - -For those who have the permission to do so: - -Update version number in `package.json`. - -``` -npm publish -``` - -Command above generates files into the `dist` folder and publishes them to npmjs.org. - -## Credits - -Many thanks to the [d3](http://d3js.org/) and [dagre-d3](https://github.com/cpettitt/dagre-d3) projects for providing the graphical layout and drawing libraries! - -Thanks also to the [js-sequence-diagram](http://bramp.github.io/js-sequence-diagrams) project for usage of the grammar for the sequence diagrams. Thanks to Jessica Peter for inspiration and starting point for gantt rendering. - -_Mermaid was created by Knut Sveidqvist for easier documentation._ - -_[Tyler Long](https://github.com/tylerlong) has became a collaborator since April 2017._ - -Here is the full list of the projects [contributors](https://github.com/knsv/mermaid/graphs/contributors). +*Mermaid was created by Knut Sveidqvist for easier documentation.* From 9a6e4ba77fe9e906d71c1f7dc0fd379c5a29d3bf Mon Sep 17 00:00:00 2001 From: Neil Cuzon <58763315+NeilCuzon@users.noreply.github.com> Date: Tue, 10 Mar 2020 19:14:46 -0700 Subject: [PATCH 26/34] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 781cee7e1..83fe09ec7 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ For more information and help in getting started, please view our [documentation With version 8.4 class diagrams have got some new features, bug fixes and documentation. Another new feature in 8.4 is the new diagram type, state diagrams. -![Image show the two new diagram types](.docs/img/new-diagrams.png) +![Image show the two new diagram types](./docs/img/new-diagrams.png) ## Special note regarding version 8.2 From e6910d3c5208b6f39b5589331764b6fbd38ad373 Mon Sep 17 00:00:00 2001 From: Neil Cuzon <58763315+NeilCuzon@users.noreply.github.com> Date: Tue, 10 Mar 2020 19:15:44 -0700 Subject: [PATCH 27/34] Update SUMMARY.md --- docs/SUMMARY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index f40657a49..e4be903f9 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -1,6 +1,6 @@ # Summary -- [mermaid-README](README.md) +- [mermaid](README.md) - [FAQ](faq.md) - [Breaking changes](breakingChanges.md) - [Usage](usage.md) From 71e0a788d1d6de7abcffaead10c21789fe3180e3 Mon Sep 17 00:00:00 2001 From: Neil Cuzon <58763315+NeilCuzon@users.noreply.github.com> Date: Tue, 10 Mar 2020 19:16:24 -0700 Subject: [PATCH 28/34] Update mermaidAPI.md --- docs/mermaidAPI.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/mermaidAPI.md b/docs/mermaidAPI.md index bd4f3787f..7b7b68e06 100644 --- a/docs/mermaidAPI.md +++ b/docs/mermaidAPI.md @@ -2,13 +2,14 @@ ## mermaidAPI -This API can be used optionally handle the integration of mermaid to a web page, instead of using the default integration methods provided by mermaid.js. +This is the api to be used when optionally handling the integration with the web page, instead of using the default integration provided by mermaid.js. -The core of this api is the [**render**][1] function which, renders the given text based input to a graph/diagram, that is returned as an svg element. +The core of this api is the [**render**][1] function which, given a graph +definition as text, renders the graph/diagram and returns an svg element for the graph. -After it is rendered, it is is then up to the user of the API to make use of the svg, which can be either inserted somewhere in the page or something else altogether. +It is is then up to the user of the API to make use of the svg, either insert it somewhere in the page or do something completely different. -In addition to the render function, a number of behavioral configuration options are also available. +In addition to the render function, a number of behavioral configuration options are available. ## Configuration From a9570f7298b88358e320ab5ae9b34859d910f75f Mon Sep 17 00:00:00 2001 From: Neil Cuzon <58763315+NeilCuzon@users.noreply.github.com> Date: Tue, 10 Mar 2020 19:24:55 -0700 Subject: [PATCH 29/34] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 83fe09ec7..781cee7e1 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ For more information and help in getting started, please view our [documentation With version 8.4 class diagrams have got some new features, bug fixes and documentation. Another new feature in 8.4 is the new diagram type, state diagrams. -![Image show the two new diagram types](./docs/img/new-diagrams.png) +![Image show the two new diagram types](.docs/img/new-diagrams.png) ## Special note regarding version 8.2 From 83c6aef0783d3bfce2fb49dbd9a957a81fa4e687 Mon Sep 17 00:00:00 2001 From: Neil Cuzon <58763315+NeilCuzon@users.noreply.github.com> Date: Tue, 10 Mar 2020 19:26:26 -0700 Subject: [PATCH 30/34] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 781cee7e1..83fe09ec7 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ For more information and help in getting started, please view our [documentation With version 8.4 class diagrams have got some new features, bug fixes and documentation. Another new feature in 8.4 is the new diagram type, state diagrams. -![Image show the two new diagram types](.docs/img/new-diagrams.png) +![Image show the two new diagram types](./docs/img/new-diagrams.png) ## Special note regarding version 8.2 From d2685f2544642f7394527f154bd7c6016c19a654 Mon Sep 17 00:00:00 2001 From: Neil Cuzon <58763315+NeilCuzon@users.noreply.github.com> Date: Tue, 10 Mar 2020 19:42:11 -0700 Subject: [PATCH 31/34] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 83fe09ec7..781cee7e1 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ For more information and help in getting started, please view our [documentation With version 8.4 class diagrams have got some new features, bug fixes and documentation. Another new feature in 8.4 is the new diagram type, state diagrams. -![Image show the two new diagram types](./docs/img/new-diagrams.png) +![Image show the two new diagram types](.docs/img/new-diagrams.png) ## Special note regarding version 8.2 From 96b8dce9821c0f1a40cdaaf37978e4e86af84356 Mon Sep 17 00:00:00 2001 From: Neil Cuzon <58763315+NeilCuzon@users.noreply.github.com> Date: Wed, 11 Mar 2020 18:59:06 -0700 Subject: [PATCH 32/34] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 781cee7e1..83fe09ec7 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ For more information and help in getting started, please view our [documentation With version 8.4 class diagrams have got some new features, bug fixes and documentation. Another new feature in 8.4 is the new diagram type, state diagrams. -![Image show the two new diagram types](.docs/img/new-diagrams.png) +![Image show the two new diagram types](./docs/img/new-diagrams.png) ## Special note regarding version 8.2 From 10583610bda772ce82645c333bc8ecc8ce09f379 Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Sat, 14 Mar 2020 08:36:49 +0100 Subject: [PATCH 33/34] Lint fixes --- src/diagrams/flowchart-v2/flowRenderer.js | 1 - src/experimental.js | 1 - 2 files changed, 2 deletions(-) diff --git a/src/diagrams/flowchart-v2/flowRenderer.js b/src/diagrams/flowchart-v2/flowRenderer.js index 10250a16c..1baeeb9ad 100644 --- a/src/diagrams/flowchart-v2/flowRenderer.js +++ b/src/diagrams/flowchart-v2/flowRenderer.js @@ -1,6 +1,5 @@ import graphlib from 'graphlib'; import * as d3 from 'd3'; -import dagre from 'dagre'; import flowDb from '../flowchart/flowDb'; import flow from '../flowchart/parser/flow'; diff --git a/src/experimental.js b/src/experimental.js index d34de469d..e6c3bd806 100644 --- a/src/experimental.js +++ b/src/experimental.js @@ -1,5 +1,4 @@ import dagre from 'dagre'; -import graphlib from 'graphlib'; // Create a new directed graph var g = new dagre.graphlib.Graph({ compound: true }); From d86a7ccf3ef38612942e8dd0ffd96428d2dafaa7 Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Sat, 14 Mar 2020 08:49:30 +0100 Subject: [PATCH 34/34] Restoring docs README --- docs/README.md | 237 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 docs/README.md diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..4fb40e62b --- /dev/null +++ b/docs/README.md @@ -0,0 +1,237 @@ +# Mermaid + +[![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid) +[![Coverage Status](https://coveralls.io/repos/github/knsv/mermaid/badge.svg?branch=master)](https://coveralls.io/github/knsv/mermaid?branch=master) +[![Join the chat at https://gitter.im/knsv/mermaid](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/knsv/mermaid?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +![banner](./img/header.png) + +Generation of diagrams and flowcharts from text in a similar manner as markdown. + +Ever wanted to simplify documentation and avoid heavy tools like Visio when explaining your code? + +This is why mermaid was born, a simple markdown-like script language for generating charts from text via javascript. + +Check out the list of [Integrations and Usages of Mermaid](./integrations.md) + +**Mermaid was nominated and won the JS Open Source Awards (2019) in the category "The most exciting use of technology"!!! Thanks to all involved, people committing pull requests, people answering questions and special thanks to Tyler Long who is helping me maintain the project.** + +## New diagrams in 8.4 + +With version 8.4 class diagrams have got some new features, bug fixes and documentation. Another new feature in 8.4 is the new diagram type, state diagrams. + +![Image show the two new diagram types](./img/new-diagrams.png) + +## Special note regarding version 8.2 + +In version 8.2 a security improvement was introduced. A securityLevel configuration was introduced which sets the level of trust to be used on the parsed diagrams. + +- **true**: (default) tags in text are encoded, click functionality is disabled +- false: tags in text are allowed, click functionality is enabled + +Closed issues: + +⚠️ **Note** : This changes the default behaviour of mermaid so that after upgrade to 8.2, if the securityLevel is not configured, tags in flowcharts are encoded as tags and clicking is prohibited. + +If your application is taking resposibility for the diagram source security you can set the securityLevel accordingly. By doing this clicks and tags are again allowed. + +```javascript +mermaidAPI.initialize({ + securityLevel: 'loose' +}); +``` + +**🖖 Keep a steady pulse: mermaid needs more Collaborators [#866](https://github.com/knsv/mermaid/issues/866)** + +## Diagrams + +### Flowchart + +``` +graph TD; + A-->B; + A-->C; + B-->D; + C-->D; +``` + +![Flowchart](./img/flow.png) + +### Sequence diagram + +``` +sequenceDiagram + participant Alice + participant Bob + Alice->>John: Hello John, how are you? + loop Healthcheck + John->>John: Fight against hypochondria + end + Note right of John: Rational thoughts
prevail! + John-->>Alice: Great! + John->>Bob: How about you? + Bob-->>John: Jolly good! +``` + +![Sequence diagram](./img/sequence.png) + +### Gantt diagram + +``` +gantt +dateFormat YYYY-MM-DD +title Adding GANTT diagram to mermaid +excludes weekdays 2014-01-10 + +section A section +Completed task :done, des1, 2014-01-06,2014-01-08 +Active task :active, des2, 2014-01-09, 3d +Future task : des3, after des2, 5d +Future task2 : des4, after des3, 5d +``` + +![Gantt diagram](./img/gantt.png) + +### Class diagram - :exclamation: experimental + +``` +classDiagram +Class01 <|-- AveryLongClass : Cool +Class03 *-- Class04 +Class05 o-- Class06 +Class07 .. Class08 +Class09 --> C2 : Where am i? +Class09 --* C3 +Class09 --|> Class07 +Class07 : equals() +Class07 : Object[] elementData +Class01 : size() +Class01 : int chimp +Class01 : int gorilla +Class08 <--> C2: Cool label +``` + +![Class diagram](./img/class.png) + +### Git graph - :exclamation: experimental + +``` +gitGraph: +options +{ + "nodeSpacing": 150, + "nodeRadius": 10 +} +end +commit +branch newbranch +checkout newbranch +commit +commit +checkout master +commit +commit +merge newbranch + +``` + +![Git graph](./img/git.png) + +## Installation + +### CDN + +``` +https://unpkg.com/mermaid@/dist/ +``` + +Replace `` with expected version number. + +Example: https://unpkg.com/mermaid@7.1.0/dist/ + +### Node.js + +``` +yarn add mermaid +``` + +## Documentation + +https://mermaidjs.github.io + +## Sibling projects + +- [mermaid CLI](https://github.com/mermaidjs/mermaid.cli) +- [mermaid live editor](https://github.com/mermaidjs/mermaid-live-editor) +- [mermaid webpack demo](https://github.com/mermaidjs/mermaid-webpack-demo) +- [mermaid Parcel demo](https://github.com/mermaidjs/mermaid-parcel-demo) + +## Request for assistance + +Things are piling up and I have a hard time keeping up. To remedy this +it would be great if we could form a core team of developers to cooperate +with the future development of mermaid. + +As part of this team you would get write access to the repository and would +represent the project when answering questions and issues. + +Together we could continue the work with things like: + +- Adding more types of diagrams like mindmaps, ert diagrams, etc. +- Improving existing diagrams + +Don't hesitate to contact me if you want to get involved. + +## For contributors + +### Setup + +``` +yarn install +``` + +### Build + +``` +yarn build:watch +``` + +### Lint + +``` +yarn lint +``` + +We use [eslint](https://eslint.org/). +We recommend you installing [editor plugins](https://eslint.org/docs/user-guide/integrations) so you can get real time lint result. + +### Test + +``` +yarn test +``` +Manual test in browser: open `dist/index.html` + +### Release + +For those who have the permission to do so: + +Update version number in `package.json`. + +``` +npm publish +``` + +Command above generates files into the `dist` folder and publishes them to npmjs.org. + +## Credits + +Many thanks to the [d3](http://d3js.org/) and [dagre-d3](https://github.com/cpettitt/dagre-d3) projects for providing the graphical layout and drawing libraries! + +Thanks also to the [js-sequence-diagram](http://bramp.github.io/js-sequence-diagrams) project for usage of the grammar for the sequence diagrams. Thanks to Jessica Peter for inspiration and starting point for gantt rendering. + +_Mermaid was created by Knut Sveidqvist for easier documentation._ + +_[Tyler Long](https://github.com/tylerlong) has became a collaborator since April 2017._ + +Here is the full list of the projects [contributors](https://github.com/knsv/mermaid/graphs/contributors).