├── src ├── images │ ├── shared │ │ └── .gitkeep │ ├── chrome │ │ ├── 1-intro.png │ │ └── 2-screenshot.png │ ├── opera │ │ ├── 1-intro.png │ │ └── 2-screenshot.png │ └── firefox │ │ ├── 1-intro.png │ │ └── 2-screenshot.png ├── icons │ ├── icon-16.png │ ├── icon-19.png │ ├── icon-38.png │ ├── icon-48.png │ ├── icon-64.png │ └── icon-128.png ├── scripts │ ├── utils │ │ ├── storage.js │ │ └── ext.js │ ├── background.js │ ├── livereload.js │ ├── options.js │ ├── popup.js │ └── contentscript.js ├── styles │ ├── modules │ │ ├── _utilities.scss │ │ ├── _variables.scss │ │ ├── _layout.scss │ │ ├── _reset.scss │ │ └── _grid.scss │ ├── options.scss │ └── popup.scss ├── _locales │ └── en │ │ └── messages.json ├── popup.html └── options.html ├── .babelrc ├── config ├── chrome.json ├── opera.json ├── development.json ├── firefox.json └── production.json ├── .gitignore ├── .travis.yml ├── resources ├── chrome-promo │ ├── large.png │ ├── marquee.png │ └── small.png ├── extension-assets.sketch ├── screenshots │ ├── flowchart.png │ ├── gantt-diagram.png │ └── sequence-diagram.png └── icons │ ├── opera.svg │ ├── chrome.svg │ └── firefox.svg ├── .editorconfig ├── LICENSE.md ├── manifest.json ├── CONTRIBUTING.md ├── package.json ├── gulpfile.babel.js └── README.md /src/images/shared/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/env"] 3 | } -------------------------------------------------------------------------------- /config/chrome.json: -------------------------------------------------------------------------------- 1 | { 2 | "extension": "chrome" 3 | } -------------------------------------------------------------------------------- /config/opera.json: -------------------------------------------------------------------------------- 1 | { 2 | "extension": "opera" 3 | } -------------------------------------------------------------------------------- /config/development.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": "development" 3 | } -------------------------------------------------------------------------------- /config/firefox.json: -------------------------------------------------------------------------------- 1 | { 2 | "extension": "firefox" 3 | } -------------------------------------------------------------------------------- /config/production.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": "production" 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | temp 3 | .tmp 4 | dist 5 | .sass-cache 6 | .DS_Store 7 | build -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: --lts 3 | cache: yarn 4 | script: 5 | - yarn test 6 | - yarn dist 7 | -------------------------------------------------------------------------------- /src/icons/icon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/backmarket-oss/github-mermaid-extension/HEAD/src/icons/icon-16.png -------------------------------------------------------------------------------- /src/icons/icon-19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/backmarket-oss/github-mermaid-extension/HEAD/src/icons/icon-19.png -------------------------------------------------------------------------------- /src/icons/icon-38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/backmarket-oss/github-mermaid-extension/HEAD/src/icons/icon-38.png -------------------------------------------------------------------------------- /src/icons/icon-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/backmarket-oss/github-mermaid-extension/HEAD/src/icons/icon-48.png -------------------------------------------------------------------------------- /src/icons/icon-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/backmarket-oss/github-mermaid-extension/HEAD/src/icons/icon-64.png -------------------------------------------------------------------------------- /src/icons/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/backmarket-oss/github-mermaid-extension/HEAD/src/icons/icon-128.png -------------------------------------------------------------------------------- /src/images/chrome/1-intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/backmarket-oss/github-mermaid-extension/HEAD/src/images/chrome/1-intro.png -------------------------------------------------------------------------------- /src/images/opera/1-intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/backmarket-oss/github-mermaid-extension/HEAD/src/images/opera/1-intro.png -------------------------------------------------------------------------------- /src/images/firefox/1-intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/backmarket-oss/github-mermaid-extension/HEAD/src/images/firefox/1-intro.png -------------------------------------------------------------------------------- /src/scripts/utils/storage.js: -------------------------------------------------------------------------------- 1 | import ext from "./ext"; 2 | 3 | module.exports = (ext.storage.sync ? ext.storage.sync : ext.storage.local); -------------------------------------------------------------------------------- /resources/chrome-promo/large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/backmarket-oss/github-mermaid-extension/HEAD/resources/chrome-promo/large.png -------------------------------------------------------------------------------- /resources/chrome-promo/marquee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/backmarket-oss/github-mermaid-extension/HEAD/resources/chrome-promo/marquee.png -------------------------------------------------------------------------------- /resources/chrome-promo/small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/backmarket-oss/github-mermaid-extension/HEAD/resources/chrome-promo/small.png -------------------------------------------------------------------------------- /resources/extension-assets.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/backmarket-oss/github-mermaid-extension/HEAD/resources/extension-assets.sketch -------------------------------------------------------------------------------- /src/images/chrome/2-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/backmarket-oss/github-mermaid-extension/HEAD/src/images/chrome/2-screenshot.png -------------------------------------------------------------------------------- /src/images/opera/2-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/backmarket-oss/github-mermaid-extension/HEAD/src/images/opera/2-screenshot.png -------------------------------------------------------------------------------- /src/styles/modules/_utilities.scss: -------------------------------------------------------------------------------- 1 | .text-muted { 2 | color: $text-secondary; 3 | } 4 | 5 | .text-center { 6 | text-align: center; 7 | } -------------------------------------------------------------------------------- /resources/screenshots/flowchart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/backmarket-oss/github-mermaid-extension/HEAD/resources/screenshots/flowchart.png -------------------------------------------------------------------------------- /src/images/firefox/2-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/backmarket-oss/github-mermaid-extension/HEAD/src/images/firefox/2-screenshot.png -------------------------------------------------------------------------------- /resources/screenshots/gantt-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/backmarket-oss/github-mermaid-extension/HEAD/resources/screenshots/gantt-diagram.png -------------------------------------------------------------------------------- /resources/screenshots/sequence-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/backmarket-oss/github-mermaid-extension/HEAD/resources/screenshots/sequence-diagram.png -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = false 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | insert_final_newline = false 15 | -------------------------------------------------------------------------------- /src/scripts/background.js: -------------------------------------------------------------------------------- 1 | import ext from "./utils/ext"; 2 | 3 | ext.runtime.onMessage.addListener( 4 | function(request, sender, sendResponse) { 5 | if(request.action === "perform-save") { 6 | console.log("Extension Type: ", "/* @echo extension */"); 7 | console.log("PERFORM AJAX", request.data); 8 | 9 | sendResponse({ action: "saved" }); 10 | } 11 | } 12 | ); -------------------------------------------------------------------------------- /src/_locales/en/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "appName": { 3 | "message": "Ext Starter", 4 | "description": "The name of the extension." 5 | }, 6 | "appDescription": { 7 | "message": "Boilerplate for building cross browser extensions", 8 | "description": "The description of the extension." 9 | }, 10 | "btnTooltip": { 11 | "message": "Ext Starter", 12 | "description": "Tooltip for the button." 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/scripts/livereload.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import ext from "./utils/ext"; 4 | 5 | var LIVERELOAD_HOST = 'localhost:'; 6 | var LIVERELOAD_PORT = 35729; 7 | var connection = new WebSocket('ws://' + LIVERELOAD_HOST + LIVERELOAD_PORT + '/livereload'); 8 | 9 | connection.onerror = function (error) { 10 | console.log('reload connection got error:', error); 11 | }; 12 | 13 | connection.onmessage = function (e) { 14 | if (e.data) { 15 | var data = JSON.parse(e.data); 16 | if (data && data.command === 'reload') { 17 | ext.runtime.reload(); 18 | } 19 | } 20 | }; -------------------------------------------------------------------------------- /src/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/styles/options.scss: -------------------------------------------------------------------------------- 1 | @import "modules/reset"; 2 | @import "modules/variables"; 3 | @import "modules/grid"; 4 | @import "modules/layout"; 5 | @import "modules/utilities"; 6 | 7 | .heading { 8 | margin: 1em auto; 9 | padding-bottom: 1em; 10 | border-bottom: 1px solid #eee; 11 | 12 | h1 + .lead { 13 | margin-top: 0.2em; 14 | } 15 | } 16 | 17 | .content { 18 | min-height: 300px; 19 | } 20 | 21 | .option { 22 | margin: 1em auto; 23 | h5 { 24 | margin-bottom: 1em; 25 | } 26 | 27 | .radio-group { 28 | label { 29 | display: block; 30 | } 31 | input[type="radio"] { 32 | display: inline-block; 33 | margin: 3px 5px; 34 | } 35 | } 36 | } 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/styles/modules/_variables.scss: -------------------------------------------------------------------------------- 1 | // Colors 2 | $black: #111111; 3 | $white: #ffffff; 4 | $gray: #eeeeee; 5 | $brand-primary: #4990E2; 6 | $text-color: $black; 7 | $text-secondary: #7A7A7A; 8 | 9 | 10 | // Typography 11 | $font-family-base: "Helvetica Neue", Helvetica, Arial, sans-serif; 12 | $headings-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 13 | $font-size-base: 16px; 14 | $line-height-base: 1.5; 15 | $headings-font-weight: 500; 16 | $headings-line-height: 1.1; 17 | $headings-color: $text-color; -------------------------------------------------------------------------------- /src/scripts/options.js: -------------------------------------------------------------------------------- 1 | import ext from "./utils/ext"; 2 | import storage from "./utils/storage"; 3 | 4 | var colorSelectors = document.querySelectorAll(".js-radio"); 5 | 6 | var setColor = (color) => { 7 | document.body.style.backgroundColor = color; 8 | }; 9 | 10 | storage.get('color', function(resp) { 11 | var color = resp.color; 12 | var option; 13 | if(color) { 14 | option = document.querySelector(`.js-radio.${color}`); 15 | setColor(color); 16 | } else { 17 | option = colorSelectors[0] 18 | } 19 | 20 | option.setAttribute("checked", "checked"); 21 | }); 22 | 23 | colorSelectors.forEach(function(el) { 24 | el.addEventListener("click", function(e) { 25 | var value = this.value; 26 | storage.set({ color: value }, function() { 27 | setColor(value); 28 | }); 29 | }) 30 | }) -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2017 Bharani / Email This 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 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "GitHub + Mermaid", 3 | "version": "0.1.1", 4 | "manifest_version": 2, 5 | "description": "A browser extension for Chrome, Opera & Firefox that adds Mermaid language support to GitHub.", 6 | "icons": { 7 | "16": "icons/icon-16.png", 8 | "128": "icons/icon-128.png" 9 | }, 10 | "default_locale": "en", 11 | "background": { 12 | "scripts": [ 13 | "scripts/background.js" 14 | ] 15 | }, 16 | "permissions": [ 17 | "https://github.com/*", 18 | "https://*.github.com/*" 19 | ], 20 | "options_ui": { 21 | "page": "options.html" 22 | }, 23 | "content_scripts": [ 24 | { 25 | "matches": [ 26 | "https://github.com/*", 27 | "https://*.github.com/*" 28 | ], 29 | "js": [ 30 | "scripts/contentscript.js" 31 | ], 32 | "run_at": "document_end", 33 | "all_frames": false 34 | } 35 | ], 36 | "browser_action": { 37 | "default_icon": { 38 | "19": "icons/icon-19.png", 39 | "38": "icons/icon-38.png" 40 | }, 41 | "default_title": "GitHub + Mermaid", 42 | "default_popup": "popup.html" 43 | } 44 | } 45 | 46 | 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Intructions 2 | 3 | > **Note:** this project was created with [EmailThis/extension-boilerplate](https://github.com/EmailThis/extension-boilerplate). 4 | 5 | ## Installation 6 | 7 | 1. Clone the repository `git clone https://github.com/BackMarket/github-mermaid-extension.git` 8 | 2. Run `yarn` 9 | 3. Run `yarn build` 10 | 11 | ### Load the extension in Chrome & Opera 12 | 13 | 1. Open Chrome/Opera browser and navigate to chrome://extensions 14 | 2. Select "Developer Mode" and then click "Load unpacked extension..." 15 | 3. From the file browser, choose to `extension-boilerplate/build/chrome` or (`extension-boilerplate/build/opera`) 16 | 17 | ### Load the extension in Firefox 18 | 19 | 1. Open Firefox browser and navigate to about:debugging 20 | 2. Click "Load Temporary Add-on" and from the file browser, choose `extension-boilerplate/build/firefox` 21 | 22 | ## Developing 23 | 24 | The following tasks can be used when you want to start developing the extension and want to enable live reload - 25 | 26 | - `yarn chrome-watch` 27 | - `yarn opera-watch` 28 | - `yarn firefox-watch` 29 | 30 | ## Packaging 31 | 32 | Run `yarn dist` to create a zipped, production-ready extension for each browser. You can then upload that to the appstore. 33 | -------------------------------------------------------------------------------- /src/scripts/utils/ext.js: -------------------------------------------------------------------------------- 1 | const apis = [ 2 | 'alarms', 3 | 'bookmarks', 4 | 'browserAction', 5 | 'commands', 6 | 'contextMenus', 7 | 'cookies', 8 | 'downloads', 9 | 'events', 10 | 'extension', 11 | 'extensionTypes', 12 | 'history', 13 | 'i18n', 14 | 'idle', 15 | 'notifications', 16 | 'pageAction', 17 | 'runtime', 18 | 'storage', 19 | 'tabs', 20 | 'webNavigation', 21 | 'webRequest', 22 | 'windows', 23 | ] 24 | 25 | function Extension () { 26 | const _this = this 27 | 28 | apis.forEach(function (api) { 29 | 30 | _this[api] = null 31 | 32 | try { 33 | if (chrome[api]) { 34 | _this[api] = chrome[api] 35 | } 36 | } catch (e) {} 37 | 38 | try { 39 | if (window[api]) { 40 | _this[api] = window[api] 41 | } 42 | } catch (e) {} 43 | 44 | try { 45 | if (browser[api]) { 46 | _this[api] = browser[api] 47 | } 48 | } catch (e) {} 49 | try { 50 | _this.api = browser.extension[api] 51 | } catch (e) {} 52 | }) 53 | 54 | try { 55 | if (browser && browser.runtime) { 56 | this.runtime = browser.runtime 57 | } 58 | } catch (e) {} 59 | 60 | try { 61 | if (browser && browser.browserAction) { 62 | this.browserAction = browser.browserAction 63 | } 64 | } catch (e) {} 65 | 66 | } 67 | 68 | module.exports = new Extension(); -------------------------------------------------------------------------------- /resources/icons/opera.svg: -------------------------------------------------------------------------------- 1 | Opera Logo -------------------------------------------------------------------------------- /src/options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Options & Settings 8 | 9 | 10 |
11 |
12 |
13 |

