├── .github └── workflows │ └── ci.yml ├── .gitignore ├── LICENSE ├── README.md ├── app.json ├── chrome-ext ├── README.md ├── manifest.json └── src │ ├── content.js │ └── static │ ├── images │ ├── logo_128.png │ ├── logo_16.png │ ├── logo_32.png │ └── logo_48.png │ └── vendor │ ├── css │ ├── diagram-js-bpmn.css │ ├── diagram-js-cmmn.css │ └── diagram-js-dmn.css │ └── js │ ├── bpmn-viewer.production.min.js │ ├── cmmn-viewer.production.min.js │ ├── dmn-viewer.production.min.js │ └── jquery-3.4.1.min.js ├── lerna.json ├── package-lock.json ├── package.json ├── probot-app ├── .env.example ├── .eslintrc ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── app.yml ├── package-lock.json ├── package.json ├── src │ ├── helper │ │ ├── extractBpmnFileUrls.js │ │ ├── index.js │ │ └── templates.js │ ├── index.js │ ├── misc │ │ └── loading.gif │ └── process-urls │ │ └── index.js └── test │ ├── fixtures │ └── issue_comment.created.json │ └── index.test.js ├── process.json ├── renovate.json ├── resources ├── basic.bpmn ├── complex.bpmn ├── complex.cmmn ├── conditions.bpmn ├── large.dmn ├── multiple-cases.cmmn ├── one-decision.dmn ├── screencast-1.gif ├── screencast-2.gif ├── screencast-3.gif ├── simple.bpmn ├── simple.cmmn └── simple.dmn └── userscript ├── .eslintrc └── index.js /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | strategy: 11 | matrix: 12 | node-version: [ 16 ] 13 | 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v4 17 | - name: Use Node.js ${{ matrix.node-version }} 18 | uses: actions/setup-node@v3 19 | with: 20 | node-version: ${{ matrix.node-version }} 21 | - name: Cache Node.js modules 22 | uses: actions/cache@v3 23 | with: 24 | # npm cache files are stored in `~/.npm` on Linux/macOS 25 | path: ~/.npm 26 | key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }} 27 | restore-keys: | 28 | ${{ runner.OS }}-node- 29 | ${{ runner.OS }}- 30 | - name: Install depedencies 31 | run: npm install 32 | - name: Execute tests 33 | run: cd probot-app && npm test 34 | env: 35 | CI: true -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Niklas Kiefer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # github-bpmn 2 | Applications Collection: Render BPMN, CMMN and DMN files on GitHub 3 | 4 | Built at 2019 [Camunda](https://camunda.com/) Hackdays 5 | 6 | ## Outline 7 | 8 | * [User Script](userscript/): Tampermonkey Extension to Render BPMN | CMMN | DMN Files on GitHub 9 | * [Chrome Extension](chrome-ext/): User Script wrapped as Chrome Extension 10 | * [Render Bpmn App](probot-app/): GitHub Application for Rendering BPMN Files in Issues and Pull Requests 11 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "render-bpmn", 3 | "description": "Render BPMN, CMMN and DMN files on GitHub", 4 | "repository": "https://github.com/pinussilvestrus/github-bpmn", 5 | "logo": "https://raw.githubusercontent.com/pinussilvestrus/github-bpmn/master/chrome-ext/src/static/images/logo_48.png", 6 | "keywords": [ 7 | "probot", 8 | "github", 9 | "probot-app", 10 | "bpmn" 11 | ] 12 | } -------------------------------------------------------------------------------- /chrome-ext/README.md: -------------------------------------------------------------------------------- 1 | # chrome-ext 2 | 3 | > A chrome extension that renders BPMN, CMMN and DMN files on GitHub on hover 4 | 5 | ## Setup 6 | 7 | Open the [Extensions view](https://support.google.com/chrome_webstore/answer/2664769?hl=en) in Chrome and click on `Load unpacked`, locate the repository and select the `chrome-ext` folder. 8 | 9 | Preview BPMN, CMMN and DMN files directly via tooltip. 10 | 11 | ![](../resources/screencast-1.gif) 12 | 13 | Furthermore, preview them on the file details page. 14 | 15 | ![](../resources/screencast-3.gif) -------------------------------------------------------------------------------- /chrome-ext/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "BPMN on Hover", 3 | "version": "0.0.1", 4 | "description": "Renders BPMN files on hover.", 5 | "manifest_version": 2, 6 | "icons": { 7 | "16": "src/static/images/logo_16.png", 8 | "32": "src/static/images/logo_32.png", 9 | "48": "src/static/images/logo_48.png", 10 | "128": "src/static/images/logo_128.png" 11 | }, 12 | "content_scripts": [ 13 | { 14 | "matches": [ 15 | "https://github.com/*/*" 16 | ], 17 | "js": ["src/static/vendor/js/bpmn-viewer.production.min.js", "src/static/vendor/js/cmmn-viewer.production.min.js", "src/static/vendor/js/dmn-viewer.production.min.js", "src/static/vendor/js/jquery-3.4.1.min.js" ,"src/content.js"] 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /chrome-ext/src/content.js: -------------------------------------------------------------------------------- 1 | 2 | const thumb_selector = '.content a'; 3 | 4 | // returns source url for GitHub 5 | function getSrc(src) { 6 | let splitSrc = src.split('/'); 7 | let notAllowed = ['blob', 'https:', 'http:', 'github.com']; 8 | 9 | splitSrc = splitSrc.filter(function(word) { 10 | if (!notAllowed.includes(word)) 11 | return word; 12 | }); 13 | 14 | let user = splitSrc.reverse().pop(); 15 | let repo = splitSrc.pop(); 16 | let ref = splitSrc.pop(); 17 | 18 | return `https://api.github.com/repos/${user}/${repo}/contents/${splitSrc.reverse().join('/').replace('#','')}?ref=${ref}`; 19 | } 20 | 21 | // returns the viewer depending on the viewer type 22 | function returnViewer(type) { 23 | switch (type) { 24 | case 'bpmn': 25 | return new BpmnJS({ 26 | container: $('#js-canvas') 27 | }); 28 | case 'cmmn': 29 | return new CmmnJS({ 30 | container: $('#js-canvas') 31 | }); 32 | case 'dmn': 33 | return new DmnJS({ 34 | container: $('#js-canvas') 35 | }); 36 | default: 37 | return; 38 | } 39 | } 40 | 41 | // exports and appends an SVG for any viewer 42 | function exportSVG(viewer, posX, posY, ele) { 43 | 44 | return new Promise((resolve, reject) => { 45 | viewer.saveSVG(function(err, svg) { 46 | 47 | if (err) reject(); 48 | 49 | ele.append(`
${svg}
`); 50 | 51 | $('.svg') 52 | .css('position', 'fixed') 53 | .css('bottom', (window.innerHeight - posY) * 0.5) 54 | .css('left', posX + 25) 55 | .css('z-index', 9999) 56 | .css('background-color', 'white') 57 | .css('height', '50%') 58 | .css('width', '50%') 59 | .css('box-shadow', '0px 0px 20px 5px rgba(0,0,0,1)'); 60 | 61 | $('.svg svg') 62 | .attr('width', '100%') 63 | .attr('height', '100%'); 64 | 65 | resolve(); 66 | }); 67 | }) 68 | 69 | } 70 | 71 | // shows BPMN, CMMN and DMN (DRD) diagrams 72 | function showDiagram(e) { 73 | let sourceUrl = this.href || e.href; 74 | let viewerType = null; 75 | 76 | // to which parent element the svg will be appended 77 | let ele = $('.file-wrap'); 78 | if (e.href) 79 | ele = $('body'); 80 | 81 | if (sourceUrl.includes('.bpmn')) { 82 | viewerType = 'bpmn'; 83 | } else if (sourceUrl.includes('.cmmn')) { 84 | viewerType = 'cmmn'; 85 | } else if (sourceUrl.includes('.dmn')) { 86 | viewerType = 'dmn'; 87 | } else { 88 | return; 89 | } 90 | 91 | var loc = getSrc(sourceUrl); 92 | 93 | $('body').append('
'); 94 | $('.js-canvas-parent').css('visibility', 'hidden'); 95 | 96 | var viewer = returnViewer(viewerType); 97 | 98 | // ajax call to request content from github usercontent 99 | return new Promise((resolve, reject) => { 100 | $.ajax(loc, { 101 | dataType: 'json' 102 | }).done(function(json) { 103 | let xml = b64DecodeUnicode(json.content); 104 | 105 | viewer.importXML(xml, async function(err) { 106 | 107 | if (viewerType == 'dmn') { 108 | var activeView = viewer.getActiveView(); 109 | // apply initial logic in DRD view 110 | if (activeView.type === 'drd') { 111 | var activeEditor = viewer.getActiveViewer(); 112 | 113 | // access active editor components 114 | var canvas = activeEditor.get('canvas'); 115 | 116 | // zoom to fit full viewport 117 | canvas.zoom('fit-viewport'); 118 | 119 | await exportSVG(activeEditor, e.clientX, e.clientY, ele); 120 | } 121 | } else { 122 | (err) ? console.error(err): viewer.get('canvas').zoom('fit-viewport'); 123 | 124 | await exportSVG(viewer, e.clientX, e.clientY, ele); 125 | 126 | resolve(); 127 | } 128 | }); 129 | }); 130 | }); 131 | } 132 | 133 | // removes diagram from drom 134 | function hideDiagram(e) { 135 | $('.svg').remove(); 136 | $('.js-canvas-parent').remove(); 137 | } 138 | 139 | function addRenderButton() { 140 | if ($('.final-path').length && 141 | $('.final-path').text().includes('.bpmn') || 142 | $('.final-path').text().includes('.cmmn') || 143 | $('.final-path').text().includes('.dmn') 144 | ) { 145 | $('.Box-header .BtnGroup').append('Render'); 146 | } 147 | $('a#render-diagram').on('click', openDiagram); 148 | } 149 | 150 | // opens the diagram in a new window 151 | async function openDiagram() { 152 | await showDiagram(this); 153 | 154 | var w = window.open(); 155 | var html = $('.svg').html(); 156 | $(w.document.body).html(html); 157 | } 158 | 159 | /** 160 | * Active calls 161 | */ 162 | 163 | // add the render button in case of a site refresh 164 | addRenderButton(); 165 | $('body').on('mouseenter', thumb_selector, showDiagram); 166 | $('body').on('mouseleave', thumb_selector, hideDiagram); 167 | 168 | // listens to node remove event in DOM, as GitHub dynamically changes the view within the a repository 169 | $('body').on('DOMNodeRemoved', async function(event) { 170 | if (typeof event.target.className == 'string' && event.target.className.includes('container-lg')) { 171 | await Sleep(500); 172 | 173 | addRenderButton(); 174 | } 175 | }); 176 | 177 | /** 178 | * Helper functions 179 | */ 180 | 181 | function b64DecodeUnicode(str) { 182 | // Going backwards: from bytestream, to percent-encoding, to original string. 183 | return decodeURIComponent(atob(str).split('').map(function(c) { 184 | return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); 185 | }).join('')); 186 | } 187 | 188 | function Sleep(milliseconds) { 189 | return new Promise(resolve => setTimeout(resolve, milliseconds)); 190 | } -------------------------------------------------------------------------------- /chrome-ext/src/static/images/logo_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinussilvestrus/github-bpmn/071e645aa18b327b401b709ac704832c48037a2f/chrome-ext/src/static/images/logo_128.png -------------------------------------------------------------------------------- /chrome-ext/src/static/images/logo_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinussilvestrus/github-bpmn/071e645aa18b327b401b709ac704832c48037a2f/chrome-ext/src/static/images/logo_16.png -------------------------------------------------------------------------------- /chrome-ext/src/static/images/logo_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinussilvestrus/github-bpmn/071e645aa18b327b401b709ac704832c48037a2f/chrome-ext/src/static/images/logo_32.png -------------------------------------------------------------------------------- /chrome-ext/src/static/images/logo_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinussilvestrus/github-bpmn/071e645aa18b327b401b709ac704832c48037a2f/chrome-ext/src/static/images/logo_48.png -------------------------------------------------------------------------------- /chrome-ext/src/static/vendor/css/diagram-js-bpmn.css: -------------------------------------------------------------------------------- 1 | /** 2 | * outline styles 3 | */ 4 | 5 | .djs-outline { 6 | fill: none; 7 | visibility: hidden; 8 | } 9 | 10 | .djs-element.hover .djs-outline, 11 | .djs-element.selected .djs-outline { 12 | visibility: visible; 13 | shape-rendering: crispEdges; 14 | stroke-dasharray: 3,3; 15 | } 16 | 17 | .djs-element.selected .djs-outline { 18 | stroke: #8888FF; 19 | stroke-width: 1px; 20 | } 21 | 22 | .djs-element.hover .djs-outline { 23 | stroke: #FF8888; 24 | stroke-width: 1px; 25 | } 26 | 27 | .djs-shape.connect-ok .djs-visual > :nth-child(1) { 28 | fill: #DCFECC /* light-green */ !important; 29 | } 30 | 31 | .djs-shape.connect-not-ok .djs-visual > :nth-child(1), 32 | .djs-shape.drop-not-ok .djs-visual > :nth-child(1) { 33 | fill: #f9dee5 /* light-red */ !important; 34 | } 35 | 36 | .djs-shape.new-parent .djs-visual > :nth-child(1) { 37 | fill: #F7F9FF !important; 38 | } 39 | 40 | svg.drop-not-ok { 41 | background: #f9dee5 /* light-red */ !important; 42 | } 43 | 44 | svg.new-parent { 45 | background: #F7F9FF /* light-blue */ !important; 46 | } 47 | 48 | .djs-connection.connect-ok .djs-visual > :nth-child(1), 49 | .djs-connection.drop-ok .djs-visual > :nth-child(1) { 50 | stroke: #90DD5F /* light-green */ !important; 51 | } 52 | 53 | .djs-connection.connect-not-ok .djs-visual > :nth-child(1), 54 | .djs-connection.drop-not-ok .djs-visual > :nth-child(1) { 55 | stroke: #E56283 /* light-red */ !important; 56 | } 57 | 58 | .drop-not-ok, 59 | .connect-not-ok { 60 | cursor: not-allowed; 61 | } 62 | 63 | .djs-element.attach-ok .djs-visual > :nth-child(1) { 64 | stroke-width: 5px !important; 65 | stroke: rgba(255, 116, 0, 0.7) !important; 66 | } 67 | 68 | .djs-frame.connect-not-ok .djs-visual > :nth-child(1), 69 | .djs-frame.drop-not-ok .djs-visual > :nth-child(1) { 70 | stroke-width: 3px !important; 71 | stroke: #E56283 /* light-red */ !important; 72 | fill: none !important; 73 | } 74 | 75 | /** 76 | * Selection box style 77 | * 78 | */ 79 | .djs-lasso-overlay { 80 | fill: rgb(255, 116, 0); 81 | fill-opacity: 0.1; 82 | 83 | stroke-dasharray: 5 1 3 1; 84 | stroke: rgb(255, 116, 0); 85 | 86 | shape-rendering: crispEdges; 87 | pointer-events: none; 88 | } 89 | 90 | /** 91 | * Resize styles 92 | */ 93 | .djs-resize-overlay { 94 | fill: none; 95 | 96 | stroke-dasharray: 5 1 3 1; 97 | stroke: rgb(255, 116, 0); 98 | 99 | pointer-events: none; 100 | } 101 | 102 | .djs-resizer-hit { 103 | fill: none; 104 | pointer-events: all; 105 | } 106 | 107 | .djs-resizer-visual { 108 | fill: white; 109 | stroke-width: 1px; 110 | stroke: black; 111 | shape-rendering: crispEdges; 112 | stroke-opacity: 0.2; 113 | } 114 | 115 | .djs-cursor-resize-nwse, 116 | .djs-resizer-nw, 117 | .djs-resizer-se { 118 | cursor: nwse-resize; 119 | } 120 | 121 | .djs-cursor-resize-nesw, 122 | .djs-resizer-ne, 123 | .djs-resizer-sw { 124 | cursor: nesw-resize; 125 | } 126 | 127 | .djs-shape.djs-resizing > .djs-outline { 128 | visibility: hidden !important; 129 | } 130 | 131 | .djs-shape.djs-resizing > .djs-resizer { 132 | visibility: hidden; 133 | } 134 | 135 | .djs-dragger > .djs-resizer { 136 | visibility: hidden; 137 | } 138 | 139 | /** 140 | * drag styles 141 | */ 142 | .djs-dragger * { 143 | fill: none !important; 144 | stroke: rgb(255, 116, 0) !important; 145 | } 146 | 147 | .djs-dragger tspan, 148 | .djs-dragger text { 149 | fill: rgb(255, 116, 0) !important; 150 | stroke: none !important; 151 | } 152 | 153 | marker.djs-dragger circle, 154 | marker.djs-dragger path, 155 | marker.djs-dragger polygon, 156 | marker.djs-dragger polyline, 157 | marker.djs-dragger rect { 158 | fill: rgb(255, 116, 0) !important; 159 | stroke: none !important; 160 | } 161 | 162 | marker.djs-dragger text, 163 | marker.djs-dragger tspan { 164 | fill: none !important; 165 | stroke: rgb(255, 116, 0) !important; 166 | } 167 | 168 | .djs-dragging { 169 | opacity: 0.3; 170 | } 171 | 172 | .djs-dragging, 173 | .djs-dragging > * { 174 | pointer-events: none !important; 175 | } 176 | 177 | .djs-dragging .djs-context-pad, 178 | .djs-dragging .djs-outline { 179 | display: none !important; 180 | } 181 | 182 | /** 183 | * no pointer events for visual 184 | */ 185 | .djs-visual, 186 | .djs-outline { 187 | pointer-events: none; 188 | } 189 | 190 | .djs-element.attach-ok .djs-hit { 191 | stroke-width: 60px !important; 192 | } 193 | 194 | /** 195 | * all pointer events for hit shape 196 | */ 197 | .djs-element > .djs-hit-all { 198 | pointer-events: all; 199 | } 200 | 201 | .djs-element > .djs-hit-stroke, 202 | .djs-element > .djs-hit-click-stroke { 203 | pointer-events: stroke; 204 | } 205 | 206 | /** 207 | * all pointer events for hit shape 208 | */ 209 | .djs-drag-active .djs-element > .djs-hit-click-stroke { 210 | pointer-events: all; 211 | } 212 | 213 | /** 214 | * shape / connection basic styles 215 | */ 216 | .djs-connection .djs-visual { 217 | stroke-width: 2px; 218 | fill: none; 219 | } 220 | 221 | .djs-cursor-grab { 222 | cursor: -webkit-grab; 223 | cursor: -moz-grab; 224 | cursor: grab; 225 | } 226 | 227 | .djs-cursor-grabbing { 228 | cursor: -webkit-grabbing; 229 | cursor: -moz-grabbing; 230 | cursor: grabbing; 231 | } 232 | 233 | .djs-cursor-crosshair { 234 | cursor: crosshair; 235 | } 236 | 237 | .djs-cursor-move { 238 | cursor: move; 239 | } 240 | 241 | .djs-cursor-resize-ns { 242 | cursor: ns-resize; 243 | } 244 | 245 | .djs-cursor-resize-ew { 246 | cursor: ew-resize; 247 | } 248 | 249 | 250 | /** 251 | * snapping 252 | */ 253 | .djs-snap-line { 254 | stroke: rgb(255, 195, 66); 255 | stroke: rgba(255, 195, 66, 0.50); 256 | stroke-linecap: round; 257 | stroke-width: 2px; 258 | pointer-events: none; 259 | } 260 | 261 | /** 262 | * snapping 263 | */ 264 | .djs-crosshair { 265 | stroke: #555; 266 | stroke-linecap: round; 267 | stroke-width: 1px; 268 | pointer-events: none; 269 | shape-rendering: crispEdges; 270 | stroke-dasharray: 5, 5; 271 | } 272 | 273 | /** 274 | * palette 275 | */ 276 | 277 | .djs-palette { 278 | position: absolute; 279 | left: 20px; 280 | top: 20px; 281 | 282 | box-sizing: border-box; 283 | width: 48px; 284 | } 285 | 286 | .djs-palette .separator { 287 | margin: 0 5px; 288 | padding-top: 5px; 289 | 290 | border: none; 291 | border-bottom: solid 1px #DDD; 292 | 293 | clear: both; 294 | } 295 | 296 | .djs-palette .entry:before { 297 | vertical-align: text-bottom; 298 | } 299 | 300 | .djs-palette .djs-palette-toggle { 301 | cursor: pointer; 302 | } 303 | 304 | .djs-palette .entry, 305 | .djs-palette .djs-palette-toggle { 306 | color: #333; 307 | font-size: 30px; 308 | 309 | text-align: center; 310 | } 311 | 312 | .djs-palette .entry { 313 | float: left; 314 | } 315 | 316 | .djs-palette .entry img { 317 | max-width: 100%; 318 | } 319 | 320 | .djs-palette .djs-palette-entries:after { 321 | content: ''; 322 | display: table; 323 | clear: both; 324 | } 325 | 326 | .djs-palette .djs-palette-toggle:hover { 327 | background: #666; 328 | } 329 | 330 | .djs-palette .entry:hover { 331 | color: rgb(255, 116, 0); 332 | } 333 | 334 | .djs-palette .highlighted-entry { 335 | color: rgb(255, 116, 0) !important; 336 | } 337 | 338 | .djs-palette .entry, 339 | .djs-palette .djs-palette-toggle { 340 | width: 46px; 341 | height: 46px; 342 | line-height: 46px; 343 | cursor: default; 344 | } 345 | 346 | /** 347 | * Palette open / two-column layout is controlled via 348 | * classes on the palette. Events to hook into palette 349 | * changed life-cycle are available in addition. 350 | */ 351 | .djs-palette.two-column.open { 352 | width: 94px; 353 | } 354 | 355 | .djs-palette:not(.open) .djs-palette-entries { 356 | display: none; 357 | } 358 | 359 | .djs-palette:not(.open) { 360 | overflow: hidden; 361 | } 362 | 363 | .djs-palette.open .djs-palette-toggle { 364 | display: none; 365 | } 366 | 367 | /** 368 | * context-pad 369 | */ 370 | .djs-overlay-context-pad { 371 | width: 72px; 372 | } 373 | 374 | .djs-context-pad { 375 | position: absolute; 376 | display: none; 377 | pointer-events: none; 378 | } 379 | 380 | .djs-context-pad .entry { 381 | width: 22px; 382 | height: 22px; 383 | text-align: center; 384 | display: inline-block; 385 | font-size: 22px; 386 | margin: 0 2px 2px 0; 387 | 388 | border-radius: 3px; 389 | 390 | cursor: default; 391 | 392 | background-color: #FEFEFE; 393 | box-shadow: 0 0 2px 1px #FEFEFE; 394 | pointer-events: all; 395 | } 396 | 397 | .djs-context-pad .entry:before { 398 | vertical-align: top; 399 | } 400 | 401 | .djs-context-pad .entry:hover { 402 | background: rgb(255, 252, 176); 403 | } 404 | 405 | .djs-context-pad.open { 406 | display: block; 407 | } 408 | 409 | /** 410 | * popup styles 411 | */ 412 | .djs-popup .entry { 413 | line-height: 20px; 414 | white-space: nowrap; 415 | cursor: default; 416 | } 417 | 418 | /* larger font for prefixed icons */ 419 | .djs-popup .entry:before { 420 | vertical-align: middle; 421 | font-size: 20px; 422 | } 423 | 424 | .djs-popup .entry > span { 425 | vertical-align: middle; 426 | font-size: 14px; 427 | } 428 | 429 | .djs-popup .entry:hover, 430 | .djs-popup .entry.active:hover { 431 | background: rgb(255, 252, 176); 432 | } 433 | 434 | .djs-popup .entry.disabled { 435 | background: inherit; 436 | } 437 | 438 | .djs-popup .djs-popup-header .entry { 439 | display: inline-block; 440 | padding: 2px 3px 2px 3px; 441 | 442 | border: solid 1px transparent; 443 | border-radius: 3px; 444 | } 445 | 446 | .djs-popup .djs-popup-header .entry.active { 447 | color: rgb(255, 116, 0); 448 | border: solid 1px rgb(255, 116, 0); 449 | background-color: #F6F6F6; 450 | } 451 | 452 | .djs-popup-body .entry { 453 | padding: 4px 10px 4px 5px; 454 | } 455 | 456 | .djs-popup-body .entry > span { 457 | margin-left: 5px; 458 | } 459 | 460 | .djs-popup-body { 461 | background-color: #FEFEFE; 462 | } 463 | 464 | .djs-popup-header { 465 | border-bottom: 1px solid #DDD; 466 | } 467 | 468 | .djs-popup-header .entry { 469 | margin: 1px; 470 | margin-left: 3px; 471 | } 472 | 473 | .djs-popup-header .entry:last-child { 474 | margin-right: 3px; 475 | } 476 | 477 | /** 478 | * popup / palette styles 479 | */ 480 | .djs-popup, .djs-palette { 481 | background: #FAFAFA; 482 | border: solid 1px #CCC; 483 | border-radius: 2px; 484 | } 485 | 486 | /** 487 | * touch 488 | */ 489 | 490 | .djs-shape, 491 | .djs-connection { 492 | touch-action: none; 493 | } 494 | 495 | .djs-segment-dragger, 496 | .djs-bendpoint { 497 | display: none; 498 | } 499 | 500 | /** 501 | * bendpoints 502 | */ 503 | .djs-segment-dragger .djs-visual { 504 | fill: rgba(255, 255, 121, 0.2); 505 | stroke-width: 1px; 506 | stroke-opacity: 1; 507 | stroke: rgba(255, 255, 121, 0.3); 508 | } 509 | 510 | .djs-bendpoint .djs-visual { 511 | fill: rgba(255, 255, 121, 0.8); 512 | stroke-width: 1px; 513 | stroke-opacity: 0.5; 514 | stroke: black; 515 | } 516 | 517 | .djs-segment-dragger:hover, 518 | .djs-bendpoints.hover .djs-segment-dragger, 519 | .djs-bendpoints.selected .djs-segment-dragger, 520 | .djs-bendpoint:hover, 521 | .djs-bendpoints.hover .djs-bendpoint, 522 | .djs-bendpoints.selected .djs-bendpoint { 523 | display: block; 524 | } 525 | 526 | .djs-drag-active .djs-bendpoints * { 527 | display: none; 528 | } 529 | 530 | .djs-bendpoints:not(.hover) .floating { 531 | display: none; 532 | } 533 | 534 | .djs-segment-dragger:hover .djs-visual, 535 | .djs-segment-dragger.djs-dragging .djs-visual, 536 | .djs-bendpoint:hover .djs-visual, 537 | .djs-bendpoint.floating .djs-visual { 538 | fill: yellow; 539 | stroke-opacity: 0.5; 540 | stroke: black; 541 | } 542 | 543 | .djs-bendpoint.floating .djs-hit { 544 | pointer-events: none; 545 | } 546 | 547 | .djs-segment-dragger .djs-hit, 548 | .djs-bendpoint .djs-hit { 549 | pointer-events: all; 550 | fill: none; 551 | } 552 | 553 | .djs-segment-dragger.horizontal .djs-hit { 554 | cursor: ns-resize; 555 | } 556 | 557 | .djs-segment-dragger.vertical .djs-hit { 558 | cursor: ew-resize; 559 | } 560 | 561 | .djs-segment-dragger.djs-dragging .djs-hit { 562 | pointer-events: none; 563 | } 564 | 565 | .djs-updating, 566 | .djs-updating > * { 567 | pointer-events: none !important; 568 | } 569 | 570 | .djs-updating .djs-context-pad, 571 | .djs-updating .djs-outline, 572 | .djs-updating .djs-bendpoint, 573 | .connect-ok .djs-bendpoint, 574 | .connect-not-ok .djs-bendpoint, 575 | .drop-ok .djs-bendpoint, 576 | .drop-not-ok .djs-bendpoint { 577 | display: none !important; 578 | } 579 | 580 | .djs-segment-dragger.djs-dragging, 581 | .djs-bendpoint.djs-dragging { 582 | display: block; 583 | opacity: 1.0; 584 | } 585 | 586 | .djs-segment-dragger.djs-dragging .djs-visual, 587 | .djs-bendpoint.djs-dragging .djs-visual { 588 | fill: yellow; 589 | stroke-opacity: 0.5; 590 | } 591 | 592 | 593 | /** 594 | * tooltips 595 | */ 596 | .djs-tooltip-error { 597 | font-size: 11px; 598 | line-height: 18px; 599 | text-align: left; 600 | 601 | padding: 5px; 602 | 603 | opacity: 0.7; 604 | } 605 | 606 | .djs-tooltip-error > * { 607 | width: 160px; 608 | 609 | background: rgb(252, 236, 240); 610 | color: rgb(158, 76, 76); 611 | padding: 3px 7px; 612 | border-radius: 5px; 613 | border-left: solid 5px rgb(174, 73, 73); 614 | } 615 | 616 | .djs-tooltip-error:hover { 617 | opacity: 1; 618 | } 619 | 620 | 621 | /** 622 | * search pad 623 | */ 624 | .djs-search-container { 625 | position: absolute; 626 | top: 20px; 627 | left: 0; 628 | right: 0; 629 | margin-left: auto; 630 | margin-right: auto; 631 | 632 | width: 25%; 633 | min-width: 300px; 634 | max-width: 400px; 635 | z-index: 10; 636 | 637 | font-size: 1.05em; 638 | opacity: 0.9; 639 | background: #FAFAFA; 640 | border: solid 1px #CCC; 641 | border-radius: 2px; 642 | } 643 | 644 | .djs-search-container:not(.open) { 645 | display: none; 646 | } 647 | 648 | .djs-search-input input { 649 | font-size: 1.05em; 650 | width: 100%; 651 | padding: 6px 10px; 652 | border: 1px solid #ccc; 653 | } 654 | 655 | .djs-search-input input:focus { 656 | outline: none; 657 | border-color: #52B415; 658 | } 659 | 660 | .djs-search-results { 661 | position: relative; 662 | overflow-y: auto; 663 | max-height: 200px; 664 | } 665 | 666 | .djs-search-results:hover { 667 | /*background: #fffdd7;*/ 668 | cursor: pointer; 669 | } 670 | 671 | .djs-search-result { 672 | width: 100%; 673 | padding: 6px 10px; 674 | background: white; 675 | border-bottom: solid 1px #AAA; 676 | border-radius: 1px; 677 | } 678 | 679 | .djs-search-highlight { 680 | color: black; 681 | } 682 | 683 | .djs-search-result-primary { 684 | margin: 0 0 10px; 685 | } 686 | 687 | .djs-search-result-secondary { 688 | font-family: monospace; 689 | margin: 0; 690 | } 691 | 692 | .djs-search-result:hover { 693 | background: #fdffd6; 694 | } 695 | 696 | .djs-search-result-selected { 697 | background: #fffcb0; 698 | } 699 | 700 | .djs-search-result-selected:hover { 701 | background: #f7f388; 702 | } 703 | 704 | .djs-search-overlay { 705 | background: yellow; 706 | opacity: 0.3; 707 | } 708 | 709 | /** 710 | * hidden styles 711 | */ 712 | .djs-element-hidden, 713 | .djs-element-hidden .djs-hit, 714 | .djs-element-hidden .djs-outline, 715 | .djs-label-hidden .djs-label { 716 | display: none !important; 717 | } 718 | -------------------------------------------------------------------------------- /chrome-ext/src/static/vendor/css/diagram-js-cmmn.css: -------------------------------------------------------------------------------- 1 | /** 2 | * outline styles 3 | */ 4 | 5 | .djs-outline { 6 | fill: none; 7 | visibility: hidden; 8 | } 9 | 10 | .djs-element.hover .djs-outline, 11 | .djs-element.selected .djs-outline { 12 | visibility: visible; 13 | shape-rendering: crispEdges; 14 | stroke-dasharray: 3,3; 15 | } 16 | 17 | .djs-element.selected .djs-outline { 18 | stroke: #8888FF; 19 | stroke-width: 1px; 20 | } 21 | 22 | .djs-element.hover .djs-outline { 23 | stroke: #FF8888; 24 | stroke-width: 1px; 25 | } 26 | 27 | .djs-shape.connect-ok .djs-visual > :nth-child(1) { 28 | fill: #DCFECC /* light-green */ !important; 29 | } 30 | 31 | .djs-shape.connect-not-ok .djs-visual > :nth-child(1), 32 | .djs-shape.drop-not-ok .djs-visual > :nth-child(1) { 33 | fill: #f9dee5 /* light-red */ !important; 34 | } 35 | 36 | .djs-shape.new-parent .djs-visual > :nth-child(1) { 37 | fill: #F7F9FF !important; 38 | } 39 | 40 | svg.drop-not-ok { 41 | background: #f9dee5 /* light-red */ !important; 42 | } 43 | 44 | svg.new-parent { 45 | background: #F7F9FF /* light-blue */ !important; 46 | } 47 | 48 | .djs-connection.connect-ok .djs-visual > :nth-child(1), 49 | .djs-connection.drop-ok .djs-visual > :nth-child(1) { 50 | stroke: #90DD5F /* light-green */ !important; 51 | } 52 | 53 | .djs-connection.connect-not-ok .djs-visual > :nth-child(1), 54 | .djs-connection.drop-not-ok .djs-visual > :nth-child(1) { 55 | stroke: #E56283 /* light-red */ !important; 56 | } 57 | 58 | .drop-not-ok, 59 | .connect-not-ok { 60 | cursor: not-allowed; 61 | } 62 | 63 | .djs-element.attach-ok .djs-visual > :nth-child(1) { 64 | stroke-width: 5px !important; 65 | stroke: rgba(255, 116, 0, 0.7) !important; 66 | } 67 | 68 | .djs-frame.connect-not-ok .djs-visual > :nth-child(1), 69 | .djs-frame.drop-not-ok .djs-visual > :nth-child(1) { 70 | stroke-width: 3px !important; 71 | stroke: #E56283 /* light-red */ !important; 72 | fill: none !important; 73 | } 74 | 75 | /** 76 | * Selection box style 77 | * 78 | */ 79 | .djs-lasso-overlay { 80 | fill: rgb(255, 116, 0); 81 | fill-opacity: 0.1; 82 | 83 | stroke-dasharray: 5 1 3 1; 84 | stroke: rgb(255, 116, 0); 85 | 86 | shape-rendering: crispEdges; 87 | pointer-events: none; 88 | } 89 | 90 | /** 91 | * Resize styles 92 | */ 93 | .djs-resize-overlay { 94 | fill: none; 95 | 96 | stroke-dasharray: 5 1 3 1; 97 | stroke: rgb(255, 116, 0); 98 | 99 | pointer-events: none; 100 | } 101 | 102 | .djs-resizer-hit { 103 | fill: none; 104 | pointer-events: all; 105 | } 106 | 107 | .djs-resizer-visual { 108 | fill: white; 109 | stroke-width: 1px; 110 | stroke: black; 111 | shape-rendering: crispEdges; 112 | stroke-opacity: 0.2; 113 | } 114 | 115 | .djs-cursor-resize-nwse, 116 | .djs-resizer-nw, 117 | .djs-resizer-se { 118 | cursor: nwse-resize; 119 | } 120 | 121 | .djs-cursor-resize-nesw, 122 | .djs-resizer-ne, 123 | .djs-resizer-sw { 124 | cursor: nesw-resize; 125 | } 126 | 127 | .djs-shape.djs-resizing > .djs-outline { 128 | visibility: hidden !important; 129 | } 130 | 131 | .djs-shape.djs-resizing > .djs-resizer { 132 | visibility: hidden; 133 | } 134 | 135 | .djs-dragger > .djs-resizer { 136 | visibility: hidden; 137 | } 138 | 139 | /** 140 | * drag styles 141 | */ 142 | .djs-dragger * { 143 | fill: none !important; 144 | stroke: rgb(255, 116, 0) !important; 145 | } 146 | 147 | .djs-dragger tspan, 148 | .djs-dragger text { 149 | fill: rgb(255, 116, 0) !important; 150 | stroke: none !important; 151 | } 152 | 153 | marker.djs-dragger circle, 154 | marker.djs-dragger path, 155 | marker.djs-dragger polygon, 156 | marker.djs-dragger polyline, 157 | marker.djs-dragger rect { 158 | fill: rgb(255, 116, 0) !important; 159 | stroke: none !important; 160 | } 161 | 162 | marker.djs-dragger text, 163 | marker.djs-dragger tspan { 164 | fill: none !important; 165 | stroke: rgb(255, 116, 0) !important; 166 | } 167 | 168 | .djs-dragging { 169 | opacity: 0.3; 170 | } 171 | 172 | .djs-dragging, 173 | .djs-dragging > * { 174 | pointer-events: none !important; 175 | } 176 | 177 | .djs-dragging .djs-context-pad, 178 | .djs-dragging .djs-outline { 179 | display: none !important; 180 | } 181 | 182 | /** 183 | * no pointer events for visual 184 | */ 185 | .djs-visual, 186 | .djs-outline { 187 | pointer-events: none; 188 | } 189 | 190 | .djs-element.attach-ok .djs-hit { 191 | stroke-width: 60px !important; 192 | } 193 | 194 | /** 195 | * all pointer events for hit shape 196 | */ 197 | .djs-shape .djs-hit { 198 | pointer-events: all; 199 | } 200 | 201 | .djs-connection .djs-hit { 202 | pointer-events: stroke; 203 | } 204 | 205 | .djs-frame .djs-hit { 206 | pointer-events: stroke; 207 | } 208 | 209 | /** 210 | * shape / connection basic styles 211 | */ 212 | .djs-connection .djs-visual { 213 | stroke-width: 2px; 214 | fill: none; 215 | } 216 | 217 | .djs-cursor-grab { 218 | cursor: -webkit-grab; 219 | cursor: -moz-grab; 220 | cursor: grab; 221 | } 222 | 223 | .djs-cursor-grabbing { 224 | cursor: -webkit-grabbing; 225 | cursor: -moz-grabbing; 226 | cursor: grabbing; 227 | } 228 | 229 | .djs-cursor-crosshair { 230 | cursor: crosshair; 231 | } 232 | 233 | .djs-cursor-move { 234 | cursor: move; 235 | } 236 | 237 | .djs-cursor-resize-ns { 238 | cursor: ns-resize; 239 | } 240 | 241 | .djs-cursor-resize-ew { 242 | cursor: ew-resize; 243 | } 244 | 245 | 246 | /** 247 | * snapping 248 | */ 249 | .djs-snap-line { 250 | stroke: rgb(255, 195, 66); 251 | stroke: rgba(255, 195, 66, 0.50); 252 | stroke-linecap: round; 253 | stroke-width: 2px; 254 | pointer-events: none; 255 | } 256 | 257 | /** 258 | * snapping 259 | */ 260 | .djs-crosshair { 261 | stroke: #555; 262 | stroke-linecap: round; 263 | stroke-width: 1px; 264 | pointer-events: none; 265 | shape-rendering: crispEdges; 266 | stroke-dasharray: 5, 5; 267 | } 268 | 269 | /** 270 | * palette 271 | */ 272 | 273 | .djs-palette { 274 | position: absolute; 275 | left: 20px; 276 | top: 20px; 277 | 278 | box-sizing: border-box; 279 | width: 48px; 280 | } 281 | 282 | .djs-palette .separator { 283 | margin: 0 5px; 284 | padding-top: 5px; 285 | 286 | border: none; 287 | border-bottom: solid 1px #DDD; 288 | 289 | clear: both; 290 | } 291 | 292 | .djs-palette .entry:before { 293 | vertical-align: text-bottom; 294 | } 295 | 296 | .djs-palette .djs-palette-toggle { 297 | cursor: pointer; 298 | } 299 | 300 | .djs-palette .entry, 301 | .djs-palette .djs-palette-toggle { 302 | color: #333; 303 | font-size: 30px; 304 | 305 | text-align: center; 306 | } 307 | 308 | .djs-palette .entry { 309 | float: left; 310 | } 311 | 312 | .djs-palette .entry img { 313 | max-width: 100%; 314 | } 315 | 316 | .djs-palette .djs-palette-entries:after { 317 | content: ''; 318 | display: table; 319 | clear: both; 320 | } 321 | 322 | .djs-palette .djs-palette-toggle:hover { 323 | background: #666; 324 | } 325 | 326 | .djs-palette .entry:hover { 327 | color: rgb(255, 116, 0); 328 | } 329 | 330 | .djs-palette .highlighted-entry { 331 | color: rgb(255, 116, 0) !important; 332 | } 333 | 334 | .djs-palette .entry, 335 | .djs-palette .djs-palette-toggle { 336 | width: 46px; 337 | height: 46px; 338 | line-height: 46px; 339 | cursor: default; 340 | } 341 | 342 | /** 343 | * Palette open / two-column layout is controlled via 344 | * classes on the palette. Events to hook into palette 345 | * changed life-cycle are available in addition. 346 | */ 347 | .djs-palette.two-column.open { 348 | width: 94px; 349 | } 350 | 351 | .djs-palette:not(.open) .djs-palette-entries { 352 | display: none; 353 | } 354 | 355 | .djs-palette:not(.open) { 356 | overflow: hidden; 357 | } 358 | 359 | .djs-palette.open .djs-palette-toggle { 360 | display: none; 361 | } 362 | 363 | /** 364 | * context-pad 365 | */ 366 | .djs-overlay-context-pad { 367 | width: 72px; 368 | } 369 | 370 | .djs-context-pad { 371 | position: absolute; 372 | display: none; 373 | pointer-events: none; 374 | } 375 | 376 | .djs-context-pad .entry { 377 | width: 22px; 378 | height: 22px; 379 | text-align: center; 380 | display: inline-block; 381 | font-size: 22px; 382 | margin: 0 2px 2px 0; 383 | 384 | border-radius: 3px; 385 | 386 | cursor: default; 387 | 388 | background-color: #FEFEFE; 389 | box-shadow: 0 0 2px 1px #FEFEFE; 390 | pointer-events: all; 391 | } 392 | 393 | .djs-context-pad .entry:before { 394 | vertical-align: top; 395 | } 396 | 397 | .djs-context-pad .entry:hover { 398 | background: rgb(255, 252, 176); 399 | } 400 | 401 | .djs-context-pad.open { 402 | display: block; 403 | } 404 | 405 | /** 406 | * popup styles 407 | */ 408 | .djs-popup .entry { 409 | line-height: 20px; 410 | white-space: nowrap; 411 | cursor: default; 412 | } 413 | 414 | /* larger font for prefixed icons */ 415 | .djs-popup .entry:before { 416 | vertical-align: middle; 417 | font-size: 20px; 418 | } 419 | 420 | .djs-popup .entry > span { 421 | vertical-align: middle; 422 | font-size: 14px; 423 | } 424 | 425 | .djs-popup .entry:hover, 426 | .djs-popup .entry.active:hover { 427 | background: rgb(255, 252, 176); 428 | } 429 | 430 | .djs-popup .entry.disabled { 431 | background: inherit; 432 | } 433 | 434 | .djs-popup .djs-popup-header .entry { 435 | display: inline-block; 436 | padding: 2px 3px 2px 3px; 437 | 438 | border: solid 1px transparent; 439 | border-radius: 3px; 440 | } 441 | 442 | .djs-popup .djs-popup-header .entry.active { 443 | color: rgb(255, 116, 0); 444 | border: solid 1px rgb(255, 116, 0); 445 | background-color: #F6F6F6; 446 | } 447 | 448 | .djs-popup-body .entry { 449 | padding: 4px 10px 4px 5px; 450 | } 451 | 452 | .djs-popup-body .entry > span { 453 | margin-left: 5px; 454 | } 455 | 456 | .djs-popup-body { 457 | background-color: #FEFEFE; 458 | } 459 | 460 | .djs-popup-header { 461 | border-bottom: 1px solid #DDD; 462 | } 463 | 464 | .djs-popup-header .entry { 465 | margin: 1px; 466 | margin-left: 3px; 467 | } 468 | 469 | .djs-popup-header .entry:last-child { 470 | margin-right: 3px; 471 | } 472 | 473 | /** 474 | * popup / palette styles 475 | */ 476 | .djs-popup, .djs-palette { 477 | background: #FAFAFA; 478 | border: solid 1px #CCC; 479 | border-radius: 2px; 480 | } 481 | 482 | /** 483 | * touch 484 | */ 485 | 486 | .djs-shape, 487 | .djs-connection { 488 | touch-action: none; 489 | } 490 | 491 | .djs-segment-dragger, 492 | .djs-bendpoint { 493 | display: none; 494 | } 495 | 496 | /** 497 | * bendpoints 498 | */ 499 | .djs-segment-dragger .djs-visual { 500 | fill: rgba(255, 255, 121, 0.2); 501 | stroke-width: 1px; 502 | stroke-opacity: 1; 503 | stroke: rgba(255, 255, 121, 0.3); 504 | } 505 | 506 | .djs-bendpoint .djs-visual { 507 | fill: rgba(255, 255, 121, 0.8); 508 | stroke-width: 1px; 509 | stroke-opacity: 0.5; 510 | stroke: black; 511 | } 512 | 513 | .djs-segment-dragger:hover, 514 | .djs-bendpoints.hover .djs-segment-dragger, 515 | .djs-bendpoints.selected .djs-segment-dragger, 516 | .djs-bendpoint:hover, 517 | .djs-bendpoints.hover .djs-bendpoint, 518 | .djs-bendpoints.selected .djs-bendpoint { 519 | display: block; 520 | } 521 | 522 | .djs-drag-active .djs-bendpoints * { 523 | display: none; 524 | } 525 | 526 | .djs-bendpoints:not(.hover) .floating { 527 | display: none; 528 | } 529 | 530 | .djs-segment-dragger:hover .djs-visual, 531 | .djs-segment-dragger.djs-dragging .djs-visual, 532 | .djs-bendpoint:hover .djs-visual, 533 | .djs-bendpoint.floating .djs-visual { 534 | fill: yellow; 535 | stroke-opacity: 0.5; 536 | stroke: black; 537 | } 538 | 539 | .djs-bendpoint.floating .djs-hit { 540 | pointer-events: none; 541 | } 542 | 543 | .djs-segment-dragger .djs-hit, 544 | .djs-bendpoint .djs-hit { 545 | pointer-events: all; 546 | fill: none; 547 | } 548 | 549 | .djs-segment-dragger.horizontal .djs-hit { 550 | cursor: ns-resize; 551 | } 552 | 553 | .djs-segment-dragger.vertical .djs-hit { 554 | cursor: ew-resize; 555 | } 556 | 557 | .djs-segment-dragger.djs-dragging .djs-hit { 558 | pointer-events: none; 559 | } 560 | 561 | .djs-updating, 562 | .djs-updating > * { 563 | pointer-events: none !important; 564 | } 565 | 566 | .djs-updating .djs-context-pad, 567 | .djs-updating .djs-outline, 568 | .djs-updating .djs-bendpoint, 569 | .connect-ok .djs-bendpoint, 570 | .connect-not-ok .djs-bendpoint, 571 | .drop-ok .djs-bendpoint, 572 | .drop-not-ok .djs-bendpoint { 573 | display: none !important; 574 | } 575 | 576 | .djs-segment-dragger.djs-dragging, 577 | .djs-bendpoint.djs-dragging { 578 | display: block; 579 | opacity: 1.0; 580 | } 581 | 582 | .djs-segment-dragger.djs-dragging .djs-visual, 583 | .djs-bendpoint.djs-dragging .djs-visual { 584 | fill: yellow; 585 | stroke-opacity: 0.5; 586 | } 587 | 588 | 589 | /** 590 | * tooltips 591 | */ 592 | .djs-tooltip-error { 593 | font-size: 11px; 594 | line-height: 18px; 595 | text-align: left; 596 | 597 | padding: 5px; 598 | 599 | opacity: 0.7; 600 | } 601 | 602 | .djs-tooltip-error > * { 603 | width: 160px; 604 | 605 | background: rgb(252, 236, 240); 606 | color: rgb(158, 76, 76); 607 | padding: 3px 7px; 608 | border-radius: 5px; 609 | border-left: solid 5px rgb(174, 73, 73); 610 | } 611 | 612 | .djs-tooltip-error:hover { 613 | opacity: 1; 614 | } 615 | 616 | 617 | /** 618 | * search pad 619 | */ 620 | .djs-search-container { 621 | position: absolute; 622 | top: 20px; 623 | left: 0; 624 | right: 0; 625 | margin-left: auto; 626 | margin-right: auto; 627 | 628 | width: 25%; 629 | min-width: 300px; 630 | max-width: 400px; 631 | z-index: 10; 632 | 633 | font-size: 1.05em; 634 | opacity: 0.9; 635 | background: #FAFAFA; 636 | border: solid 1px #CCC; 637 | border-radius: 2px; 638 | } 639 | 640 | .djs-search-container:not(.open) { 641 | display: none; 642 | } 643 | 644 | .djs-search-input input { 645 | font-size: 1.05em; 646 | width: 100%; 647 | padding: 6px 10px; 648 | border: 1px solid #ccc; 649 | } 650 | 651 | .djs-search-input input:focus { 652 | outline: none; 653 | border-color: #52B415; 654 | } 655 | 656 | .djs-search-results { 657 | position: relative; 658 | overflow-y: auto; 659 | max-height: 200px; 660 | } 661 | 662 | .djs-search-results:hover { 663 | /*background: #fffdd7;*/ 664 | cursor: pointer; 665 | } 666 | 667 | .djs-search-result { 668 | width: 100%; 669 | padding: 6px 10px; 670 | background: white; 671 | border-bottom: solid 1px #AAA; 672 | border-radius: 1px; 673 | } 674 | 675 | .djs-search-highlight { 676 | color: black; 677 | } 678 | 679 | .djs-search-result-primary { 680 | margin: 0 0 10px; 681 | } 682 | 683 | .djs-search-result-secondary { 684 | font-family: monospace; 685 | margin: 0; 686 | } 687 | 688 | .djs-search-result:hover { 689 | background: #fdffd6; 690 | } 691 | 692 | .djs-search-result-selected { 693 | background: #fffcb0; 694 | } 695 | 696 | .djs-search-result-selected:hover { 697 | background: #f7f388; 698 | } 699 | 700 | .djs-search-overlay { 701 | background: yellow; 702 | opacity: 0.3; 703 | } 704 | 705 | /** 706 | * hidden styles 707 | */ 708 | .djs-element-hidden, 709 | .djs-element-hidden .djs-hit, 710 | .djs-element-hidden .djs-outline, 711 | .djs-label-hidden .djs-label { 712 | display: none !important; 713 | } 714 | -------------------------------------------------------------------------------- /chrome-ext/src/static/vendor/css/diagram-js-dmn.css: -------------------------------------------------------------------------------- 1 | /** 2 | * outline styles 3 | */ 4 | 5 | .djs-outline { 6 | fill: none; 7 | visibility: hidden; 8 | } 9 | 10 | .djs-element.hover .djs-outline, 11 | .djs-element.selected .djs-outline { 12 | visibility: visible; 13 | shape-rendering: crispEdges; 14 | stroke-dasharray: 3,3; 15 | } 16 | 17 | .djs-element.selected .djs-outline { 18 | stroke: #8888FF; 19 | stroke-width: 1px; 20 | } 21 | 22 | .djs-element.hover .djs-outline { 23 | stroke: #FF8888; 24 | stroke-width: 1px; 25 | } 26 | 27 | .djs-shape.connect-ok .djs-visual > :nth-child(1) { 28 | fill: #DCFECC /* light-green */ !important; 29 | } 30 | 31 | .djs-shape.connect-not-ok .djs-visual > :nth-child(1), 32 | .djs-shape.drop-not-ok .djs-visual > :nth-child(1) { 33 | fill: #f9dee5 /* light-red */ !important; 34 | } 35 | 36 | .djs-shape.new-parent .djs-visual > :nth-child(1) { 37 | fill: #F7F9FF !important; 38 | } 39 | 40 | svg.drop-not-ok { 41 | background: #f9dee5 /* light-red */ !important; 42 | } 43 | 44 | svg.new-parent { 45 | background: #F7F9FF /* light-blue */ !important; 46 | } 47 | 48 | .djs-connection.connect-ok .djs-visual > :nth-child(1), 49 | .djs-connection.drop-ok .djs-visual > :nth-child(1) { 50 | stroke: #90DD5F /* light-green */ !important; 51 | } 52 | 53 | .djs-connection.connect-not-ok .djs-visual > :nth-child(1), 54 | .djs-connection.drop-not-ok .djs-visual > :nth-child(1) { 55 | stroke: #E56283 /* light-red */ !important; 56 | } 57 | 58 | .drop-not-ok, 59 | .connect-not-ok { 60 | cursor: not-allowed; 61 | } 62 | 63 | .djs-element.attach-ok .djs-visual > :nth-child(1) { 64 | stroke-width: 5px !important; 65 | stroke: rgba(255, 116, 0, 0.7) !important; 66 | } 67 | 68 | .djs-frame.connect-not-ok .djs-visual > :nth-child(1), 69 | .djs-frame.drop-not-ok .djs-visual > :nth-child(1) { 70 | stroke-width: 3px !important; 71 | stroke: #E56283 /* light-red */ !important; 72 | fill: none !important; 73 | } 74 | 75 | /** 76 | * Selection box style 77 | * 78 | */ 79 | .djs-lasso-overlay { 80 | fill: rgb(255, 116, 0); 81 | fill-opacity: 0.1; 82 | 83 | stroke-dasharray: 5 1 3 1; 84 | stroke: rgb(255, 116, 0); 85 | 86 | shape-rendering: crispEdges; 87 | pointer-events: none; 88 | } 89 | 90 | /** 91 | * Resize styles 92 | */ 93 | .djs-resize-overlay { 94 | fill: none; 95 | 96 | stroke-dasharray: 5 1 3 1; 97 | stroke: rgb(255, 116, 0); 98 | 99 | pointer-events: none; 100 | } 101 | 102 | .djs-resizer-hit { 103 | fill: none; 104 | pointer-events: all; 105 | } 106 | 107 | .djs-resizer-visual { 108 | fill: white; 109 | stroke-width: 1px; 110 | stroke: black; 111 | shape-rendering: crispEdges; 112 | stroke-opacity: 0.2; 113 | } 114 | 115 | .djs-cursor-resize-nwse, 116 | .djs-resizer-nw, 117 | .djs-resizer-se { 118 | cursor: nwse-resize; 119 | } 120 | 121 | .djs-cursor-resize-nesw, 122 | .djs-resizer-ne, 123 | .djs-resizer-sw { 124 | cursor: nesw-resize; 125 | } 126 | 127 | .djs-shape.djs-resizing > .djs-outline { 128 | visibility: hidden !important; 129 | } 130 | 131 | .djs-shape.djs-resizing > .djs-resizer { 132 | visibility: hidden; 133 | } 134 | 135 | .djs-dragger > .djs-resizer { 136 | visibility: hidden; 137 | } 138 | 139 | /** 140 | * drag styles 141 | */ 142 | .djs-dragger * { 143 | fill: none !important; 144 | stroke: rgb(255, 116, 0) !important; 145 | } 146 | 147 | .djs-dragger tspan, 148 | .djs-dragger text { 149 | fill: rgb(255, 116, 0) !important; 150 | stroke: none !important; 151 | } 152 | 153 | marker.djs-dragger circle, 154 | marker.djs-dragger path, 155 | marker.djs-dragger polygon, 156 | marker.djs-dragger polyline, 157 | marker.djs-dragger rect { 158 | fill: rgb(255, 116, 0) !important; 159 | stroke: none !important; 160 | } 161 | 162 | marker.djs-dragger text, 163 | marker.djs-dragger tspan { 164 | fill: none !important; 165 | stroke: rgb(255, 116, 0) !important; 166 | } 167 | 168 | .djs-dragging { 169 | opacity: 0.3; 170 | } 171 | 172 | .djs-dragging, 173 | .djs-dragging > * { 174 | pointer-events: none !important; 175 | } 176 | 177 | .djs-dragging .djs-context-pad, 178 | .djs-dragging .djs-outline { 179 | display: none !important; 180 | } 181 | 182 | /** 183 | * no pointer events for visual 184 | */ 185 | .djs-visual, 186 | .djs-outline { 187 | pointer-events: none; 188 | } 189 | 190 | .djs-element.attach-ok .djs-hit { 191 | stroke-width: 60px !important; 192 | } 193 | 194 | /** 195 | * all pointer events for hit shape 196 | */ 197 | .djs-shape .djs-hit { 198 | pointer-events: all; 199 | } 200 | 201 | .djs-connection .djs-hit { 202 | pointer-events: stroke; 203 | } 204 | 205 | .djs-frame .djs-hit { 206 | pointer-events: stroke; 207 | } 208 | 209 | /** 210 | * shape / connection basic styles 211 | */ 212 | .djs-connection .djs-visual { 213 | stroke-width: 2px; 214 | fill: none; 215 | } 216 | 217 | .djs-cursor-grab { 218 | cursor: -webkit-grab; 219 | cursor: -moz-grab; 220 | cursor: grab; 221 | } 222 | 223 | .djs-cursor-grabbing { 224 | cursor: -webkit-grabbing; 225 | cursor: -moz-grabbing; 226 | cursor: grabbing; 227 | } 228 | 229 | .djs-cursor-crosshair { 230 | cursor: crosshair; 231 | } 232 | 233 | .djs-cursor-move { 234 | cursor: move; 235 | } 236 | 237 | .djs-cursor-resize-ns { 238 | cursor: ns-resize; 239 | } 240 | 241 | .djs-cursor-resize-ew { 242 | cursor: ew-resize; 243 | } 244 | 245 | 246 | /** 247 | * snapping 248 | */ 249 | .djs-snap-line { 250 | stroke: rgb(255, 195, 66); 251 | stroke: rgba(255, 195, 66, 0.50); 252 | stroke-linecap: round; 253 | stroke-width: 2px; 254 | pointer-events: none; 255 | } 256 | 257 | /** 258 | * snapping 259 | */ 260 | .djs-crosshair { 261 | stroke: #555; 262 | stroke-linecap: round; 263 | stroke-width: 1px; 264 | pointer-events: none; 265 | shape-rendering: crispEdges; 266 | stroke-dasharray: 5, 5; 267 | } 268 | 269 | /** 270 | * palette 271 | */ 272 | 273 | .djs-palette { 274 | position: absolute; 275 | left: 20px; 276 | top: 20px; 277 | 278 | box-sizing: border-box; 279 | width: 48px; 280 | } 281 | 282 | .djs-palette .separator { 283 | margin: 0 5px; 284 | padding-top: 5px; 285 | 286 | border: none; 287 | border-bottom: solid 1px #DDD; 288 | 289 | clear: both; 290 | } 291 | 292 | .djs-palette .entry:before { 293 | vertical-align: text-bottom; 294 | } 295 | 296 | .djs-palette .djs-palette-toggle { 297 | cursor: pointer; 298 | } 299 | 300 | .djs-palette .entry, 301 | .djs-palette .djs-palette-toggle { 302 | color: #333; 303 | font-size: 30px; 304 | 305 | text-align: center; 306 | } 307 | 308 | .djs-palette .entry { 309 | float: left; 310 | } 311 | 312 | .djs-palette .entry img { 313 | max-width: 100%; 314 | } 315 | 316 | .djs-palette .djs-palette-entries:after { 317 | content: ''; 318 | display: table; 319 | clear: both; 320 | } 321 | 322 | .djs-palette .djs-palette-toggle:hover { 323 | background: #666; 324 | } 325 | 326 | .djs-palette .entry:hover { 327 | color: rgb(255, 116, 0); 328 | } 329 | 330 | .djs-palette .highlighted-entry { 331 | color: rgb(255, 116, 0) !important; 332 | } 333 | 334 | .djs-palette .entry, 335 | .djs-palette .djs-palette-toggle { 336 | width: 46px; 337 | height: 46px; 338 | line-height: 46px; 339 | cursor: default; 340 | } 341 | 342 | /** 343 | * Palette open / two-column layout is controlled via 344 | * classes on the palette. Events to hook into palette 345 | * changed life-cycle are available in addition. 346 | */ 347 | .djs-palette.two-column.open { 348 | width: 94px; 349 | } 350 | 351 | .djs-palette:not(.open) .djs-palette-entries { 352 | display: none; 353 | } 354 | 355 | .djs-palette:not(.open) { 356 | overflow: hidden; 357 | } 358 | 359 | .djs-palette.open .djs-palette-toggle { 360 | display: none; 361 | } 362 | 363 | /** 364 | * context-pad 365 | */ 366 | .djs-overlay-context-pad { 367 | width: 72px; 368 | } 369 | 370 | .djs-context-pad { 371 | position: absolute; 372 | display: none; 373 | pointer-events: none; 374 | } 375 | 376 | .djs-context-pad .entry { 377 | width: 22px; 378 | height: 22px; 379 | text-align: center; 380 | display: inline-block; 381 | font-size: 22px; 382 | margin: 0 2px 2px 0; 383 | 384 | border-radius: 3px; 385 | 386 | cursor: default; 387 | 388 | background-color: #FEFEFE; 389 | box-shadow: 0 0 2px 1px #FEFEFE; 390 | pointer-events: all; 391 | } 392 | 393 | .djs-context-pad .entry:before { 394 | vertical-align: top; 395 | } 396 | 397 | .djs-context-pad .entry:hover { 398 | background: rgb(255, 252, 176); 399 | } 400 | 401 | .djs-context-pad.open { 402 | display: block; 403 | } 404 | 405 | /** 406 | * popup styles 407 | */ 408 | .djs-popup .entry { 409 | line-height: 20px; 410 | white-space: nowrap; 411 | cursor: default; 412 | } 413 | 414 | /* larger font for prefixed icons */ 415 | .djs-popup .entry:before { 416 | vertical-align: middle; 417 | font-size: 20px; 418 | } 419 | 420 | .djs-popup .entry > span { 421 | vertical-align: middle; 422 | font-size: 14px; 423 | } 424 | 425 | .djs-popup .entry:hover, 426 | .djs-popup .entry.active:hover { 427 | background: rgb(255, 252, 176); 428 | } 429 | 430 | .djs-popup .entry.disabled { 431 | background: inherit; 432 | } 433 | 434 | .djs-popup .djs-popup-header .entry { 435 | display: inline-block; 436 | padding: 2px 3px 2px 3px; 437 | 438 | border: solid 1px transparent; 439 | border-radius: 3px; 440 | } 441 | 442 | .djs-popup .djs-popup-header .entry.active { 443 | color: rgb(255, 116, 0); 444 | border: solid 1px rgb(255, 116, 0); 445 | background-color: #F6F6F6; 446 | } 447 | 448 | .djs-popup-body .entry { 449 | padding: 4px 10px 4px 5px; 450 | } 451 | 452 | .djs-popup-body .entry > span { 453 | margin-left: 5px; 454 | } 455 | 456 | .djs-popup-body { 457 | background-color: #FEFEFE; 458 | } 459 | 460 | .djs-popup-header { 461 | border-bottom: 1px solid #DDD; 462 | } 463 | 464 | .djs-popup-header .entry { 465 | margin: 1px; 466 | margin-left: 3px; 467 | } 468 | 469 | .djs-popup-header .entry:last-child { 470 | margin-right: 3px; 471 | } 472 | 473 | /** 474 | * popup / palette styles 475 | */ 476 | .djs-popup, .djs-palette { 477 | background: #FAFAFA; 478 | border: solid 1px #CCC; 479 | border-radius: 2px; 480 | } 481 | 482 | /** 483 | * touch 484 | */ 485 | 486 | .djs-shape, 487 | .djs-connection { 488 | touch-action: none; 489 | } 490 | 491 | .djs-segment-dragger, 492 | .djs-bendpoint { 493 | display: none; 494 | } 495 | 496 | /** 497 | * bendpoints 498 | */ 499 | .djs-segment-dragger .djs-visual { 500 | fill: rgba(255, 255, 121, 0.2); 501 | stroke-width: 1px; 502 | stroke-opacity: 1; 503 | stroke: rgba(255, 255, 121, 0.3); 504 | } 505 | 506 | .djs-bendpoint .djs-visual { 507 | fill: rgba(255, 255, 121, 0.8); 508 | stroke-width: 1px; 509 | stroke-opacity: 0.5; 510 | stroke: black; 511 | } 512 | 513 | .djs-segment-dragger:hover, 514 | .djs-bendpoints.hover .djs-segment-dragger, 515 | .djs-bendpoints.selected .djs-segment-dragger, 516 | .djs-bendpoint:hover, 517 | .djs-bendpoints.hover .djs-bendpoint, 518 | .djs-bendpoints.selected .djs-bendpoint { 519 | display: block; 520 | } 521 | 522 | .djs-drag-active .djs-bendpoints * { 523 | display: none; 524 | } 525 | 526 | .djs-bendpoints:not(.hover) .floating { 527 | display: none; 528 | } 529 | 530 | .djs-segment-dragger:hover .djs-visual, 531 | .djs-segment-dragger.djs-dragging .djs-visual, 532 | .djs-bendpoint:hover .djs-visual, 533 | .djs-bendpoint.floating .djs-visual { 534 | fill: yellow; 535 | stroke-opacity: 0.5; 536 | stroke: black; 537 | } 538 | 539 | .djs-bendpoint.floating .djs-hit { 540 | pointer-events: none; 541 | } 542 | 543 | .djs-segment-dragger .djs-hit, 544 | .djs-bendpoint .djs-hit { 545 | pointer-events: all; 546 | fill: none; 547 | } 548 | 549 | .djs-segment-dragger.horizontal .djs-hit { 550 | cursor: ns-resize; 551 | } 552 | 553 | .djs-segment-dragger.vertical .djs-hit { 554 | cursor: ew-resize; 555 | } 556 | 557 | .djs-segment-dragger.djs-dragging .djs-hit { 558 | pointer-events: none; 559 | } 560 | 561 | .djs-updating, 562 | .djs-updating > * { 563 | pointer-events: none !important; 564 | } 565 | 566 | .djs-updating .djs-context-pad, 567 | .djs-updating .djs-outline, 568 | .djs-updating .djs-bendpoint, 569 | .connect-ok .djs-bendpoint, 570 | .connect-not-ok .djs-bendpoint, 571 | .drop-ok .djs-bendpoint, 572 | .drop-not-ok .djs-bendpoint { 573 | display: none !important; 574 | } 575 | 576 | .djs-segment-dragger.djs-dragging, 577 | .djs-bendpoint.djs-dragging { 578 | display: block; 579 | opacity: 1.0; 580 | } 581 | 582 | .djs-segment-dragger.djs-dragging .djs-visual, 583 | .djs-bendpoint.djs-dragging .djs-visual { 584 | fill: yellow; 585 | stroke-opacity: 0.5; 586 | } 587 | 588 | 589 | /** 590 | * tooltips 591 | */ 592 | .djs-tooltip-error { 593 | font-size: 11px; 594 | line-height: 18px; 595 | text-align: left; 596 | 597 | padding: 5px; 598 | 599 | opacity: 0.7; 600 | } 601 | 602 | .djs-tooltip-error > * { 603 | width: 160px; 604 | 605 | background: rgb(252, 236, 240); 606 | color: rgb(158, 76, 76); 607 | padding: 3px 7px; 608 | border-radius: 5px; 609 | border-left: solid 5px rgb(174, 73, 73); 610 | } 611 | 612 | .djs-tooltip-error:hover { 613 | opacity: 1; 614 | } 615 | 616 | 617 | /** 618 | * search pad 619 | */ 620 | .djs-search-container { 621 | position: absolute; 622 | top: 20px; 623 | left: 0; 624 | right: 0; 625 | margin-left: auto; 626 | margin-right: auto; 627 | 628 | width: 25%; 629 | min-width: 300px; 630 | max-width: 400px; 631 | z-index: 10; 632 | 633 | font-size: 1.05em; 634 | opacity: 0.9; 635 | background: #FAFAFA; 636 | border: solid 1px #CCC; 637 | border-radius: 2px; 638 | } 639 | 640 | .djs-search-container:not(.open) { 641 | display: none; 642 | } 643 | 644 | .djs-search-input input { 645 | font-size: 1.05em; 646 | width: 100%; 647 | padding: 6px 10px; 648 | border: 1px solid #ccc; 649 | } 650 | 651 | .djs-search-input input:focus { 652 | outline: none; 653 | border-color: #52B415; 654 | } 655 | 656 | .djs-search-results { 657 | position: relative; 658 | overflow-y: auto; 659 | max-height: 200px; 660 | } 661 | 662 | .djs-search-results:hover { 663 | /*background: #fffdd7;*/ 664 | cursor: pointer; 665 | } 666 | 667 | .djs-search-result { 668 | width: 100%; 669 | padding: 6px 10px; 670 | background: white; 671 | border-bottom: solid 1px #AAA; 672 | border-radius: 1px; 673 | } 674 | 675 | .djs-search-highlight { 676 | color: black; 677 | } 678 | 679 | .djs-search-result-primary { 680 | margin: 0 0 10px; 681 | } 682 | 683 | .djs-search-result-secondary { 684 | font-family: monospace; 685 | margin: 0; 686 | } 687 | 688 | .djs-search-result:hover { 689 | background: #fdffd6; 690 | } 691 | 692 | .djs-search-result-selected { 693 | background: #fffcb0; 694 | } 695 | 696 | .djs-search-result-selected:hover { 697 | background: #f7f388; 698 | } 699 | 700 | .djs-search-overlay { 701 | background: yellow; 702 | opacity: 0.3; 703 | } 704 | 705 | /** 706 | * hidden styles 707 | */ 708 | .djs-element-hidden, 709 | .djs-element-hidden .djs-hit, 710 | .djs-element-hidden .djs-outline, 711 | .djs-label-hidden .djs-label { 712 | display: none !important; 713 | } 714 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | "probot-app" 4 | ], 5 | "version": "1.5.1" 6 | } 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "root", 3 | "private": true, 4 | "devDependencies": { 5 | "lerna": "^8.0.0" 6 | }, 7 | "scripts": { 8 | "postinstall": "lerna exec -- npm i", 9 | "release": "lerna publish", 10 | "start": "cd probot-app && npm run start" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /probot-app/.env.example: -------------------------------------------------------------------------------- 1 | # The ID of your GitHub App 2 | APP_ID= 3 | WEBHOOK_SECRET=development 4 | 5 | # Use `trace` to get verbose logging or `info` to show less 6 | LOG_LEVEL=debug 7 | 8 | # Go to https://smee.io/new set this to the URL that you are redirected to. 9 | WEBHOOK_PROXY_URL= 10 | -------------------------------------------------------------------------------- /probot-app/.eslintrc: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "extends": [ 4 | "plugin:bpmn-io/node" 5 | ], 6 | "rules": { 7 | "no-useless-catch": 0 8 | } 9 | } -------------------------------------------------------------------------------- /probot-app/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | 63 | *.txt 64 | *.png 65 | -------------------------------------------------------------------------------- /probot-app/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | education, socio-economic status, nationality, personal appearance, race, 10 | religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at niklas.kiefer@camunda.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | -------------------------------------------------------------------------------- /probot-app/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | [fork]: /fork 4 | [pr]: /compare 5 | [style]: https://github.com/bpmn-io/eslint-plugin-bpmn-io 6 | [code-of-conduct]: CODE_OF_CONDUCT.md 7 | 8 | Hi there! We're thrilled that you'd like to contribute to this project. Your help is essential for keeping it great. 9 | 10 | Please note that this project is released with a [Contributor Code of Conduct][code-of-conduct]. By participating in this project you agree to abide by its terms. 11 | 12 | ## Issues and PRs 13 | 14 | If you have suggestions for how this project could be improved, or want to report a bug, open an issue! We'd love all and any contributions. If you have questions, too, we'd love to hear them. 15 | 16 | We'd also love PRs. If you're thinking of a large PR, we advise opening up an issue first to talk about it, though! Look at the links below if you're not sure how to open a PR. 17 | 18 | ## Submitting a pull request 19 | 20 | 1. [Fork][fork] and clone the repository. 21 | 1. Configure and install the dependencies: `npm install`. 22 | 1. Make sure the tests pass on your machine: `npm test`, note: these tests also apply the linter, so there's no need to lint separately. 23 | 1. Create a new branch: `git checkout -b my-branch-name`. 24 | 1. Make your change, add tests, and make sure the tests still pass. 25 | 1. Push to your fork and [submit a pull request][pr]. 26 | 1. Pat your self on the back and wait for your pull request to be reviewed and merged. 27 | 28 | Here are a few things you can do that will increase the likelihood of your pull request being accepted: 29 | 30 | - Follow the [style guide][style] which is using standard. Any linting errors should be shown when running `npm test`. 31 | - Write and update tests. 32 | - Keep your changes as focused as possible. If there are multiple changes you would like to make that are not dependent upon each other, consider submitting them as separate pull requests. 33 | - Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html). 34 | 35 | Work in Progress pull requests are also welcome to get feedback early on, or if there is something blocked you. 36 | 37 | ## Resources 38 | 39 | - [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/) 40 | - [Using Pull Requests](https://help.github.com/articles/about-pull-requests/) 41 | - [GitHub Help](https://help.github.com) 42 | -------------------------------------------------------------------------------- /probot-app/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Niklas Kiefer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /probot-app/README.md: -------------------------------------------------------------------------------- 1 | > Note: Currently it's not possible to upload `.bpmn` files via drag and drop on GitHub. Attaching a `.txt` extension at the end can be a workaround. 2 | 3 | # render-bpmn 4 | 5 | ![Build Status](https://github.com/pinussilvestrus/github-bpmn/workflows/ci/badge.svg) 6 | 7 | A GitHub App built with [Probot](https://github.com/probot/probot) that automatically renders BPMN files on GitHub Issues and Pull Requests. 8 | 9 | ![](../resources/screencast-2.gif) 10 | 11 | ## Setup 12 | 13 | The application is connected to GitHub as a [GitHub app](https://developer.github.com/apps/). Get started by creating a GitHub app, either via the development setup or using [manual configuration steps](#manual-steps) as documented below. 14 | 15 | 16 | ### Automatic Development Setup 17 | 18 | Checkout, install and run the application in development mode as shown below: 19 | 20 | ```bash 21 | git clone git@github.com:pinussilvestrus/github-bpmn.git 22 | cd probot-app 23 | npm install 24 | npm run dev 25 | ``` 26 | 27 | Access the application on [`localhost:3000`](http://localhost:3000). [Probot](https://probot.github.io/), the app framework used by the render-bpmn application, helps you to create your GitHub app. Give your app a unique name and remember it. 28 | 29 | Once the setup completes probot writes the basic app configuration to the `probot-app/.env` file. Go to your app page on GitHub, fetch client ID and client secret and add these properties to the `.env` file as `GITHUB_CLIENT_ID` and `GITHUB_CLIENT_SECRET`, respectively. 30 | 31 | __Note:__ on additional start after registering could be needed work properly, causing registering delays to the smee.io proxy. 32 | 33 | ### Manual Steps 34 | 35 | [Create your GitHub app](https://github.com/settings/apps/new) and configure it according to the [provided app mainfest](../probot-app/app.yml). 36 | 37 | Create a `.env` file with the required configuration variables as provided by GitHub. Use the [provided example](../probot-app/.env.example) as a starting point. 38 | 39 | ## Deploy 40 | 41 | Tryout the Heroku Deploy Button below and [follow the setup instructions](https://probot.github.io/docs/deployment/#heroku). 42 | 43 | [![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/pinussilvestrus/github-bpmn) 44 | 45 | Also feel free to have a look at [the other deployment options](https://probot.github.io/docs/deployment/). 46 | 47 | 48 | ## Contributing 49 | 50 | If you have suggestions for how probot could be improved, or want to report a bug, open an issue! We'd love all and any contributions. 51 | 52 | For more, check out the [Contributing Guide](CONTRIBUTING.md). 53 | 54 | ## License 55 | 56 | [MIT](LICENSE) © 2019 Niklas Kiefer 57 | 58 | Contains parts ([bpmn-to-image](https://github.com/bpmn-io/bpmn-to-image)) released under the [bpmn.io license](http://bpmn.io/license). 59 | -------------------------------------------------------------------------------- /probot-app/app.yml: -------------------------------------------------------------------------------- 1 | # This is a GitHub App Manifest. These settings will be used by default when 2 | # initially configuring your GitHub App. 3 | # 4 | # NOTE: changing this file will not update your GitHub App settings. 5 | # You must visit github.com/settings/apps/your-app-name to edit them. 6 | # 7 | # Read more about configuring your GitHub App: 8 | # https://probot.github.io/docs/development/#configuring-a-github-app 9 | # 10 | # Read more about GitHub App Manifests: 11 | # https://developer.github.com/apps/building-github-apps/creating-github-apps-from-a-manifest/ 12 | 13 | # The list of events the GitHub App subscribes to. 14 | # Uncomment the event names below to enable them. 15 | default_events: 16 | # - content_reference 17 | # - check_run 18 | # - check_suite 19 | # - commit_comment 20 | # - create 21 | # - delete 22 | # - deployment 23 | # - deployment_status 24 | # - fork 25 | # - gollum 26 | - issue_comment 27 | - issues 28 | # - label 29 | # - milestone 30 | # - member 31 | # - membership 32 | # - org_block 33 | # - organization 34 | # - page_build 35 | # - project 36 | # - project_card 37 | # - project_column 38 | # - public 39 | - pull_request 40 | # - pull_request_review 41 | # - pull_request_review_comment 42 | # - push 43 | # - release 44 | # - repository 45 | # - repository_import 46 | # - status 47 | # - team 48 | # - team_add 49 | # - watch 50 | 51 | # The set of permissions needed by the GitHub App. The format of the object uses 52 | # the permission name for the key (for example, issues) and the access type for 53 | # the value (for example, write). 54 | # Valid values are `read`, `write`, and `none` 55 | default_permissions: 56 | # Repository creation, deletion, settings, teams, and collaborators. 57 | # https://developer.github.com/v3/apps/permissions/#permission-on-administration 58 | # administration: read 59 | 60 | # Checks on code. 61 | # https://developer.github.com/v3/apps/permissions/#permission-on-checks 62 | # checks: read 63 | 64 | # Repository contents, commits, branches, downloads, releases, and merges. 65 | # https://developer.github.com/v3/apps/permissions/#permission-on-contents 66 | # contents: write 67 | 68 | # Deployments and deployment statuses. 69 | # https://developer.github.com/v3/apps/permissions/#permission-on-deployments 70 | # deployments: read 71 | 72 | # Issues and related comments, assignees, labels, and milestones. 73 | # https://developer.github.com/v3/apps/permissions/#permission-on-issues 74 | issues: write 75 | 76 | # Search repositories, list collaborators, and access repository metadata. 77 | # https://developer.github.com/v3/apps/permissions/#metadata-permissions 78 | metadata: read 79 | 80 | # Retrieve Pages statuses, configuration, and builds, as well as create new builds. 81 | # https://developer.github.com/v3/apps/permissions/#permission-on-pages 82 | # pages: read 83 | 84 | # Pull requests and related comments, assignees, labels, milestones, and merges. 85 | # https://developer.github.com/v3/apps/permissions/#permission-on-pull-requests 86 | pull_requests: write 87 | 88 | # Manage the post-receive hooks for a repository. 89 | # https://developer.github.com/v3/apps/permissions/#permission-on-repository-hooks 90 | # repository_hooks: read 91 | 92 | # Manage repository projects, columns, and cards. 93 | # https://developer.github.com/v3/apps/permissions/#permission-on-repository-projects 94 | # repository_projects: read 95 | 96 | # Retrieve security vulnerability alerts. 97 | # https://developer.github.com/v4/object/repositoryvulnerabilityalert/ 98 | # vulnerability_alerts: read 99 | 100 | # Commit statuses. 101 | # https://developer.github.com/v3/apps/permissions/#permission-on-statuses 102 | # statuses: read 103 | 104 | # Organization members and teams. 105 | # https://developer.github.com/v3/apps/permissions/#permission-on-members 106 | # members: read 107 | 108 | # View and manage users blocked by the organization. 109 | # https://developer.github.com/v3/apps/permissions/#permission-on-organization-user-blocking 110 | # organization_user_blocking: read 111 | 112 | # Manage organization projects, columns, and cards. 113 | # https://developer.github.com/v3/apps/permissions/#permission-on-organization-projects 114 | # organization_projects: read 115 | 116 | # Manage team discussions and related comments. 117 | # https://developer.github.com/v3/apps/permissions/#permission-on-team-discussions 118 | # team_discussions: read 119 | 120 | # Manage the post-receive hooks for an organization. 121 | # https://developer.github.com/v3/apps/permissions/#permission-on-organization-hooks 122 | # organization_hooks: read 123 | 124 | # Get notified of, and update, content references. 125 | # https://developer.github.com/v3/apps/permissions/ 126 | # organization_administration: read 127 | 128 | 129 | # The name of the GitHub App. Defaults to the name specified in package.json 130 | # name: My Probot App 131 | 132 | # The homepage of your GitHub App. 133 | # url: https://example.com/ 134 | 135 | # A description of the GitHub App. 136 | # description: A description of my awesome app 137 | 138 | # Set to true when your GitHub App is available to the public or false when it is only accessible to the owner of the app. 139 | # Default: true 140 | # public: false 141 | -------------------------------------------------------------------------------- /probot-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "render-bpmn", 3 | "version": "1.5.1", 4 | "description": "Hackdays Project: Render BPMN, CMMN and DMN files on GitHub", 5 | "author": "Niklas Kiefer ", 6 | "license": "MIT", 7 | "repository": "https://github.com/pinussilvestrus/github-bpmn.git", 8 | "homepage": "https://github.com/pinussilvestrus/github-bpmn/probot-app", 9 | "bugs": "https://github.com/pinussilvestrus/github-bpmn/issues", 10 | "keywords": [ 11 | "probot", 12 | "github", 13 | "probot-app", 14 | "bpmn" 15 | ], 16 | "scripts": { 17 | "all": "run-s test", 18 | "dev": "nodemon", 19 | "start": "probot run ./src/index.js", 20 | "lint": "eslint .", 21 | "test": "jest && npm run lint", 22 | "test:watch": "jest --watch --notify --notifyMode=change --coverage" 23 | }, 24 | "dependencies": { 25 | "bpmn-to-image": "^0.9.0", 26 | "imgur": "^1.0.2", 27 | "probot": "^12.3.3", 28 | "request": "^2.88.2", 29 | "request-promise": "^4.2.6" 30 | }, 31 | "devDependencies": { 32 | "eslint": "^8.54.0", 33 | "eslint-plugin-bpmn-io": "^1.0.0", 34 | "jest": "^29.7.0", 35 | "nock": "^13.4.0", 36 | "nodemon": "^3.0.1", 37 | "npm-run-all": "^4.1.5", 38 | "smee-client": "^1.2.3" 39 | }, 40 | "engines": { 41 | "node": ">= 8.3.0" 42 | }, 43 | "standard": { 44 | "env": [ 45 | "jest" 46 | ] 47 | }, 48 | "nodemonConfig": { 49 | "exec": "npm start", 50 | "watch": [ 51 | ".env", 52 | "." 53 | ] 54 | }, 55 | "jest": { 56 | "testEnvironment": "node" 57 | }, 58 | "gitHead": "50f909f9b5bae34547c2cf8dd3f5c9a636186474" 59 | } 60 | -------------------------------------------------------------------------------- /probot-app/src/helper/extractBpmnFileUrls.js: -------------------------------------------------------------------------------- 1 | // const regex = new RegExp("/\[.*\]\((https:\/\/|http:\/\/).*\)/g"); 2 | const regex = /\[.+\]\((https:\/\/|http:\/\/).*(\.bpmn|\.txt|\.xml)\)/g; 3 | 4 | function resolveUrl(occurrence) { 5 | return occurrence.substring( 6 | occurrence.lastIndexOf('(') + 1, 7 | occurrence.lastIndexOf(')') 8 | ); 9 | } 10 | 11 | /** 12 | * Find all urls and return in the form of 13 | * { from: , to: , url: , raw: } 14 | * @param {String} content 15 | * 16 | * @return Array 17 | */ 18 | module.exports = function(content) { 19 | 20 | if (!content) { 21 | return; 22 | } 23 | 24 | let result, occurrences = []; 25 | 26 | while ((result = regex.exec(content)) !== null) { 27 | 28 | const occurrence = result[0], 29 | index = result.index, 30 | url = resolveUrl(occurrence); 31 | 32 | // do not include already rendered diagrams 33 | if (content.includes(`data-original=${url}`)) { 34 | continue; 35 | } 36 | 37 | occurrences.push({ 38 | raw: occurrence, 39 | from: index, 40 | to: index + occurrence.length, 41 | url: url 42 | }); 43 | } 44 | 45 | return occurrences; 46 | }; -------------------------------------------------------------------------------- /probot-app/src/helper/index.js: -------------------------------------------------------------------------------- 1 | const extractBpmnFileUrls = require('./extractBpmnFileUrls'); 2 | 3 | const templates = require('./templates'); 4 | 5 | module.exports = { 6 | extractBpmnFileUrls, 7 | templates 8 | }; -------------------------------------------------------------------------------- /probot-app/src/helper/templates.js: -------------------------------------------------------------------------------- 1 | function renderDiagramTmpl(options) { 2 | 3 | const { 4 | uploadedUrl, 5 | url 6 | } = options; 7 | 8 | return `
`; 9 | } 10 | 11 | function renderSpinnerTmpl(options) { 12 | 13 | const { 14 | url 15 | } = options; 16 | 17 | 18 | return ` 19 | ![](https://github.com/pinussilvestrus/github-bpmn/blob/master/probot-app/src/misc/loading.gif?raw=true) 20 | `; 21 | } 22 | 23 | module.exports = { 24 | renderDiagramTmpl, 25 | renderSpinnerTmpl 26 | }; -------------------------------------------------------------------------------- /probot-app/src/index.js: -------------------------------------------------------------------------------- 1 | const { 2 | extractBpmnFileUrls, 3 | templates 4 | } = require('./helper'); 5 | 6 | const processUrls = require('./process-urls'); 7 | 8 | let log; 9 | 10 | /** 11 | * Generates String which contains necessary information about the current 12 | * processed comment | issue | pull_request 13 | * 14 | * @param {Comment} options.comment 15 | * @param {Issue} options.issue 16 | * @param {PullRequest} options.pull_request 17 | * @param {Repository} options.repository 18 | * 19 | * @return {String} 20 | */ 21 | function getContextString(options) { 22 | 23 | const { 24 | comment, 25 | issue, 26 | pull_request, 27 | repository 28 | } = options; 29 | 30 | return JSON.stringify({ 31 | repository: repository.full_name, 32 | issue: comment ? comment.issue_url : (issue || {}).url, 33 | pull_request: (pull_request || {}).url, 34 | comment: (comment || {}).id 35 | }); 36 | 37 | } 38 | 39 | function cleanupSpinners(options) { 40 | 41 | const { 42 | urls, 43 | body 44 | } = options; 45 | 46 | urls.forEach(u => { 47 | body.replace(templates.renderSpinnerTmpl({ url: u.url }), ''); 48 | }); 49 | } 50 | 51 | /** 52 | * Patches a comment or issue or pull request content. 53 | * 54 | * @param {String} options.body 55 | * @param {Array} options.urls 56 | * @param {Comment} options.comment 57 | * @param {GithubApiClient} options.github 58 | * @param {Issue} options.issue 59 | * @param {PullRequest} options.pull_request 60 | * @param {Repository} options.repository 61 | * @param {Function} options.templateFn 62 | * 63 | * @return {Promise} 64 | */ 65 | async function updateComment(options) { 66 | 67 | let { 68 | body, 69 | urls 70 | } = options; 71 | 72 | const { 73 | comment, 74 | github, 75 | issue, 76 | pull_request, 77 | repository, 78 | templateFn 79 | } = options; 80 | 81 | urls.forEach(u => { 82 | const { 83 | url 84 | } = u; 85 | 86 | // updated 'to' idx 87 | const to = u.to = body.indexOf(url) + url.length; 88 | 89 | const tag = templateFn(u); 90 | 91 | body = body.slice(0, to + 1) + tag + body.slice(to + 1); 92 | 93 | }); 94 | 95 | cleanupSpinners({ urls, body }); 96 | 97 | // TODO: refactor me to a better fit pattern 98 | if (comment) { 99 | await github.issues.updateComment({ 100 | owner: repository.owner.login, 101 | repo: repository.name, 102 | comment_id: comment.id, 103 | body: body 104 | }); 105 | } else if (issue) { 106 | 107 | await github.issues.update({ 108 | owner: repository.owner.login, 109 | repo: repository.name, 110 | issue_number: issue.number, 111 | body: body 112 | }); 113 | } else { 114 | 115 | await github.pullRequests.update({ 116 | owner: repository.owner.login, 117 | repo: repository.name, 118 | pull_number: pull_request.number, 119 | body: body 120 | }); 121 | } 122 | 123 | 124 | } 125 | 126 | /** 127 | * Adds a loading spinner for every url occurence 128 | * @param {*} options 129 | * 130 | * @return {Promise} 131 | */ 132 | async function addLoadingSpinners(options) { 133 | 134 | await updateComment({ 135 | ...options, 136 | templateFn: templates.renderSpinnerTmpl 137 | }); 138 | 139 | } 140 | 141 | /** 142 | * Renders all attached bpmn file urls to actual diagram 143 | * 144 | * @param {*} context 145 | * 146 | * @return {Promise} 147 | */ 148 | async function renderDiagrams(context) { 149 | 150 | const { 151 | octokit: github, 152 | payload 153 | } = context; 154 | 155 | const { 156 | comment, 157 | issue, 158 | pull_request, 159 | repository 160 | } = payload; 161 | 162 | let { 163 | body 164 | } = comment || issue || pull_request; 165 | 166 | const contextString = getContextString({ comment, issue, pull_request, repository }); 167 | 168 | if (!body) { 169 | return; 170 | } 171 | 172 | // check whether comment contains uploaded bpmn file 173 | const urls = extractBpmnFileUrls(body); 174 | 175 | if (!urls || !urls.length) { 176 | return; 177 | } 178 | 179 | log.info(`Processing of Created Comment started, ${contextString}`); 180 | 181 | await addLoadingSpinners({ 182 | body, 183 | comment, 184 | github, 185 | issue, 186 | pull_request, 187 | repository, 188 | urls 189 | }); 190 | 191 | log.info(`Added Loading Spinners, ${contextString}`); 192 | 193 | await processUrls(urls); 194 | 195 | await updateComment({ 196 | body, 197 | comment, 198 | github, 199 | issue, 200 | pull_request, 201 | repository, 202 | templateFn: templates.renderDiagramTmpl, 203 | urls 204 | }); 205 | 206 | log.info(`Comment updated with Rendered Diagrams, ${contextString}`); 207 | 208 | // TODO: cleanup imgur files afterwards? 209 | } 210 | 211 | /** 212 | * Probot App entry point 213 | * @param {import('probot').Application} app 214 | */ 215 | module.exports = app => { 216 | 217 | log = app.log; 218 | 219 | app.on([ 220 | 'issue_comment.created', 221 | 'issue_comment.edited', 222 | 'issues.opened', 223 | 'issues.edited', 224 | 'pull_request.opened', 225 | 'pull_request.edited' 226 | ], renderDiagrams); 227 | }; 228 | -------------------------------------------------------------------------------- /probot-app/src/misc/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinussilvestrus/github-bpmn/071e645aa18b327b401b709ac704832c48037a2f/probot-app/src/misc/loading.gif -------------------------------------------------------------------------------- /probot-app/src/process-urls/index.js: -------------------------------------------------------------------------------- 1 | const rp = require('request-promise'); 2 | 3 | const fs = require('fs'); 4 | 5 | const imgur = require('imgur'); 6 | 7 | const { 8 | promisify 9 | } = require('util'); 10 | 11 | const { 12 | convertAll 13 | } = require('bpmn-to-image'); 14 | 15 | const writeFileAsync = promisify(fs.writeFile); 16 | 17 | const deleteFileAsync = promisify(fs.unlink); 18 | 19 | /** 20 | * Processes all url occurrences by 21 | * - Fetching the url's content 22 | * - Saving file content to disk 23 | * - Render bpmn content to image 24 | * - Upload to imgur file space 25 | * 26 | * @param {Array} urls 27 | * 28 | * @return {Promise} 29 | */ 30 | module.exports = async function processUrls(urls) { 31 | 32 | await Promise.all(urls.map(async (u, idx) => { 33 | 34 | const { 35 | url 36 | } = u; 37 | 38 | if (!url) { 39 | return; 40 | } 41 | 42 | // fetch file content 43 | const content = await rp(url); 44 | 45 | // save to temp file 46 | const tmpFile = `${__dirname}/../diagram.${idx}.txt`, 47 | tmpImgFile = `diagram.${idx}.png`; 48 | 49 | await writeFileAsync(tmpFile, content); 50 | 51 | // generate + upload image 52 | let response; 53 | 54 | try { 55 | await convertAll([ 56 | { 57 | input: tmpFile, 58 | outputs: [ tmpImgFile ] 59 | } 60 | ]); 61 | 62 | // TODO: way to simply display raw image on GitHub markdown? 63 | response = await imgur.uploadFile(tmpImgFile); 64 | 65 | } catch (error) { 66 | 67 | // TODO: better error handling 68 | return; 69 | } 70 | 71 | if (!response || !response.data.link) { 72 | 73 | return; 74 | } 75 | 76 | // cleanup 77 | deleteFileAsync(tmpFile); 78 | deleteFileAsync(tmpImgFile); 79 | 80 | Object.assign(u, { 81 | uploadedUrl: response.data.link 82 | }); 83 | 84 | })); 85 | }; -------------------------------------------------------------------------------- /probot-app/test/fixtures/issue_comment.created.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "created", 3 | "issue": { 4 | "number": 1, 5 | "user": { 6 | "login": "pinussilvestrus" 7 | } 8 | }, 9 | "comment": { 10 | "id": 1, 11 | "body": "[diagram_copypaste.bpmn.txt](https://github.com/pinussilvestrus/github-bpmn/files/3504544/diagram_copypaste.bpmn.txt)" 12 | }, 13 | "repository": { 14 | "name": "github-bpmn", 15 | "owner": { 16 | "login": "pinussilvestrus" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /probot-app/test/index.test.js: -------------------------------------------------------------------------------- 1 | /* global jest, expect, describe, test, beforeEach */ 2 | 3 | const nock = require('nock'); 4 | 5 | const { Probot } = require('probot'); 6 | 7 | jest.mock('bpmn-to-image'); 8 | jest.mock('imgur'); 9 | 10 | const renderBpmnApp = require('../src'); 11 | 12 | const payload = require('./fixtures/issue_comment.created'); 13 | 14 | const xml = ` 15 | 16 | 17 | 18 | SequenceFlow_0xbi38e 19 | 20 | 21 | 22 | SequenceFlow_0wetfnk 23 | 24 | 25 | 26 | SequenceFlow_087tlq4 27 | SequenceFlow_0wetfnk 28 | 29 | 30 | 31 | SequenceFlow_0xbi38e 32 | SequenceFlow_0t7oahk 33 | 34 | 35 | SequenceFlow_0t7oahk 36 | SequenceFlow_087tlq4 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | `; 78 | 79 | nock.disableNetConnect(); 80 | 81 | describe('render-bpmn', () => { 82 | let probot; 83 | 84 | // load probot 85 | beforeEach(() => { 86 | probot = new Probot({ id: 123, githubToken: 'test' }); 87 | probot.load(renderBpmnApp); 88 | }); 89 | 90 | // mock requests 91 | beforeEach(() => { 92 | 93 | nock.enableNetConnect(); 94 | 95 | nock('https://api.github.com') 96 | .post('/app/installations/2/access_tokens') 97 | .reply(200, { token: 'test' }); 98 | 99 | nock('https://github.com') 100 | .get('/pinussilvestrus/github-bpmn/files/3504544/diagram_copypaste.bpmn.txt') 101 | .reply(200, xml); 102 | 103 | nock('https://api.imgur.com') 104 | .post('/3/image') 105 | .reply(200, { 106 | data: { 107 | link: 'foo' 108 | } 109 | }); 110 | 111 | }); 112 | 113 | test('update comment after created', async () => { 114 | 115 | nock('https://api.github.com') 116 | .patch( 117 | '/repos/pinussilvestrus/github-bpmn/issues/comments/1', (body) => { 118 | 119 | // then, update #1 loading spinner 120 | expect(body).not.toBeUndefined(); 121 | expect(body.body).toContain( 122 | '![](https://github.com/pinussilvestrus/github-bpmn/blob/master/probot-app/src/misc/loading.gif?raw=true)' 123 | ); 124 | 125 | nock('https://api.github.com') 126 | .patch( 127 | '/repos/pinussilvestrus/github-bpmn/issues/comments/1', (body) => { 128 | 129 | // then, update #2 rendered diagram 130 | expect(body).not.toBeUndefined(); 131 | expect(body.body).toContain( 132 | ' 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /resources/complex.cmmn: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | complete 36 | 37 | 38 | 39 | 40 | complete 41 | 42 | 43 | 44 | 45 | 46 | complete 47 | 48 | 49 | 50 | 51 | complete 52 | 53 | 54 | 55 | 56 | complete 57 | 58 | 59 | 60 | 61 | complete 62 | 63 | 64 | 65 | 66 | complete 67 | 68 | 69 | 70 | 71 | complete 72 | 73 | 74 | 75 | 76 | 77 | 79 | 80 | 81 | 82 | 83 | 84 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | complete 97 | 98 | 99 | 100 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 110 | 111 | 112 | 113 | 114 | 115 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 130 | 131 | 133 | 134 | 135 | 136 | 137 | 139 | 140 | 141 | 142 | 143 | 145 | 146 | 147 | 148 | 149 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | -------------------------------------------------------------------------------- /resources/conditions.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SequenceFlow_1 6 | SequenceFlow_3 7 | SequenceFlow_4 8 | 9 | 10 | bar}]]> 11 | 12 | 13 | SequenceFlow_2 14 | SequenceFlow_4 15 | 16 | 17 | SequenceFlow_1 18 | SequenceFlow_2 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | SequenceFlow_3 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /resources/large.dmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | status 7 | 8 | 9 | 10 | sum 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | = 1000]]> 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /resources/multiple-cases.cmmn: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /resources/one-decision.dmn: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | season 16 | 17 | 18 | 19 | 20 | guestCount 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 8]]> 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 10]]> 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | = 10]]> 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /resources/screencast-1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinussilvestrus/github-bpmn/071e645aa18b327b401b709ac704832c48037a2f/resources/screencast-1.gif -------------------------------------------------------------------------------- /resources/screencast-2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinussilvestrus/github-bpmn/071e645aa18b327b401b709ac704832c48037a2f/resources/screencast-2.gif -------------------------------------------------------------------------------- /resources/screencast-3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinussilvestrus/github-bpmn/071e645aa18b327b401b709ac704832c48037a2f/resources/screencast-3.gif -------------------------------------------------------------------------------- /resources/simple.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SequenceFlow_3 6 | SequenceFlow_2 7 | 8 | SequenceFlow_1 9 | 10 | 11 | SequenceFlow_1 12 | 13 | 14 | 15 | 16 | SequenceFlow_2 17 | 18 | 19 | 20 | SequenceFlow_3 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /resources/simple.cmmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | occur 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /resources/simple.dmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | status 8 | 9 | 10 | 11 | 12 | sum 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | = 1000]]> 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /userscript/.eslintrc: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "extends": [ 4 | "plugin:bpmn-io/es6" 5 | ], 6 | "rules": { 7 | "no-useless-catch": 0 8 | } 9 | } -------------------------------------------------------------------------------- /userscript/index.js: -------------------------------------------------------------------------------- 1 | /* global $, BpmnJS, CmmnJS, window, atob, Promise, DmnJS */ 2 | 3 | // ==UserScript== 4 | // @name BPMN on hover 5 | // @namespace https://github.com/pinussilvestrus/github-bpmn 6 | // @version 0.1.0 7 | // @description On hover over a bpmn file it will display it 8 | // @author Langleu 9 | // @match https://github.com/* 10 | // @require https://code.jquery.com/jquery-3.4.1.min.js 11 | // @require https://unpkg.com/bpmn-js@5.0.0/dist/bpmn-viewer.production.min.js 12 | // @require https://unpkg.com/cmmn-js@0.19.2/dist/cmmn-viewer.production.min.js 13 | // @require https://unpkg.com/dmn-js@7.0.0/dist/dmn-viewer.production.min.js 14 | // @resource https://unpkg.com/bpmn-js@5.0.0/dist/assets/diagram-js.css 15 | // @resource https://unpkg.com/cmmn-js@0.19.2/dist/assets/diagram-js.css 16 | // @resource https://unpkg.com/dmn-js@7.0.0/dist/assets/diagram-js.css 17 | // @grant none 18 | // ==/UserScript== 19 | 20 | const thumb_selector = '.content a'; 21 | 22 | // returns source url for GitHub 23 | function getSrc(src) { 24 | let splitSrc = src.split('/'); 25 | let notAllowed = ['blob', 'https:', 'http:', 'github.com']; 26 | 27 | splitSrc = splitSrc.filter(function(word) { 28 | if (!notAllowed.includes(word)) 29 | return word; 30 | }); 31 | 32 | let user = splitSrc.reverse().pop(); 33 | let repo = splitSrc.pop(); 34 | let ref = splitSrc.pop(); 35 | 36 | return `https://api.github.com/repos/${user}/${repo}/contents/${splitSrc.reverse().join('/').replace('#','')}?ref=${ref}`; 37 | } 38 | 39 | // returns the viewer depending on the viewer type 40 | function returnViewer(type) { 41 | switch (type) { 42 | case 'bpmn': 43 | return new BpmnJS({ 44 | container: $('#js-canvas') 45 | }); 46 | case 'cmmn': 47 | return new CmmnJS({ 48 | container: $('#js-canvas') 49 | }); 50 | case 'dmn': 51 | return new DmnJS({ 52 | container: $('#js-canvas') 53 | }); 54 | default: 55 | return; 56 | } 57 | } 58 | 59 | // exports and appends an SVG for any viewer 60 | function exportSVG(viewer, posX, posY, ele) { 61 | 62 | return new Promise((resolve, reject) => { 63 | viewer.saveSVG(function(err, svg) { 64 | 65 | if (err) reject(); 66 | 67 | ele.append(`
${svg}
`); 68 | 69 | $('.svg') 70 | .css('position', 'fixed') 71 | .css('bottom', (window.innerHeight - posY) * 0.5) 72 | .css('left', posX + 25) 73 | .css('z-index', 9999) 74 | .css('background-color', 'white') 75 | .css('height', '50%') 76 | .css('width', '50%') 77 | .css('box-shadow', '0px 0px 20px 5px rgba(0,0,0,1)'); 78 | 79 | $('.svg svg') 80 | .attr('width', '100%') 81 | .attr('height', '100%'); 82 | 83 | resolve(); 84 | }); 85 | }) 86 | 87 | } 88 | 89 | // shows BPMN, CMMN and DMN (DRD) diagrams 90 | function showDiagram(e) { 91 | let sourceUrl = this.href || e.href; 92 | let viewerType = null; 93 | 94 | // to which parent element the svg will be appended 95 | let ele = $('.file-wrap'); 96 | if (e.href) 97 | ele = $('body'); 98 | 99 | if (sourceUrl.includes('.bpmn')) { 100 | viewerType = 'bpmn'; 101 | } else if (sourceUrl.includes('.cmmn')) { 102 | viewerType = 'cmmn'; 103 | } else if (sourceUrl.includes('.dmn')) { 104 | viewerType = 'dmn'; 105 | } else { 106 | return; 107 | } 108 | 109 | var loc = getSrc(sourceUrl); 110 | 111 | $('body').append('
'); 112 | $('.js-canvas-parent').css('visibility', 'hidden'); 113 | 114 | var viewer = returnViewer(viewerType); 115 | 116 | // ajax call to request content from github usercontent 117 | return new Promise((resolve, reject) => { 118 | $.ajax(loc, { 119 | dataType: 'json' 120 | }).done(function(json) { 121 | let xml = b64DecodeUnicode(json.content); 122 | 123 | viewer.importXML(xml, async function(err) { 124 | 125 | if (viewerType == 'dmn') { 126 | var activeView = viewer.getActiveView(); 127 | // apply initial logic in DRD view 128 | if (activeView.type === 'drd') { 129 | var activeEditor = viewer.getActiveViewer(); 130 | 131 | // access active editor components 132 | var canvas = activeEditor.get('canvas'); 133 | 134 | // zoom to fit full viewport 135 | canvas.zoom('fit-viewport'); 136 | 137 | await exportSVG(activeEditor, e.clientX, e.clientY, ele); 138 | } 139 | } else { 140 | (err) ? console.error(err): viewer.get('canvas').zoom('fit-viewport'); 141 | 142 | await exportSVG(viewer, e.clientX, e.clientY, ele); 143 | 144 | resolve(); 145 | } 146 | }); 147 | }); 148 | }); 149 | } 150 | 151 | // removes diagram from drom 152 | function hideDiagram(e) { 153 | $('.svg').remove(); 154 | $('.js-canvas-parent').remove(); 155 | } 156 | 157 | function addRenderButton() { 158 | if ($('.final-path').length && 159 | $('.final-path').text().includes('.bpmn') || 160 | $('.final-path').text().includes('.cmmn') || 161 | $('.final-path').text().includes('.dmn') 162 | ) { 163 | $('.Box-header .BtnGroup').append('Render'); 164 | } 165 | $('a#render-diagram').on('click', openDiagram); 166 | } 167 | 168 | // opens the diagram in a new window 169 | async function openDiagram() { 170 | await showDiagram(this); 171 | 172 | var w = window.open(); 173 | var html = $('.svg').html(); 174 | $(w.document.body).html(html); 175 | } 176 | 177 | /** 178 | * Active calls 179 | */ 180 | 181 | // add the render button in case of a site refresh 182 | addRenderButton(); 183 | $('body').on('mouseenter', thumb_selector, showDiagram); 184 | $('body').on('mouseleave', thumb_selector, hideDiagram); 185 | 186 | // listens to node remove event in DOM, as GitHub dynamically changes the view within the a repository 187 | $('body').on('DOMNodeRemoved', async function(event) { 188 | if (typeof event.target.className == 'string' && event.target.className.includes('container-lg')) { 189 | await Sleep(500); 190 | 191 | addRenderButton(); 192 | } 193 | }); 194 | 195 | /** 196 | * Helper functions 197 | */ 198 | 199 | function b64DecodeUnicode(str) { 200 | // Going backwards: from bytestream, to percent-encoding, to original string. 201 | return decodeURIComponent(atob(str).split('').map(function(c) { 202 | return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); 203 | }).join('')); 204 | } 205 | 206 | function Sleep(milliseconds) { 207 | return new Promise(resolve => setTimeout(resolve, milliseconds)); 208 | } --------------------------------------------------------------------------------