react-modeling
Version:
Collection of modeling utils
1,480 lines (1,374 loc) • 63 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var React = require('react');
var mermaid = require('mermaid');
var lodash = _interopDefault(require('lodash'));
var dagre$1 = _interopDefault(require('dagre'));
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _objectSpread(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i] != null ? arguments[i] : {};
var ownKeys = Object.keys(source);
if (typeof Object.getOwnPropertySymbols === 'function') {
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
}));
}
ownKeys.forEach(function (key) {
_defineProperty(target, key, source[key]);
});
}
return target;
}
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
return target;
}
function _objectWithoutProperties(source, excluded) {
if (source == null) return {};
var target = _objectWithoutPropertiesLoose(source, excluded);
var key, i;
if (Object.getOwnPropertySymbols) {
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
for (i = 0; i < sourceSymbolKeys.length; i++) {
key = sourceSymbolKeys[i];
if (excluded.indexOf(key) >= 0) continue;
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
target[key] = source[key];
}
}
return target;
}
function factory(tag, drawwer) {
return function (props) {
var domRef = React.useRef();
var defaultContent = props.defaultContent,
children = props.children,
rest = _objectWithoutProperties(props, ["defaultContent", "children"]);
function draw(content) {
drawwer(content, domRef.current, props);
}
React.useEffect(function () {
if (!children && defaultContent) draw(defaultContent);
}, []);
React.useEffect(function () {
if (children) draw(children);
}, [children]);
return React.createElement(tag, _objectSpread({
ref: domRef
}, rest));
};
}
var Mermaid = factory("div", function (content, node, _ref) {
var onError = _ref.onError;
if (node) try {
var id = 'mermaid_draw';
var insertSvg = function insertSvg(svgCode, bindFunctions) {
node.innerHTML = svgCode;
};
var graph = mermaid.mermaidAPI.render(id, content, insertSvg, node);
} catch (e) {
console.error(e);
onError && onError(e, content);
}
});
function createCommonjsModule(fn, module) {
return module = { exports: {} }, fn(module, module.exports), module.exports;
}
var nomnoml = createCommonjsModule(function (module) {
(function (factoryFn) {
if (module.exports)
module.exports = factoryFn(lodash, dagre$1);
else this.nomnoml = factoryFn(_, dagre);
})(function (_, dagre) {
var skanaar = skanaar || {};
skanaar.Canvas = function (canvas, callbacks){
var ctx = canvas.getContext('2d');
var mousePos = { x: 0, y: 0 };
var twopi = 2*3.1416;
function mouseEventToPos(event){
var e = canvas;
return {
x: event.clientX - e.getBoundingClientRect().left - e.clientLeft + e.scrollLeft,
y: event.clientY - e.getBoundingClientRect().top - e.clientTop + e.scrollTop
}
}
if (callbacks) {
canvas.addEventListener('mousedown', function (event){
if (callbacks.mousedown) callbacks.mousedown(mouseEventToPos(event));
});
canvas.addEventListener('mouseup', function (event){
if (callbacks.mouseup) callbacks.mouseup(mouseEventToPos(event));
});
canvas.addEventListener('mousemove', function (event){
mousePos = mouseEventToPos(event);
if (callbacks.mousemove) callbacks.mousemove(mouseEventToPos(event));
});
}
var chainable = {
stroke: function (){
ctx.stroke();
return chainable
},
fill: function (){
ctx.fill();
return chainable
},
fillAndStroke: function (){
ctx.fill();
ctx.stroke();
return chainable
}
};
function color255(r, g, b, a){
var optionalAlpha = a === undefined ? 1 : a;
var comps = [Math.floor(r), Math.floor(g), Math.floor(b), optionalAlpha];
return 'rgba('+ comps.join() +')'
}
function tracePath(path, offset, s){
s = s === undefined ? 1 : s;
offset = offset || {x:0, y:0};
ctx.beginPath();
ctx.moveTo(offset.x + s*path[0].x, offset.y + s*path[0].y);
for(var i=1, len=path.length; i<len; i++)
ctx.lineTo(offset.x + s*path[i].x, offset.y + s*path[i].y);
return chainable
}
return {
mousePos: function (){ return mousePos },
width: function (){ return canvas.width },
height: function (){ return canvas.height },
ctx: ctx,
background: function (r, g, b){
ctx.fillStyle = color255(r, g, b);
ctx.fillRect (0, 0, canvas.width, canvas.height);
},
clear: function (){
ctx.clearRect(0, 0, canvas.width, canvas.height);
},
circle: function (x, y, r){
ctx.beginPath();
if (arguments.length === 2)
ctx.arc(x.x, x.y, y, 0, twopi);
else
ctx.arc(x, y, r, 0, twopi);
return chainable
},
ellipse: function (center, rx, ry, start, stop){
if (start === undefined) start = 0;
if (stop === undefined) stop = twopi;
ctx.beginPath();
ctx.save();
ctx.translate(center.x, center.y);
ctx.scale(1, ry/rx);
ctx.arc(0, 0, rx/2, start, stop);
ctx.restore();
return chainable
},
arc: function (x, y, r, start, stop){
ctx.beginPath();
ctx.moveTo(x,y);
ctx.arc(x, y, r, start, stop);
return chainable
},
roundRect: function (x, y, w, h, r){
ctx.beginPath();
ctx.moveTo(x+r, y);
ctx.arcTo(x+w, y, x+w, y+r, r);
ctx.lineTo(x+w, y+h-r);
ctx.arcTo(x+w, y+h, x+w-r, y+h, r);
ctx.lineTo(x+r, y+h);
ctx.arcTo(x, y+h, x, y+h-r, r);
ctx.lineTo(x, y+r);
ctx.arcTo(x, y, x+r, y, r);
ctx.closePath();
return chainable
},
rect: function (x, y, w, h){
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x+w, y);
ctx.lineTo(x+w, y+h);
ctx.lineTo(x, y+h);
ctx.closePath();
return chainable
},
path: tracePath,
circuit: function (path, offset, s){
tracePath(path, offset, s);
ctx.closePath();
return chainable
},
colorNorm: function (r, g, b, a){
return color255(255*r, 255*g, 255*b, a)
},
color255: color255,
colorObjHSL: function (hue, sat, lit){
function component(v){
var x = Math.cos(6.283*v)/2 + 0.5;
return lit*(1-sat + sat*x*x)
}
return {
r: component(hue),
g: component(hue-1/3),
b: component(hue+1/3)
}
},
radialGradient: function (x, y, r1, r2, colors){
var grad = ctx.createRadialGradient(x, y, r1, x, y, r2);
for(var key in colors)
if (colors.hasOwnProperty(key))
grad.addColorStop(key, colors[key]);
return grad
},
font: function (f){ ctx.font = f; },
fillStyle: function (s){ ctx.fillStyle = s; },
strokeStyle: function (s){ ctx.strokeStyle = s; },
textAlign: function (a){ ctx.textAlign = a; },
lineCap: function (cap){ ctx.lineCap = cap; },
lineJoin: function (join){ ctx.lineJoin = join; },
lineWidth: function (w){ ctx.lineWidth = w; },
arcTo: function (){ return ctx.arcTo.apply( ctx, arguments) },
beginPath: function (){ return ctx.beginPath.apply( ctx, arguments) },
fillText: function (){ return ctx.fillText.apply( ctx, arguments) },
lineTo: function (){ return ctx.lineTo.apply( ctx, arguments) },
measureText: function (){ return ctx.measureText.apply(ctx, arguments) },
moveTo: function (){ return ctx.moveTo.apply( ctx, arguments) },
restore: function (){ return ctx.restore.apply( ctx, arguments) },
save: function (){ return ctx.save.apply( ctx, arguments) },
scale: function (){ return ctx.scale.apply( ctx, arguments) },
setLineDash: function (){ return ctx.setLineDash.apply(ctx, arguments) },
stroke: function (){ return ctx.stroke.apply( ctx, arguments) },
translate: function (){ return ctx.translate.apply( ctx, arguments) }
}
};
var skanaar = skanaar || {};
skanaar.sum = function sum(list, plucker){
var transform = {
'undefined': _.identity,
'string': function (obj){ return obj[plucker] },
'number': function (obj){ return obj[plucker] },
'function': plucker
}[typeof plucker];
for(var i=0, summation=0, len=list.length; i<len; i++)
summation += transform(list[i]);
return summation
};
skanaar.hasSubstring = function hasSubstring(haystack, needle){
if (needle === '') return true
if (!haystack) return false
return haystack.indexOf(needle) !== -1
};
skanaar.format = function format(template /* variadic params */){
var parts = Array.prototype.slice.call(arguments, 1);
return _.flatten(_.zip(template.split('#'), parts)).join('')
};
skanaar.indexBy = function (list, key) {
var obj = {};
for(var i=0; i<list.length; i++)
obj[list[i][key]] = list[i];
return obj
};
var skanaar = skanaar || {};
skanaar.vector = {
dist: function (a,b){ return skanaar.vector.mag(skanaar.vector.diff(a,b)) },
add: function (a,b){ return { x: a.x + b.x, y: a.y + b.y } },
diff: function (a,b){ return { x: a.x - b.x, y: a.y - b.y } },
mult: function (v,factor){ return { x: factor*v.x, y: factor*v.y } },
mag: function (v){ return Math.sqrt(v.x*v.x + v.y*v.y) },
normalize: function (v){ return skanaar.vector.mult(v, 1/skanaar.vector.mag(v)) },
rot: function (a){ return { x: a.y, y: -a.x } }
};
var skanaar = skanaar || {};
skanaar.Svg = function (globalStyle, canvas){
var initialState = {
x: 0,
y: 0,
stroke: 'none',
dashArray: 'none',
fill: 'none',
textAlign: 'left'
};
var states = [initialState];
var elements = [];
// canvas is an optional parameter
canvas = canvas || 0;
var ctx = canvas ? canvas.getContext('2d') : null;
var canUseCanvas = false;
var waitingForFirstFont = true;
var docFont = '';
function Element(name, attr, content) {
attr.style = attr.style || '';
return {
name: name,
attr: attr,
content: content || undefined,
stroke: function (){
this.attr.style += 'stroke:'+lastDefined('stroke')+
';fill:none;stroke-dasharray:' + lastDefined('dashArray') + ';';
return this
},
fill: function (){
this.attr.style += 'stroke:none; fill:'+lastDefined('fill')+';';
return this
},
fillAndStroke: function (){
this.attr.style += 'stroke:'+lastDefined('stroke')+';fill:'+lastDefined('fill')+
';stroke-dasharray:' + lastDefined('dashArray') + ';';
return this
}
}
}
function State(dx, dy){
return { x: dx, y: dy, stroke: null, fill: null, textAlign: null }
}
function trans(coord, axis){
states.forEach(function (t){ coord += t[axis]; });
return coord
}
function tX(coord){ return Math.round(10*trans(coord, 'x'))/10 }
function tY(coord){ return Math.round(10*trans(coord, 'y'))/10 }
function lastDefined(property){
for(var i=states.length-1; i>=0; i--)
if (states[i][property])
return states[i][property]
return undefined
}
function last(list){ return list[list.length-1] }
function tracePath(path, offset, s){
s = s === undefined ? 1 : s;
offset = offset || {x:0, y:0};
var d = path.map(function (e, i){
return (i ? 'L' : 'M') + tX(offset.x + s*e.x) + ' ' + tY(offset.y + s*e.y)
}).join(' ');
return newElement('path', { d: d })
}
function newElement(type, attr, content) {
var element = Element(type, attr, content);
elements.push(element);
return element
}
return {
width: function (){ return elements.width },
height: function (){ return elements.height },
background: function (/*r, g, b*/){},
clear: function (){},
circle: function (x, y, r){
var attr = (arguments.length === 2) ?
{r: y, cx: tX(x.x), cy: tY(x.y)} :
{r: r, cx: tX(x), cy: tY(y)};
var element = Element('circle', attr);
elements.push(element);
return element
},
ellipse: function (center, w, h, start, stop){
if (stop) {
// This code does not render a general partial ellipse. It only
// renders the bottom half of an ellipse. Useful for database visuals.
var y = tY(center.y);
return newElement('path', { d:
'M' + tX(center.x - w/2) + ' ' + y +
'A' + w/2 + ' ' + h/2 + ' 0 1 0 ' + tX(center.x + w/2) + ' ' + y
})
} else {
return newElement('ellipse',
{ cx: tX(center.x), cy: tY(center.y), rx: w/2, ry: h/2 })
}
},
arc: function (x, y, r /*, start, stop*/){
return newElement('ellipse',
{ cx: tX(x), cy: tY(y), rx: r, ry: r })
},
roundRect: function (x, y, w, h, r){
return newElement('rect',
{ x: tX(x), y: tY(y), rx: r, ry: r, height: h, width: w })
},
rect: function (x, y, w, h){
return newElement('rect',
{ x: tX(x), y: tY(y), height: h, width: w })
},
path: tracePath,
circuit: function (path, offset, s){
var element = tracePath(path, offset, s);
element.attr.d += ' Z';
return element
},
font: function (font){
last(states).font = font;
if (waitingForFirstFont) {
// This is our first chance to test if we can use a canvas to measure text width.
if (ctx) {
var primaryFont = font.replace(/^.*family:/, '').replace(/[, ].*$/, '');
primaryFont = primaryFont.replace(/'/g, '');
canUseCanvas = /^(Arial|Helvetica|Times|Times New Roman)$/.test(primaryFont);
if (canUseCanvas) {
var fontSize = font.replace(/^.*font-size:/, '').replace(/;.*$/, '') + ' ';
if (primaryFont === 'Arial') {
docFont = fontSize + 'Arial, Helvetica, sans-serif';
} else if (primaryFont === 'Helvetica') {
docFont = fontSize + 'Helvetica, Arial, sans-serif';
} else if (primaryFont === 'Times New Roman') {
docFont = fontSize + '"Times New Roman", Times, serif';
} else if (primaryFont === 'Times') {
docFont = fontSize + 'Times, "Times New Roman", serif';
}
}
}
waitingForFirstFont = false;
}
},
strokeStyle: function (stroke){
last(states).stroke = stroke;
},
fillStyle: function (fill){
last(states).fill = fill;
},
arcTo: function (x1, y1, x2, y2){
last(elements).attr.d += ('L'+tX(x1)+' '+tY(y1)+' L'+tX(x2)+' '+tY(y2)+' ');
},
beginPath: function (){
return newElement('path', {d:''})
},
fillText: function (text, x, y){
if (lastDefined('textAlign') === 'center')
x -= this.measureText(text).width/2;
var attr = { x: tX(x), y: tY(y), style: '' };
var font = lastDefined('font');
if (font.indexOf('bold') === -1) {
attr.style = 'font-weight:normal;';
}
if (font.indexOf('italic') > -1) {
attr.style += 'font-style:italic;';
}
return newElement('text', attr, _.escape(text))
},
lineCap: function (cap){ globalStyle += ';stroke-linecap:'+cap; },
lineJoin: function (join){ globalStyle += ';stroke-linejoin:'+join; },
lineTo: function (x, y){
last(elements).attr.d += ('L' + tX(x) + ' ' + tY(y) + ' ');
},
lineWidth: function (w){ globalStyle += ';stroke-width:'+w;},
measureText: function (s){
if (canUseCanvas) {
var fontStr = lastDefined('font');
var italicSpec = (/\bitalic\b/.test(fontStr) ? 'italic' : 'normal') + ' normal ';
var boldSpec = /\bbold\b/.test(fontStr) ? 'bold ' : 'normal ';
ctx.font = italicSpec + boldSpec + docFont;
return ctx.measureText(s)
} else {
return {
width: skanaar.sum(s, function (c){
if (c === 'M' || c === 'W') { return 14 }
return c.charCodeAt(0) < 200 ? 9.5 : 16
})
}
}
},
moveTo: function (x, y){
last(elements).attr.d += ('M' + tX(x) + ' ' + tY(y) + ' ');
},
restore: function (){
states.pop();
},
save: function (){
states.push(State(0, 0));
},
scale: function (){},
setLineDash: function (d){
last(states).dashArray = (d.length === 0) ? 'none' : d[0] + ' ' + d[1];
},
stroke: function (){
last(elements).stroke();
},
textAlign: function (a){
last(states).textAlign = a;
},
translate: function (dx, dy){
last(states).x += dx;
last(states).y += dy;
},
serialize: function (_attributes){
var attrs = _attributes || {};
attrs.version = attrs.version || '1.1';
attrs.baseProfile = attrs.baseProfile || 'full';
attrs.width = attrs.width || '100%';
attrs.height = attrs.height || '100%';
if(attrs.width !== '100%' && attrs.height != '100%') {
attrs.viewbox = '0 0 ' + attrs.width + ' ' + attrs.height;
}
attrs.xmlns = attrs.xmlns || 'http://www.w3.org/2000/svg';
attrs['xmlns:xlink'] = attrs['xmlns:xlink'] || 'http://www.w3.org/1999/xlink';
attrs['xmlns:ev'] = attrs['xmlns:ev'] || 'http://www.w3.org/2001/xml-events';
attrs.style = attrs.style || lastDefined('font') + ';' + globalStyle;
function toAttr(obj){
function toKeyValue(key){ return key + '="' + obj[key] + '"' }
return Object.keys(obj).map(toKeyValue).join(' ')
}
function toHtml(e){
return '<'+e.name+' '+toAttr(e.attr)+'>'+(e.content || '')+'</'+e.name+'>'
}
var innerSvg = elements.map(toHtml).join('\n');
return toHtml(Element('svg', attrs, innerSvg))
}
}
};
/* parser generated by jison 0.4.13 */
/*
Returns a Parser object of the following structure:
Parser: {
yy: {}
}
Parser.prototype: {
yy: {},
trace: function(),
symbols_: {associative list: name ==> number},
terminals_: {associative list: number ==> name},
productions_: [...],
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$),
table: [...],
defaultActions: {...},
parseError: function(str, hash),
parse: function(input),
lexer: {
EOF: 1,
parseError: function(str, hash),
setInput: function(input),
input: function(),
unput: function(str),
more: function(),
less: function(n),
pastInput: function(),
upcomingInput: function(),
showPosition: function(),
test_match: function(regex_match_array, rule_index),
next: function(),
lex: function(),
begin: function(condition),
popState: function(),
_currentRules: function(),
topState: function(),
pushState: function(condition),
options: {
ranges: boolean (optional: true ==> token location info will include a .range[] member)
flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match)
backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code)
},
performAction: function(yy, yy_, $avoiding_name_collisions, YY_START),
rules: [...],
conditions: {associative list: name ==> set},
}
}
token location info (@$, _$, etc.): {
first_line: n,
last_line: n,
first_column: n,
last_column: n,
range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based)
}
the parseError function receives a 'hash' object with these members for lexer and parser errors: {
text: (matched text)
token: (the produced terminal token, if any)
line: (yylineno)
}
while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: {
loc: (yylloc)
expected: (string describing the set of expected tokens)
recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
}
*/
var nomnomlCoreParser = (function(){
var parser = {trace: function trace () { },
yy: {},
symbols_: {"error":2,"root":3,"compartment":4,"EOF":5,"slot":6,"IDENT":7,"class":8,"association":9,"SEP":10,"parts":11,"|":12,"[":13,"]":14,"$accept":0,"$end":1},
terminals_: {2:"error",5:"EOF",7:"IDENT",10:"SEP",12:"|",13:"[",14:"]"},
productions_: [0,[3,2],[6,1],[6,1],[6,1],[4,1],[4,3],[11,1],[11,3],[11,2],[9,3],[8,3]],
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */
) {
/* this == yyval */
var $0 = $$.length - 1;
switch (yystate) {
case 1: return $$[$0-1]
break;
case 2:this.$ = $$[$0].trim().replace(/\\(\[|\]|\|)/g, '$'+'1');
break;
case 3:this.$ = $$[$0];
break;
case 4:this.$ = $$[$0];
break;
case 5:this.$ = [$$[$0]];
break;
case 6:this.$ = $$[$0-2].concat($$[$0]);
break;
case 7:this.$ = [$$[$0]];
break;
case 8:this.$ = $$[$0-2].concat([$$[$0]]);
break;
case 9:this.$ = $$[$0-1].concat([[]]);
break;
case 10:
var t = $$[$0-1].trim().replace(/\\(\[|\]|\|)/g, '$'+'1').match('^(.*?)([<:o+]*-/?-*[:o+>]*)(.*)$');
this.$ = {assoc:t[2], start:$$[$0-2], end:$$[$0], startLabel:t[1].trim(), endLabel:t[3].trim()};
break;
case 11:
var type = 'CLASS';
var id = $$[$0-1][0][0];
var typeMatch = $$[$0-1][0][0].match('<([a-z]*)>(.*)');
if (typeMatch) {
type = typeMatch[1].toUpperCase();
id = typeMatch[2].trim();
}
$$[$0-1][0][0] = id;
this.$ = {type:type, id:id, parts:$$[$0-1]};
break;
}
},
table: [{3:1,4:2,6:3,7:[1,4],8:5,9:6,13:[1,7]},{1:[3]},{5:[1,8],10:[1,9]},{5:[2,5],10:[2,5],12:[2,5],14:[2,5]},{5:[2,2],10:[2,2],12:[2,2],14:[2,2]},{5:[2,3],7:[1,10],10:[2,3],12:[2,3],14:[2,3]},{5:[2,4],10:[2,4],12:[2,4],14:[2,4]},{4:12,6:3,7:[1,4],8:5,9:6,11:11,13:[1,7]},{1:[2,1]},{6:13,7:[1,4],8:5,9:6,13:[1,7]},{8:14,13:[1,7]},{12:[1,16],14:[1,15]},{10:[1,9],12:[2,7],14:[2,7]},{5:[2,6],10:[2,6],12:[2,6],14:[2,6]},{5:[2,10],10:[2,10],12:[2,10],14:[2,10]},{5:[2,11],7:[2,11],10:[2,11],12:[2,11],14:[2,11]},{4:17,6:3,7:[1,4],8:5,9:6,12:[2,9],13:[1,7],14:[2,9]},{10:[1,9],12:[2,8],14:[2,8]}],
defaultActions: {8:[2,1]},
parseError: function parseError (str, hash) {
if (hash.recoverable) {
this.trace(str);
} else {
throw new Error(str);
}
},
parse: function parse(input) {
var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, TERROR = 2, EOF = 1;
var args = lstack.slice.call(arguments, 1);
this.lexer.setInput(input);
this.lexer.yy = this.yy;
this.yy.lexer = this.lexer;
this.yy.parser = this;
if (typeof this.lexer.yylloc == 'undefined') {
this.lexer.yylloc = {};
}
var yyloc = this.lexer.yylloc;
lstack.push(yyloc);
var ranges = this.lexer.options && this.lexer.options.ranges;
if (typeof this.yy.parseError === 'function') {
this.parseError = this.yy.parseError;
} else {
this.parseError = Object.getPrototypeOf(this).parseError;
}
function lex() {
var token;
token = self.lexer.lex() || EOF;
if (typeof token !== 'number') {
token = self.symbols_[token] || token;
}
return token;
}
var symbol, preErrorSymbol, state, action, r, yyval = {}, p, len, newState, expected;
while (true) {
state = stack[stack.length - 1];
if (this.defaultActions[state]) {
action = this.defaultActions[state];
} else {
if (symbol === null || typeof symbol == 'undefined') {
symbol = lex();
}
action = table[state] && table[state][symbol];
}
if (typeof action === 'undefined' || !action.length || !action[0]) {
var errStr = '';
expected = [];
for (p in table[state]) {
if (this.terminals_[p] && p > TERROR) {
expected.push('\'' + this.terminals_[p] + '\'');
}
}
if (this.lexer.showPosition) {
errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + this.lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
} else {
errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
}
this.parseError(errStr, {
text: this.lexer.match,
token: this.terminals_[symbol] || symbol,
line: this.lexer.yylineno,
loc: yyloc,
expected: expected
});
}
if (action[0] instanceof Array && action.length > 1) {
throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
}
switch (action[0]) {
case 1:
stack.push(symbol);
vstack.push(this.lexer.yytext);
lstack.push(this.lexer.yylloc);
stack.push(action[1]);
symbol = null;
if (!preErrorSymbol) {
yyleng = this.lexer.yyleng;
yytext = this.lexer.yytext;
yylineno = this.lexer.yylineno;
yyloc = this.lexer.yylloc;
} else {
symbol = preErrorSymbol;
preErrorSymbol = null;
}
break;
case 2:
len = this.productions_[action[1]][1];
yyval.$ = vstack[vstack.length - len];
yyval._$ = {
first_line: lstack[lstack.length - (len || 1)].first_line,
last_line: lstack[lstack.length - 1].last_line,
first_column: lstack[lstack.length - (len || 1)].first_column,
last_column: lstack[lstack.length - 1].last_column
};
if (ranges) {
yyval._$.range = [
lstack[lstack.length - (len || 1)].range[0],
lstack[lstack.length - 1].range[1]
];
}
r = this.performAction.apply(yyval, [
yytext,
yyleng,
yylineno,
this.yy,
action[1],
vstack,
lstack
].concat(args));
if (typeof r !== 'undefined') {
return r;
}
if (len) {
stack = stack.slice(0, -1 * len * 2);
vstack = vstack.slice(0, -1 * len);
lstack = lstack.slice(0, -1 * len);
}
stack.push(this.productions_[action[1]][0]);
vstack.push(yyval.$);
lstack.push(yyval._$);
newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
stack.push(newState);
break;
case 3:
return true;
}
}
return true;
}};
/* generated by jison-lex 0.2.1 */
var lexer = (function(){
var lexer = {
EOF:1,
parseError:function parseError(str, hash) {
if (this.yy.parser) {
this.yy.parser.parseError(str, hash);
} else {
throw new Error(str);
}
},
// resets the lexer, sets new input
setInput:function (input) {
this._input = input;
this._more = this._backtrack = this.done = false;
this.yylineno = this.yyleng = 0;
this.yytext = this.matched = this.match = '';
this.conditionStack = ['INITIAL'];
this.yylloc = {
first_line: 1,
first_column: 0,
last_line: 1,
last_column: 0
};
if (this.options.ranges) {
this.yylloc.range = [0,0];
}
this.offset = 0;
return this;
},
// consumes and returns one char from the input
input:function () {
var ch = this._input[0];
this.yytext += ch;
this.yyleng++;
this.offset++;
this.match += ch;
this.matched += ch;
var lines = ch.match(/(?:\r\n?|\n).*/g);
if (lines) {
this.yylineno++;
this.yylloc.last_line++;
} else {
this.yylloc.last_column++;
}
if (this.options.ranges) {
this.yylloc.range[1]++;
}
this._input = this._input.slice(1);
return ch;
},
// unshifts one char (or a string) into the input
unput:function (ch) {
var len = ch.length;
var lines = ch.split(/(?:\r\n?|\n)/g);
this._input = ch + this._input;
this.yytext = this.yytext.substr(0, this.yytext.length - len - 1);
//this.yyleng -= len;
this.offset -= len;
var oldLines = this.match.split(/(?:\r\n?|\n)/g);
this.match = this.match.substr(0, this.match.length - 1);
this.matched = this.matched.substr(0, this.matched.length - 1);
if (lines.length - 1) {
this.yylineno -= lines.length - 1;
}
var r = this.yylloc.range;
this.yylloc = {
first_line: this.yylloc.first_line,
last_line: this.yylineno + 1,
first_column: this.yylloc.first_column,
last_column: lines ?
(lines.length === oldLines.length ? this.yylloc.first_column : 0)
+ oldLines[oldLines.length - lines.length].length - lines[0].length :
this.yylloc.first_column - len
};
if (this.options.ranges) {
this.yylloc.range = [r[0], r[0] + this.yyleng - len];
}
this.yyleng = this.yytext.length;
return this;
},
// When called from action, caches matched text and appends it on next action
more:function () {
this._more = true;
return this;
},
// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
reject:function () {
if (this.options.backtrack_lexer) {
this._backtrack = true;
} else {
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
text: "",
token: null,
line: this.yylineno
});
}
return this;
},
// retain first n characters of the match
less:function (n) {
this.unput(this.match.slice(n));
},
// displays already matched input, i.e. for error messages
pastInput:function () {
var past = this.matched.substr(0, this.matched.length - this.match.length);
return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
},
// displays upcoming input, i.e. for error messages
upcomingInput:function () {
var next = this.match;
if (next.length < 20) {
next += this._input.substr(0, 20-next.length);
}
return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
},
// displays the character position where the lexing error occurred, i.e. for error messages
showPosition:function () {
var pre = this.pastInput();
var c = new Array(pre.length + 1).join("-");
return pre + this.upcomingInput() + "\n" + c + "^";
},
// test the lexed token: return FALSE when not a match, otherwise return token
test_match:function(match, indexed_rule) {
var token,
lines,
backup;
if (this.options.backtrack_lexer) {
// save context
backup = {
yylineno: this.yylineno,
yylloc: {
first_line: this.yylloc.first_line,
last_line: this.last_line,
first_column: this.yylloc.first_column,
last_column: this.yylloc.last_column
},
yytext: this.yytext,
match: this.match,
matches: this.matches,
matched: this.matched,
yyleng: this.yyleng,
offset: this.offset,
_more: this._more,
_input: this._input,
yy: this.yy,
conditionStack: this.conditionStack.slice(0),
done: this.done
};
if (this.options.ranges) {
backup.yylloc.range = this.yylloc.range.slice(0);
}
}
lines = match[0].match(/(?:\r\n?|\n).*/g);
if (lines) {
this.yylineno += lines.length;
}
this.yylloc = {
first_line: this.yylloc.last_line,
last_line: this.yylineno + 1,
first_column: this.yylloc.last_column,
last_column: lines ?
lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length :
this.yylloc.last_column + match[0].length
};
this.yytext += match[0];
this.match += match[0];
this.matches = match;
this.yyleng = this.yytext.length;
if (this.options.ranges) {
this.yylloc.range = [this.offset, this.offset += this.yyleng];
}
this._more = false;
this._backtrack = false;
this._input = this._input.slice(match[0].length);
this.matched += match[0];
token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
if (this.done && this._input) {
this.done = false;
}
if (token) {
return token;
} else if (this._backtrack) {
// recover context
for (var k in backup) {
this[k] = backup[k];
}
return false; // rule action called reject() implying the next rule should be tested instead.
}
return false;
},
// return next match in input
next:function () {
if (this.done) {
return this.EOF;
}
if (!this._input) {
this.done = true;
}
var token,
match,
tempMatch,
index;
if (!this._more) {
this.yytext = '';
this.match = '';
}
var rules = this._currentRules();
for (var i = 0; i < rules.length; i++) {
tempMatch = this._input.match(this.rules[rules[i]]);
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
match = tempMatch;
index = i;
if (this.options.backtrack_lexer) {
token = this.test_match(tempMatch, rules[i]);
if (token !== false) {
return token;
} else if (this._backtrack) {
match = false;
continue; // rule action called reject() implying a rule MISmatch.
} else {
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
return false;
}
} else if (!this.options.flex) {
break;
}
}
}
if (match) {
token = this.test_match(match, rules[index]);
if (token !== false) {
return token;
}
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
return false;
}
if (this._input === "") {
return this.EOF;
} else {
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
text: "",
token: null,
line: this.yylineno
});
}
},
// return next match that has a token
lex:function lex () {
var r = this.next();
if (r) {
return r;
} else {
return this.lex();
}
},
// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
begin:function begin (condition) {
this.conditionStack.push(condition);
},
// pop the previously active lexer condition state off the condition stack
popState:function popState () {
var n = this.conditionStack.length - 1;
if (n > 0) {
return this.conditionStack.pop();
} else {
return this.conditionStack[0];
}
},
// produce the lexer rule set which is active for the currently active lexer condition state
_currentRules:function _currentRules () {
if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
} else {
return this.conditions["INITIAL"].rules;
}
},
// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
topState:function topState (n) {
n = this.conditionStack.length - 1 - Math.abs(n || 0);
if (n >= 0) {
return this.conditionStack[n];
} else {
return "INITIAL";
}
},
// alias for begin(condition)
pushState:function pushState (condition) {
this.begin(condition);
},
// return the number of states currently on the stack
stateStackSize:function stateStackSize() {
return this.conditionStack.length;
},
options: {},
performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START
) {
switch($avoiding_name_collisions) {
case 0:return 12
break;
case 1:return 7
break;
case 2:return 13
break;
case 3:return 14
break;
case 4:return 10
break;
case 5:return 5
break;
case 6:return 'INVALID'
break;
}
},
rules: [/^(?:\s*\|\s*)/,/^(?:(\\(\[|\]|\|)|[^\]\[|;\n])+)/,/^(?:\[)/,/^(?:\s*\])/,/^(?:[ ]*(;|\n)+[ ]*)/,/^(?:$)/,/^(?:.)/],
conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6],"inclusive":true}}
};
return lexer;
})();
parser.lexer = lexer;
function Parser () {
this.yy = {};
}
Parser.prototype = parser;parser.Parser = Parser;
return new Parser;
})();var nomnoml = nomnoml || {};
_.maxBy = _.maxBy || _.max; // polyfill the differences between lodash and underscore
nomnoml.parse = function (source){
function onlyCompilables(line){
var ok = line[0] !== '#' && line.trim().substring(0,2) !== '//';
return ok ? line.trim() : ''
}
var isDirective = function (line){ return line.text[0] === '#' };
var lines = source.split('\n').map(function (s, i){
return {text: s, index: i }
});
var pureDirectives = _.filter(lines, isDirective);
var directives = {};
_.each(pureDirectives, function (line){
try {
var tokens = line.text.substring(1).split(':');
directives[tokens[0].trim()] = tokens[1].trim();
}
catch (e) {
throw new Error('line ' + (line.index + 1))
}
});
var pureDiagramCode = _.map(_.map(lines, 'text'), onlyCompilables).join('\n').trim();
var ast = nomnoml.transformParseIntoSyntaxTree(nomnoml.intermediateParse(pureDiagramCode));
ast.directives = directives;
ast.config = getConfig(ast.directives);
return ast
function directionToDagre(word) {
return { down: 'TB', right: 'LR' }[word] || 'TB'
}
function parseCustomStyle(styleDef) {
var contains = skanaar.hasSubstring;
return {
bold: contains(styleDef, 'bold'),
underline: contains(styleDef, 'underline'),
italic: contains(styleDef, 'italic'),
dashed: contains(styleDef, 'dashed'),
empty: contains(styleDef, 'empty'),
center: _.last(styleDef.match('align=([^ ]*)')) == 'left' ? false : true,
fill: _.last(styleDef.match('fill=([^ ]*)')),
stroke: _.last(styleDef.match('stroke=([^ ]*)')),
visual: _.last(styleDef.match('visual=([^ ]*)')) || 'class',
direction: directionToDagre(_.last(styleDef.match('direction=([^ ]*)')))
}
}
function getConfig(d) {
var userStyles = {};
_.each(d, function (styleDef, key){
if (key[0] != '.') return
userStyles[key.substring(1).toUpperCase()] = parseCustomStyle(styleDef);
});
return {
arrowSize: +d.arrowSize || 1,
bendSize: +d.bendSize || 0.3,
direction: directionToDagre(d.direction),
gutter: +d.gutter || 5,
edgeMargin: (+d.edgeMargin) || 0,
edges: { hard: 'hard', rounded: 'rounded' }[d.edges] || 'rounded',
fill: (d.fill || '#eee8d5;#fdf6e3;#eee8d5;#fdf6e3').split(';'),
fillArrows: d.fillArrows === 'true',
font: d.font || 'Calibri',
fontSize: (+d.fontSize) || 12,
leading: (+d.leading) || 1.25,
lineWidth: (+d.lineWidth) || 3,
padding: (+d.padding) || 8,
spacing: (+d.spacing) || 40,
stroke: d.stroke || '#33322E',
title: d.title || 'nomnoml',
zoom: +d.zoom || 1,
styles: _.extend({}, nomnoml.styles, userStyles)
};
}
};
nomnoml.intermediateParse = function (source){
return nomnomlCoreParser.parse(source)
};
nomnoml.transformParseIntoSyntaxTree = function (entity){
var relationId = 0;
function transformCompartment(parts){
var lines = [];
var rawClassifiers = [];
var relations = [];
_.each(parts, function (p){
if (typeof p === 'string')
lines.push(p);
if (p.assoc){ // is a relation
rawClassifiers.push(p.start);
rawClassifiers.push(p.end);
relations.push({
id: relationId++,
assoc: p.assoc,
start: p.start.parts[0][0],
end: p.end.parts[0][0],
startLabel: p.startLabel,
endLabel: p.endLabel
});
}
if (p.parts){ // is a classifier
rawClassifiers.push(p);
}
});
var allClassifiers = _.map(rawClassifiers, transformItem);
var noDuplicates = _.map(_.groupBy(allClassifiers, 'name'), function (cList){
return _.maxBy(cList, function (c){ return c.compartments.length })
});
return nomnoml.Compartment(lines, noDuplicates, relations)
}
function transformItem(entity){
if (typeof entity === 'string')
return entity
if (_.isArray(entity))
return transformCompartment(entity)
if (entity.parts){
var compartments = _.map(entity.parts, transformCompartment);
return nomnoml.Classifier(entity.type, entity.id, compartments)
}
return undefined
}
return transformItem(entity)
}
;
/* jshint maxlen:130 */
var nomnoml = nomnoml || {};
nomnoml.styles = {
ABSTRACT: { center:1, bold:0, direction:null, underline:0, italic:1, dashed:0, empty:0, hull:'auto', visual:'class' },
ACTOR: { center:1, bold:0, direction:null, underline:0, italic:0, dashed:0, empty:0, hull:'auto', visual:'actor' },
CHOICE: { center:1, bold:0, direction:null, underline:0, italic:0, dashed:0, empty:0, hull:'auto', visual:'rhomb' },
CLASS: { center:1, bold:1, direction:null, underline:0, italic:0, dashed:0, empty:0, hull:'auto', visual:'class' },
DATABASE: { center:1, bold:1, direction:null, underline:0, italic:0, dashed:0, empty:0, hull:'auto', visual:'database' },
END: { center:1, bold:0, direction:null, underline:0, italic:0, dashed:0, empty:1, hull:'icon', visual:'end' },
FRAME: { center:0, bold:0, direction:null, underline:0, italic:0, dashed:0, empty:0, hull:'auto', visual:'frame' },
HIDDEN: { center:1, bold:0, direction:null, underline:0, italic:0, dashed:0, empty:1, hull:'empty', visual:'hidden' },
INPUT: { center:1, bold:0, direction:null, underline:0, italic:0, dashed:0, empty:0, hull:'auto', visual:'input' },
INSTANCE: { center:1, bold:0, direction:null, underline:1, italic:0, dashed:0, empty:0, hull:'auto', visual:'class' },
LABEL: { center:0, bold:0, direction:null, underline:0, italic:0, dashed:0, empty:0, hull:'auto', visual:'none' },
NOTE: { center:0, bold:0, direction:null, underline:0, italic:0, dashed:0, empty:0, hull:'auto', visual:'note' },
PACKAGE: { center:0, bold:0, direction:null, underline:0, italic:0, dashed:0, empty:0, hull:'auto', visual:'package' },
RECEIVER: { center:0, bold:0, direction:null, underline:0, italic:0, dashed:0, empty:0, hull:'auto', visual:'receiver' },
REFERENCE:{ center:1, bold:0, direction:null, underline:0, italic:0, dashed:1, empty:0, hull:'auto', visual:'class' },
SENDER: { center:0, bold:0, direction:null, underline:0, italic:0, dashed:0, empty:0, hull:'auto', visual:'sender' },
START: { center:1, bold:0, direction:null, underline:0, italic:0, dashed:0, empty:1, hull:'icon', visual:'start' },
STATE: { center:1, bold:0, direction:null, underline:0, italic:0, dashed:0, empty:0, hull:'auto', visual:'roundrect' },
TRANSCEIVER:
{ center:0, bold:0, direction:null, underline:0, italic:0, dashed:0, empty:0, hull:'auto', visual:'transceiver' },
USECASE: { center:1, bold:0, direction:null, underline:0, italic:0, dashed:0, empty:0, hull:'auto', visual:'ellipse' },
};
nomnoml.visualizers = {
actor : function (node, x, y, padding, config, g) {
var a = padding/2;
var yp = y + a/2;
var actorCenter = {x: node.x, y: yp-a};
g.circle(actorCenter, a).fillAndStroke();
g.path([ {x: node.x, y: yp}, {x: node.x, y: yp+2*a} ]).stroke();
g.path([ {x: node.x-a, y: yp+a}, {x: node.x+a, y: yp+a} ]).stroke();
g.path([ {x: node.x-a, y: yp+a+padding},
{x: node.x , y: yp+padding},
{x: node.x+a, y: yp+a+padding} ]).stroke();
},
class : function (node, x, y, padding, config, g) {
g.rect(x, y, node.width, node.height).fillAndStroke();
},
database : function (node, x, y, padding, config, g) {
var cy = y-padding/2;
var pi = 3.1416;
g.rect(x, y, node.width, node.height).fill();
g.path([{x: x, y: cy}, {x: x, y: cy+node.height}]).stroke();
g.path([
{x: x+node.width, y: cy},
{x: x+node.width, y: cy+node.height}]).stroke();
g.ellipse({x: node.x, y: cy}, node.width, padding*1.5).fillAndStroke();
g.ellipse({x: node.x, y: cy+node.height}, node.width, padding*1.5, 0, pi)
.fillAndStroke();
},
ellipse : function (node, x, y, padding, config, g) {
g.ellipse({x: node.x, y: node.y}, node.width, node.height).fillAndStroke();
},
end : function (node, x, y, padding, config, g) {
g.circle(node.x, y+node.height/2, node.height/3).fillAndStroke();
g.fillStyle(config.stroke);
g.circle(node.x, y+node.height/2, node.height/3-padding/2).fill();
},
frame : function (node, x, y, padding, config, g) {
g.rect(x, y, node.width, node.height).fillAndStroke();
},
hidden : function (node, x, y, padding, config, g) {
},
input : function (node, x, y, padding, config, g) {
g.circuit([
{x:x+padding, y:y},
{x:x+node.width, y:y},
{x:x+node.width-padding, y:y+node.height},
{x:x, y:y+node.height}
]).fillAndStroke();
},
none : function (node, x, y, padding, config, g) {
},
note : function (node, x, y, padding, config, g) {
g.circuit([
{x: x, y: y},
{x: x+node.width-padding, y: y},
{x: x+node.width, y: y+padding},
{x: x+node.width, y: y+node.height},
{x: x, y: y+node.height},
{x: x, y: y}
]).fillAndStroke();
g.path([
{x: x+node.width-padding, y: y},
{x: x+node.width-padding, y: y+padding},
{x: x+node.width, y: y+padding}
]).stroke();
},
package : function (node, x, y, padding, config, g) {
var headHeight = node.compartments[0].height;
g.rect(x, y+headHeight, node.width, node.height-headHeight).fillAndStroke();
var w = g.measureText(node.name).width + 2*padding;
g.circuit([
{x:x, y:y+headHeight},
{x:x, y:y},
{x:x+w, y:y},
{x:x+w, y:y+headHeight}
]).fillAndStroke();
},
receiver : function (node, x, y, padding, config, g) {
g.circuit([
{x: x-padding, y: y},
{x: x+node.width, y: y},
{x: x+node.width, y: y+node.height},
{x: x-padding, y: y+node.height},
{x: x, y: y+node.height/2},
]).fillAndStroke();
},
rhomb : function (node, x, y, padding, config, g) {
g.circuit([
{x:node.x, y:y - padding},
{x:x+node.width + padding, y:node.y},
{x:node.x, y:y+node.height + padding},
{x:x - padding, y:node.y}
]).fillAndStroke();
},
roundrect : function (node, x, y, padding, config, g) {
var r = Math.min(padding*2*config.leading, node.height/2);
g.roundRect(x, y, node.width, node.height, r).fillAndStroke();
},
sender : function (node, x, y, padding, config, g) {
g.circuit([
{x: x, y: y},
{x: x+node.width-padding, y: y},
{x: x+node.width, y: y+node.height/2},
{x: x+node.width-padding, y: y+node.height},
{x: x, y: y+node.height}
]).fillAndStroke();
},
start : function (node, x, y, padding, config, g) {
g.fillStyle(config.stroke);
g.circle(node.x, y+node.height/2, node.height/2.5).fill();
},
transceiver : function (node, x, y, padding, config, g) {
g.circuit([
{x: x-padding, y: y},
{x: x+node.width, y: y},
{x: x+node.width+padding, y: y+node.height/2},
{x: x+node.width, y: y+node.height},
{x: x-padding, y: y+node.height},
{x: x, y: y+node.height/2}
]).fillAndStroke();
},
}
;
var nomnoml = nomnoml || {};
nomnoml.layout = function (measurer, config, ast){
function runDagre(input, style){
return dagre.layout()
.rankS