Extension Boilerplate

14 |

A foundation for creating cross-browser extensions

15 |
16 |
17 |
18 | 19 |
20 |
21 |
22 |
23 |
Popup color
24 |
25 | 26 | 27 | 28 |
29 |
30 | 31 |
32 | ...display your extensions' options here... 33 |
34 | 35 |
36 |
37 |
38 | 39 | 40 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /resources/icons/chrome.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 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 | -------------------------------------------------------------------------------- /src/styles/modules/_layout.scss: -------------------------------------------------------------------------------- 1 | html, body { 2 | box-sizing: border-box; 3 | &:before, &:after { 4 | box-sizing: border-box; 5 | } 6 | } 7 | 8 | body { 9 | font-family: $font-family-base; 10 | line-height: $line-height-base; 11 | font-size: $font-size-base; 12 | color: $text-color; 13 | font-weight: normal; 14 | } 15 | 16 | h1, h2, h3, h4, h5, h6 { 17 | font-family: $headings-font-family; 18 | font-weight: $headings-font-weight; 19 | line-height: $headings-line-height; 20 | margin: 0; 21 | padding: 0; 22 | } 23 | 24 | h1 { font-size: 1.75em; } 25 | h2 { font-size: 1.5em; } 26 | h3 { font-size: 1.25em; } 27 | h4 { font-size: 1.10em; } 28 | h5 { font-size: 1em; } 29 | h6 { font-size: .85em; } 30 | 31 | nav { 32 | margin: 1em 0; 33 | 34 | ul { 35 | list-style: none; 36 | margin: 0; 37 | padding: 0; 38 | 39 | li { 40 | display: inline-block; 41 | margin-right: 1em; 42 | margin-bottom: .25em; 43 | } 44 | } 45 | } 46 | 47 | a { 48 | text-decoration: none; 49 | color: $brand-primary; 50 | &:hover, &:focus { 51 | color: darken($brand-primary, 6.25%); 52 | } 53 | } 54 | 55 | ul, ol { 56 | margin-top: 0; 57 | padding-top: 0; 58 | padding-left: 2.5em; 59 | } 60 | 61 | p { 62 | margin: 1em 0; 63 | hyphens: auto; 64 | 65 | &.lead { 66 | font-size: 1.2em; 67 | } 68 | 69 | &:first-child { 70 | margin-top: 0; 71 | } 72 | 73 | &:last-child { 74 | margin-bottom: 0; 75 | } 76 | 77 | + ul, + ol { 78 | margin-top: -.75em; 79 | } 80 | } 81 | 82 | dd { 83 | margin-bottom: 1em; 84 | margin-left: 0; 85 | padding-left: 2.5em; 86 | } 87 | 88 | dt { 89 | font-weight: 700; 90 | } 91 | 92 | blockquote { 93 | margin: 0; 94 | padding-left: 2.5em; 95 | } -------------------------------------------------------------------------------- /src/styles/popup.scss: -------------------------------------------------------------------------------- 1 | @import "modules/reset"; 2 | @import "modules/variables"; 3 | @import "modules/layout"; 4 | 5 | body, html { 6 | padding: 0; 7 | margin: 0; 8 | } 9 | 10 | #app { 11 | padding: 20px 20px; 12 | background: $white; 13 | } 14 | 15 | footer { 16 | color: $text-secondary; 17 | text-align: right; 18 | font-size: 0.8em; 19 | a { 20 | outline: none; 21 | color: lighten($text-secondary, 10%); 22 | &:hover { 23 | color: $text-secondary; 24 | } 25 | } 26 | } 27 | 28 | .popup-content { 29 | min-width: 220px; 30 | min-height: 100px; 31 | max-width: 350px; 32 | } 33 | 34 | .app-name { 35 | font-size: 14px; 36 | text-transform: uppercase; 37 | color: $text-secondary; 38 | text-align: center; 39 | margin: 0 auto 1em auto; 40 | padding: 0; 41 | } 42 | 43 | .site-description { 44 | padding: 0.5em; 45 | border: 1px solid $gray; 46 | margin: 0; 47 | 48 | h3 { 49 | margin: 0; 50 | padding: 0; 51 | border-bottom: 1px solid $gray; 52 | padding-bottom: 0.5em; 53 | } 54 | 55 | .description { 56 | color: $text-secondary; 57 | max-height: 100px; 58 | font-size: 0.8em; 59 | line-height: 1.2; 60 | } 61 | 62 | .url { 63 | outline: none; 64 | text-decoration: none; 65 | line-height: 1.2; 66 | font-size: 0.8em; 67 | word-break: break-word; 68 | display: block; 69 | } 70 | } 71 | 72 | .action-container { 73 | margin: 1em auto; 74 | } 75 | 76 | .btn { 77 | background: none; 78 | border: none; 79 | display: inline-block; 80 | cursor: pointer; 81 | padding: 0.5em 1.5em; 82 | background: $brand-primary; 83 | color: $white; 84 | font-weight: $headings-font-weight; 85 | border-radius: 2px; 86 | outline: none; 87 | font-size: 1em; 88 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "test": "echo 'Warning: test not implemented' >&2", 5 | "chrome-build": "cross-env TARGET=chrome gulp", 6 | "opera-build": "cross-env TARGET=opera gulp", 7 | "firefox-build": "cross-env TARGET=firefox gulp", 8 | "build": "cross-env NODE_ENV=production npm run chrome-build && cross-env NODE_ENV=production npm run opera-build && cross-env NODE_ENV=production npm run firefox-build", 9 | "chrome-watch": "cross-env TARGET=chrome gulp watch", 10 | "opera-watch": "cross-env TARGET=opera gulp watch", 11 | "firefox-watch": "cross-env TARGET=firefox gulp watch", 12 | "chrome-dist": "cross-env NODE_ENV=production cross-env TARGET=chrome gulp dist", 13 | "opera-dist": "cross-env NODE_ENV=production cross-env TARGET=opera gulp dist", 14 | "firefox-dist": "cross-env NODE_ENV=production cross-env TARGET=firefox gulp dist", 15 | "dist": "npm run chrome-dist && npm run opera-dist && npm run firefox-dist" 16 | }, 17 | "dependencies": { 18 | "@babel/polyfill": "^7.4.3", 19 | "mermaid": "^8.0.0" 20 | }, 21 | "devDependencies": { 22 | "@babel/core": "^7.4.3", 23 | "@babel/preset-env": "^7.4.3", 24 | "@babel/register": "^7.4.0", 25 | "babel-core": "^7.0.0-bridge.0", 26 | "babelify": "^10.0.0", 27 | "browserify": "^16.2.3", 28 | "core-js": "^3.0.1", 29 | "cross-env": "^5.2.0", 30 | "del": "^4.1.0", 31 | "event-stream": "^4.0.1", 32 | "gulp": "^4.0.1", 33 | "gulp-if": "^2.0.2", 34 | "gulp-livereload": "^4.0.1", 35 | "gulp-merge-json": "^1.3.1", 36 | "gulp-plumber": "^1.2.1", 37 | "gulp-sass": "^4.0.2", 38 | "gulp-zip": "^5.0.0", 39 | "preprocessify": "^1.0.1", 40 | "vinyl-buffer": "^1.0.1", 41 | "vinyl-source-stream": "^2.0.0" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/styles/modules/_reset.scss: -------------------------------------------------------------------------------- 1 | /* 2 | App reset by Ben Frain @benfrain / benfrain.com 3 | Slightly modified by Bharani @bharani91 / github.com/bharani91 4 | */ 5 | 6 | /*Hat tip to @thierrykoblentz for this approach: https://css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice/ */ 7 | html { 8 | box-sizing: border-box; 9 | } 10 | 11 | * { 12 | user-select: none; 13 | -webkit-tap-highlight-color: rgba(255,255,255,0); 14 | -webkit-tap-highlight-color: transparent; 15 | box-sizing: inherit; 16 | } 17 | 18 | *:before, 19 | *:after { 20 | box-sizing: inherit; 21 | } 22 | 23 | input[type], 24 | [contenteditable] { 25 | user-select: text; 26 | } 27 | 28 | body, 29 | h1, 30 | h2, 31 | h3, 32 | h4, 33 | h5, 34 | h6, 35 | p { 36 | margin: 0; 37 | font-size: 1rem; 38 | font-weight: 400; 39 | } 40 | 41 | a { 42 | text-decoration: none; 43 | color: inherit; 44 | } 45 | 46 | /*IMPORTANT: This removes the focus outline for most browsers. Be aware this is a backwards accessibilty step! Mozilla (i.e. Firefox) also adds a dotted outline around a tags and buttons when they receive tab focus which I haven't found an unhacky way of removing.*/ 47 | a:focus, 48 | button:focus { 49 | outline: 0; 50 | } 51 | 52 | button { 53 | appearance: none; 54 | background-color: transparent; 55 | border: 0; 56 | padding: 0; 57 | } 58 | 59 | input, 60 | fieldset { 61 | appearance: none; 62 | border: 0; 63 | padding: 0; 64 | margin: 0; 65 | min-width: 0; 66 | font-size: 1rem; 67 | font-family: inherit; 68 | } 69 | 70 | /*This switches the default outline off when an input receives focus (really important for users tabbing through with a keyboard) so ensure you put something decent in for your input focus instead!!*/ 71 | input:focus { 72 | outline: 0; 73 | } 74 | 75 | img { 76 | max-width: 100%; 77 | display: block; 78 | } 79 | 80 | /*Removes the default focusring that Mozilla places on select items. From: http://stackoverflow.com/a/18853002/1147859 81 | Ensure you set `#000` to the colour you want your text to appear */ 82 | select:-moz-focusring { 83 | color: transparent; 84 | text-shadow: 0 0 0 #000; 85 | } -------------------------------------------------------------------------------- /src/scripts/popup.js: -------------------------------------------------------------------------------- 1 | import ext from "./utils/ext"; 2 | import storage from "./utils/storage"; 3 | 4 | var popup = document.getElementById("app"); 5 | storage.get('color', function(resp) { 6 | var color = resp.color; 7 | if(color) { 8 | popup.style.backgroundColor = color 9 | } 10 | }); 11 | 12 | var template = (data) => { 13 | var json = JSON.stringify(data); 14 | return (` 15 |
16 |

${data.title}

17 |

${data.description}

18 | ${data.url} 19 |
20 |
21 | 22 |
23 | `); 24 | } 25 | var renderMessage = (message) => { 26 | var displayContainer = document.getElementById("display-container"); 27 | displayContainer.innerHTML = `

${message}

`; 28 | } 29 | 30 | var renderBookmark = (data) => { 31 | var displayContainer = document.getElementById("display-container") 32 | if(data) { 33 | var tmpl = template(data); 34 | displayContainer.innerHTML = tmpl; 35 | } else { 36 | renderMessage("Sorry, could not extract this page's title and URL") 37 | } 38 | } 39 | 40 | ext.tabs.query({active: true, currentWindow: true}, function(tabs) { 41 | var activeTab = tabs[0]; 42 | chrome.tabs.sendMessage(activeTab.id, { action: 'process-page' }, renderBookmark); 43 | }); 44 | 45 | popup.addEventListener("click", function(e) { 46 | if(e.target && e.target.matches("#save-btn")) { 47 | e.preventDefault(); 48 | var data = e.target.getAttribute("data-bookmark"); 49 | ext.runtime.sendMessage({ action: "perform-save", data: data }, function(response) { 50 | if(response && response.action === "saved") { 51 | renderMessage("Your bookmark was saved successfully!"); 52 | } else { 53 | renderMessage("Sorry, there was an error while saving your bookmark."); 54 | } 55 | }) 56 | } 57 | }); 58 | 59 | var optionsLink = document.querySelector(".js-options"); 60 | optionsLink.addEventListener("click", function(e) { 61 | e.preventDefault(); 62 | ext.tabs.create({'url': ext.extension.getURL('options.html')}); 63 | }) 64 | -------------------------------------------------------------------------------- /src/styles/modules/_grid.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Gridism 3 | * A simple, responsive, and handy CSS grid by @cobyism 4 | * https://github.com/cobyism/gridism 5 | */ 6 | 7 | /* Preserve some sanity */ 8 | .grid, 9 | .unit { 10 | -webkit-box-sizing: border-box; 11 | -moz-box-sizing: border-box; 12 | box-sizing: border-box; 13 | } 14 | 15 | /* Set up some rules to govern the grid */ 16 | .grid { 17 | display: block; 18 | clear: both; 19 | } 20 | .grid .unit { 21 | float: left; 22 | width: 100%; 23 | padding: 10px; 24 | } 25 | 26 | /* This ensures the outer gutters are equal to the (doubled) inner gutters. */ 27 | .grid .unit:first-child { padding-left: 20px; } 28 | .grid .unit:last-child { padding-right: 20px; } 29 | 30 | /* Nested grids already have padding though, so let's nuke it */ 31 | .unit .unit:first-child { padding-left: 0; } 32 | .unit .unit:last-child { padding-right: 0; } 33 | .unit .grid:first-child > .unit { padding-top: 0; } 34 | .unit .grid:last-child > .unit { padding-bottom: 0; } 35 | 36 | /* Let people nuke the gutters/padding completely in a couple of ways */ 37 | .no-gutters .unit, 38 | .unit.no-gutters { 39 | padding: 0 !important; 40 | } 41 | 42 | /* Wrapping at a maximum width is optional */ 43 | .wrap .grid, 44 | .grid.wrap { 45 | max-width: 978px; 46 | margin: 0 auto; 47 | } 48 | 49 | /* Width classes also have shorthand versions numbered as fractions 50 | * For example: for a grid unit 1/3 (one third) of the parent width, 51 | * simply apply class="w-1-3" to the element. */ 52 | .grid .whole, .grid .w-1-1 { width: 100%; } 53 | .grid .half, .grid .w-1-2 { width: 50%; } 54 | .grid .one-third, .grid .w-1-3 { width: 33.3332%; } 55 | .grid .two-thirds, .grid .w-2-3 { width: 66.6665%; } 56 | .grid .one-quarter, 57 | .grid .one-fourth, .grid .w-1-4 { width: 25%; } 58 | .grid .three-quarters, 59 | .grid .three-fourths, .grid .w-3-4 { width: 75%; } 60 | .grid .one-fifth, .grid .w-1-5 { width: 20%; } 61 | .grid .two-fifths, .grid .w-2-5 { width: 40%; } 62 | .grid .three-fifths, .grid .w-3-5 { width: 60%; } 63 | .grid .four-fifths, .grid .w-4-5 { width: 80%; } 64 | .grid .golden-small, .grid .w-g-s { width: 38.2716%; } /* Golden section: smaller piece */ 65 | .grid .golden-large, .grid .w-g-l { width: 61.7283%; } /* Golden section: larger piece */ 66 | 67 | /* Clearfix after every .grid */ 68 | .grid { 69 | *zoom: 1; 70 | } 71 | .grid:before, .grid:after { 72 | display: table; 73 | content: ""; 74 | line-height: 0; 75 | } 76 | .grid:after { 77 | clear: both; 78 | } 79 | 80 | /* Utility classes */ 81 | .align-center { text-align: center; } 82 | .align-left { text-align: left; } 83 | .align-right { text-align: right; } 84 | .pull-left { float: left; } 85 | .pull-right { float: right; } 86 | 87 | /* A property for a better rendering of images in units: in 88 | this way bigger pictures are just resized if the unit 89 | becomes smaller */ 90 | .unit img { 91 | max-width: 100%; 92 | } 93 | 94 | /* Hide elements using this class by default */ 95 | .only-on-mobiles { 96 | display: none !important; 97 | } 98 | 99 | /* Responsive Stuff */ 100 | @media screen and (max-width: 568px) { 101 | /* Stack anything that isn't full-width on smaller screens 102 | and doesn't provide the no-stacking-on-mobiles class */ 103 | .grid:not(.no-stacking-on-mobiles) > .unit { 104 | width: 100% !important; 105 | padding-left: 20px; 106 | padding-right: 20px; 107 | } 108 | .unit .grid .unit { 109 | padding-left: 0px; 110 | padding-right: 0px; 111 | } 112 | 113 | /* Sometimes, you just want to be different on small screens */ 114 | .center-on-mobiles { 115 | text-align: center !important; 116 | } 117 | .hide-on-mobiles { 118 | display: none !important; 119 | } 120 | .only-on-mobiles { 121 | display: block !important; 122 | } 123 | } 124 | 125 | /* Expand the wrap a bit further on larger screens */ 126 | @media screen and (min-width: 1180px) { 127 | .wider .grid, 128 | .grid.wider { 129 | max-width: 1180px; 130 | margin: 0 auto; 131 | } 132 | } -------------------------------------------------------------------------------- /src/scripts/contentscript.js: -------------------------------------------------------------------------------- 1 | import '@babel/polyfill' 2 | import ext from "./utils/ext" 3 | import mermaidAPI from 'mermaid' 4 | 5 | var extractTags = () => { 6 | var url = document.location.href; 7 | if(!url || !url.match(/^http/)) return; 8 | 9 | var data = { 10 | title: "", 11 | description: "", 12 | url: document.location.href 13 | } 14 | 15 | var ogTitle = document.querySelector("meta[property='og:title']"); 16 | if(ogTitle) { 17 | data.title = ogTitle.getAttribute("content") 18 | } else { 19 | data.title = document.title 20 | } 21 | 22 | var descriptionTag = document.querySelector("meta[property='og:description']") || document.querySelector("meta[name='description']") 23 | if(descriptionTag) { 24 | data.description = descriptionTag.getAttribute("content") 25 | } 26 | 27 | return data; 28 | } 29 | 30 | function onRequest(request, sender, sendResponse) { 31 | if (request.action === 'process-page') { 32 | sendResponse(extractTags()) 33 | } 34 | } 35 | 36 | ext.runtime.onMessage.addListener(onRequest); 37 | 38 | // --- 39 | 40 | /** 41 | * Unique IDs generator. 42 | * 43 | * @generator 44 | * @function idGenerator 45 | * @yields {string} A unique id. 46 | */ 47 | function *idGenerator() { 48 | for (let i = 0; true; i++) { 49 | yield `github-mermaid-extension-${i}` 50 | } 51 | } 52 | 53 | /** 54 | * Render a Mermaid diagram. 55 | * @param {string} code Diagram source code, in Mermaid language. 56 | * @param {HTMLDivElement} target Element to insert into. 57 | * @param {string} id A unique element id. 58 | */ 59 | function render(code, target, id) { 60 | mermaidAPI.render(id, code, (svgCode, bindFunctions) => { 61 | target.innerHTML = svgCode 62 | bindFunctions(target) 63 | }, target) 64 | } 65 | 66 | /** 67 | * Render a Mermaid error. 68 | * @param {string} message Mermaid error message. 69 | * @param {HTMLDivElement} target Element to insert error message into. 70 | */ 71 | function renderError(message, target) { 72 | target.style.color = 'red' 73 | target.innerHTML = ` 74 |

Mermaid syntax error

75 |
${message}
76 | ` 77 | } 78 | 79 | /** 80 | * Generate a Mermaid diagram into a new
81 | * @param {HTMLPreElement} source Element containing the diagram source code, in Mermaid language. 82 | * @param {string} id A unique element id. 83 | * @returns {HTMLDivElement} The new
element. 84 | */ 85 | function processElement(source, id) { 86 | const target = document.createElement('div') 87 | source.after(target) // Note: must happen before render 88 | try { 89 | let code; 90 | if ([...source.classList].includes('rich-diff-level-one')) { 91 | // When code block is a diff, we need to remove all `` elements. 92 | // Note: we leave the block visible in this case, as the graph doesn't 93 | // display all the information 94 | const sourceClone = source.cloneNode(true) 95 | sourceClone.querySelectorAll('del').forEach(del => del.parentElement.removeChild(del)) 96 | code = sourceClone.textContent 97 | } else { 98 | code = source.textContent 99 | source.style.display = 'none' 100 | } 101 | 102 | render(code, target, id) 103 | } catch (error) { 104 | renderError(error.message, target) 105 | throw error 106 | } 107 | return target 108 | } 109 | 110 | /** 111 | * Process all `pre[lang="mermaid"]` elements that don't have 112 | * `[data-processed="true"]`. 113 | * @param {Iterator} idIterator Id iterator 114 | */ 115 | function processUnprocessedElements(idIterator) { 116 | const selector = 'pre[lang="mermaid"]:not([data-processed])'; 117 | [...document.querySelectorAll(selector)].forEach(source => { 118 | source.setAttribute('data-processed', 'true') 119 | const target = processElement(source, idIterator.next().value) 120 | }) 121 | } 122 | 123 | // Mermaid setup 124 | // Read more: https://mermaidjs.github.io/mermaidAPI.html#configuration 125 | mermaidAPI.initialize({ 126 | startOnLoad: false 127 | }) 128 | 129 | const globalIdIterator = idGenerator() 130 | 131 | // Observe nodeList and attribute changes on the page, and 132 | // process all unprocessed elements on the page. 133 | new MutationObserver( 134 | () => processUnprocessedElements(globalIdIterator) 135 | ).observe( 136 | document.body, 137 | { childList: true, subtree: true } 138 | ) 139 | 140 | // Initial pass 141 | processUnprocessedElements(globalIdIterator) 142 | -------------------------------------------------------------------------------- /gulpfile.babel.js: -------------------------------------------------------------------------------- 1 | import del from 'del'; 2 | import fs from 'fs'; 3 | import gulp from 'gulp'; 4 | import gulpIf from 'gulp-if' 5 | import livereload from 'gulp-livereload' 6 | import mergeJson from 'gulp-merge-json' 7 | import plumber from 'gulp-plumber' 8 | import sass from 'gulp-sass' 9 | import zip from 'gulp-zip' 10 | import { merge } from 'event-stream' 11 | import browserify from 'browserify'; 12 | import source from 'vinyl-source-stream'; 13 | import buffer from 'vinyl-buffer'; 14 | import preprocessify from 'preprocessify'; 15 | 16 | const production = process.env.NODE_ENV === 'production'; 17 | const target = process.env.TARGET || 'chrome'; 18 | const environment = process.env.NODE_ENV || 'development'; 19 | 20 | const generic = JSON.parse(fs.readFileSync(`./config/${environment}.json`)); 21 | const specific = JSON.parse(fs.readFileSync(`./config/${target}.json`)); 22 | const context = Object.assign({}, generic, specific); 23 | 24 | const manifest = { 25 | dev: { 26 | background: { 27 | scripts: [ 28 | 'scripts/livereload.js', 29 | 'scripts/background.js' 30 | ] 31 | } 32 | }, 33 | 34 | firefox: { 35 | applications: { 36 | gecko: { 37 | id: 'github-mermaid-extension@amercier.com' 38 | } 39 | } 40 | } 41 | } 42 | 43 | gulp.task('clean:build', () => del(`./build/${target}`)) 44 | gulp.task('clean:dist', () => del(`./dist/${target}.zip`)) 45 | 46 | gulp.task('styles', () => 47 | gulp.src('src/styles/**/*.scss') 48 | .pipe(plumber()) 49 | .pipe(sass.sync({ 50 | outputStyle: 'expanded', 51 | precision: 10, 52 | includePaths: ['.'] 53 | }).on('error', sass.logError)) 54 | .pipe(gulp.dest(`build/${target}/styles`)) 55 | ); 56 | 57 | gulp.task('manifest', () => 58 | gulp.src('./manifest.json') 59 | .pipe(gulpIf(!production, mergeJson({ 60 | fileName: 'manifest.json', 61 | jsonSpace: ' '.repeat(4), 62 | endObj: manifest.dev 63 | }))) 64 | .pipe(gulpIf(target === 'firefox', mergeJson({ 65 | fileName: 'manifest.json', 66 | jsonSpace: ' '.repeat(4), 67 | endObj: manifest.firefox 68 | }))) 69 | .pipe(gulp.dest(`./build/${target}`)) 70 | ); 71 | 72 | const scripts = [ 73 | 'background.js', 74 | 'contentscript.js', 75 | 'options.js', 76 | 'popup.js', 77 | 'livereload.js' 78 | ] 79 | 80 | scripts.forEach(script => { 81 | gulp.task(`scripts:${script}`, () => 82 | browserify({ 83 | entries: 'src/scripts/' + script, 84 | debug: !production, 85 | }) 86 | .transform('babelify', { 87 | presets: [ 88 | [ 89 | '@babel/env', { 90 | targets: { 91 | browsers: ['last 2 versions', 'safari >= 7'] 92 | }, 93 | useBuiltIns: false 94 | } 95 | ] 96 | ] 97 | }) 98 | .transform(preprocessify, { 99 | includeExtensions: ['.js'], 100 | context: context 101 | }) 102 | .bundle() 103 | .pipe(source(script)) 104 | .pipe(buffer()) 105 | .pipe(gulp.dest(`build/${target}/scripts`)) 106 | ) 107 | }) 108 | 109 | gulp.task('scripts', gulp.parallel( 110 | ...scripts.map(script => `scripts:${script}`) 111 | )) 112 | 113 | const resources = [ 114 | ['icons', './src/icons/**/*', `./build/${target}/icons`], 115 | ['locales', './src/_locales/**/*', `./build/${target}/_locales`], 116 | ['images', `./src/images/${target}/**/*`, `./build/${target}/images`], 117 | ['shared-images', './src/images/shared/**/*', `./build/${target}/images`], 118 | ['html', './src/**/*.html', `./build/${target}`], 119 | ] 120 | 121 | resources.forEach(([name, src, dest]) => { 122 | gulp.task( 123 | `resources:${name}`, 124 | () => gulp.src(src).pipe(gulp.dest(dest)) 125 | ) 126 | }) 127 | 128 | gulp.task('resources', gulp.parallel( 129 | ...resources.map(([name]) => `resources:${name}`)) 130 | ) 131 | 132 | gulp.task('extension', gulp.parallel( 133 | 'manifest', 134 | 'scripts', 135 | 'styles', 136 | 'resources' 137 | )) 138 | 139 | gulp.task('build', gulp.series('clean:build', 'extension')) 140 | 141 | gulp.task('livereload', () => { 142 | livereload.listen(); 143 | gulp.watch('./src/**/*', gulp.series('build')) 144 | }) 145 | 146 | gulp.task('watch', gulp.series( 147 | 'build', 148 | 'livereload', 149 | )); 150 | 151 | gulp.task('zip', () => 152 | gulp 153 | .src(`./build/${target}/**/*`) 154 | .pipe(zip(`${target}.zip`)) 155 | .pipe(gulp.dest('dist')) 156 | ) 157 | 158 | gulp.task('dist', gulp.series( 159 | 'build', 160 | 'clean:dist', 161 | 'zip' 162 | )); 163 | 164 | gulp.task('default', gulp.series('build')) 165 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

3 | Github + Mermaid 4 |

5 | 6 |

7 | 8 | A browser extension for Chrome, Opera & Firefox that adds 9 | 10 | Mermaid 11 | language support to 12 | 13 | Github Markdown. 14 | 15 |

16 |
17 | 18 |
19 | Extension Boilerplate 20 | 21 |

22 | Install • 23 | Features • 24 | How to use • 25 | Roadmap • 26 | License • 27 | Contributing 28 |

29 | 30 |

31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |

44 |
45 |
46 | 47 | ## Install 48 | 49 | - **Google Chrome**: [GitHub + Mermaid - Chrome Web Store](https://chrome.google.com/webstore/detail/github-%20-mermaid/goiiopgdnkogdbjmncgedmgpoajilohe) 50 | - **Firefox**: [GitHub + Mermaid - Firefox Add-ons](https://addons.mozilla.org/en-GB/firefox/addon/github-mermaid/) 51 | - **Opera**: coming later 52 | 53 | ## Features 54 | 55 | ### Supported GitHub features 56 | 57 | - [x] Pull requests & issues description (preview + published) - [Demo](https://github.com/BackMarket/github-mermaid-extension/issues/1) 58 | - [x] Pull requests & issues comment (preview + published) 59 | - [x] Markdown (`.md`) files (diff + published) 60 | - [x] Gists - [Demo](https://gist.github.com/amercier/df2e07a994315d323e398120bdda3989) 61 | 62 | ### Diagram types 63 | 64 | #### Flowcharts 65 | 66 | ![Flowchart example](/resources/screenshots/flowchart.png) 67 | 68 |
69 | Show source code 70 | 71 | ``` 72 | ```mermaid 73 | graph LR 74 | 75 | A(Start) 76 | 77 | A --> B[Look for an item] 78 | 79 | B --> C{Did you find it?} 80 | C -->|Yes| D(Stop looking) 81 | C -->|No| E{Do you need it?} 82 | E -->|Yes| B 83 | E -->|No| D 84 | ``` 85 |
86 | 87 | #### Sequence Diagrams 88 | 89 | ![Sequence Diagram example](/resources/screenshots/sequence-diagram.png) 90 | 91 |
92 | Show source code 93 | 94 | ``` 95 | ```mermaid 96 | sequenceDiagram 97 | participant U as User 98 | participant C as Client 99 | participant S as Server 100 | participant DB as Database 101 | 102 | U ->> C: Fill username 103 | U ->> C: Fill password 104 | C ->> U: Enable "Login" button 105 | U ->> C: Click "Login" button 106 | C ->>+ S: POST /login 107 | S ->>+ DB: SELECT FROM users 108 | Note over S,DB: See login.py for impl. details 109 | DB -->>- S: results 110 | S -->>- C: { authenticated: true } 111 | C ->> U: redirect /home 112 | ``` 113 |
114 | 115 | #### Gantt Diagrams 116 | 117 | ![Gantt Diagram example](/resources/screenshots/gantt-diagram.png) 118 | 119 |
120 | Show source code 121 | 122 | ``` 123 | ```mermaid 124 | gantt 125 | title A Gantt Diagram 126 | dateFormat YYYY-MM-DD 127 | section Section 128 | A task :a1, 2014-01-01, 30d 129 | Another task :after a1 , 20d 130 | section Another 131 | Task in sec :2014-01-12 , 12d 132 | another task : 24d 133 | ``` 134 |
135 | 136 | ## How to use 137 | 138 | Simply put Mermaid code into ```mermaid. See 139 | [Mermaid official website](https://mermaidjs.github.io/gantt.html) for more 140 | information about the Mermaid syntax. 141 | 142 | ## Roadmap 143 | 144 | - [x] Initial implementation 145 | - [x] Publish Chrome extension 146 | - [x] Documentation 147 | - [x] Publish Firefox extension 148 | - [ ] Publish Opera extension 149 | - [x] Continuous Integration 150 | - [x] Upgrade dependencies 151 | - [x] Automatic dependency management 152 | - [x] Fix #3 153 | - [ ] Testing 154 | - [ ] Dark theme + option page 155 | - [ ] Cleanup 156 | 157 | ## License 158 | 159 | [![License](https://img.shields.io/github/license/BackMarket/github-mermaid-extension.svg)](/LICENSE.md) 160 | 161 | ## Contributing 162 | 163 | Contributions (issues ♥, pull requests ♥♥♥) are more than welcome! Feel free to clone, fork, modify, extend, etc. 164 | 165 | See [contributing intructions](/CONTRIBUTING.md) for details. 166 | -------------------------------------------------------------------------------- /resources/icons/firefox.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 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 | 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 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | firefox-logo 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | --------------------------------------------------------------------------------