├── .babelrc ├── .eslintrc.js ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── _config.yml ├── build.sh ├── css ├── seapig.css └── tooltip.css ├── docs ├── _config.yml ├── github.css ├── index.md └── mathjax.html ├── images ├── digraph.png ├── digraph.svg ├── mathjax.png ├── mermaid.png ├── seapig-toolbar.png ├── seapig.png ├── uiflow.png └── uiflow_ja.png ├── js ├── editor.js ├── md2html.js ├── pdfWorker.js ├── preview.js ├── renderer.js ├── renderer_funcs.js ├── sanitize.js ├── seapig.js ├── tex2svg.js └── utils.js ├── mainwindow.html ├── package.json ├── photon ├── css │ ├── photon.css │ └── photon.min.css └── fonts │ ├── photon-entypo.eot │ ├── photon-entypo.svg │ ├── photon-entypo.ttf │ └── photon-entypo.woff ├── scripts └── build-dep.js ├── seapig.icns ├── seapig.ico ├── seapig.png ├── templates ├── github.css └── template.html └── test ├── mathjax.md ├── md2html.test.js └── mermaid.md /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-env" 4 | ], 5 | "env": { 6 | "development": { 7 | "presets": [ 8 | "power-assert" 9 | ] 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "node": true, 4 | "browser": true, 5 | "commonjs": true, 6 | "es6": true 7 | }, 8 | "extends": "eslint:recommended", 9 | "parserOptions": { 10 | "sourceType": "module" 11 | }, 12 | "rules": { 13 | "accessor-pairs": "error", 14 | "array-bracket-spacing": "off", 15 | "array-callback-return": "error", 16 | "arrow-body-style": "error", 17 | "arrow-parens": "error", 18 | "arrow-spacing": "error", 19 | "block-scoped-var": "error", 20 | "block-spacing": "error", 21 | "brace-style": [ 22 | "error", 23 | "1tbs" 24 | ], 25 | "callback-return": "error", 26 | "camelcase": "off", 27 | "comma-dangle": "error", 28 | "comma-spacing": "off", 29 | "comma-style": [ 30 | "error", 31 | "last" 32 | ], 33 | "complexity": "error", 34 | "computed-property-spacing": "error", 35 | "consistent-return": "error", 36 | "consistent-this": "error", 37 | "curly": "off", 38 | "default-case": "error", 39 | "dot-location": [ 40 | "error", 41 | "property" 42 | ], 43 | "dot-notation": "error", 44 | "eol-last": "error", 45 | "eqeqeq": "off", 46 | "func-call-spacing": "off", 47 | "func-names": [ 48 | "error", 49 | "never" 50 | ], 51 | "func-style": [ 52 | "error", 53 | "declaration" 54 | ], 55 | "generator-star-spacing": "error", 56 | "global-require": "error", 57 | "guard-for-in": "error", 58 | "handle-callback-err": "error", 59 | "id-blacklist": "error", 60 | "id-length": "warn", 61 | "id-match": "error", 62 | "indent": "off", 63 | "init-declarations": "error", 64 | "jsx-quotes": "error", 65 | "key-spacing": "error", 66 | "keyword-spacing": [ 67 | "error", 68 | { 69 | "after": true, 70 | "before": true 71 | } 72 | ], 73 | "linebreak-style": [ 74 | "error", 75 | "unix" 76 | ], 77 | "lines-around-comment": "error", 78 | "max-depth": "error", 79 | "max-len": "error", 80 | "max-lines": "error", 81 | "max-nested-callbacks": "error", 82 | "max-params": "error", 83 | "max-statements": "error", 84 | "max-statements-per-line": "error", 85 | "multiline-ternary": "error", 86 | "new-cap": "error", 87 | "new-parens": "error", 88 | "newline-after-var": "off", 89 | "newline-before-return": "error", 90 | "newline-per-chained-call": "error", 91 | "no-alert": "error", 92 | "no-array-constructor": "error", 93 | "no-bitwise": "error", 94 | "no-caller": "error", 95 | "no-catch-shadow": "error", 96 | "no-confusing-arrow": "error", 97 | "no-continue": "error", 98 | "no-div-regex": "error", 99 | "no-duplicate-imports": "error", 100 | "no-else-return": "error", 101 | "no-empty-function": "error", 102 | "no-eq-null": "error", 103 | "no-eval": "error", 104 | "no-extend-native": "error", 105 | "no-extra-bind": "error", 106 | "no-extra-label": "error", 107 | "no-extra-parens": "error", 108 | "no-floating-decimal": "error", 109 | "no-global-assign": "error", 110 | "no-implicit-coercion": "error", 111 | "no-implicit-globals": "error", 112 | "no-implied-eval": "error", 113 | "no-inline-comments": "error", 114 | "no-invalid-this": "error", 115 | "no-iterator": "error", 116 | "no-label-var": "error", 117 | "no-labels": "error", 118 | "no-lone-blocks": "error", 119 | "no-lonely-if": "error", 120 | "no-loop-func": "error", 121 | "no-magic-numbers": "error", 122 | "no-mixed-operators": "error", 123 | "no-mixed-requires": "error", 124 | "no-multi-spaces": "off", 125 | "no-multi-str": "error", 126 | "no-multiple-empty-lines": "error", 127 | "no-negated-condition": "error", 128 | "no-nested-ternary": "error", 129 | "no-new": "error", 130 | "no-new-func": "error", 131 | "no-new-object": "error", 132 | "no-new-require": "error", 133 | "no-new-wrappers": "error", 134 | "no-octal-escape": "error", 135 | "no-param-reassign": "error", 136 | "no-path-concat": "error", 137 | "no-plusplus": [ 138 | "error", 139 | { 140 | "allowForLoopAfterthoughts": true 141 | } 142 | ], 143 | "no-process-env": "off", 144 | "no-process-exit": "error", 145 | "no-proto": "error", 146 | "no-prototype-builtins": "error", 147 | "no-restricted-globals": "error", 148 | "no-restricted-imports": "error", 149 | "no-restricted-modules": "error", 150 | "no-restricted-syntax": "error", 151 | "no-return-assign": "error", 152 | "no-script-url": "error", 153 | "no-self-compare": "error", 154 | "no-sequences": "error", 155 | "no-shadow": "error", 156 | "no-shadow-restricted-names": "error", 157 | "no-spaced-func": "off", 158 | "no-sync": "warn", 159 | "no-tabs": "off", 160 | "no-template-curly-in-string": "error", 161 | "no-ternary": "error", 162 | "no-throw-literal": "error", 163 | "no-trailing-spaces": "error", 164 | "no-undef": "warn", 165 | "no-undef-init": "warn", 166 | "no-undefined": "warn", 167 | "no-underscore-dangle": "error", 168 | "no-unmodified-loop-condition": "error", 169 | "no-unneeded-ternary": "error", 170 | "no-unsafe-negation": "error", 171 | "no-unused-expressions": "error", 172 | "no-use-before-define": "error", 173 | "no-useless-call": "error", 174 | "no-useless-computed-key": "error", 175 | "no-useless-concat": "error", 176 | "no-useless-constructor": "error", 177 | "no-useless-escape": "error", 178 | "no-useless-rename": "error", 179 | "no-var": "off", 180 | "no-void": "error", 181 | "no-warning-comments": "error", 182 | "no-whitespace-before-property": "error", 183 | "no-with": "error", 184 | "object-curly-newline": "error", 185 | "object-curly-spacing": "off", 186 | "object-property-newline": [ 187 | "error", 188 | { 189 | "allowMultiplePropertiesPerLine": true 190 | } 191 | ], 192 | "object-shorthand": "error", 193 | "one-var": "off", 194 | "one-var-declaration-per-line": "error", 195 | "operator-assignment": "error", 196 | "operator-linebreak": "error", 197 | "padded-blocks": "off", 198 | "prefer-arrow-callback": "off", 199 | "prefer-const": "off", 200 | "prefer-reflect": "error", 201 | "prefer-rest-params": "error", 202 | "prefer-spread": "error", 203 | "prefer-template": "error", 204 | "quote-props": "off", 205 | "quotes": "off", 206 | "radix": "error", 207 | "require-jsdoc": "off", 208 | "rest-spread-spacing": "error", 209 | "semi": "off", 210 | "semi-spacing": "error", 211 | "sort-imports": "error", 212 | "sort-keys": "off", 213 | "sort-vars": "error", 214 | "space-before-blocks": "error", 215 | "space-before-function-paren": "off", 216 | "space-in-parens": [ 217 | "error", 218 | "never" 219 | ], 220 | "space-infix-ops": "error", 221 | "space-unary-ops": "error", 222 | "spaced-comment": [ 223 | "error", 224 | "always" 225 | ], 226 | "strict": "error", 227 | "template-curly-spacing": "error", 228 | "unicode-bom": [ 229 | "error", 230 | "never" 231 | ], 232 | "valid-jsdoc": "error", 233 | "vars-on-top": "error", 234 | "wrap-iife": "error", 235 | "wrap-regex": "error", 236 | "yield-star-spacing": "error", 237 | "yoda": [ 238 | "error", 239 | "never" 240 | ] 241 | } 242 | }; 243 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | *.pid.lock 11 | 12 | # Directory for instrumented libs generated by jscoverage/JSCover 13 | lib-cov 14 | 15 | # Coverage directory used by tools like istanbul 16 | coverage 17 | 18 | # nyc test coverage 19 | .nyc_output 20 | 21 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 22 | .grunt 23 | 24 | # node-waf configuration 25 | .lock-wscript 26 | 27 | # Compiled binary addons (http://nodejs.org/api/addons.html) 28 | build/Release 29 | 30 | # Dependency directories 31 | node_modules 32 | jspm_packages 33 | 34 | # Optional npm cache directory 35 | .npm 36 | 37 | # Optional REPL history 38 | .node_repl_history 39 | 40 | # Project only 41 | releases 42 | package-lock.json 43 | *.swp 44 | external/ 45 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "ace-builds"] 2 | path = ace-builds 3 | url = https://github.com/ajaxorg/ace-builds.git 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-2019 Yasumichi Akahoshi 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 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SeaPig 2 | ===== 3 | 4 | ![](seapig.png)SeaPig is converter from markdown to html with marked.js and highlight.js. 5 | 6 | ![](images/seapig.png) 7 | 8 | ## Usage 9 | 10 | SeaPig has two panes. Left pane is editor. Right pane is HTML previewer. 11 | 12 | When you input markdown, SeaPig refresh HTML preview. 13 | 14 | You can use [GitHub Flavored Markdown](https://github.github.com/gfm/). 15 | 16 | SeaPig has tool bar contains one drop down list and eight buttons. 17 | 18 | ![](images/seapig-toolbar.png) 19 | 20 | You can select key bindings from drop down list. (default/emacs/vim/sublime) 21 | 22 | Eight buttons has feature below. 23 | 24 | - New markdown file (Open new window) 25 | - Open markdown file to editor. 26 | - Save markdown file from editor. 27 | - Export HTML file from previewer.(At the same time css stylesheet is copied to same folder.) 28 | - Export PDF file 29 | - Hide editor 30 | - Hide previewer 31 | - Refresh HTML preview 32 | 33 | ### viz.js support 34 | 35 | When You write code block as `graphviz` language and write dot language, rendering graph image at svg as below. 36 | 37 |
 38 | ```graphviz
 39 | digraph g { a -> b; }
 40 | ```
 41 | 
42 | 43 | to 44 | 45 | ![](images/digraph.png) 46 | 47 | ### uiflow support 48 | 49 | When You write code block as `uiflow` language and write uiflow language, rendering graph image at svg as below. 50 | 51 |
 52 | ```uiflow
 53 | [top page]
 54 | user name
 55 | password
 56 | --
 57 | login
 58 | ==>mypage
 59 | 
 60 | [mypage]
 61 | favorite list
 62 | ```
 63 | 
64 | 65 | to 66 | 67 | ![](images/uiflow.png) 68 | 69 | ### MathJax support (code block only) 70 | 71 |
 72 | ```math
 73 | E=mc^2
 74 | ```
 75 | 
76 | 77 | to 78 | 79 | ![](images/mathjax.png) 80 | 81 | More example, [test/mathjax.md](test/mathjax.md) 82 | 83 | ### mermaid support 84 | 85 | When You write code block as `mermaid` language and write mermaid language, rendering graph image at svg as below. 86 | 87 |
 88 | ```mermaid
 89 | sequenceDiagram
 90 |     participant main
 91 |     participant renderer
 92 |     participant previewer
 93 |     main->>renderer: Open file
 94 |     renderer->>previewer: Refresh preview
 95 | ```
 96 | 
97 | 98 | to 99 | 100 | ![](images/mermaid.png) 101 | 102 | ## For developers 103 | 104 | ### How to build 105 | 106 | ``` 107 | $ git clone https://github.com/yasumichi/seapig.git 108 | $ cd seapig 109 | $ git submodule update -i 110 | $ npm install 111 | $ npm build-dep 112 | ... 113 | ``` 114 | 115 | ### How to lunch 116 | 117 | ``` 118 | $ npm start 119 | ``` 120 | 121 | ### How to package 122 | 123 | ``` 124 | $ npm run package:win32 125 | ``` 126 | 127 | ### How to package all (on Linux) 128 | 129 | ``` 130 | $ ./build.sh 131 | ``` 132 | 133 | ## ToDo 134 | 135 | - [x] save your favorite keybindings (default/emacs/vim) 136 | - [x] support task list item. 137 | - [x] add viz.js support 138 | - [x] add [uiflow](https://github.com/hirokidaichi/uiflow) support. 139 | - [x] add mermaid support 140 | - [x] add simultaneous scroll 141 | - [x] add original menu 142 | - [x] add new document 143 | - [ ] add alternative stylesheet 144 | - [x] control display editor and previewer 145 | - [ ] add batch mode 146 | - [x] introduce virtual dom framework (mithril.js) 147 | 148 | ## Special Thanks 149 | 150 | - [Ace - The High Performance Code Editor for the Web](https://ace.c9.io/) 151 | - [Electron - Build cross platform desktop apps with JavaScript, HTML, and CSS.](http://electron.atom.io/) 152 | - [electron-json-storage](https://github.com/jviotti/electron-json-storage) 153 | - [electron-localshortcut](https://github.com/parro-it/electron-localshortcut) 154 | - [Github Markdown CSS - for Markdown Editor Preview](https://gist.github.com/andyferra/2554919) 155 | - [highlight.js](https://highlightjs.org/) 156 | - [marked](https://github.com/chjj/marked) 157 | - [MathJax](https://www.mathjax.org/) 158 | - [mermaid](https://knsv.github.io/mermaid/) 159 | - [mithril](https://mithril.js.org/) 160 | - [Node.js](https://nodejs.org/en/) 161 | - [Photon](http://photonkit.com/) 162 | - [sanitize-html](https://github.com/apostrophecms/sanitize-html) 163 | - [viz.js](https://github.com/mdaines/viz.js) 164 | - [uiflow](https://github.com/hirokidaichi/uiflow)(use [forked version](https://github.com/tkrkt/uiflow#fix-argument-in-compile)) 165 | - [いらすとや](http://www.irasutoya.com/)(application icon) 166 | - [jpzukin/electron-sample-print-to-pdf](https://github.com/jpzukin/electron-sample-print-to-pdf) 167 | 168 | # License 169 | 170 | MIT (excludes photon, node_modules and icons) 171 | 172 | Copyright © 2016-2019 Yasumichi Akahoshi 173 | 174 | # Icons copyright 175 | 176 | - seapig.icns 177 | - seapig.ico 178 | - seapig.png 179 | 180 | Copyright © いらすとや. All Rights Reserved. 181 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | VERSION=`grep version package.json | sed -e 's/.*"version": "//' -e 's/",//'` 4 | LOGFILE=${HOME}/seapig_build.log 5 | 6 | # clean directory releases 7 | echo -e "\e[32m[clean]\e[m old releases" 8 | rm -rf releases > ${LOGFILE} 2>&1 9 | 10 | # install node_modules 11 | echo -e "\e[32m[install]\e[m dependencies node modules" 12 | npm install --global-style >> ${LOGFILE} 2>&1 13 | 14 | # make packages 15 | for PLATFORM in darwin win32 linux 16 | do 17 | echo -e "\e[32m[package]\e[m ${PLATFORM}" 18 | npm run-script package:${PLATFORM} >> ${LOGFILE} 2>&1 19 | done 20 | 21 | # archive packages 22 | cd releases 23 | for DIR in seapig-* 24 | do 25 | ZIP_FILE=${DIR}-${VERSION}.zip 26 | echo -e "\e[32m[archive]\e[m `pwd`/${ZIP_FILE}" 27 | zip -r ${ZIP_FILE} ${DIR} >> ${LOGFILE} 2>&1 28 | done 29 | 30 | # complete message 31 | echo 32 | echo -e "When problems is happened, see \e[31m${LOGFILE}\e[m" 33 | -------------------------------------------------------------------------------- /css/seapig.css: -------------------------------------------------------------------------------- 1 | .toolbar { 2 | position: relative; 3 | z-index: 3; 4 | } 5 | 6 | .window-content { 7 | position: relative; 8 | z-index: 2; 9 | } 10 | 11 | #mermaidWorkArea { 12 | position: absolute; 13 | left: 0; 14 | right: 0; 15 | width: 1200px; 16 | height: 800px; 17 | z-index: 1; 18 | } 19 | 20 | #mithrilRoot { 21 | padding-top: 10px; 22 | padding-bottom: 10px; 23 | padding-left: 30px; 24 | padding-right: 30px; 25 | } 26 | -------------------------------------------------------------------------------- /css/tooltip.css: -------------------------------------------------------------------------------- 1 | /** 2 | * base idea 3 | * from http://www.kollermedia.at/archive/2008/03/24/easy-css-tooltip/ 4 | */ 5 | .tooltip { position: relative; display: inline-block; } 6 | .tooltip .tooltiptext { visibility: hidden; padding:2px 3px; margin-left:8px; width:120px; left: 55%; top: 95%; position:absolute; background: Cornsilk; border:1px solid #cccccc; color: black; z-index:1 } 7 | .tooltip:hover .tooltiptext { visibility: visible; } 8 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate -------------------------------------------------------------------------------- /docs/github.css: -------------------------------------------------------------------------------- 1 | /* 2 | * https://gist.github.com/andyferra/2554919 3 | */ 4 | body { 5 | font-family: Helvetica, arial, sans-serif; 6 | font-size: 14px; 7 | line-height: 1.6; 8 | padding-top: 10px; 9 | padding-bottom: 10px; 10 | background-color: white; 11 | padding: 30px; } 12 | 13 | body > *:first-child { 14 | margin-top: 0 !important; } 15 | body > *:last-child { 16 | margin-bottom: 0 !important; } 17 | 18 | a { 19 | color: #4183C4; } 20 | a.absent { 21 | color: #cc0000; } 22 | a.anchor { 23 | display: block; 24 | padding-left: 30px; 25 | margin-left: -30px; 26 | cursor: pointer; 27 | position: absolute; 28 | top: 0; 29 | left: 0; 30 | bottom: 0; } 31 | 32 | h1, h2, h3, h4, h5, h6 { 33 | margin: 20px 0 10px; 34 | padding: 0; 35 | font-weight: bold; 36 | -webkit-font-smoothing: antialiased; 37 | cursor: text; 38 | position: relative; } 39 | 40 | h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, h5:hover a.anchor, h6:hover a.anchor { 41 | background: url("../../images/modules/styleguide/para.png") no-repeat 10px center; 42 | text-decoration: none; } 43 | 44 | h1 tt, h1 code { 45 | font-size: inherit; } 46 | 47 | h2 tt, h2 code { 48 | font-size: inherit; } 49 | 50 | h3 tt, h3 code { 51 | font-size: inherit; } 52 | 53 | h4 tt, h4 code { 54 | font-size: inherit; } 55 | 56 | h5 tt, h5 code { 57 | font-size: inherit; } 58 | 59 | h6 tt, h6 code { 60 | font-size: inherit; } 61 | 62 | h1 { 63 | font-size: 28px; 64 | color: black; } 65 | 66 | h2 { 67 | font-size: 24px; 68 | border-bottom: 1px solid #cccccc; 69 | color: black; } 70 | 71 | h3 { 72 | font-size: 18px; } 73 | 74 | h4 { 75 | font-size: 16px; } 76 | 77 | h5 { 78 | font-size: 14px; } 79 | 80 | h6 { 81 | color: #777777; 82 | font-size: 14px; } 83 | 84 | p, blockquote, ul, ol, dl, li, table, pre { 85 | margin: 15px 0; } 86 | 87 | body > h2:first-child { 88 | margin-top: 0; 89 | padding-top: 0; } 90 | body > h1:first-child { 91 | margin-top: 0; 92 | padding-top: 0; } 93 | body > h1:first-child + h2 { 94 | margin-top: 0; 95 | padding-top: 0; } 96 | body > h3:first-child, body > h4:first-child, body > h5:first-child, body > h6:first-child { 97 | margin-top: 0; 98 | padding-top: 0; } 99 | 100 | a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 { 101 | margin-top: 0; 102 | padding-top: 0; } 103 | 104 | h1 p, h2 p, h3 p, h4 p, h5 p, h6 p { 105 | margin-top: 0; } 106 | 107 | li p.first { 108 | display: inline-block; } 109 | 110 | ul, ol { 111 | padding-left: 30px; } 112 | 113 | ul :first-child, ol :first-child { 114 | margin-top: 0; } 115 | 116 | ul :last-child, ol :last-child { 117 | margin-bottom: 0; } 118 | 119 | dl { 120 | padding: 0; } 121 | dl dt { 122 | font-size: 14px; 123 | font-weight: bold; 124 | font-style: italic; 125 | padding: 0; 126 | margin: 15px 0 5px; } 127 | dl dt:first-child { 128 | padding: 0; } 129 | dl dt > :first-child { 130 | margin-top: 0; } 131 | dl dt > :last-child { 132 | margin-bottom: 0; } 133 | dl dd { 134 | margin: 0 0 15px; 135 | padding: 0 15px; } 136 | dl dd > :first-child { 137 | margin-top: 0; } 138 | dl dd > :last-child { 139 | margin-bottom: 0; } 140 | 141 | blockquote { 142 | border-left: 4px solid #dddddd; 143 | padding: 0 15px; 144 | color: #777777; } 145 | blockquote > :first-child { 146 | margin-top: 0; } 147 | blockquote > :last-child { 148 | margin-bottom: 0; } 149 | 150 | table { 151 | padding: 0; 152 | border-collapse: collapse; 153 | } 154 | table tr { 155 | border-top: 1px solid #cccccc; 156 | background-color: white; 157 | margin: 0; 158 | padding: 0; } 159 | table tr:nth-child(2n) { 160 | background-color: #f8f8f8; } 161 | table tr th { 162 | font-weight: bold; 163 | border: 1px solid #cccccc; 164 | text-align: left; 165 | margin: 0; 166 | padding: 6px 13px; } 167 | table tr td { 168 | border: 1px solid #cccccc; 169 | text-align: left; 170 | margin: 0; 171 | padding: 6px 13px; } 172 | table tr th :first-child, table tr td :first-child { 173 | margin-top: 0; } 174 | table tr th :last-child, table tr td :last-child { 175 | margin-bottom: 0; } 176 | 177 | img { 178 | max-width: 100%; } 179 | 180 | span.frame { 181 | display: block; 182 | overflow: hidden; } 183 | span.frame > span { 184 | border: 1px solid #dddddd; 185 | display: block; 186 | float: left; 187 | overflow: hidden; 188 | margin: 13px 0 0; 189 | padding: 7px; 190 | width: auto; } 191 | span.frame span img { 192 | display: block; 193 | float: left; } 194 | span.frame span span { 195 | clear: both; 196 | color: #333333; 197 | display: block; 198 | padding: 5px 0 0; } 199 | span.align-center { 200 | display: block; 201 | overflow: hidden; 202 | clear: both; } 203 | span.align-center > span { 204 | display: block; 205 | overflow: hidden; 206 | margin: 13px auto 0; 207 | text-align: center; } 208 | span.align-center span img { 209 | margin: 0 auto; 210 | text-align: center; } 211 | span.align-right { 212 | display: block; 213 | overflow: hidden; 214 | clear: both; } 215 | span.align-right > span { 216 | display: block; 217 | overflow: hidden; 218 | margin: 13px 0 0; 219 | text-align: right; } 220 | span.align-right span img { 221 | margin: 0; 222 | text-align: right; } 223 | span.float-left { 224 | display: block; 225 | margin-right: 13px; 226 | overflow: hidden; 227 | float: left; } 228 | span.float-left span { 229 | margin: 13px 0 0; } 230 | span.float-right { 231 | display: block; 232 | margin-left: 13px; 233 | overflow: hidden; 234 | float: right; } 235 | span.float-right > span { 236 | display: block; 237 | overflow: hidden; 238 | margin: 13px auto 0; 239 | text-align: right; } 240 | 241 | code, tt { 242 | margin: 0 2px; 243 | padding: 0 5px; 244 | white-space: nowrap; 245 | border: 1px solid #eaeaea; 246 | background-color: #f8f8f8; 247 | border-radius: 3px; } 248 | 249 | pre code { 250 | margin: 0; 251 | padding: 0; 252 | white-space: pre; 253 | border: none; 254 | background: transparent; } 255 | 256 | .highlight pre { 257 | background-color: #f8f8f8; 258 | border: 1px solid #cccccc; 259 | font-size: 13px; 260 | line-height: 19px; 261 | overflow: auto; 262 | padding: 6px 10px; 263 | border-radius: 3px; } 264 | 265 | pre { 266 | background-color: #f8f8f8; 267 | border: 1px solid #cccccc; 268 | font-size: 13px; 269 | line-height: 19px; 270 | overflow: auto; 271 | padding: 6px 10px; 272 | border-radius: 3px; } 273 | pre code, pre tt { 274 | background-color: transparent; 275 | border: none; } 276 | 277 | /* 278 | * from highlight.js 279 | */ 280 | 281 | /* 282 | 283 | github.com style (c) Vasily Polovnyov 284 | 285 | */ 286 | 287 | .hljs { 288 | display: block; 289 | overflow-x: auto; 290 | padding: 0.5em; 291 | color: #333; 292 | background: #f8f8f8; 293 | } 294 | 295 | .hljs-comment, 296 | .hljs-quote { 297 | color: #998; 298 | font-style: italic; 299 | } 300 | 301 | .hljs-keyword, 302 | .hljs-selector-tag, 303 | .hljs-subst { 304 | color: #333; 305 | font-weight: bold; 306 | } 307 | 308 | .hljs-number, 309 | .hljs-literal, 310 | .hljs-variable, 311 | .hljs-template-variable, 312 | .hljs-tag .hljs-attr { 313 | color: #008080; 314 | } 315 | 316 | .hljs-string, 317 | .hljs-doctag { 318 | color: #d14; 319 | } 320 | 321 | .hljs-title, 322 | .hljs-section, 323 | .hljs-selector-id { 324 | color: #900; 325 | font-weight: bold; 326 | } 327 | 328 | .hljs-subst { 329 | font-weight: normal; 330 | } 331 | 332 | .hljs-type, 333 | .hljs-class .hljs-title { 334 | color: #458; 335 | font-weight: bold; 336 | } 337 | 338 | .hljs-tag, 339 | .hljs-name, 340 | .hljs-attribute { 341 | color: #000080; 342 | font-weight: normal; 343 | } 344 | 345 | .hljs-regexp, 346 | .hljs-link { 347 | color: #009926; 348 | } 349 | 350 | .hljs-symbol, 351 | .hljs-bullet { 352 | color: #990073; 353 | } 354 | 355 | .hljs-built_in, 356 | .hljs-builtin-name { 357 | color: #0086b3; 358 | } 359 | 360 | .hljs-meta { 361 | color: #999; 362 | font-weight: bold; 363 | } 364 | 365 | .hljs-deletion { 366 | background: #fdd; 367 | } 368 | 369 | .hljs-addition { 370 | background: #dfd; 371 | } 372 | 373 | .hljs-emphasis { 374 | font-style: italic; 375 | } 376 | 377 | .hljs-strong { 378 | font-weight: bold; 379 | } 380 | 381 | /* 382 | * For task-list-item 383 | */ 384 | 385 | .task-list-item { 386 | list-style-type: none; 387 | } 388 | 389 | /* 390 | * Settings for PDF 391 | */ 392 | @media print { 393 | hr { 394 | visibility: hidden; 395 | page-break-after: always; 396 | } 397 | } 398 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | SeaPig 2 | ===== 3 | 4 | ![](https://raw.githubusercontent.com/yasumichi/seapig/master/seapig.png)SeaPig is converter from markdown to html with marked.js and highlight.js. 5 | 6 | ![](https://raw.githubusercontent.com/yasumichi/seapig/master/images/seapig.png) 7 | 8 | ## Usage 9 | 10 | SeaPig has two panes. Left pane is editor. Right pane is HTML previewer. 11 | 12 | When you input markdown, SeaPig refresh HTML preview. 13 | 14 | You can use [GitHub Flavored Markdown](https://github.github.com/gfm/). 15 | 16 | SeaPig has tool bar contains one drop down list and eight buttons. 17 | 18 | ![](https://raw.githubusercontent.com/yasumichi/seapig/master/images/seapig-toolbar.png) 19 | 20 | You can select key bindings from drop down list. (default/emacs/vim/sublime) 21 | 22 | Eight buttons has feature below. 23 | 24 | - New markdown file (Open new window) 25 | - Open markdown file to editor. 26 | - Save markdown file from editor. 27 | - Export HTML file from previewer.(At the same time css stylesheet is copied to same folder.) 28 | - Export PDF file 29 | - Hide editor 30 | - Hide previewer 31 | - Refresh HTML preview 32 | 33 | ### viz.js support 34 | 35 | When You write code block as `graphviz` language and write dot language, rendering graph image at svg as below. 36 | 37 |
 38 | ```graphviz
 39 | digraph g { a -> b; }
 40 | ```
 41 | 
42 | 43 | to 44 | 45 | ![](https://raw.githubusercontent.com/yasumichi/seapig/master/images/digraph.png) 46 | 47 | ### uiflow support 48 | 49 | When You write code block as `uiflow` language and write uiflow language, rendering graph image at svg as below. 50 | 51 |
 52 | ```uiflow
 53 | [top page]
 54 | user name
 55 | password
 56 | --
 57 | login
 58 | ==>mypage
 59 | 
 60 | [mypage]
 61 | favorite list
 62 | ```
 63 | 
64 | 65 | to 66 | 67 | ![](https://raw.githubusercontent.com/yasumichi/seapig/master/images/uiflow.png) 68 | 69 | ### MathJax support (code block only) 70 | 71 |
 72 | ```math
 73 | E=mc^2
 74 | ```
 75 | 
76 | 77 | to 78 | 79 | ![](https://raw.githubusercontent.com/yasumichi/seapig/master/images/mathjax.png) 80 | 81 | More example, [test file for mathjax support](mathjax.html) 82 | 83 | ### mermaid support 84 | 85 | When You write code block as `mermaid` language and write mermaid language, rendering graph image at svg as below. 86 | 87 |
 88 | ```mermaid
 89 | sequenceDiagram
 90 |     participant main
 91 |     participant renderer
 92 |     participant previewer
 93 |     main->>renderer: Open file
 94 |     renderer->>previewer: Refresh preview
 95 | ```
 96 | 
97 | 98 | to 99 | 100 | ![](https://raw.githubusercontent.com/yasumichi/seapig/master/images/mermaid.png) 101 | 102 | ## For developers 103 | 104 | ### How to build 105 | 106 | ``` 107 | $ git clone https://github.com/yasumichi/seapig.git 108 | $ cd seapig 109 | $ git submodule update -i 110 | $ npm install 111 | $ npm build-dep 112 | ... 113 | ``` 114 | 115 | ### How to lunch 116 | 117 | ``` 118 | $ npm start 119 | ``` 120 | 121 | ### How to package 122 | 123 | ``` 124 | $ npm run package:win32 125 | ``` 126 | 127 | ### How to package all (on Linux) 128 | 129 | ``` 130 | $ ./build.sh 131 | ``` 132 | 133 | ## ToDo 134 | 135 | - [x] save your favorite keybindings (default/emacs/vim) 136 | - [x] support task list item. 137 | - [x] add viz.js support 138 | - [x] add [uiflow](https://github.com/hirokidaichi/uiflow) support. 139 | - [x] add mermaid support 140 | - [x] add simultaneous scroll 141 | - [x] add original menu 142 | - [x] add new document 143 | - [ ] add alternative stylesheet 144 | - [x] control display editor and previewer 145 | - [ ] add batch mode 146 | - [x] introduce virtual dom framework (mithril.js) 147 | 148 | ## Special Thanks 149 | 150 | - [Ace - The High Performance Code Editor for the Web](https://ace.c9.io/) 151 | - [Electron - Build cross platform desktop apps with JavaScript, HTML, and CSS.](http://electron.atom.io/) 152 | - [electron-json-storage](https://github.com/jviotti/electron-json-storage) 153 | - [electron-localshortcut](https://github.com/parro-it/electron-localshortcut) 154 | - [Github Markdown CSS - for Markdown Editor Preview](https://gist.github.com/andyferra/2554919) 155 | - [highlight.js](https://highlightjs.org/) 156 | - [marked](https://github.com/chjj/marked) 157 | - [MathJax](https://www.mathjax.org/) 158 | - [mermaid](https://knsv.github.io/mermaid/) 159 | - [mithril](https://mithril.js.org/) 160 | - [Node.js](https://nodejs.org/en/) 161 | - [Photon](http://photonkit.com/) 162 | - [sanitize-html](https://github.com/apostrophecms/sanitize-html) 163 | - [viz.js](https://github.com/mdaines/viz.js) 164 | - [uiflow](https://github.com/hirokidaichi/uiflow)(use [forked version](https://github.com/tkrkt/uiflow#fix-argument-in-compile)) 165 | - [いらすとや](http://www.irasutoya.com/)(application icon) 166 | - [jpzukin/electron-sample-print-to-pdf](https://github.com/jpzukin/electron-sample-print-to-pdf) 167 | 168 | # License 169 | 170 | MIT (excludes photon, node_modules and icons) 171 | 172 | Copyright © 2016-2019 Yasumichi Akahoshi 173 | 174 | # Icons copyright 175 | 176 | - seapig.icns 177 | - seapig.ico 178 | - seapig.png 179 | 180 | Copyright © いらすとや. All Rights Reserved. 181 | -------------------------------------------------------------------------------- /images/digraph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yasumichi/seapig/dd3cb12ca113ac8ba5db040d7af960398d82536f/images/digraph.png -------------------------------------------------------------------------------- /images/digraph.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | g 4 | 5 | 6 | a 7 | 8 | a 9 | 10 | 11 | b 12 | 13 | b 14 | 15 | 16 | a->b 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /images/mathjax.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yasumichi/seapig/dd3cb12ca113ac8ba5db040d7af960398d82536f/images/mathjax.png -------------------------------------------------------------------------------- /images/mermaid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yasumichi/seapig/dd3cb12ca113ac8ba5db040d7af960398d82536f/images/mermaid.png -------------------------------------------------------------------------------- /images/seapig-toolbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yasumichi/seapig/dd3cb12ca113ac8ba5db040d7af960398d82536f/images/seapig-toolbar.png -------------------------------------------------------------------------------- /images/seapig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yasumichi/seapig/dd3cb12ca113ac8ba5db040d7af960398d82536f/images/seapig.png -------------------------------------------------------------------------------- /images/uiflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yasumichi/seapig/dd3cb12ca113ac8ba5db040d7af960398d82536f/images/uiflow.png -------------------------------------------------------------------------------- /images/uiflow_ja.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yasumichi/seapig/dd3cb12ca113ac8ba5db040d7af960398d82536f/images/uiflow_ja.png -------------------------------------------------------------------------------- /js/editor.js: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Yasumichi Akahoshi 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | const {app} = require('electron').remote; 26 | const path = require('path'); 27 | const acePath = path.join(app.getAppPath(), 'external/ace'); 28 | const ace = require(path.join(acePath, 'ace.js')); 29 | ace.config.set('basePath', acePath); 30 | ace.require('theme-twilight'); 31 | ace.require('mode-markdown'); 32 | ace.require('keybinding-emacs'); 33 | ace.require('keybinding-vim'); 34 | ace.require('keybinding-sublime'); 35 | 36 | (function() { 37 | 38 | const editor = ace.edit("aceEditor"); 39 | editor.setTheme("ace/theme/twilight"); 40 | editor.getSession().setMode("ace/mode/markdown"); 41 | editor.getSession().setUseWrapMode(true); 42 | editor.focus(); 43 | 44 | module.exports = editor; 45 | 46 | }()); 47 | -------------------------------------------------------------------------------- /js/md2html.js: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Yasumichi Akahoshi 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | const marked = require('marked'); 26 | const { 27 | rendererCode, rendererBlockquote, rendererListitem, rendererHtml, 28 | rendererHeading, rendererParagraph, rendererTablecell 29 | } = require('./utils.js'); 30 | 31 | (function() { 32 | 33 | /** 34 | * This class is a wrapper of marked. 35 | * @class 36 | */ 37 | class Md2Html { 38 | 39 | /** 40 | * Create a Md2Html 41 | */ 42 | constructor() { 43 | this.marked = marked; 44 | this.renderer = new marked.Renderer(); 45 | 46 | this.renderer.code = rendererCode; 47 | this.renderer.blockquote = rendererBlockquote; 48 | this.renderer.listitem = rendererListitem; 49 | this.renderer.html = rendererHtml; 50 | this.renderer.heading = rendererHeading; 51 | this.renderer.paragraph = rendererParagraph; 52 | this.renderer.tablecell = rendererTablecell; 53 | 54 | marked.setOptions({ 55 | renderer: this.renderer, 56 | gfm: true, 57 | breaks: false 58 | }); 59 | } 60 | 61 | /** 62 | * @method 63 | * @name convert 64 | * @description convert markdown to html 65 | * @param {string} markdown - markdown text 66 | * @return {string} HTML text is converted from markdown 67 | */ 68 | convert (markdown) { 69 | return this.marked(markdown); 70 | } 71 | } 72 | 73 | module.exports = Md2Html; 74 | 75 | }()); 76 | -------------------------------------------------------------------------------- /js/pdfWorker.js: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019 Yasumichi Akahoshi 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | window.onload = (e) => { 26 | // Referenced https://github.com/jpzukin/electron-sample-print-to-pdf 27 | const {ipcRenderer} = require('electron'); 28 | const {app} = require('electron').remote; 29 | var thisPdfPath; 30 | 31 | const waitImagesComplete = () => { 32 | var ilist = document.images; 33 | for(var i = 0; i < ilist.length; i++) { 34 | if(ilist[i].complete === false) { 35 | setTimeout(waitImagesComplete, 1000); 36 | return; 37 | } 38 | } 39 | ipcRenderer.send('ready-print-to-pdf', thisPdfPath); 40 | } 41 | 42 | ipcRenderer.on('print-to-pdf', (event, contents, baseHref, css, pdfPath) => { 43 | thisPdfPath = pdfPath; 44 | let base = document.getElementsByTagName("base")[0]; 45 | base.href = baseHref; 46 | 47 | let link = document.getElementsByTagName("link")[0]; 48 | link.href = css; 49 | 50 | document.body.insertAdjacentHTML('afterbegin' ,contents); 51 | 52 | setTimeout(waitImagesComplete); 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /js/preview.js: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Yasumichi Akahoshi 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | (function() { 26 | const {remote} = require('electron'); 27 | const {app} = require('electron').remote; 28 | const {dialog} = require('electron').remote; 29 | const {ipcRenderer} = require('electron'); 30 | const fs = require('fs'); 31 | const path = require('path'); 32 | const m = require("../external/mithril/mithril.min.js"); 33 | const Md2Html = require('./md2html.js'); 34 | const mithrilRoot = document.getElementById("mithrilRoot"); 35 | const FIRST_IDX = 0; 36 | const NO_SCROLL = 0; 37 | const baseTag = document.getElementsByTagName("base")[FIRST_IDX]; 38 | const previewer = document.getElementById("previewer"); 39 | 40 | /** 41 | * @module js/preview.js 42 | */ 43 | 44 | var md2html = new Md2Html(); 45 | 46 | /** 47 | * Get contents of first h1 48 | * @returns {string} contents of first h1 49 | */ 50 | function getContentsOfFirstH1 () { 51 | let h1List = document.getElementsByTagName("h1"); 52 | if (h1List.length) { 53 | return h1List[FIRST_IDX].innerHTML 54 | .replace(/]*>/g, '') 55 | .replace(/<\/a>/g, '') 56 | .replace(/\n/g, ''); 57 | } 58 | 59 | return ''; 60 | } 61 | 62 | /** 63 | * Set document title 64 | * @returns {title} setted title 65 | */ 66 | function getDocumentTitle () { 67 | let workTitle = getContentsOfFirstH1(); 68 | let title; 69 | if (/^(]*>\s*)+$/.test(workTitle)) { 70 | let alts = workTitle.match(/ alt="[^"]*"/gi); 71 | if (alts) { 72 | title = 73 | alts[FIRST_IDX].trim() 74 | .replace(/alt=/i, '') 75 | .replace(/"/g, ''); 76 | } 77 | } else { 78 | title = workTitle.replace(/<[^>]*>/g, "").trim(); 79 | } 80 | 81 | return title; 82 | } 83 | 84 | 85 | /** 86 | * Refresh preview 87 | * @param {string} data - markdown text 88 | * @param {string} baseURI 89 | */ 90 | module.exports.preview = (data, baseURI) => { 91 | if (baseURI != "") { 92 | baseTag.setAttribute("href", baseURI); 93 | } 94 | baseTag.setAttribute("target", "_blank"); 95 | 96 | // render body 97 | m.render(mithrilRoot, m.trust(md2html.convert(data))); 98 | 99 | // process task list items 100 | var listitems = document.getElementsByTagName("li"); 101 | for(var i=0; i { 114 | let html = 115 | '\n' 116 | + `\n` 117 | + '\n' 118 | + ' \n' 119 | + ' \n' 120 | + ' \n' 121 | + ` ${getDocumentTitle()}\n` 122 | + '\n' 123 | + '\n' 124 | + mithrilRoot.innerHTML 125 | + '\n' 126 | + ''; 127 | 128 | return html; 129 | } 130 | 131 | /** 132 | * Export HTML 133 | * @param {object} event 134 | * @param {string} filename - exported HTML file name 135 | * @listen export-HTML 136 | */ 137 | module.exports.exportHTML = (filename) => { 138 | // http://blog.mudatobunka.org/entry/2015/12/23/211425#postscript 139 | fs.writeFile (filename, serializeExportHTML(), 140 | (error) => { 141 | if (error !== null) { 142 | dialog.showMessageBox( 143 | remote.getCurrentWindow(), 144 | { 145 | type: "error", 146 | title: "SeaPig", 147 | message: `${error}`, 148 | buttons: ["OK"] 149 | } 150 | ); 151 | 152 | return; 153 | } 154 | let src_css = path.join(__dirname, '../templates/github.css'); 155 | let dest_css = path.join(path.dirname(filename), "github.css"); 156 | fs.createReadStream(src_css).pipe(fs.createWriteStream(dest_css)); 157 | }); 158 | } 159 | 160 | /** 161 | * Scroll 162 | * @param {object} event 163 | * @param {number} scrollRatio 164 | * @returns {void} 165 | */ 166 | module.exports.scrollPreviewer = (scrollRatio) => { 167 | let scrollTop = mithrilRoot.clientHeight * scrollRatio; 168 | previewer.scrollTo(NO_SCROLL, scrollTop); 169 | } 170 | 171 | }()); 172 | -------------------------------------------------------------------------------- /js/renderer.js: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Yasumichi Akahoshi 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | window.onload = (e) => { 26 | const {remote} = require('electron'); 27 | const {app, dialog} = require('electron').remote; 28 | const ipc = require('electron').ipcRenderer; 29 | const shell = require('electron').shell; 30 | const fs = require('fs'); 31 | const path = require('path'); 32 | const storage = require('electron-json-storage'); 33 | const funcs_path = path.join(app.getAppPath(), 'js', 'renderer_funcs.js'); 34 | const {refreshPreview} = require(funcs_path); 35 | const {showErrorMessage} = require(funcs_path); 36 | const {openFile, saveFile} = require(funcs_path); 37 | const { 38 | exportHTML, 39 | scrollPreviewer 40 | } = require(path.join(app.getAppPath(), 'js', 'preview.js')); 41 | 42 | const mithrilRoot = document.getElementById("mithrilRoot"); 43 | const FIRST_ITEM = 0; 44 | 45 | // Status of document 46 | var {docStatus} = require(funcs_path); 47 | 48 | // Initialize ace editor 49 | const {editor} = require(funcs_path); 50 | 51 | // Emitted whenever the document is changed 52 | editor.on("change", (event) => { 53 | docStatus.modified = true; 54 | ipc.send('doc-modified', docStatus.modified); 55 | refreshPreview(docStatus.filename); 56 | }); 57 | 58 | // Emmited whenever editor is scrolled 59 | editor.getSession().on("changeScrollTop", (scrollTop) => { 60 | let height = editor.renderer.scrollBarV.inner.clientHeight; 61 | if (height) { 62 | let scrollRatio = scrollTop / height; 63 | 64 | scrollPreviewer(scrollRatio); 65 | } 66 | }); 67 | 68 | // disable drag and drop to document 69 | document.ondragover = document.ondrop = (event) => { 70 | event.preventDefault(); 71 | 72 | return false; 73 | }; 74 | 75 | // change keybindings 76 | const keybindings = document.getElementById("keybindings"); 77 | 78 | function changeKeyBindings() { 79 | if (keybindings.value == "default") { 80 | editor.setKeyboardHandler(null); 81 | } else { 82 | editor.setKeyboardHandler(keybindings.value); 83 | } 84 | let json = { key_bindings: keybindings.selectedIndex }; 85 | storage.set('key_bindings', json, (error) => { 86 | if (error) throw error; 87 | }); 88 | editor.focus(); 89 | } 90 | 91 | keybindings.addEventListener("change", changeKeyBindings); 92 | 93 | // load keybindings 94 | storage.get('key_bindings', (error, data) => { 95 | if (error) throw error; 96 | 97 | if (Object.keys(data).length) { 98 | keybindings.selectedIndex = data.key_bindings; 99 | } else { 100 | keybindings.selectedIndex = FIRST_ITEM; 101 | } 102 | changeKeyBindings(); 103 | }); 104 | 105 | // new file 106 | const newBtn = document.getElementById("newBtn"); 107 | newBtn.addEventListener("click", () => { 108 | ipc.send('new-file'); 109 | }); 110 | 111 | // open file 112 | const openBtn = document.getElementById("openBtn"); 113 | const callOpenDialog = () => { 114 | let isNewWindow = false; 115 | if (docStatus.filename) { 116 | isNewWindow = true; 117 | } else if (docStatus.modified === true || editor.getValue().length) { 118 | isNewWindow = true; 119 | } 120 | ipc.send('open-file-dialog', docStatus.filename, isNewWindow); 121 | }; 122 | 123 | openBtn.addEventListener("click", callOpenDialog); 124 | 125 | ipc.on('open-menu-click', callOpenDialog); 126 | 127 | ipc.on('selected-file', (event, fullpath) => { 128 | openFile(fullpath[FIRST_ITEM]); 129 | }); 130 | 131 | ipc.on('open-file', (event, fullpath) => { 132 | openFile(fullpath); 133 | }); 134 | 135 | // save file 136 | const saveBtn = document.getElementById("saveBtn"); 137 | const callSaveFile = () => { 138 | if (docStatus.filename == "") { 139 | ipc.send('save-new-file'); 140 | } else { 141 | saveFile(docStatus.filename); 142 | } 143 | }; 144 | const callSaveAsFile = () => { 145 | ipc.send('save-new-file'); 146 | }; 147 | 148 | saveBtn.addEventListener("click", callSaveFile); 149 | 150 | ipc.on('save-menu-click', callSaveFile); 151 | 152 | ipc.on('saveas-menu-click', callSaveAsFile); 153 | 154 | ipc.on('selected-save-file', (event, filename) => { 155 | saveFile(filename); 156 | }); 157 | 158 | // export html 159 | const exportHTMLBtn = document.getElementById("exportHTMLBtn"); 160 | const callExportHTML = () => { 161 | ipc.send('export-HTML', docStatus.filename); 162 | }; 163 | 164 | exportHTMLBtn.addEventListener("click", callExportHTML); 165 | 166 | ipc.on('export-html-click', callExportHTML); 167 | 168 | ipc.on('selected-HTML-file', (event, filename) => { 169 | exportHTML(filename); 170 | editor.focus(); 171 | }); 172 | 173 | // export pdf 174 | const exportPdfBtn = document.getElementById("exportPdfBtn"); 175 | const callPrintToPDF = () => { 176 | ipc.send('export-pdf-file', docStatus.filename, mithrilRoot.innerHTML); 177 | editor.focus(); 178 | }; 179 | 180 | exportPdfBtn.addEventListener("click", callPrintToPDF); 181 | 182 | ipc.on('print-pdf-click', callPrintToPDF); 183 | 184 | /* 185 | * controle display panes 186 | */ 187 | const aceEditor = document.getElementById("aceEditor"); 188 | const previewer = document.getElementById("previewer"); 189 | 190 | // hide editor 191 | const hideEditorBtn = document.getElementById("hideEditorBtn"); 192 | hideEditorBtn.addEventListener("click", () => { 193 | if (aceEditor.hasAttribute("style") == false && 194 | previewer.hasAttribute("style") == false) { 195 | aceEditor.setAttribute("style", "display:none"); 196 | } else if ( 197 | aceEditor.hasAttribute("style") == false && 198 | previewer.hasAttribute("style") == true) { 199 | previewer.removeAttribute("style"); 200 | editor.resize(true); 201 | } 202 | }); 203 | 204 | // hide preview 205 | const HidePreviewBtn = document.getElementById("HidePreviewBtn"); 206 | HidePreviewBtn.addEventListener("click", () => { 207 | if (aceEditor.hasAttribute("style") == true && 208 | previewer.hasAttribute("style") == false) { 209 | aceEditor.removeAttribute("style"); 210 | editor.resize (true); 211 | } else if ( 212 | aceEditor.hasAttribute("style") == false && 213 | previewer.hasAttribute("style") == false) { 214 | previewer.setAttribute("style", "display:none"); 215 | editor.resize(true); 216 | } 217 | }); 218 | 219 | // Refresh preview 220 | const refreshBtn = document.getElementById("refreshBtn"); 221 | refreshBtn.addEventListener("click", () => { 222 | refreshPreview(docStatus.filename); 223 | editor.focus(); 224 | }); 225 | }; 226 | -------------------------------------------------------------------------------- /js/renderer_funcs.js: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Yasumichi Akahoshi 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | const {remote} = require('electron'); 26 | const {app, dialog} = require('electron').remote; 27 | const ipc = require('electron').ipcRenderer; 28 | const fs = require('fs'); 29 | const path = require('path'); 30 | const {preview} = require(path.join(app.getAppPath(), 'js', 'preview.js')); 31 | const DOCUMENT_START = -1; 32 | 33 | // Initialize ace editor 34 | const editor = require('./editor.js'); 35 | 36 | (function() { 37 | 38 | var docStatus = { 39 | filename: "", 40 | modified: false 41 | }; 42 | 43 | module.exports.editor = editor; 44 | module.exports.docStatus = docStatus; 45 | 46 | /** 47 | * Show error message dialog 48 | * @param {string} message - error message 49 | * @returns {void} 50 | */ 51 | function showErrorMessage(message) { 52 | dialog.showMessageBox( 53 | remote.getCurrentWindow(), 54 | { 55 | type: "error", 56 | title: "SeaPig", 57 | message: String(message), 58 | buttons: ["OK"] 59 | } 60 | ); 61 | } 62 | 63 | module.exports.showErrorMessage = showErrorMessage; 64 | 65 | /** 66 | * Refresh preview pane 67 | * @param {string} currentFile - current file name 68 | * @returns {void} 69 | */ 70 | function refreshPreview(currentFile) { 71 | let baseURI = ""; 72 | if (currentFile != "") { 73 | baseURI = `file://${path.dirname(currentFile)}/`; 74 | } 75 | preview(editor.getValue(), baseURI); 76 | } 77 | 78 | module.exports.refreshPreview = refreshPreview; 79 | 80 | /** 81 | * Open file to set editor 82 | * @param {string} fullpath - full path 83 | * @returns {void} 84 | */ 85 | module.exports.openFile = (fullpath) => { 86 | document.title = `SeaPig - [${fullpath}]`; 87 | refreshPreview(fullpath); 88 | fs.readFile(fullpath, (error, text) => { 89 | if (error !== null) { 90 | showErrorMessage(error); 91 | 92 | return; 93 | } 94 | editor.setValue(text.toString(), DOCUMENT_START); 95 | docStatus.filename = fullpath; 96 | docStatus.modified = false; 97 | ipc.send('doc-modified', docStatus.modified); 98 | refreshPreview(fullpath); 99 | }); 100 | editor.focus(); 101 | } 102 | 103 | /** 104 | * Save file from editor 105 | * @param {string} filename - full path 106 | * @returns {void} 107 | */ 108 | module.exports.saveFile = (filename) => { 109 | fs.writeFile (filename, editor.getValue(), (error) => { 110 | if (error !== null) { 111 | showErrorMessage(error); 112 | 113 | return; 114 | } 115 | document.title = `SeaPig - [${filename}]`; 116 | docStatus.modified = false; 117 | ipc.send('doc-modified', docStatus.modified); 118 | docStatus.filename = filename; 119 | docStatus.modified = false; 120 | editor.focus(); 121 | }); 122 | } 123 | 124 | }()); 125 | -------------------------------------------------------------------------------- /js/sanitize.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | const sanitizeHtml = require('sanitize-html'); 3 | const seapigAllowedTags = sanitizeHtml.defaults.allowedTags.concat([ 4 | 'h1', 'h2', 5 | 'img', 6 | 'input', 7 | ]); 8 | const seapigAllowedAttributes = { 9 | a: [ 'href', 'name', 'target' ], 10 | img: [ 'src' ], 11 | input: [ 12 | { 13 | name: 'type', 14 | values: 'checkbox' 15 | }, 16 | 'checked', 17 | 'disabled' 18 | ] 19 | }; 20 | 21 | module.exports.sanitizeHtmlCustom = (html) => { 22 | return sanitizeHtml(html, { 23 | allowedTags: seapigAllowedTags, 24 | allowedAttributes: seapigAllowedAttributes 25 | }); 26 | } 27 | }()); 28 | -------------------------------------------------------------------------------- /js/seapig.js: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Yasumichi Akahoshi 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | // Load electron modules 26 | const electron = require('electron'); 27 | const app = electron.app; 28 | const BrowserWindow = electron.BrowserWindow; 29 | const localShortcut = require("electron-localshortcut"); 30 | const Menu = electron.Menu; 31 | const ipc = require('electron').ipcMain; 32 | const dialog = require('electron').dialog; 33 | const shell = electron.shell; 34 | 35 | // Load node native module 36 | const fs = require('fs'); 37 | const path = require('path'); 38 | 39 | // Constants 40 | const FIRST_ARG = 0; 41 | const SECOND_ARG = 1; 42 | const THIRD_ARG = 2; 43 | const IDX_OFFSET = 1; 44 | const markdownExt = /\.(md|mdwn|mkdn|mark.*|txt)$/ 45 | const W_WIDTH = 800; 46 | const W_HEIGHT = 600; 47 | const SHIFT = 20; 48 | 49 | var winList = []; 50 | var screenWidth = null; 51 | var screenHeight = null; 52 | var docModified = false; 53 | var pdfWorkerWindow = null; 54 | 55 | // Parse command line arguments 56 | function getArguments() { 57 | let argv = []; 58 | let tmp_args = []; 59 | let tmp_opts = []; 60 | 61 | if (/^electron/.test(path.basename(process.argv[FIRST_ARG]))) { 62 | argv = process.argv.slice(THIRD_ARG); 63 | } else { 64 | argv = process.argv.slice(SECOND_ARG); 65 | } 66 | argv.forEach((element) => { 67 | if (/^-/.test(element) === true) { 68 | tmp_opts.push(element); 69 | } else { 70 | tmp_args.push(element); 71 | } 72 | }); 73 | 74 | return { opts: tmp_opts, args: tmp_args }; 75 | } 76 | 77 | /** 78 | * Create new window when File-New menu is clicked or CommandOrControl+N is 79 | * pressed. 80 | */ 81 | function createNewFile() { 82 | winList.push(createWindow()); 83 | } 84 | 85 | /** 86 | * Inform renderer process to click File-Open menu or press 87 | * CommandOrControl+O. 88 | */ 89 | function callOpenFile() { 90 | let win = BrowserWindow.getFocusedWindow(); 91 | win.webContents.send('open-menu-click'); 92 | } 93 | 94 | /** 95 | * Inform renderer process to click File-Save menu or press 96 | * CommandOrControl+O. 97 | */ 98 | function callSaveFile() { 99 | let win = BrowserWindow.getFocusedWindow(); 100 | win.webContents.send('save-menu-click'); 101 | } 102 | 103 | /** 104 | * Inform renderer process to click File-SaveAs menu. 105 | */ 106 | function callSaveAsFile() { 107 | let win = BrowserWindow.getFocusedWindow(); 108 | win.webContents.send('saveas-menu-click'); 109 | } 110 | 111 | /** 112 | * Inform renderer process to click File-ExportAsHTML menu. 113 | */ 114 | function callExportAsHTML() { 115 | let win = BrowserWindow.getFocusedWindow(); 116 | win.webContents.send('export-html-click'); 117 | } 118 | 119 | /** 120 | * Inform renderer process to click File-PrintToPDF menu. 121 | */ 122 | function callPrintToPDF() { 123 | let win = BrowserWindow.getFocusedWindow(); 124 | win.webContents.send('print-pdf-click'); 125 | } 126 | 127 | // Define menu templates 128 | // { role: 'fileMenu'} 129 | const fileMenu = { 130 | label: '&File', 131 | submenu: [ 132 | { 133 | label: '&New', 134 | accelerator: 'CommandOrControl+N', 135 | click: createNewFile 136 | }, 137 | { 138 | label: '&Open', 139 | accelerator: 'CommandOrControl+O', 140 | click: callOpenFile 141 | }, 142 | { type: 'separator' }, 143 | { 144 | label: '&Save', 145 | accelerator: 'CommandOrControl+S', 146 | click: callSaveFile 147 | }, 148 | { 149 | label: 'Save&As', 150 | click: callSaveAsFile 151 | }, 152 | { type: 'separator' }, 153 | { 154 | label: 'Export as &HTML', 155 | click: callExportAsHTML 156 | }, 157 | { 158 | label: '&Print to PDF', 159 | accelerator: 'CommandOrControl+P', 160 | click: callPrintToPDF 161 | }, 162 | { type: 'separator' }, 163 | // isMac ? { role: 'close' } : { role: 'quit' } 164 | { role: 'quit' } 165 | ] 166 | }; 167 | 168 | // { role: 'viewMenu'} 169 | const viewMenu = { 170 | label: '&View', 171 | submenu: [ 172 | { role: 'toggleDevTools' }, 173 | { type: 'separator' }, 174 | { role: 'togglefullscreen' } 175 | ] 176 | }; 177 | 178 | // { role: 'helpMenu'} 179 | const helpMenu = { 180 | label: '&Help', 181 | submenu: [ 182 | { 183 | label: '&README', 184 | click: async () => { 185 | await shell.openExternal('https://github.com/yasumichi/seapig/blob/master/README.md'); 186 | } 187 | }, 188 | { 189 | label: 'Search &Issues', 190 | click: async () => { 191 | await shell.openExternal('https://github.com/yasumichi/seapig/issues'); 192 | } 193 | } 194 | ] 195 | }; 196 | 197 | /** 198 | * Create menu 199 | */ 200 | function createMenu() { 201 | const template = [ 202 | fileMenu, 203 | viewMenu, 204 | helpMenu 205 | ]; 206 | 207 | const menu = Menu.buildFromTemplate(template); 208 | Menu.setApplicationMenu(menu); 209 | } 210 | 211 | /** 212 | * Regist global shortcuts 213 | */ 214 | function registLocalShortcuts(win) { 215 | localShortcut.register(win, 'CommandOrControl+N', createNewFile); 216 | localShortcut.register(win, 'CommandOrControl+O', callOpenFile); 217 | localShortcut.register(win, 'CommandOrControl+P', callPrintToPDF); 218 | localShortcut.register(win, 'CommandOrControl+S', callSaveFile); 219 | } 220 | 221 | // Create window 222 | function createWindow() { 223 | let mainWindow = null; 224 | 225 | // Create a instance of BrowserWindow 226 | mainWindow = new BrowserWindow({ 227 | width: W_WIDTH, 228 | height: W_HEIGHT, 229 | x: winList.length * SHIFT % (screenWidth - W_WIDTH), 230 | y: winList.length * SHIFT % (screenHeight - W_HEIGHT), 231 | icon: path.join(__dirname, '../seapig.png'), 232 | webPreferences: { 233 | preload: path.join(app.getAppPath(), 'js', 'renderer.js') 234 | } 235 | }); 236 | 237 | createMenu(); 238 | 239 | // Load mainwindow.html 240 | mainWindow.loadURL( 241 | `file://${path.resolve(__dirname ,'../mainwindow.html')}` 242 | ); 243 | 244 | // Process close request 245 | mainWindow.on('close', (e) => { 246 | var closeable = true; 247 | 248 | e.preventDefault(); 249 | 250 | if (docModified === true) { 251 | let msg = `The document has not yet been saved. 252 | Are you sure you want to quit?`; 253 | let result = dialog.showMessageBoxSync( 254 | mainWindow, 255 | { 256 | type: "info", 257 | title: "SeaPig", 258 | message: msg, 259 | buttons: ["OK", "Cancel"] 260 | } 261 | ); 262 | if (result === 1) { 263 | closeable = false; 264 | } 265 | } 266 | 267 | if (closeable === true) { 268 | mainWindow.destroy(); 269 | } 270 | }); 271 | 272 | // Destroy when window is closed 273 | mainWindow.on('closed', () => { 274 | mainWindow = null; 275 | }); 276 | 277 | if (process.env.DEBUG) { 278 | mainWindow.toggleDevTools(); 279 | } 280 | 281 | return mainWindow; 282 | } 283 | 284 | function getScreenSize() { 285 | screenWidth = electron.screen.getPrimaryDisplay().workAreaSize.width; 286 | screenHeight = electron.screen.getPrimaryDisplay().workAreaSize.height; 287 | } 288 | 289 | // Show window when app is ready. 290 | app.on('ready', () => { 291 | let ignoreList = []; 292 | let isFile = false; 293 | let program = getArguments(); 294 | 295 | getScreenSize(); 296 | if (program.args.length) { 297 | program.args.forEach((element) => { 298 | let fullpath = element; 299 | if (!path.isAbsolute(element)) { 300 | fullpath = path.resolve(process.cwd(), element); 301 | } 302 | try { 303 | isFile = fs.statSync(fullpath).isFile(); 304 | } catch (error) { 305 | isFile = false; 306 | } 307 | if (isFile && markdownExt.test(fullpath)) { 308 | let winIndex = winList.push(createWindow()) - IDX_OFFSET; 309 | winList[winIndex].webContents.on('did-finish-load', () => { 310 | registLocalShortcuts(winList[winIndex]); 311 | winList[winIndex].webContents.send('open-file', fullpath); 312 | }); 313 | } else { 314 | ignoreList.push(`${fullpath} isn't file.`); 315 | } 316 | }); 317 | } 318 | if (!winList.length) { 319 | let winIndex = winList.push(createWindow()) - IDX_OFFSET; 320 | winList[winIndex].webContents.on('did-finish-load', () => { 321 | registLocalShortcuts(winList[winIndex]); 322 | }); 323 | } 324 | if (ignoreList.length) { 325 | dialog.showMessageBox({ 326 | title: "Warning", 327 | type: "warning", 328 | message: 'Ignore bellow arguments.', 329 | detail: ignoreList.join('\n'), 330 | buttons: ['OK'] 331 | }); 332 | } 333 | }) 334 | 335 | // Cancel new window when link is clicked and open url by defualt browser. 336 | app.on('web-contents-created', (event, contents) => { 337 | contents.on('new-window', (event, url, frameName, disposition, options) => { 338 | if ( ! /^devtools:/.test(url)) { 339 | event.preventDefault(); 340 | shell.openExternal(url); 341 | } 342 | }) 343 | }) 344 | 345 | // Exit application when all window is closed. 346 | app.on('window-all-closed', () => { 347 | if (process.platform !== 'darwin') { 348 | app.quit(); 349 | } 350 | }) 351 | 352 | // getDefaultPath 353 | function getDefaultPath(currentFile) { 354 | let defaultPath = ""; 355 | 356 | if (currentFile == "") { 357 | defaultPath = path.join(app.getPath('documents'), 'new_file'); 358 | } else { 359 | defaultPath = path.join( 360 | path.dirname(currentFile), 361 | path.basename(currentFile, path.extname(currentFile)) 362 | ); 363 | } 364 | 365 | return defaultPath; 366 | } 367 | 368 | // request new file 369 | ipc.on('new-file', () => { 370 | winList.push(createWindow()); 371 | }); 372 | 373 | // request open file dialog 374 | ipc.on('open-file-dialog', (event, currentFile, isNewWindow) => { 375 | let options = { 376 | title: 'Open Markdown File', 377 | properties: ['openFile'], 378 | defaultPath: path.dirname(currentFile), 379 | filters: [ 380 | { 381 | name: 'Markdown', 382 | extensions: [ 'md', 'mdwn', 'mkd', 'mkdn', 'mark*', 'txt' ] 383 | } 384 | ] 385 | }; 386 | dialog.showOpenDialog( 387 | options 388 | ).then(result => { 389 | if (result.canceled === false) { 390 | let filenames = result.filePaths; 391 | if (isNewWindow === true) { 392 | let newWindow = createWindow(); 393 | winList.push(newWindow); 394 | newWindow.webContents.on('did-finish-load', () => { 395 | newWindow.webContents.send('open-file', filenames[FIRST_ARG]); 396 | }); 397 | } else { 398 | event.sender.send ('selected-file', filenames); 399 | } 400 | } 401 | }).catch(err => { 402 | console.log(err); 403 | }); 404 | }); 405 | 406 | // request save new file 407 | ipc.on('save-new-file', (event) => { 408 | let options = { 409 | title: 'Save Markdown File', 410 | properties: ['openFile'], 411 | defaultPath: `${getDefaultPath('')}.md`, 412 | filters: [ 413 | { 414 | name: 'Markdown', 415 | extensions: [ 'md' ] 416 | } 417 | ] 418 | }; 419 | let filenames = dialog.showSaveDialogSync( 420 | options 421 | ); 422 | if (filenames) { 423 | if (filenames) event.sender.send ('selected-save-file', filenames); 424 | } 425 | }); 426 | 427 | // request export HTML 428 | ipc.on('export-HTML', (event, currentFile) => { 429 | let options = { 430 | title: 'Export HTML file', 431 | properties: ['openFile'], 432 | defaultPath: `${getDefaultPath(currentFile)}.html`, 433 | filters: [ 434 | { name: 'HTML', extensions: [ 'html' ] } 435 | ] 436 | }; 437 | let filenames = dialog.showSaveDialogSync( 438 | options 439 | ); 440 | if (filenames) { 441 | event.sender.send ('selected-HTML-file', filenames); 442 | } 443 | }); 444 | 445 | // request export pfd 446 | ipc.on('export-pdf-file', (event, currentFile, contents) => { 447 | let options = { 448 | title: 'Export PDF file', 449 | properties: ['openFile'], 450 | defaultPath: `${getDefaultPath(currentFile)}.pdf`, 451 | filters: [ 452 | { name: 'PDF', extensions: [ 'pdf' ] } 453 | ] 454 | }; 455 | let filenames = dialog.showSaveDialogSync( 456 | options 457 | ); 458 | if (filenames) { 459 | console.log(filenames); 460 | if(pdfWorkerWindow !== null) { 461 | pdfWorkerWindow.close(); 462 | } 463 | 464 | pdfWorkerWindow = new BrowserWindow( 465 | { 466 | show: false, 467 | webPreferences: { 468 | preload: path.join(app.getAppPath(), 'js', 'pdfWorker.js') 469 | } 470 | } 471 | ); 472 | pdfWorkerWindow.on("closed", () => { 473 | pdfWorkerWindow = null; 474 | }); 475 | 476 | let template = path.join(app.getAppPath(), 'templates', 'template.html'); 477 | pdfWorkerWindow.loadURL(`file://${template}`); 478 | pdfWorkerWindow.webContents.on("did-finish-load", () => { 479 | let css = `file://${path.join(app.getAppPath(), 'templates', 'github.css')}`; 480 | let baseHref = `file://${getDefaultPath(currentFile)}` 481 | pdfWorkerWindow.send("print-to-pdf", contents, baseHref, css, filenames); 482 | }); 483 | } 484 | }); 485 | 486 | ipc.on('ready-print-to-pdf', (event, pdfPath) => { 487 | const options = { printBackground: true }; 488 | 489 | pdfWorkerWindow.webContents.printToPDF( 490 | options 491 | ).then(result => { 492 | fs.writeFile(pdfPath, result, (error) => { 493 | if (error) { 494 | throw error; 495 | } 496 | shell.openItem(pdfPath); 497 | pdfWorkerWindow.close(); 498 | }); 499 | }).catch(error => { 500 | throw error; 501 | }); 502 | }); 503 | 504 | // request error message 505 | ipc.on('error-message', (event, error_msg) => { 506 | dialog.showMessageBox({ 507 | title: "Error", 508 | type: "error", 509 | message: error_msg, 510 | buttons: ['OK'] 511 | }); 512 | }); 513 | 514 | // recieve document status 515 | ipc.on('doc-modified', (event, modified) => { 516 | docModified = modified; 517 | }); 518 | -------------------------------------------------------------------------------- /js/tex2svg.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | require('../external/mathjax/tex-svg-full.js'); 3 | 4 | module.exports.tex2svg = (code) => { 5 | let svg = MathJax.tex2svg(code, {}).innerHTML; 6 | return '
' + svg + '
'; 7 | } 8 | }()); 9 | -------------------------------------------------------------------------------- /js/utils.js: -------------------------------------------------------------------------------- 1 | const hljs = require('highlight.js'); 2 | const viz = require("viz.js"); 3 | const uiflow = require("uiflow"); 4 | const mermaidAPI = require('../external/mermaid/mermaid.min.js').mermaidAPI; 5 | const {sanitizeHtmlCustom} = require('./sanitize.js'); 6 | const {tex2svg} = require('./tex2svg.js'); 7 | 8 | (function() { 9 | const mermaidWorkArea = document.getElementById("mermaidWorkArea"); 10 | 11 | mermaidAPI.initialize({ 12 | startOnLoad: false, 13 | theme: "default", 14 | flowchart: { 15 | htmlLabels: false 16 | } 17 | }); 18 | 19 | /** 20 | * @function 21 | * @name escapeHtml 22 | * @param {string} html - String includes HTML special characters. 23 | * @returns {string} String was escaped HTML special characters. 24 | * @description escape HTML special characters, from 25 | * {@link http://qiita.com/noriaki/items/4bfef8d7cf85dc1035b3} 26 | */ 27 | function escapeHtml(html) { 28 | var escapeMap = { 29 | '&': '&', 30 | '\x27': ''', 31 | '"': '"', 32 | '<': '<', 33 | '>': '>' 34 | }; 35 | 36 | return html.replace(/[&"'<>]/g, (char) => { 37 | let retChar = escapeMap[char]; 38 | 39 | return retChar; 40 | }); 41 | } 42 | 43 | const codeConverters = { 44 | "graphviz": (code) => { 45 | let svg = viz(code); 46 | 47 | return svg; 48 | }, 49 | "mathjax": tex2svg, 50 | "math": tex2svg, 51 | "mermaid": (code) => { 52 | let date = new Date(); 53 | let svgId = "m" + date.getFullYear() + ('0' + (date.getMonth() + 1)).slice(-2) 54 | + ('0' + date.getDate()).slice(-2) + ('0' + date.getHours()).slice(-2) 55 | + ('0' + date.getMinutes()).slice(-2) + ('0' + date.getSeconds()).slice(-2) 56 | + ('00' + date.getMilliseconds()).slice(-3); 57 | let svg = mermaidAPI.render(svgId, code, undefined, mermaidWorkArea); 58 | 59 | return `
\n${svg.replace("", "")}
\n`; 60 | }, 61 | "uiflow": (code) => { 62 | let dot = uiflow.compile(code); 63 | let svg = viz(dot); 64 | 65 | return svg; 66 | } 67 | }; 68 | 69 | /** 70 | * customize to render list item 71 | * @param {string} text - contents of list item 72 | * @param {boolean} task - is listitem task? 73 | * @param {boolean} checked - is listitem checked? 74 | * @returns {string} converted list item 75 | */ 76 | module.exports.rendererListitem = (text, task, checked) => { 77 | return `
  • ${sanitizeHtmlCustom(text)}
  • `; 78 | } 79 | 80 | /** 81 | * customize to render code 82 | * @param {string} code - contents of code block 83 | * @param {string} language - program language of code block 84 | * @returns {string} converted code block 85 | */ 86 | module.exports.rendererCode = (code, language) => { 87 | const ERR_HEAD = 88 | "\n******************* Convert Error *******************\n"; 89 | const ERR_TAIL = 90 | "\n*****************************************************\n"; 91 | let hljsCode = hljs.highlightAuto(code).value; 92 | 93 | if (codeConverters[language]) { 94 | try { 95 | return codeConverters[language](code); 96 | } catch (error) { 97 | let errMsg = String(error).trim(); 98 | let retCode = 99 | `
    ${hljsCode}${ERR_HEAD}${errMsg}${ERR_TAIL}
    `; 100 | 101 | return retCode; 102 | } 103 | } 104 | 105 | return `
    ${hljsCode}
    `; 106 | } 107 | 108 | /** 109 | * customize to render blockquote 110 | * @param {string} quote - contents of blockquote 111 | * @returns {string} converted blockquote block 112 | */ 113 | module.exports.rendererBlockquote = (quote) => { 114 | return `
    ${sanitizeHtmlCustom(quote)}
    \n`; 115 | } 116 | 117 | /** 118 | * customize to render HTML (sanitize script) 119 | * @param {string} html - contents of html code block 120 | * @returns {string} html or html code block 121 | */ 122 | module.exports.rendererHtml = (html) => { 123 | return sanitizeHtmlCustom(html); 124 | } 125 | 126 | /** 127 | * customize to render heading 128 | * @param {string} text - contents of heading 129 | * @param {number} level - level of heading 130 | * @returns {string} HTML heading element 131 | */ 132 | module.exports.rendererHeading = (text, level, raw, slugger) => { 133 | let id = slugger.slug(encodeURI(text)); 134 | 135 | return `${sanitizeHtmlCustom(text)}\n`; 136 | } 137 | 138 | /** 139 | * customize to render paragraph 140 | * @param {string} text - contents of paragraph 141 | * @returns {string} HTML paragraph element 142 | */ 143 | module.exports.rendererParagraph = (text) => { 144 | return `

    ${sanitizeHtmlCustom(text)}

    \n`; 145 | } 146 | 147 | /** 148 | * customize to render tablecell 149 | * @param {string} content - contents of cell 150 | * @param {object} flags - contents of cell 151 | * @returns {string} HTML tablecell element 152 | */ 153 | module.exports.rendererTablecell = (content, flags) => { 154 | var tag = flags.header ? 'th' : 'td'; 155 | var align = flags.align ? ` align="${flags.align}"` : ''; 156 | 157 | return `<${tag}${align}>${sanitizeHtmlCustom(content)}`; 158 | } 159 | 160 | module.exports.escapeHtml = escapeHtml; 161 | 162 | }()); 163 | -------------------------------------------------------------------------------- /mainwindow.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | SeaPig 11 | 12 | 13 |
    14 |
    15 |
    16 | 17 | 23 |
    24 |
    25 | 26 | New File 27 |
    28 |
    29 | 30 | Open File... 31 |
    32 |
    33 | 34 | Save File... 35 |
    36 |
    37 | 38 | Export as HTML... 39 |
    40 |
    41 | 42 | Print to PDF... 43 |
    44 |
    45 |
    46 |
    47 | 48 | Hide editor 49 |
    50 |
    51 | 52 | Hide preview 53 |
    54 |
    55 |
    56 | 57 | Refresh preview 58 |
    59 |
    60 |
    61 |
    62 |
    63 |
    64 |
    65 |
    66 |
    67 |
    68 |
    69 |
    70 |
    71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "seapig", 3 | "version": "0.9.1", 4 | "description": "SeaPig is converter from markdown to html.", 5 | "main": "js/seapig.js", 6 | "scripts": { 7 | "start": "electron .", 8 | "test": "mocha -r jsdom-global/register", 9 | "lint": "eslint", 10 | "lint-all": "eslint js", 11 | "clean": "rimraf releases *.log external", 12 | "build-dep": "node scripts/build-dep.js", 13 | "package:darwin": "electron-packager --ignore='^/ace-builds' --ignore='^/docs' --ignore='^/scripts' --platform=darwin --arch=all --prune --asar --out=releases --icon=seapig.icns .", 14 | "package:win32": "electron-packager --ignore='^/ace-builds' --ignore='^/docs' --ignore='^/scripts' --platform=win32 --arch=all --prune --asar --out=releases --icon=seapig.ico .", 15 | "package:linux": "electron-packager --ignore='^/ace-builds' --ignore='^/docs' --ignore='^/scripts' --platform=linux --arch=all --prune --asar --out=releases ." 16 | }, 17 | "author": "Yasumichi Akahoshi ", 18 | "license": "MIT", 19 | "dependencies": { 20 | "electron-json-storage": "^4.1.7", 21 | "electron-localshortcut": "^3.1.0", 22 | "highlight.js": "^9.15.10", 23 | "marked": "^0.7.0", 24 | "sanitize-html": "^1.20.1", 25 | "uiflow": "git+https://github.com/tkrkt/uiflow.git#fix-argument-in-compile", 26 | "viz.js": "^1.8.2" 27 | }, 28 | "devDependencies": { 29 | "@babel/cli": "^7.6.0", 30 | "@babel/core": "^7.6.0", 31 | "@babel/preset-env": "^7.6.0", 32 | "@babel/register": "^7.6.0", 33 | "electron": "^7.0.0", 34 | "electron-packager": "^14.0.5", 35 | "eslint": "^6.3.0", 36 | "jsdoc": "^3.6.3", 37 | "jsdom": "^15.1.1", 38 | "jsdom-global": "^3.0.2", 39 | "mathjax": "^3.0.0", 40 | "mermaid": "^8.2.6", 41 | "mithril": "^2.0.4", 42 | "mocha": "^6.2.0", 43 | "power-assert": "^1.6.1", 44 | "rimraf": "^3.0.0" 45 | }, 46 | "repository": { 47 | "type": "git", 48 | "url": "git+https://github.com/yasumichi/seapig.git" 49 | }, 50 | "keywords": [ 51 | "markdown" 52 | ], 53 | "bugs": { 54 | "url": "https://github.com/yasumichi/seapig/issues" 55 | }, 56 | "homepage": "https://github.com/yasumichi/seapig#readme" 57 | } 58 | -------------------------------------------------------------------------------- /photon/css/photon.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * ===================================================== 3 | * Photon v0.1.1 4 | * Copyright 2015 Connor Sears 5 | * Licensed under MIT (https://github.com/connors/proton/blob/master/LICENSE) 6 | * 7 | * v0.1.1 designed by @connors. 8 | * ===================================================== 9 | */ 10 | 11 | @charset "UTF-8"; 12 | audio, 13 | canvas, 14 | progress, 15 | video { 16 | vertical-align: baseline; 17 | } 18 | 19 | audio:not([controls]) { 20 | display: none; 21 | } 22 | 23 | a:active, 24 | a:hover { 25 | outline: 0; 26 | } 27 | 28 | abbr[title] { 29 | border-bottom: 1px dotted; 30 | } 31 | 32 | b, 33 | strong { 34 | font-weight: bold; 35 | } 36 | 37 | dfn { 38 | font-style: italic; 39 | } 40 | 41 | h1 { 42 | font-size: 2em; 43 | margin: 0.67em 0; 44 | } 45 | 46 | small { 47 | font-size: 80%; 48 | } 49 | 50 | sub, 51 | sup { 52 | font-size: 75%; 53 | line-height: 0; 54 | position: relative; 55 | vertical-align: baseline; 56 | } 57 | 58 | sup { 59 | top: -0.5em; 60 | } 61 | 62 | sub { 63 | bottom: -0.25em; 64 | } 65 | 66 | pre { 67 | overflow: auto; 68 | } 69 | 70 | code, 71 | kbd, 72 | pre, 73 | samp { 74 | font-family: monospace, monospace; 75 | font-size: 1em; 76 | } 77 | 78 | button, 79 | input, 80 | optgroup, 81 | select, 82 | textarea { 83 | color: inherit; 84 | font: inherit; 85 | margin: 0; 86 | } 87 | 88 | input[type="number"]::-webkit-inner-spin-button, 89 | input[type="number"]::-webkit-outer-spin-button { 90 | height: auto; 91 | } 92 | 93 | input[type="search"] { 94 | -webkit-appearance: textfield; 95 | box-sizing: content-box; 96 | } 97 | 98 | input[type="search"]::-webkit-search-cancel-button, 99 | input[type="search"]::-webkit-search-decoration { 100 | -webkit-appearance: none; 101 | } 102 | 103 | fieldset { 104 | border: 1px solid #c0c0c0; 105 | margin: 0 2px; 106 | padding: 0.35em 0.625em 0.75em; 107 | } 108 | 109 | legend { 110 | border: 0; 111 | padding: 0; 112 | } 113 | 114 | table { 115 | border-collapse: collapse; 116 | border-spacing: 0; 117 | } 118 | 119 | td, 120 | th { 121 | padding: 0; 122 | } 123 | 124 | * { 125 | cursor: default; 126 | -webkit-user-drag: text; 127 | -webkit-user-select: none; 128 | -webkit-box-sizing: border-box; 129 | box-sizing: border-box; 130 | } 131 | 132 | html { 133 | height: 100%; 134 | width: 100%; 135 | overflow: hidden; 136 | } 137 | 138 | body { 139 | height: 100%; 140 | padding: 0; 141 | margin: 0; 142 | font-family: system, -apple-system, ".SFNSDisplay-Regular", "Helvetica Neue", Helvetica, "Segoe UI", sans-serif; 143 | font-size: 13px; 144 | line-height: 1.6; 145 | color: #333; 146 | background-color: transparent; 147 | } 148 | 149 | hr { 150 | margin: 15px 0; 151 | overflow: hidden; 152 | background: transparent; 153 | border: 0; 154 | border-bottom: 1px solid #ddd; 155 | } 156 | 157 | h1, h2, h3, h4, h5, h6 { 158 | margin-top: 20px; 159 | margin-bottom: 10px; 160 | font-weight: 500; 161 | white-space: nowrap; 162 | overflow: hidden; 163 | text-overflow: ellipsis; 164 | } 165 | 166 | h1 { 167 | font-size: 36px; 168 | } 169 | 170 | h2 { 171 | font-size: 30px; 172 | } 173 | 174 | h3 { 175 | font-size: 24px; 176 | } 177 | 178 | h4 { 179 | font-size: 18px; 180 | } 181 | 182 | h5 { 183 | font-size: 14px; 184 | } 185 | 186 | h6 { 187 | font-size: 12px; 188 | } 189 | 190 | .window { 191 | position: absolute; 192 | top: 0; 193 | right: 0; 194 | bottom: 0; 195 | left: 0; 196 | display: flex; 197 | flex-direction: column; 198 | background-color: #fff; 199 | } 200 | 201 | .window-content { 202 | position: relative; 203 | overflow-y: auto; 204 | display: flex; 205 | flex: 1; 206 | } 207 | 208 | .selectable-text { 209 | cursor: text; 210 | -webkit-user-select: text; 211 | } 212 | 213 | .text-center { 214 | text-align: center; 215 | } 216 | 217 | .text-right { 218 | text-align: right; 219 | } 220 | 221 | .text-left { 222 | text-align: left; 223 | } 224 | 225 | .pull-left { 226 | float: left; 227 | } 228 | 229 | .pull-right { 230 | float: right; 231 | } 232 | 233 | .padded { 234 | padding: 10px; 235 | } 236 | 237 | .padded-less { 238 | padding: 5px; 239 | } 240 | 241 | .padded-more { 242 | padding: 20px; 243 | } 244 | 245 | .padded-vertically { 246 | padding-top: 10px; 247 | padding-bottom: 10px; 248 | } 249 | 250 | .padded-vertically-less { 251 | padding-top: 5px; 252 | padding-bottom: 5px; 253 | } 254 | 255 | .padded-vertically-more { 256 | padding-top: 20px; 257 | padding-bottom: 20px; 258 | } 259 | 260 | .padded-horizontally { 261 | padding-right: 10px; 262 | padding-left: 10px; 263 | } 264 | 265 | .padded-horizontally-less { 266 | padding-right: 5px; 267 | padding-left: 5px; 268 | } 269 | 270 | .padded-horizontally-more { 271 | padding-right: 20px; 272 | padding-left: 20px; 273 | } 274 | 275 | .padded-top { 276 | padding-top: 10px; 277 | } 278 | 279 | .padded-top-less { 280 | padding-top: 5px; 281 | } 282 | 283 | .padded-top-more { 284 | padding-top: 20px; 285 | } 286 | 287 | .padded-bottom { 288 | padding-bottom: 10px; 289 | } 290 | 291 | .padded-bottom-less { 292 | padding-bottom: 5px; 293 | } 294 | 295 | .padded-bottom-more { 296 | padding-bottom: 20px; 297 | } 298 | 299 | .sidebar { 300 | background-color: #f5f5f4; 301 | } 302 | 303 | .draggable { 304 | -webkit-app-region: drag; 305 | } 306 | 307 | .clearfix:before, .clearfix:after { 308 | display: table; 309 | content: " "; 310 | } 311 | .clearfix:after { 312 | clear: both; 313 | } 314 | 315 | .btn { 316 | display: inline-block; 317 | padding: 3px 8px; 318 | margin-bottom: 0; 319 | font-size: 12px; 320 | line-height: 1.4; 321 | text-align: center; 322 | white-space: nowrap; 323 | vertical-align: middle; 324 | cursor: default; 325 | background-image: none; 326 | border: 1px solid transparent; 327 | border-radius: 4px; 328 | box-shadow: 0 1px 1px rgba(0, 0, 0, 0.06); 329 | -webkit-app-region: no-drag; 330 | } 331 | .btn:focus { 332 | outline: none; 333 | box-shadow: none; 334 | } 335 | 336 | .btn-mini { 337 | padding: 2px 6px; 338 | } 339 | 340 | .btn-large { 341 | padding: 6px 12px; 342 | } 343 | 344 | .btn-form { 345 | padding-right: 20px; 346 | padding-left: 20px; 347 | } 348 | 349 | .btn-default { 350 | color: #333; 351 | border-top-color: #c2c0c2; 352 | border-right-color: #c2c0c2; 353 | border-bottom-color: #a19fa1; 354 | border-left-color: #c2c0c2; 355 | background-color: #fcfcfc; 356 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fcfcfc), color-stop(100%, #f1f1f1)); 357 | background-image: -webkit-linear-gradient(top, #fcfcfc 0%, #f1f1f1 100%); 358 | background-image: linear-gradient(to bottom, #fcfcfc 0%, #f1f1f1 100%); 359 | } 360 | .btn-default:active { 361 | background-color: #ddd; 362 | background-image: none; 363 | } 364 | 365 | .btn-primary, 366 | .btn-positive, 367 | .btn-negative, 368 | .btn-warning { 369 | color: #fff; 370 | text-shadow: 0 1px 1px rgba(0, 0, 0, 0.1); 371 | } 372 | 373 | .btn-primary { 374 | border-color: #388df8; 375 | border-bottom-color: #0866dc; 376 | background-color: #6eb4f7; 377 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #6eb4f7), color-stop(100%, #1a82fb)); 378 | background-image: -webkit-linear-gradient(top, #6eb4f7 0%, #1a82fb 100%); 379 | background-image: linear-gradient(to bottom, #6eb4f7 0%, #1a82fb 100%); 380 | } 381 | .btn-primary:active { 382 | background-color: #3e9bf4; 383 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #3e9bf4), color-stop(100%, #0469de)); 384 | background-image: -webkit-linear-gradient(top, #3e9bf4 0%, #0469de 100%); 385 | background-image: linear-gradient(to bottom, #3e9bf4 0%, #0469de 100%); 386 | } 387 | 388 | .btn-positive { 389 | border-color: #29a03b; 390 | border-bottom-color: #248b34; 391 | background-color: #5bd46d; 392 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bd46d), color-stop(100%, #29a03b)); 393 | background-image: -webkit-linear-gradient(top, #5bd46d 0%, #29a03b 100%); 394 | background-image: linear-gradient(to bottom, #5bd46d 0%, #29a03b 100%); 395 | } 396 | .btn-positive:active { 397 | background-color: #34c84a; 398 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #34c84a), color-stop(100%, #248b34)); 399 | background-image: -webkit-linear-gradient(top, #34c84a 0%, #248b34 100%); 400 | background-image: linear-gradient(to bottom, #34c84a 0%, #248b34 100%); 401 | } 402 | 403 | .btn-negative { 404 | border-color: #fb2f29; 405 | border-bottom-color: #fb1710; 406 | background-color: #fd918d; 407 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fd918d), color-stop(100%, #fb2f29)); 408 | background-image: -webkit-linear-gradient(top, #fd918d 0%, #fb2f29 100%); 409 | background-image: linear-gradient(to bottom, #fd918d 0%, #fb2f29 100%); 410 | } 411 | .btn-negative:active { 412 | background-color: #fc605b; 413 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fc605b), color-stop(100%, #fb1710)); 414 | background-image: -webkit-linear-gradient(top, #fc605b 0%, #fb1710 100%); 415 | background-image: linear-gradient(to bottom, #fc605b 0%, #fb1710 100%); 416 | } 417 | 418 | .btn-warning { 419 | border-color: #fcaa0e; 420 | border-bottom-color: #ee9d02; 421 | background-color: #fece72; 422 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fece72), color-stop(100%, #fcaa0e)); 423 | background-image: -webkit-linear-gradient(top, #fece72 0%, #fcaa0e 100%); 424 | background-image: linear-gradient(to bottom, #fece72 0%, #fcaa0e 100%); 425 | } 426 | .btn-warning:active { 427 | background-color: #fdbc40; 428 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fdbc40), color-stop(100%, #ee9d02)); 429 | background-image: -webkit-linear-gradient(top, #fdbc40 0%, #ee9d02 100%); 430 | background-image: linear-gradient(to bottom, #fdbc40 0%, #ee9d02 100%); 431 | } 432 | 433 | .btn .icon { 434 | float: left; 435 | width: 14px; 436 | height: 14px; 437 | margin-top: 1px; 438 | margin-bottom: 1px; 439 | color: #737475; 440 | font-size: 14px; 441 | line-height: 1; 442 | } 443 | 444 | .btn .icon-text { 445 | margin-right: 5px; 446 | } 447 | 448 | .btn-dropdown:after { 449 | font-family: "photon-entypo"; 450 | margin-left: 5px; 451 | content: ""; 452 | } 453 | 454 | .btn-group { 455 | position: relative; 456 | display: inline-block; 457 | vertical-align: middle; 458 | -webkit-app-region: no-drag; 459 | } 460 | .btn-group .btn { 461 | position: relative; 462 | float: left; 463 | } 464 | .btn-group .btn:focus, .btn-group .btn:active { 465 | z-index: 2; 466 | } 467 | .btn-group .btn.active { 468 | z-index: 3; 469 | } 470 | 471 | .btn-group .btn + .btn, 472 | .btn-group .btn + .btn-group, 473 | .btn-group .btn-group + .btn, 474 | .btn-group .btn-group + .btn-group { 475 | margin-left: -1px; 476 | } 477 | .btn-group > .btn:first-child { 478 | border-top-right-radius: 0; 479 | border-bottom-right-radius: 0; 480 | } 481 | .btn-group > .btn:last-child { 482 | border-top-left-radius: 0; 483 | border-bottom-left-radius: 0; 484 | } 485 | .btn-group > .btn:not(:first-child):not(:last-child) { 486 | border-radius: 0; 487 | } 488 | .btn-group .btn + .btn { 489 | border-left: 1px solid #c2c0c2; 490 | } 491 | .btn-group .btn + .btn.active { 492 | border-left: 0; 493 | } 494 | .btn-group .active { 495 | color: #fff; 496 | border: 1px solid transparent; 497 | background-color: #6d6c6d; 498 | background-image: none; 499 | } 500 | .btn-group .active .icon { 501 | color: #fff; 502 | } 503 | 504 | .toolbar { 505 | min-height: 22px; 506 | box-shadow: inset 0 1px 0 #f5f4f5; 507 | background-color: #e8e6e8; 508 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #e8e6e8), color-stop(100%, #d1cfd1)); 509 | background-image: -webkit-linear-gradient(top, #e8e6e8 0%, #d1cfd1 100%); 510 | background-image: linear-gradient(to bottom, #e8e6e8 0%, #d1cfd1 100%); 511 | } 512 | .toolbar:before, .toolbar:after { 513 | display: table; 514 | content: " "; 515 | } 516 | .toolbar:after { 517 | clear: both; 518 | } 519 | 520 | .toolbar-header { 521 | border-bottom: 1px solid #c2c0c2; 522 | } 523 | .toolbar-header .title { 524 | margin-top: 1px; 525 | } 526 | 527 | .toolbar-footer { 528 | border-top: 1px solid #c2c0c2; 529 | -webkit-app-region: drag; 530 | } 531 | 532 | .title { 533 | margin: 0; 534 | font-size: 12px; 535 | font-weight: 400; 536 | text-align: center; 537 | color: #555; 538 | cursor: default; 539 | } 540 | 541 | .toolbar-borderless { 542 | border-top: 0; 543 | border-bottom: 0; 544 | } 545 | 546 | .toolbar-actions { 547 | margin-top: 4px; 548 | margin-bottom: 3px; 549 | padding-right: 3px; 550 | padding-left: 3px; 551 | padding-bottom: 3px; 552 | -webkit-app-region: drag; 553 | } 554 | .toolbar-actions:before, .toolbar-actions:after { 555 | display: table; 556 | content: " "; 557 | } 558 | .toolbar-actions:after { 559 | clear: both; 560 | } 561 | .toolbar-actions > .btn, 562 | .toolbar-actions > .btn-group { 563 | margin-left: 4px; 564 | margin-right: 4px; 565 | } 566 | 567 | label { 568 | display: inline-block; 569 | font-size: 13px; 570 | margin-bottom: 5px; 571 | white-space: nowrap; 572 | overflow: hidden; 573 | text-overflow: ellipsis; 574 | } 575 | 576 | input[type="search"] { 577 | box-sizing: border-box; 578 | } 579 | 580 | input[type="radio"], 581 | input[type="checkbox"] { 582 | margin: 4px 0 0; 583 | line-height: normal; 584 | } 585 | 586 | .form-control { 587 | display: inline-block; 588 | width: 100%; 589 | min-height: 25px; 590 | padding: 5px 10px; 591 | font-size: 13px; 592 | line-height: 1.6; 593 | background-color: #fff; 594 | border: 1px solid #ddd; 595 | border-radius: 4px; 596 | outline: none; 597 | } 598 | .form-control:focus { 599 | border-color: #6db3fd; 600 | box-shadow: 3px 3px 0 #6db3fd, -3px -3px 0 #6db3fd, -3px 3px 0 #6db3fd, 3px -3px 0 #6db3fd; 601 | } 602 | 603 | textarea { 604 | height: auto; 605 | } 606 | 607 | .form-group { 608 | margin-bottom: 10px; 609 | } 610 | 611 | .radio, 612 | .checkbox { 613 | position: relative; 614 | display: block; 615 | margin-top: 10px; 616 | margin-bottom: 10px; 617 | } 618 | .radio label, 619 | .checkbox label { 620 | padding-left: 20px; 621 | margin-bottom: 0; 622 | font-weight: normal; 623 | } 624 | 625 | .radio input[type="radio"], 626 | .radio-inline input[type="radio"], 627 | .checkbox input[type="checkbox"], 628 | .checkbox-inline input[type="checkbox"] { 629 | position: absolute; 630 | margin-left: -20px; 631 | margin-top: 4px; 632 | } 633 | 634 | .form-actions .btn { 635 | margin-right: 10px; 636 | } 637 | .form-actions .btn:last-child { 638 | margin-right: 0; 639 | } 640 | 641 | .pane-group { 642 | position: absolute; 643 | top: 0; 644 | right: 0; 645 | bottom: 0; 646 | left: 0; 647 | display: flex; 648 | } 649 | 650 | .pane { 651 | position: relative; 652 | overflow-y: auto; 653 | flex: 1; 654 | border-left: 1px solid #ddd; 655 | } 656 | .pane:first-child { 657 | border-left: 0; 658 | } 659 | 660 | .pane-sm { 661 | max-width: 220px; 662 | min-width: 150px; 663 | } 664 | 665 | .pane-mini { 666 | width: 80px; 667 | flex: none; 668 | } 669 | 670 | .pane-one-fourth { 671 | width: 25%; 672 | flex: none; 673 | } 674 | 675 | .pane-one-third { 676 | width: 33.3%; 677 | } 678 | 679 | img { 680 | -webkit-user-drag: text; 681 | } 682 | 683 | .img-circle { 684 | border-radius: 50%; 685 | } 686 | 687 | .img-rounded { 688 | border-radius: 4px; 689 | } 690 | 691 | .list-group { 692 | width: 100%; 693 | list-style: none; 694 | margin: 0; 695 | padding: 0; 696 | } 697 | .list-group * { 698 | margin: 0; 699 | white-space: nowrap; 700 | overflow: hidden; 701 | text-overflow: ellipsis; 702 | } 703 | 704 | .list-group-item { 705 | padding: 10px; 706 | font-size: 12px; 707 | color: #414142; 708 | border-top: 1px solid #ddd; 709 | } 710 | .list-group-item:first-child { 711 | border-top: 0; 712 | } 713 | .list-group-item.active, .list-group-item.selected { 714 | color: #fff; 715 | background-color: #116cd6; 716 | } 717 | 718 | .list-group-header { 719 | padding: 10px; 720 | } 721 | 722 | .media-object { 723 | margin-top: 3px; 724 | } 725 | 726 | .media-object.pull-left { 727 | margin-right: 10px; 728 | } 729 | 730 | .media-object.pull-right { 731 | margin-left: 10px; 732 | } 733 | 734 | .media-body { 735 | overflow: hidden; 736 | } 737 | 738 | .nav-group { 739 | font-size: 14px; 740 | } 741 | 742 | .nav-group-item { 743 | padding: 2px 10px 2px 25px; 744 | display: block; 745 | color: #333; 746 | text-decoration: none; 747 | white-space: nowrap; 748 | overflow: hidden; 749 | text-overflow: ellipsis; 750 | } 751 | .nav-group-item:active, .nav-group-item.active { 752 | background-color: #dcdfe1; 753 | } 754 | .nav-group-item .icon { 755 | width: 19px; 756 | height: 18px; 757 | float: left; 758 | color: #737475; 759 | margin-top: -3px; 760 | margin-right: 7px; 761 | font-size: 18px; 762 | text-align: center; 763 | } 764 | 765 | .nav-group-title { 766 | margin: 0; 767 | padding: 10px 10px 2px; 768 | font-size: 12px; 769 | font-weight: 500; 770 | color: #666666; 771 | } 772 | 773 | @font-face { 774 | font-family: "photon-entypo"; 775 | src: url("../fonts/photon-entypo.eot"); 776 | src: url("../fonts/photon-entypo.eot?#iefix") format("eot"), url("../fonts/photon-entypo.woff") format("woff"), url("../fonts/photon-entypo.ttf") format("truetype"); 777 | font-weight: normal; 778 | font-style: normal; 779 | } 780 | .icon:before { 781 | position: relative; 782 | display: inline-block; 783 | font-family: "photon-entypo"; 784 | speak: none; 785 | font-size: 100%; 786 | font-style: normal; 787 | font-weight: normal; 788 | font-variant: normal; 789 | text-transform: none; 790 | line-height: 1; 791 | -webkit-font-smoothing: antialiased; 792 | -moz-osx-font-smoothing: grayscale; 793 | } 794 | 795 | .icon-note:before { 796 | content: '\e800'; 797 | } 798 | 799 | /* '' */ 800 | .icon-note-beamed:before { 801 | content: '\e801'; 802 | } 803 | 804 | /* '' */ 805 | .icon-music:before { 806 | content: '\e802'; 807 | } 808 | 809 | /* '' */ 810 | .icon-search:before { 811 | content: '\e803'; 812 | } 813 | 814 | /* '' */ 815 | .icon-flashlight:before { 816 | content: '\e804'; 817 | } 818 | 819 | /* '' */ 820 | .icon-mail:before { 821 | content: '\e805'; 822 | } 823 | 824 | /* '' */ 825 | .icon-heart:before { 826 | content: '\e806'; 827 | } 828 | 829 | /* '' */ 830 | .icon-heart-empty:before { 831 | content: '\e807'; 832 | } 833 | 834 | /* '' */ 835 | .icon-star:before { 836 | content: '\e808'; 837 | } 838 | 839 | /* '' */ 840 | .icon-star-empty:before { 841 | content: '\e809'; 842 | } 843 | 844 | /* '' */ 845 | .icon-user:before { 846 | content: '\e80a'; 847 | } 848 | 849 | /* '' */ 850 | .icon-users:before { 851 | content: '\e80b'; 852 | } 853 | 854 | /* '' */ 855 | .icon-user-add:before { 856 | content: '\e80c'; 857 | } 858 | 859 | /* '' */ 860 | .icon-video:before { 861 | content: '\e80d'; 862 | } 863 | 864 | /* '' */ 865 | .icon-picture:before { 866 | content: '\e80e'; 867 | } 868 | 869 | /* '' */ 870 | .icon-camera:before { 871 | content: '\e80f'; 872 | } 873 | 874 | /* '' */ 875 | .icon-layout:before { 876 | content: '\e810'; 877 | } 878 | 879 | /* '' */ 880 | .icon-menu:before { 881 | content: '\e811'; 882 | } 883 | 884 | /* '' */ 885 | .icon-check:before { 886 | content: '\e812'; 887 | } 888 | 889 | /* '' */ 890 | .icon-cancel:before { 891 | content: '\e813'; 892 | } 893 | 894 | /* '' */ 895 | .icon-cancel-circled:before { 896 | content: '\e814'; 897 | } 898 | 899 | /* '' */ 900 | .icon-cancel-squared:before { 901 | content: '\e815'; 902 | } 903 | 904 | /* '' */ 905 | .icon-plus:before { 906 | content: '\e816'; 907 | } 908 | 909 | /* '' */ 910 | .icon-plus-circled:before { 911 | content: '\e817'; 912 | } 913 | 914 | /* '' */ 915 | .icon-plus-squared:before { 916 | content: '\e818'; 917 | } 918 | 919 | /* '' */ 920 | .icon-minus:before { 921 | content: '\e819'; 922 | } 923 | 924 | /* '' */ 925 | .icon-minus-circled:before { 926 | content: '\e81a'; 927 | } 928 | 929 | /* '' */ 930 | .icon-minus-squared:before { 931 | content: '\e81b'; 932 | } 933 | 934 | /* '' */ 935 | .icon-help:before { 936 | content: '\e81c'; 937 | } 938 | 939 | /* '' */ 940 | .icon-help-circled:before { 941 | content: '\e81d'; 942 | } 943 | 944 | /* '' */ 945 | .icon-info:before { 946 | content: '\e81e'; 947 | } 948 | 949 | /* '' */ 950 | .icon-info-circled:before { 951 | content: '\e81f'; 952 | } 953 | 954 | /* '' */ 955 | .icon-back:before { 956 | content: '\e820'; 957 | } 958 | 959 | /* '' */ 960 | .icon-home:before { 961 | content: '\e821'; 962 | } 963 | 964 | /* '' */ 965 | .icon-link:before { 966 | content: '\e822'; 967 | } 968 | 969 | /* '' */ 970 | .icon-attach:before { 971 | content: '\e823'; 972 | } 973 | 974 | /* '' */ 975 | .icon-lock:before { 976 | content: '\e824'; 977 | } 978 | 979 | /* '' */ 980 | .icon-lock-open:before { 981 | content: '\e825'; 982 | } 983 | 984 | /* '' */ 985 | .icon-eye:before { 986 | content: '\e826'; 987 | } 988 | 989 | /* '' */ 990 | .icon-tag:before { 991 | content: '\e827'; 992 | } 993 | 994 | /* '' */ 995 | .icon-bookmark:before { 996 | content: '\e828'; 997 | } 998 | 999 | /* '' */ 1000 | .icon-bookmarks:before { 1001 | content: '\e829'; 1002 | } 1003 | 1004 | /* '' */ 1005 | .icon-flag:before { 1006 | content: '\e82a'; 1007 | } 1008 | 1009 | /* '' */ 1010 | .icon-thumbs-up:before { 1011 | content: '\e82b'; 1012 | } 1013 | 1014 | /* '' */ 1015 | .icon-thumbs-down:before { 1016 | content: '\e82c'; 1017 | } 1018 | 1019 | /* '' */ 1020 | .icon-download:before { 1021 | content: '\e82d'; 1022 | } 1023 | 1024 | /* '' */ 1025 | .icon-upload:before { 1026 | content: '\e82e'; 1027 | } 1028 | 1029 | /* '' */ 1030 | .icon-upload-cloud:before { 1031 | content: '\e82f'; 1032 | } 1033 | 1034 | /* '' */ 1035 | .icon-reply:before { 1036 | content: '\e830'; 1037 | } 1038 | 1039 | /* '' */ 1040 | .icon-reply-all:before { 1041 | content: '\e831'; 1042 | } 1043 | 1044 | /* '' */ 1045 | .icon-forward:before { 1046 | content: '\e832'; 1047 | } 1048 | 1049 | /* '' */ 1050 | .icon-quote:before { 1051 | content: '\e833'; 1052 | } 1053 | 1054 | /* '' */ 1055 | .icon-code:before { 1056 | content: '\e834'; 1057 | } 1058 | 1059 | /* '' */ 1060 | .icon-export:before { 1061 | content: '\e835'; 1062 | } 1063 | 1064 | /* '' */ 1065 | .icon-pencil:before { 1066 | content: '\e836'; 1067 | } 1068 | 1069 | /* '' */ 1070 | .icon-feather:before { 1071 | content: '\e837'; 1072 | } 1073 | 1074 | /* '' */ 1075 | .icon-print:before { 1076 | content: '\e838'; 1077 | } 1078 | 1079 | /* '' */ 1080 | .icon-retweet:before { 1081 | content: '\e839'; 1082 | } 1083 | 1084 | /* '' */ 1085 | .icon-keyboard:before { 1086 | content: '\e83a'; 1087 | } 1088 | 1089 | /* '' */ 1090 | .icon-comment:before { 1091 | content: '\e83b'; 1092 | } 1093 | 1094 | /* '' */ 1095 | .icon-chat:before { 1096 | content: '\e83c'; 1097 | } 1098 | 1099 | /* '' */ 1100 | .icon-bell:before { 1101 | content: '\e83d'; 1102 | } 1103 | 1104 | /* '' */ 1105 | .icon-attention:before { 1106 | content: '\e83e'; 1107 | } 1108 | 1109 | /* '' */ 1110 | .icon-alert:before { 1111 | content: '\e83f'; 1112 | } 1113 | 1114 | /* '' */ 1115 | .icon-vcard:before { 1116 | content: '\e840'; 1117 | } 1118 | 1119 | /* '' */ 1120 | .icon-address:before { 1121 | content: '\e841'; 1122 | } 1123 | 1124 | /* '' */ 1125 | .icon-location:before { 1126 | content: '\e842'; 1127 | } 1128 | 1129 | /* '' */ 1130 | .icon-map:before { 1131 | content: '\e843'; 1132 | } 1133 | 1134 | /* '' */ 1135 | .icon-direction:before { 1136 | content: '\e844'; 1137 | } 1138 | 1139 | /* '' */ 1140 | .icon-compass:before { 1141 | content: '\e845'; 1142 | } 1143 | 1144 | /* '' */ 1145 | .icon-cup:before { 1146 | content: '\e846'; 1147 | } 1148 | 1149 | /* '' */ 1150 | .icon-trash:before { 1151 | content: '\e847'; 1152 | } 1153 | 1154 | /* '' */ 1155 | .icon-doc:before { 1156 | content: '\e848'; 1157 | } 1158 | 1159 | /* '' */ 1160 | .icon-docs:before { 1161 | content: '\e849'; 1162 | } 1163 | 1164 | /* '' */ 1165 | .icon-doc-landscape:before { 1166 | content: '\e84a'; 1167 | } 1168 | 1169 | /* '' */ 1170 | .icon-doc-text:before { 1171 | content: '\e84b'; 1172 | } 1173 | 1174 | /* '' */ 1175 | .icon-doc-text-inv:before { 1176 | content: '\e84c'; 1177 | } 1178 | 1179 | /* '' */ 1180 | .icon-newspaper:before { 1181 | content: '\e84d'; 1182 | } 1183 | 1184 | /* '' */ 1185 | .icon-book-open:before { 1186 | content: '\e84e'; 1187 | } 1188 | 1189 | /* '' */ 1190 | .icon-book:before { 1191 | content: '\e84f'; 1192 | } 1193 | 1194 | /* '' */ 1195 | .icon-folder:before { 1196 | content: '\e850'; 1197 | } 1198 | 1199 | /* '' */ 1200 | .icon-archive:before { 1201 | content: '\e851'; 1202 | } 1203 | 1204 | /* '' */ 1205 | .icon-box:before { 1206 | content: '\e852'; 1207 | } 1208 | 1209 | /* '' */ 1210 | .icon-rss:before { 1211 | content: '\e853'; 1212 | } 1213 | 1214 | /* '' */ 1215 | .icon-phone:before { 1216 | content: '\e854'; 1217 | } 1218 | 1219 | /* '' */ 1220 | .icon-cog:before { 1221 | content: '\e855'; 1222 | } 1223 | 1224 | /* '' */ 1225 | .icon-tools:before { 1226 | content: '\e856'; 1227 | } 1228 | 1229 | /* '' */ 1230 | .icon-share:before { 1231 | content: '\e857'; 1232 | } 1233 | 1234 | /* '' */ 1235 | .icon-shareable:before { 1236 | content: '\e858'; 1237 | } 1238 | 1239 | /* '' */ 1240 | .icon-basket:before { 1241 | content: '\e859'; 1242 | } 1243 | 1244 | /* '' */ 1245 | .icon-bag:before { 1246 | content: '\e85a'; 1247 | } 1248 | 1249 | /* '' */ 1250 | .icon-calendar:before { 1251 | content: '\e85b'; 1252 | } 1253 | 1254 | /* '' */ 1255 | .icon-login:before { 1256 | content: '\e85c'; 1257 | } 1258 | 1259 | /* '' */ 1260 | .icon-logout:before { 1261 | content: '\e85d'; 1262 | } 1263 | 1264 | /* '' */ 1265 | .icon-mic:before { 1266 | content: '\e85e'; 1267 | } 1268 | 1269 | /* '' */ 1270 | .icon-mute:before { 1271 | content: '\e85f'; 1272 | } 1273 | 1274 | /* '' */ 1275 | .icon-sound:before { 1276 | content: '\e860'; 1277 | } 1278 | 1279 | /* '' */ 1280 | .icon-volume:before { 1281 | content: '\e861'; 1282 | } 1283 | 1284 | /* '' */ 1285 | .icon-clock:before { 1286 | content: '\e862'; 1287 | } 1288 | 1289 | /* '' */ 1290 | .icon-hourglass:before { 1291 | content: '\e863'; 1292 | } 1293 | 1294 | /* '' */ 1295 | .icon-lamp:before { 1296 | content: '\e864'; 1297 | } 1298 | 1299 | /* '' */ 1300 | .icon-light-down:before { 1301 | content: '\e865'; 1302 | } 1303 | 1304 | /* '' */ 1305 | .icon-light-up:before { 1306 | content: '\e866'; 1307 | } 1308 | 1309 | /* '' */ 1310 | .icon-adjust:before { 1311 | content: '\e867'; 1312 | } 1313 | 1314 | /* '' */ 1315 | .icon-block:before { 1316 | content: '\e868'; 1317 | } 1318 | 1319 | /* '' */ 1320 | .icon-resize-full:before { 1321 | content: '\e869'; 1322 | } 1323 | 1324 | /* '' */ 1325 | .icon-resize-small:before { 1326 | content: '\e86a'; 1327 | } 1328 | 1329 | /* '' */ 1330 | .icon-popup:before { 1331 | content: '\e86b'; 1332 | } 1333 | 1334 | /* '' */ 1335 | .icon-publish:before { 1336 | content: '\e86c'; 1337 | } 1338 | 1339 | /* '' */ 1340 | .icon-window:before { 1341 | content: '\e86d'; 1342 | } 1343 | 1344 | /* '' */ 1345 | .icon-arrow-combo:before { 1346 | content: '\e86e'; 1347 | } 1348 | 1349 | /* '' */ 1350 | .icon-down-circled:before { 1351 | content: '\e86f'; 1352 | } 1353 | 1354 | /* '' */ 1355 | .icon-left-circled:before { 1356 | content: '\e870'; 1357 | } 1358 | 1359 | /* '' */ 1360 | .icon-right-circled:before { 1361 | content: '\e871'; 1362 | } 1363 | 1364 | /* '' */ 1365 | .icon-up-circled:before { 1366 | content: '\e872'; 1367 | } 1368 | 1369 | /* '' */ 1370 | .icon-down-open:before { 1371 | content: '\e873'; 1372 | } 1373 | 1374 | /* '' */ 1375 | .icon-left-open:before { 1376 | content: '\e874'; 1377 | } 1378 | 1379 | /* '' */ 1380 | .icon-right-open:before { 1381 | content: '\e875'; 1382 | } 1383 | 1384 | /* '' */ 1385 | .icon-up-open:before { 1386 | content: '\e876'; 1387 | } 1388 | 1389 | /* '' */ 1390 | .icon-down-open-mini:before { 1391 | content: '\e877'; 1392 | } 1393 | 1394 | /* '' */ 1395 | .icon-left-open-mini:before { 1396 | content: '\e878'; 1397 | } 1398 | 1399 | /* '' */ 1400 | .icon-right-open-mini:before { 1401 | content: '\e879'; 1402 | } 1403 | 1404 | /* '' */ 1405 | .icon-up-open-mini:before { 1406 | content: '\e87a'; 1407 | } 1408 | 1409 | /* '' */ 1410 | .icon-down-open-big:before { 1411 | content: '\e87b'; 1412 | } 1413 | 1414 | /* '' */ 1415 | .icon-left-open-big:before { 1416 | content: '\e87c'; 1417 | } 1418 | 1419 | /* '' */ 1420 | .icon-right-open-big:before { 1421 | content: '\e87d'; 1422 | } 1423 | 1424 | /* '' */ 1425 | .icon-up-open-big:before { 1426 | content: '\e87e'; 1427 | } 1428 | 1429 | /* '' */ 1430 | .icon-down:before { 1431 | content: '\e87f'; 1432 | } 1433 | 1434 | /* '' */ 1435 | .icon-left:before { 1436 | content: '\e880'; 1437 | } 1438 | 1439 | /* '' */ 1440 | .icon-right:before { 1441 | content: '\e881'; 1442 | } 1443 | 1444 | /* '' */ 1445 | .icon-up:before { 1446 | content: '\e882'; 1447 | } 1448 | 1449 | /* '' */ 1450 | .icon-down-dir:before { 1451 | content: '\e883'; 1452 | } 1453 | 1454 | /* '' */ 1455 | .icon-left-dir:before { 1456 | content: '\e884'; 1457 | } 1458 | 1459 | /* '' */ 1460 | .icon-right-dir:before { 1461 | content: '\e885'; 1462 | } 1463 | 1464 | /* '' */ 1465 | .icon-up-dir:before { 1466 | content: '\e886'; 1467 | } 1468 | 1469 | /* '' */ 1470 | .icon-down-bold:before { 1471 | content: '\e887'; 1472 | } 1473 | 1474 | /* '' */ 1475 | .icon-left-bold:before { 1476 | content: '\e888'; 1477 | } 1478 | 1479 | /* '' */ 1480 | .icon-right-bold:before { 1481 | content: '\e889'; 1482 | } 1483 | 1484 | /* '' */ 1485 | .icon-up-bold:before { 1486 | content: '\e88a'; 1487 | } 1488 | 1489 | /* '' */ 1490 | .icon-down-thin:before { 1491 | content: '\e88b'; 1492 | } 1493 | 1494 | /* '' */ 1495 | .icon-left-thin:before { 1496 | content: '\e88c'; 1497 | } 1498 | 1499 | /* '' */ 1500 | .icon-right-thin:before { 1501 | content: '\e88d'; 1502 | } 1503 | 1504 | /* '' */ 1505 | .icon-up-thin:before { 1506 | content: '\e88e'; 1507 | } 1508 | 1509 | /* '' */ 1510 | .icon-ccw:before { 1511 | content: '\e88f'; 1512 | } 1513 | 1514 | /* '' */ 1515 | .icon-cw:before { 1516 | content: '\e890'; 1517 | } 1518 | 1519 | /* '' */ 1520 | .icon-arrows-ccw:before { 1521 | content: '\e891'; 1522 | } 1523 | 1524 | /* '' */ 1525 | .icon-level-down:before { 1526 | content: '\e892'; 1527 | } 1528 | 1529 | /* '' */ 1530 | .icon-level-up:before { 1531 | content: '\e893'; 1532 | } 1533 | 1534 | /* '' */ 1535 | .icon-shuffle:before { 1536 | content: '\e894'; 1537 | } 1538 | 1539 | /* '' */ 1540 | .icon-loop:before { 1541 | content: '\e895'; 1542 | } 1543 | 1544 | /* '' */ 1545 | .icon-switch:before { 1546 | content: '\e896'; 1547 | } 1548 | 1549 | /* '' */ 1550 | .icon-play:before { 1551 | content: '\e897'; 1552 | } 1553 | 1554 | /* '' */ 1555 | .icon-stop:before { 1556 | content: '\e898'; 1557 | } 1558 | 1559 | /* '' */ 1560 | .icon-pause:before { 1561 | content: '\e899'; 1562 | } 1563 | 1564 | /* '' */ 1565 | .icon-record:before { 1566 | content: '\e89a'; 1567 | } 1568 | 1569 | /* '' */ 1570 | .icon-to-end:before { 1571 | content: '\e89b'; 1572 | } 1573 | 1574 | /* '' */ 1575 | .icon-to-start:before { 1576 | content: '\e89c'; 1577 | } 1578 | 1579 | /* '' */ 1580 | .icon-fast-forward:before { 1581 | content: '\e89d'; 1582 | } 1583 | 1584 | /* '' */ 1585 | .icon-fast-backward:before { 1586 | content: '\e89e'; 1587 | } 1588 | 1589 | /* '' */ 1590 | .icon-progress-0:before { 1591 | content: '\e89f'; 1592 | } 1593 | 1594 | /* '' */ 1595 | .icon-progress-1:before { 1596 | content: '\e8a0'; 1597 | } 1598 | 1599 | /* '' */ 1600 | .icon-progress-2:before { 1601 | content: '\e8a1'; 1602 | } 1603 | 1604 | /* '' */ 1605 | .icon-progress-3:before { 1606 | content: '\e8a2'; 1607 | } 1608 | 1609 | /* '' */ 1610 | .icon-target:before { 1611 | content: '\e8a3'; 1612 | } 1613 | 1614 | /* '' */ 1615 | .icon-palette:before { 1616 | content: '\e8a4'; 1617 | } 1618 | 1619 | /* '' */ 1620 | .icon-list:before { 1621 | content: '\e8a5'; 1622 | } 1623 | 1624 | /* '' */ 1625 | .icon-list-add:before { 1626 | content: '\e8a6'; 1627 | } 1628 | 1629 | /* '' */ 1630 | .icon-signal:before { 1631 | content: '\e8a7'; 1632 | } 1633 | 1634 | /* '' */ 1635 | .icon-trophy:before { 1636 | content: '\e8a8'; 1637 | } 1638 | 1639 | /* '' */ 1640 | .icon-battery:before { 1641 | content: '\e8a9'; 1642 | } 1643 | 1644 | /* '' */ 1645 | .icon-back-in-time:before { 1646 | content: '\e8aa'; 1647 | } 1648 | 1649 | /* '' */ 1650 | .icon-monitor:before { 1651 | content: '\e8ab'; 1652 | } 1653 | 1654 | /* '' */ 1655 | .icon-mobile:before { 1656 | content: '\e8ac'; 1657 | } 1658 | 1659 | /* '' */ 1660 | .icon-network:before { 1661 | content: '\e8ad'; 1662 | } 1663 | 1664 | /* '' */ 1665 | .icon-cd:before { 1666 | content: '\e8ae'; 1667 | } 1668 | 1669 | /* '' */ 1670 | .icon-inbox:before { 1671 | content: '\e8af'; 1672 | } 1673 | 1674 | /* '' */ 1675 | .icon-install:before { 1676 | content: '\e8b0'; 1677 | } 1678 | 1679 | /* '' */ 1680 | .icon-globe:before { 1681 | content: '\e8b1'; 1682 | } 1683 | 1684 | /* '' */ 1685 | .icon-cloud:before { 1686 | content: '\e8b2'; 1687 | } 1688 | 1689 | /* '' */ 1690 | .icon-cloud-thunder:before { 1691 | content: '\e8b3'; 1692 | } 1693 | 1694 | /* '' */ 1695 | .icon-flash:before { 1696 | content: '\e8b4'; 1697 | } 1698 | 1699 | /* '' */ 1700 | .icon-moon:before { 1701 | content: '\e8b5'; 1702 | } 1703 | 1704 | /* '' */ 1705 | .icon-flight:before { 1706 | content: '\e8b6'; 1707 | } 1708 | 1709 | /* '' */ 1710 | .icon-paper-plane:before { 1711 | content: '\e8b7'; 1712 | } 1713 | 1714 | /* '' */ 1715 | .icon-leaf:before { 1716 | content: '\e8b8'; 1717 | } 1718 | 1719 | /* '' */ 1720 | .icon-lifebuoy:before { 1721 | content: '\e8b9'; 1722 | } 1723 | 1724 | /* '' */ 1725 | .icon-mouse:before { 1726 | content: '\e8ba'; 1727 | } 1728 | 1729 | /* '' */ 1730 | .icon-briefcase:before { 1731 | content: '\e8bb'; 1732 | } 1733 | 1734 | /* '' */ 1735 | .icon-suitcase:before { 1736 | content: '\e8bc'; 1737 | } 1738 | 1739 | /* '' */ 1740 | .icon-dot:before { 1741 | content: '\e8bd'; 1742 | } 1743 | 1744 | /* '' */ 1745 | .icon-dot-2:before { 1746 | content: '\e8be'; 1747 | } 1748 | 1749 | /* '' */ 1750 | .icon-dot-3:before { 1751 | content: '\e8bf'; 1752 | } 1753 | 1754 | /* '' */ 1755 | .icon-brush:before { 1756 | content: '\e8c0'; 1757 | } 1758 | 1759 | /* '' */ 1760 | .icon-magnet:before { 1761 | content: '\e8c1'; 1762 | } 1763 | 1764 | /* '' */ 1765 | .icon-infinity:before { 1766 | content: '\e8c2'; 1767 | } 1768 | 1769 | /* '' */ 1770 | .icon-erase:before { 1771 | content: '\e8c3'; 1772 | } 1773 | 1774 | /* '' */ 1775 | .icon-chart-pie:before { 1776 | content: '\e8c4'; 1777 | } 1778 | 1779 | /* '' */ 1780 | .icon-chart-line:before { 1781 | content: '\e8c5'; 1782 | } 1783 | 1784 | /* '' */ 1785 | .icon-chart-bar:before { 1786 | content: '\e8c6'; 1787 | } 1788 | 1789 | /* '' */ 1790 | .icon-chart-area:before { 1791 | content: '\e8c7'; 1792 | } 1793 | 1794 | /* '' */ 1795 | .icon-tape:before { 1796 | content: '\e8c8'; 1797 | } 1798 | 1799 | /* '' */ 1800 | .icon-graduation-cap:before { 1801 | content: '\e8c9'; 1802 | } 1803 | 1804 | /* '' */ 1805 | .icon-language:before { 1806 | content: '\e8ca'; 1807 | } 1808 | 1809 | /* '' */ 1810 | .icon-ticket:before { 1811 | content: '\e8cb'; 1812 | } 1813 | 1814 | /* '' */ 1815 | .icon-water:before { 1816 | content: '\e8cc'; 1817 | } 1818 | 1819 | /* '' */ 1820 | .icon-droplet:before { 1821 | content: '\e8cd'; 1822 | } 1823 | 1824 | /* '' */ 1825 | .icon-air:before { 1826 | content: '\e8ce'; 1827 | } 1828 | 1829 | /* '' */ 1830 | .icon-credit-card:before { 1831 | content: '\e8cf'; 1832 | } 1833 | 1834 | /* '' */ 1835 | .icon-floppy:before { 1836 | content: '\e8d0'; 1837 | } 1838 | 1839 | /* '' */ 1840 | .icon-clipboard:before { 1841 | content: '\e8d1'; 1842 | } 1843 | 1844 | /* '' */ 1845 | .icon-megaphone:before { 1846 | content: '\e8d2'; 1847 | } 1848 | 1849 | /* '' */ 1850 | .icon-database:before { 1851 | content: '\e8d3'; 1852 | } 1853 | 1854 | /* '' */ 1855 | .icon-drive:before { 1856 | content: '\e8d4'; 1857 | } 1858 | 1859 | /* '' */ 1860 | .icon-bucket:before { 1861 | content: '\e8d5'; 1862 | } 1863 | 1864 | /* '' */ 1865 | .icon-thermometer:before { 1866 | content: '\e8d6'; 1867 | } 1868 | 1869 | /* '' */ 1870 | .icon-key:before { 1871 | content: '\e8d7'; 1872 | } 1873 | 1874 | /* '' */ 1875 | .icon-flow-cascade:before { 1876 | content: '\e8d8'; 1877 | } 1878 | 1879 | /* '' */ 1880 | .icon-flow-branch:before { 1881 | content: '\e8d9'; 1882 | } 1883 | 1884 | /* '' */ 1885 | .icon-flow-tree:before { 1886 | content: '\e8da'; 1887 | } 1888 | 1889 | /* '' */ 1890 | .icon-flow-line:before { 1891 | content: '\e8db'; 1892 | } 1893 | 1894 | /* '' */ 1895 | .icon-flow-parallel:before { 1896 | content: '\e8dc'; 1897 | } 1898 | 1899 | /* '' */ 1900 | .icon-rocket:before { 1901 | content: '\e8dd'; 1902 | } 1903 | 1904 | /* '' */ 1905 | .icon-gauge:before { 1906 | content: '\e8de'; 1907 | } 1908 | 1909 | /* '' */ 1910 | .icon-traffic-cone:before { 1911 | content: '\e8df'; 1912 | } 1913 | 1914 | /* '' */ 1915 | .icon-cc:before { 1916 | content: '\e8e0'; 1917 | } 1918 | 1919 | /* '' */ 1920 | .icon-cc-by:before { 1921 | content: '\e8e1'; 1922 | } 1923 | 1924 | /* '' */ 1925 | .icon-cc-nc:before { 1926 | content: '\e8e2'; 1927 | } 1928 | 1929 | /* '' */ 1930 | .icon-cc-nc-eu:before { 1931 | content: '\e8e3'; 1932 | } 1933 | 1934 | /* '' */ 1935 | .icon-cc-nc-jp:before { 1936 | content: '\e8e4'; 1937 | } 1938 | 1939 | /* '' */ 1940 | .icon-cc-sa:before { 1941 | content: '\e8e5'; 1942 | } 1943 | 1944 | /* '' */ 1945 | .icon-cc-nd:before { 1946 | content: '\e8e6'; 1947 | } 1948 | 1949 | /* '' */ 1950 | .icon-cc-pd:before { 1951 | content: '\e8e7'; 1952 | } 1953 | 1954 | /* '' */ 1955 | .icon-cc-zero:before { 1956 | content: '\e8e8'; 1957 | } 1958 | 1959 | /* '' */ 1960 | .icon-cc-share:before { 1961 | content: '\e8e9'; 1962 | } 1963 | 1964 | /* '' */ 1965 | .icon-cc-remix:before { 1966 | content: '\e8ea'; 1967 | } 1968 | 1969 | /* '' */ 1970 | .icon-github:before { 1971 | content: '\e8eb'; 1972 | } 1973 | 1974 | /* '' */ 1975 | .icon-github-circled:before { 1976 | content: '\e8ec'; 1977 | } 1978 | 1979 | /* '' */ 1980 | .icon-flickr:before { 1981 | content: '\e8ed'; 1982 | } 1983 | 1984 | /* '' */ 1985 | .icon-flickr-circled:before { 1986 | content: '\e8ee'; 1987 | } 1988 | 1989 | /* '' */ 1990 | .icon-vimeo:before { 1991 | content: '\e8ef'; 1992 | } 1993 | 1994 | /* '' */ 1995 | .icon-vimeo-circled:before { 1996 | content: '\e8f0'; 1997 | } 1998 | 1999 | /* '' */ 2000 | .icon-twitter:before { 2001 | content: '\e8f1'; 2002 | } 2003 | 2004 | /* '' */ 2005 | .icon-twitter-circled:before { 2006 | content: '\e8f2'; 2007 | } 2008 | 2009 | /* '' */ 2010 | .icon-facebook:before { 2011 | content: '\e8f3'; 2012 | } 2013 | 2014 | /* '' */ 2015 | .icon-facebook-circled:before { 2016 | content: '\e8f4'; 2017 | } 2018 | 2019 | /* '' */ 2020 | .icon-facebook-squared:before { 2021 | content: '\e8f5'; 2022 | } 2023 | 2024 | /* '' */ 2025 | .icon-gplus:before { 2026 | content: '\e8f6'; 2027 | } 2028 | 2029 | /* '' */ 2030 | .icon-gplus-circled:before { 2031 | content: '\e8f7'; 2032 | } 2033 | 2034 | /* '' */ 2035 | .icon-pinterest:before { 2036 | content: '\e8f8'; 2037 | } 2038 | 2039 | /* '' */ 2040 | .icon-pinterest-circled:before { 2041 | content: '\e8f9'; 2042 | } 2043 | 2044 | /* '' */ 2045 | .icon-tumblr:before { 2046 | content: '\e8fa'; 2047 | } 2048 | 2049 | /* '' */ 2050 | .icon-tumblr-circled:before { 2051 | content: '\e8fb'; 2052 | } 2053 | 2054 | /* '' */ 2055 | .icon-linkedin:before { 2056 | content: '\e8fc'; 2057 | } 2058 | 2059 | /* '' */ 2060 | .icon-linkedin-circled:before { 2061 | content: '\e8fd'; 2062 | } 2063 | 2064 | /* '' */ 2065 | .icon-dribbble:before { 2066 | content: '\e8fe'; 2067 | } 2068 | 2069 | /* '' */ 2070 | .icon-dribbble-circled:before { 2071 | content: '\e8ff'; 2072 | } 2073 | 2074 | /* '' */ 2075 | .icon-stumbleupon:before { 2076 | content: '\e900'; 2077 | } 2078 | 2079 | /* '' */ 2080 | .icon-stumbleupon-circled:before { 2081 | content: '\e901'; 2082 | } 2083 | 2084 | /* '' */ 2085 | .icon-lastfm:before { 2086 | content: '\e902'; 2087 | } 2088 | 2089 | /* '' */ 2090 | .icon-lastfm-circled:before { 2091 | content: '\e903'; 2092 | } 2093 | 2094 | /* '' */ 2095 | .icon-rdio:before { 2096 | content: '\e904'; 2097 | } 2098 | 2099 | /* '' */ 2100 | .icon-rdio-circled:before { 2101 | content: '\e905'; 2102 | } 2103 | 2104 | /* '' */ 2105 | .icon-spotify:before { 2106 | content: '\e906'; 2107 | } 2108 | 2109 | /* '' */ 2110 | .icon-spotify-circled:before { 2111 | content: '\e907'; 2112 | } 2113 | 2114 | /* '' */ 2115 | .icon-qq:before { 2116 | content: '\e908'; 2117 | } 2118 | 2119 | /* '' */ 2120 | .icon-instagram:before { 2121 | content: '\e909'; 2122 | } 2123 | 2124 | /* '' */ 2125 | .icon-dropbox:before { 2126 | content: '\e90a'; 2127 | } 2128 | 2129 | /* '' */ 2130 | .icon-evernote:before { 2131 | content: '\e90b'; 2132 | } 2133 | 2134 | /* '' */ 2135 | .icon-flattr:before { 2136 | content: '\e90c'; 2137 | } 2138 | 2139 | /* '' */ 2140 | .icon-skype:before { 2141 | content: '\e90d'; 2142 | } 2143 | 2144 | /* '' */ 2145 | .icon-skype-circled:before { 2146 | content: '\e90e'; 2147 | } 2148 | 2149 | /* '' */ 2150 | .icon-renren:before { 2151 | content: '\e90f'; 2152 | } 2153 | 2154 | /* '' */ 2155 | .icon-sina-weibo:before { 2156 | content: '\e910'; 2157 | } 2158 | 2159 | /* '' */ 2160 | .icon-paypal:before { 2161 | content: '\e911'; 2162 | } 2163 | 2164 | /* '' */ 2165 | .icon-picasa:before { 2166 | content: '\e912'; 2167 | } 2168 | 2169 | /* '' */ 2170 | .icon-soundcloud:before { 2171 | content: '\e913'; 2172 | } 2173 | 2174 | /* '' */ 2175 | .icon-mixi:before { 2176 | content: '\e914'; 2177 | } 2178 | 2179 | /* '' */ 2180 | .icon-behance:before { 2181 | content: '\e915'; 2182 | } 2183 | 2184 | /* '' */ 2185 | .icon-google-circles:before { 2186 | content: '\e916'; 2187 | } 2188 | 2189 | /* '' */ 2190 | .icon-vkontakte:before { 2191 | content: '\e917'; 2192 | } 2193 | 2194 | /* '' */ 2195 | .icon-smashing:before { 2196 | content: '\e918'; 2197 | } 2198 | 2199 | /* '' */ 2200 | .icon-sweden:before { 2201 | content: '\e919'; 2202 | } 2203 | 2204 | /* '' */ 2205 | .icon-db-shape:before { 2206 | content: '\e91a'; 2207 | } 2208 | 2209 | /* '' */ 2210 | .icon-logo-db:before { 2211 | content: '\e91b'; 2212 | } 2213 | 2214 | /* '' */ 2215 | table { 2216 | width: 100%; 2217 | border: 0; 2218 | border-collapse: separate; 2219 | font-size: 12px; 2220 | text-align: left; 2221 | } 2222 | 2223 | thead { 2224 | background-color: #f5f5f4; 2225 | } 2226 | 2227 | tbody { 2228 | background-color: #fff; 2229 | } 2230 | 2231 | .table-striped tr:nth-child(even) { 2232 | background-color: #f5f5f4; 2233 | } 2234 | 2235 | tr:active, 2236 | .table-striped tr:active:nth-child(even) { 2237 | color: #fff; 2238 | background-color: #116cd6; 2239 | } 2240 | 2241 | thead tr:active { 2242 | color: #333; 2243 | background-color: #f5f5f4; 2244 | } 2245 | 2246 | th { 2247 | font-weight: normal; 2248 | border-right: 1px solid #ddd; 2249 | border-bottom: 1px solid #ddd; 2250 | } 2251 | 2252 | th, 2253 | td { 2254 | padding: 2px 15px; 2255 | white-space: nowrap; 2256 | overflow: hidden; 2257 | text-overflow: ellipsis; 2258 | } 2259 | th:last-child, 2260 | td:last-child { 2261 | border-right: 0; 2262 | } 2263 | 2264 | .tab-group { 2265 | margin-top: -1px; 2266 | display: flex; 2267 | border-top: 1px solid #989698; 2268 | border-bottom: 1px solid #989698; 2269 | } 2270 | 2271 | .tab-item { 2272 | position: relative; 2273 | flex: 1; 2274 | padding: 3px; 2275 | font-size: 12px; 2276 | text-align: center; 2277 | border-left: 1px solid #989698; 2278 | background-color: #b8b6b8; 2279 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #b8b6b8), color-stop(100%, #b0aeb0)); 2280 | background-image: -webkit-linear-gradient(top, #b8b6b8 0%, #b0aeb0 100%); 2281 | background-image: linear-gradient(to bottom, #b8b6b8 0%, #b0aeb0 100%); 2282 | } 2283 | .tab-item:first-child { 2284 | border-left: 0; 2285 | } 2286 | .tab-item.active { 2287 | background-color: #d4d2d4; 2288 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #d4d2d4), color-stop(100%, #cccacc)); 2289 | background-image: -webkit-linear-gradient(top, #d4d2d4 0%, #cccacc 100%); 2290 | background-image: linear-gradient(to bottom, #d4d2d4 0%, #cccacc 100%); 2291 | } 2292 | .tab-item .icon-close-tab { 2293 | position: absolute; 2294 | top: 50%; 2295 | left: 5px; 2296 | width: 15px; 2297 | height: 15px; 2298 | font-size: 15px; 2299 | line-height: 15px; 2300 | text-align: center; 2301 | color: #666; 2302 | opacity: 0; 2303 | transition: opacity .1s linear, background-color .1s linear; 2304 | border-radius: 3px; 2305 | transform: translateY(-50%); 2306 | z-index: 10; 2307 | } 2308 | .tab-item:after { 2309 | position: absolute; 2310 | top: 0; 2311 | right: 0; 2312 | bottom: 0; 2313 | left: 0; 2314 | content: ""; 2315 | background-color: rgba(0, 0, 0, 0.08); 2316 | opacity: 0; 2317 | transition: opacity .1s linear; 2318 | z-index: 1; 2319 | } 2320 | .tab-item:hover:not(.active):after { 2321 | opacity: 1; 2322 | } 2323 | .tab-item:hover .icon-close-tab { 2324 | opacity: 1; 2325 | } 2326 | .tab-item .icon-close-tab:hover { 2327 | background-color: rgba(0, 0, 0, 0.08); 2328 | } 2329 | 2330 | .tab-item-fixed { 2331 | flex: none; 2332 | padding: 3px 10px; 2333 | } 2334 | -------------------------------------------------------------------------------- /photon/css/photon.min.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8";/*! 2 | * ===================================================== 3 | * Photon v0.1.1 4 | * Copyright 2015 Connor Sears 5 | * Licensed under MIT (https://github.com/connors/proton/blob/master/LICENSE) 6 | * 7 | * v0.1.1 designed by @connors. 8 | * ===================================================== 9 | */audio,canvas,progress,sub,sup,video{vertical-align:baseline}body,html{height:100%}hr,html,label{overflow:hidden}.clearfix:after,.toolbar-actions:after,.toolbar:after{clear:both}*,img{-webkit-user-drag:text}.list-group *,.nav-group-item,h1,h2,h3,h4,h5,h6,label,td,th{white-space:nowrap;text-overflow:ellipsis}audio:not([controls]){display:none}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:36px}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative}sup{top:-.5em}.pane-group,.window{top:0;left:0;right:0}sub{bottom:-.25em}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}*{cursor:default;-webkit-user-select:none;-webkit-box-sizing:border-box;box-sizing:border-box}html{width:100%}body{padding:0;margin:0;font-family:system,-apple-system,".SFNSDisplay-Regular","Helvetica Neue",Helvetica,"Segoe UI",sans-serif;font-size:13px;line-height:1.6;color:#333;background-color:transparent}.btn-dropdown:after,.icon:before{font-family:photon-entypo}hr{margin:15px 0;background:0 0;border:0;border-bottom:1px solid #ddd}h1,h2,h3,h4,h5,h6{margin-top:20px;margin-bottom:10px;font-weight:500;overflow:hidden}.btn .icon,.toolbar-header .title{margin-top:1px}h2{font-size:30px}h3{font-size:24px}h4{font-size:18px}h5{font-size:14px}.btn,h6{font-size:12px}.window{position:absolute;bottom:0;display:flex;flex-direction:column;background-color:#fff}.window-content{position:relative;overflow-y:auto;display:flex;flex:1}.selectable-text{cursor:text;-webkit-user-select:text}.btn,.title{cursor:default}.text-center{text-align:center}.text-right{text-align:right}.text-left{text-align:left}.btn,.title{text-align:center}.pull-left{float:left}.pull-right{float:right}.padded{padding:10px}.padded-less{padding:5px}.padded-more{padding:20px}.padded-vertically{padding-top:10px;padding-bottom:10px}.padded-vertically-less{padding-top:5px;padding-bottom:5px}.padded-vertically-more{padding-top:20px;padding-bottom:20px}.padded-horizontally{padding-right:10px;padding-left:10px}.padded-horizontally-less{padding-right:5px;padding-left:5px}.padded-horizontally-more{padding-right:20px;padding-left:20px}.padded-top{padding-top:10px}.padded-top-less{padding-top:5px}.padded-top-more{padding-top:20px}.padded-bottom{padding-bottom:10px}.padded-bottom-less{padding-bottom:5px}.padded-bottom-more{padding-bottom:20px}.sidebar{background-color:#f5f5f4}.draggable{-webkit-app-region:drag}.btn,.btn-group{vertical-align:middle;-webkit-app-region:no-drag}.clearfix:after,.clearfix:before{display:table;content:" "}.btn{display:inline-block;padding:3px 8px;margin-bottom:0;line-height:1.4;white-space:nowrap;background-image:none;border:1px solid transparent;border-radius:4px;box-shadow:0 1px 1px rgba(0,0,0,.06)}.btn:focus{outline:0;box-shadow:none}.btn-mini{padding:2px 6px}.btn-large{padding:6px 12px}.btn-form{padding-right:20px;padding-left:20px}.btn-default{color:#333;background-color:#fcfcfc;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fcfcfc),color-stop(100%,#f1f1f1));background-image:-webkit-linear-gradient(top,#fcfcfc 0,#f1f1f1 100%);background-image:linear-gradient(to bottom,#fcfcfc 0,#f1f1f1 100%);border-color:#c2c0c2 #c2c0c2 #a19fa1}.btn-default:active{background-color:#ddd;background-image:none}.btn-negative,.btn-positive,.btn-primary,.btn-warning{color:#fff;text-shadow:0 1px 1px rgba(0,0,0,.1)}.btn-primary{border-color:#388df8 #388df8 #0866dc;background-color:#6eb4f7;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#6eb4f7),color-stop(100%,#1a82fb));background-image:-webkit-linear-gradient(top,#6eb4f7 0,#1a82fb 100%);background-image:linear-gradient(to bottom,#6eb4f7 0,#1a82fb 100%)}.btn-primary:active{background-color:#3e9bf4;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#3e9bf4),color-stop(100%,#0469de));background-image:-webkit-linear-gradient(top,#3e9bf4 0,#0469de 100%);background-image:linear-gradient(to bottom,#3e9bf4 0,#0469de 100%)}.btn-positive{border-color:#29a03b #29a03b #248b34;background-color:#5bd46d;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#5bd46d),color-stop(100%,#29a03b));background-image:-webkit-linear-gradient(top,#5bd46d 0,#29a03b 100%);background-image:linear-gradient(to bottom,#5bd46d 0,#29a03b 100%)}.btn-positive:active{background-color:#34c84a;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#34c84a),color-stop(100%,#248b34));background-image:-webkit-linear-gradient(top,#34c84a 0,#248b34 100%);background-image:linear-gradient(to bottom,#34c84a 0,#248b34 100%)}.btn-negative{border-color:#fb2f29 #fb2f29 #fb1710;background-color:#fd918d;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fd918d),color-stop(100%,#fb2f29));background-image:-webkit-linear-gradient(top,#fd918d 0,#fb2f29 100%);background-image:linear-gradient(to bottom,#fd918d 0,#fb2f29 100%)}.btn-negative:active{background-color:#fc605b;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fc605b),color-stop(100%,#fb1710));background-image:-webkit-linear-gradient(top,#fc605b 0,#fb1710 100%);background-image:linear-gradient(to bottom,#fc605b 0,#fb1710 100%)}.btn-warning{border-color:#fcaa0e #fcaa0e #ee9d02;background-color:#fece72;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fece72),color-stop(100%,#fcaa0e));background-image:-webkit-linear-gradient(top,#fece72 0,#fcaa0e 100%);background-image:linear-gradient(to bottom,#fece72 0,#fcaa0e 100%)}.btn-warning:active{background-color:#fdbc40;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fdbc40),color-stop(100%,#ee9d02));background-image:-webkit-linear-gradient(top,#fdbc40 0,#ee9d02 100%);background-image:linear-gradient(to bottom,#fdbc40 0,#ee9d02 100%)}.btn .icon{float:left;width:14px;height:14px;margin-bottom:1px;color:#737475;font-size:14px;line-height:1}.btn .icon-text{margin-right:5px}.btn-dropdown:after{margin-left:5px;content:""}.btn-group{position:relative;display:inline-block}.toolbar-actions:after,.toolbar-actions:before,.toolbar:after,.toolbar:before{display:table;content:" "}.btn-group .btn{position:relative;float:left}.btn-group .btn:active,.btn-group .btn:focus{z-index:2}.btn-group .btn.active{z-index:3}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-group>.btn:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group .btn+.btn{border-left:1px solid #c2c0c2}.btn-group .btn+.btn.active{border-left:0}.btn-group .active{color:#fff;border:1px solid transparent;background-color:#6d6c6d;background-image:none}.btn-group .active .icon{color:#fff}.toolbar{min-height:22px;box-shadow:inset 0 1px 0 #f5f4f5;background-color:#e8e6e8;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#e8e6e8),color-stop(100%,#d1cfd1));background-image:-webkit-linear-gradient(top,#e8e6e8 0,#d1cfd1 100%);background-image:linear-gradient(to bottom,#e8e6e8 0,#d1cfd1 100%)}.toolbar-header{border-bottom:1px solid #c2c0c2}.toolbar-footer{border-top:1px solid #c2c0c2;-webkit-app-region:drag}.title{margin:0;font-size:12px;font-weight:400;color:#555}.toolbar-borderless{border-top:0;border-bottom:0}.toolbar-actions{margin-top:4px;margin-bottom:3px;padding-right:3px;padding-left:3px;padding-bottom:3px;-webkit-app-region:drag}.form-control,label{display:inline-block;font-size:13px}.toolbar-actions>.btn,.toolbar-actions>.btn-group{margin-left:4px;margin-right:4px}label{margin-bottom:5px}input[type=search]{-webkit-appearance:textfield;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;line-height:normal}.checkbox,.form-group,.radio{margin-bottom:10px}.form-control{width:100%;min-height:25px;padding:5px 10px;line-height:1.6;background-color:#fff;border:1px solid #ddd;border-radius:4px;outline:0}.form-control:focus{border-color:#6db3fd;box-shadow:3px 3px 0 #6db3fd,-3px -3px 0 #6db3fd,-3px 3px 0 #6db3fd,3px -3px 0 #6db3fd}textarea{height:auto}.checkbox,.radio{position:relative;display:block;margin-top:10px}.checkbox label,.radio label{padding-left:20px;margin-bottom:0;font-weight:400}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-left:-20px;margin-top:4px}.form-actions .btn{margin-right:10px}.form-actions .btn:last-child{margin-right:0}.pane-group{position:absolute;bottom:0;display:flex}.icon:before,.pane,.tab-item{position:relative}.pane{overflow-y:auto;flex:1;border-left:1px solid #ddd}.list-group *,.media-body,.nav-group-item,td,th{overflow:hidden}.pane:first-child{border-left:0}.pane-sm{max-width:220px;min-width:150px}.pane-mini{width:80px;flex:none}.pane-one-fourth{width:25%;flex:none}.pane-one-third{width:33.3%}.img-circle{border-radius:50%}.img-rounded{border-radius:4px}.list-group{width:100%;list-style:none;margin:0;padding:0}.list-group *{margin:0}.list-group-item{padding:10px;font-size:12px;color:#414142;border-top:1px solid #ddd}.list-group-item:first-child{border-top:0}.list-group-item.active,.list-group-item.selected{color:#fff;background-color:#116cd6}.list-group-header{padding:10px}.media-object{margin-top:3px}.media-object.pull-left{margin-right:10px}.media-object.pull-right{margin-left:10px}.nav-group{font-size:14px}.nav-group-item{padding:2px 10px 2px 25px;display:block;color:#333;text-decoration:none}.nav-group-item.active,.nav-group-item:active{background-color:#dcdfe1}.nav-group-item .icon{width:19px;height:18px;float:left;color:#737475;margin-top:-3px;margin-right:7px;font-size:18px;text-align:center}.nav-group-title{margin:0;padding:10px 10px 2px;font-size:12px;font-weight:500;color:#666}.icon:before,th{font-weight:400}@font-face{font-family:photon-entypo;src:url(../fonts/photon-entypo.eot);src:url(../fonts/photon-entypo.eot?#iefix) format("eot"),url(../fonts/photon-entypo.woff) format("woff"),url(../fonts/photon-entypo.ttf) format("truetype");font-weight:400;font-style:normal}.icon:before{display:inline-block;speak:none;font-size:100%;font-style:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-note:before{content:'\e800'}.icon-note-beamed:before{content:'\e801'}.icon-music:before{content:'\e802'}.icon-search:before{content:'\e803'}.icon-flashlight:before{content:'\e804'}.icon-mail:before{content:'\e805'}.icon-heart:before{content:'\e806'}.icon-heart-empty:before{content:'\e807'}.icon-star:before{content:'\e808'}.icon-star-empty:before{content:'\e809'}.icon-user:before{content:'\e80a'}.icon-users:before{content:'\e80b'}.icon-user-add:before{content:'\e80c'}.icon-video:before{content:'\e80d'}.icon-picture:before{content:'\e80e'}.icon-camera:before{content:'\e80f'}.icon-layout:before{content:'\e810'}.icon-menu:before{content:'\e811'}.icon-check:before{content:'\e812'}.icon-cancel:before{content:'\e813'}.icon-cancel-circled:before{content:'\e814'}.icon-cancel-squared:before{content:'\e815'}.icon-plus:before{content:'\e816'}.icon-plus-circled:before{content:'\e817'}.icon-plus-squared:before{content:'\e818'}.icon-minus:before{content:'\e819'}.icon-minus-circled:before{content:'\e81a'}.icon-minus-squared:before{content:'\e81b'}.icon-help:before{content:'\e81c'}.icon-help-circled:before{content:'\e81d'}.icon-info:before{content:'\e81e'}.icon-info-circled:before{content:'\e81f'}.icon-back:before{content:'\e820'}.icon-home:before{content:'\e821'}.icon-link:before{content:'\e822'}.icon-attach:before{content:'\e823'}.icon-lock:before{content:'\e824'}.icon-lock-open:before{content:'\e825'}.icon-eye:before{content:'\e826'}.icon-tag:before{content:'\e827'}.icon-bookmark:before{content:'\e828'}.icon-bookmarks:before{content:'\e829'}.icon-flag:before{content:'\e82a'}.icon-thumbs-up:before{content:'\e82b'}.icon-thumbs-down:before{content:'\e82c'}.icon-download:before{content:'\e82d'}.icon-upload:before{content:'\e82e'}.icon-upload-cloud:before{content:'\e82f'}.icon-reply:before{content:'\e830'}.icon-reply-all:before{content:'\e831'}.icon-forward:before{content:'\e832'}.icon-quote:before{content:'\e833'}.icon-code:before{content:'\e834'}.icon-export:before{content:'\e835'}.icon-pencil:before{content:'\e836'}.icon-feather:before{content:'\e837'}.icon-print:before{content:'\e838'}.icon-retweet:before{content:'\e839'}.icon-keyboard:before{content:'\e83a'}.icon-comment:before{content:'\e83b'}.icon-chat:before{content:'\e83c'}.icon-bell:before{content:'\e83d'}.icon-attention:before{content:'\e83e'}.icon-alert:before{content:'\e83f'}.icon-vcard:before{content:'\e840'}.icon-address:before{content:'\e841'}.icon-location:before{content:'\e842'}.icon-map:before{content:'\e843'}.icon-direction:before{content:'\e844'}.icon-compass:before{content:'\e845'}.icon-cup:before{content:'\e846'}.icon-trash:before{content:'\e847'}.icon-doc:before{content:'\e848'}.icon-docs:before{content:'\e849'}.icon-doc-landscape:before{content:'\e84a'}.icon-doc-text:before{content:'\e84b'}.icon-doc-text-inv:before{content:'\e84c'}.icon-newspaper:before{content:'\e84d'}.icon-book-open:before{content:'\e84e'}.icon-book:before{content:'\e84f'}.icon-folder:before{content:'\e850'}.icon-archive:before{content:'\e851'}.icon-box:before{content:'\e852'}.icon-rss:before{content:'\e853'}.icon-phone:before{content:'\e854'}.icon-cog:before{content:'\e855'}.icon-tools:before{content:'\e856'}.icon-share:before{content:'\e857'}.icon-shareable:before{content:'\e858'}.icon-basket:before{content:'\e859'}.icon-bag:before{content:'\e85a'}.icon-calendar:before{content:'\e85b'}.icon-login:before{content:'\e85c'}.icon-logout:before{content:'\e85d'}.icon-mic:before{content:'\e85e'}.icon-mute:before{content:'\e85f'}.icon-sound:before{content:'\e860'}.icon-volume:before{content:'\e861'}.icon-clock:before{content:'\e862'}.icon-hourglass:before{content:'\e863'}.icon-lamp:before{content:'\e864'}.icon-light-down:before{content:'\e865'}.icon-light-up:before{content:'\e866'}.icon-adjust:before{content:'\e867'}.icon-block:before{content:'\e868'}.icon-resize-full:before{content:'\e869'}.icon-resize-small:before{content:'\e86a'}.icon-popup:before{content:'\e86b'}.icon-publish:before{content:'\e86c'}.icon-window:before{content:'\e86d'}.icon-arrow-combo:before{content:'\e86e'}.icon-down-circled:before{content:'\e86f'}.icon-left-circled:before{content:'\e870'}.icon-right-circled:before{content:'\e871'}.icon-up-circled:before{content:'\e872'}.icon-down-open:before{content:'\e873'}.icon-left-open:before{content:'\e874'}.icon-right-open:before{content:'\e875'}.icon-up-open:before{content:'\e876'}.icon-down-open-mini:before{content:'\e877'}.icon-left-open-mini:before{content:'\e878'}.icon-right-open-mini:before{content:'\e879'}.icon-up-open-mini:before{content:'\e87a'}.icon-down-open-big:before{content:'\e87b'}.icon-left-open-big:before{content:'\e87c'}.icon-right-open-big:before{content:'\e87d'}.icon-up-open-big:before{content:'\e87e'}.icon-down:before{content:'\e87f'}.icon-left:before{content:'\e880'}.icon-right:before{content:'\e881'}.icon-up:before{content:'\e882'}.icon-down-dir:before{content:'\e883'}.icon-left-dir:before{content:'\e884'}.icon-right-dir:before{content:'\e885'}.icon-up-dir:before{content:'\e886'}.icon-down-bold:before{content:'\e887'}.icon-left-bold:before{content:'\e888'}.icon-right-bold:before{content:'\e889'}.icon-up-bold:before{content:'\e88a'}.icon-down-thin:before{content:'\e88b'}.icon-left-thin:before{content:'\e88c'}.icon-right-thin:before{content:'\e88d'}.icon-up-thin:before{content:'\e88e'}.icon-ccw:before{content:'\e88f'}.icon-cw:before{content:'\e890'}.icon-arrows-ccw:before{content:'\e891'}.icon-level-down:before{content:'\e892'}.icon-level-up:before{content:'\e893'}.icon-shuffle:before{content:'\e894'}.icon-loop:before{content:'\e895'}.icon-switch:before{content:'\e896'}.icon-play:before{content:'\e897'}.icon-stop:before{content:'\e898'}.icon-pause:before{content:'\e899'}.icon-record:before{content:'\e89a'}.icon-to-end:before{content:'\e89b'}.icon-to-start:before{content:'\e89c'}.icon-fast-forward:before{content:'\e89d'}.icon-fast-backward:before{content:'\e89e'}.icon-progress-0:before{content:'\e89f'}.icon-progress-1:before{content:'\e8a0'}.icon-progress-2:before{content:'\e8a1'}.icon-progress-3:before{content:'\e8a2'}.icon-target:before{content:'\e8a3'}.icon-palette:before{content:'\e8a4'}.icon-list:before{content:'\e8a5'}.icon-list-add:before{content:'\e8a6'}.icon-signal:before{content:'\e8a7'}.icon-trophy:before{content:'\e8a8'}.icon-battery:before{content:'\e8a9'}.icon-back-in-time:before{content:'\e8aa'}.icon-monitor:before{content:'\e8ab'}.icon-mobile:before{content:'\e8ac'}.icon-network:before{content:'\e8ad'}.icon-cd:before{content:'\e8ae'}.icon-inbox:before{content:'\e8af'}.icon-install:before{content:'\e8b0'}.icon-globe:before{content:'\e8b1'}.icon-cloud:before{content:'\e8b2'}.icon-cloud-thunder:before{content:'\e8b3'}.icon-flash:before{content:'\e8b4'}.icon-moon:before{content:'\e8b5'}.icon-flight:before{content:'\e8b6'}.icon-paper-plane:before{content:'\e8b7'}.icon-leaf:before{content:'\e8b8'}.icon-lifebuoy:before{content:'\e8b9'}.icon-mouse:before{content:'\e8ba'}.icon-briefcase:before{content:'\e8bb'}.icon-suitcase:before{content:'\e8bc'}.icon-dot:before{content:'\e8bd'}.icon-dot-2:before{content:'\e8be'}.icon-dot-3:before{content:'\e8bf'}.icon-brush:before{content:'\e8c0'}.icon-magnet:before{content:'\e8c1'}.icon-infinity:before{content:'\e8c2'}.icon-erase:before{content:'\e8c3'}.icon-chart-pie:before{content:'\e8c4'}.icon-chart-line:before{content:'\e8c5'}.icon-chart-bar:before{content:'\e8c6'}.icon-chart-area:before{content:'\e8c7'}.icon-tape:before{content:'\e8c8'}.icon-graduation-cap:before{content:'\e8c9'}.icon-language:before{content:'\e8ca'}.icon-ticket:before{content:'\e8cb'}.icon-water:before{content:'\e8cc'}.icon-droplet:before{content:'\e8cd'}.icon-air:before{content:'\e8ce'}.icon-credit-card:before{content:'\e8cf'}.icon-floppy:before{content:'\e8d0'}.icon-clipboard:before{content:'\e8d1'}.icon-megaphone:before{content:'\e8d2'}.icon-database:before{content:'\e8d3'}.icon-drive:before{content:'\e8d4'}.icon-bucket:before{content:'\e8d5'}.icon-thermometer:before{content:'\e8d6'}.icon-key:before{content:'\e8d7'}.icon-flow-cascade:before{content:'\e8d8'}.icon-flow-branch:before{content:'\e8d9'}.icon-flow-tree:before{content:'\e8da'}.icon-flow-line:before{content:'\e8db'}.icon-flow-parallel:before{content:'\e8dc'}.icon-rocket:before{content:'\e8dd'}.icon-gauge:before{content:'\e8de'}.icon-traffic-cone:before{content:'\e8df'}.icon-cc:before{content:'\e8e0'}.icon-cc-by:before{content:'\e8e1'}.icon-cc-nc:before{content:'\e8e2'}.icon-cc-nc-eu:before{content:'\e8e3'}.icon-cc-nc-jp:before{content:'\e8e4'}.icon-cc-sa:before{content:'\e8e5'}.icon-cc-nd:before{content:'\e8e6'}.icon-cc-pd:before{content:'\e8e7'}.icon-cc-zero:before{content:'\e8e8'}.icon-cc-share:before{content:'\e8e9'}.icon-cc-remix:before{content:'\e8ea'}.icon-github:before{content:'\e8eb'}.icon-github-circled:before{content:'\e8ec'}.icon-flickr:before{content:'\e8ed'}.icon-flickr-circled:before{content:'\e8ee'}.icon-vimeo:before{content:'\e8ef'}.icon-vimeo-circled:before{content:'\e8f0'}.icon-twitter:before{content:'\e8f1'}.icon-twitter-circled:before{content:'\e8f2'}.icon-facebook:before{content:'\e8f3'}.icon-facebook-circled:before{content:'\e8f4'}.icon-facebook-squared:before{content:'\e8f5'}.icon-gplus:before{content:'\e8f6'}.icon-gplus-circled:before{content:'\e8f7'}.icon-pinterest:before{content:'\e8f8'}.icon-pinterest-circled:before{content:'\e8f9'}.icon-tumblr:before{content:'\e8fa'}.icon-tumblr-circled:before{content:'\e8fb'}.icon-linkedin:before{content:'\e8fc'}.icon-linkedin-circled:before{content:'\e8fd'}.icon-dribbble:before{content:'\e8fe'}.icon-dribbble-circled:before{content:'\e8ff'}.icon-stumbleupon:before{content:'\e900'}.icon-stumbleupon-circled:before{content:'\e901'}.icon-lastfm:before{content:'\e902'}.icon-lastfm-circled:before{content:'\e903'}.icon-rdio:before{content:'\e904'}.icon-rdio-circled:before{content:'\e905'}.icon-spotify:before{content:'\e906'}.icon-spotify-circled:before{content:'\e907'}.icon-qq:before{content:'\e908'}.icon-instagram:before{content:'\e909'}.icon-dropbox:before{content:'\e90a'}.icon-evernote:before{content:'\e90b'}.icon-flattr:before{content:'\e90c'}.icon-skype:before{content:'\e90d'}.icon-skype-circled:before{content:'\e90e'}.icon-renren:before{content:'\e90f'}.icon-sina-weibo:before{content:'\e910'}.icon-paypal:before{content:'\e911'}.icon-picasa:before{content:'\e912'}.icon-soundcloud:before{content:'\e913'}.icon-mixi:before{content:'\e914'}.icon-behance:before{content:'\e915'}.icon-google-circles:before{content:'\e916'}.icon-vkontakte:before{content:'\e917'}.icon-smashing:before{content:'\e918'}.icon-sweden:before{content:'\e919'}.icon-db-shape:before{content:'\e91a'}.icon-logo-db:before{content:'\e91b'}table{border-spacing:0;width:100%;border:0;border-collapse:separate;font-size:12px;text-align:left}.table-striped tr:nth-child(even),thead{background-color:#f5f5f4}tbody{background-color:#fff}.table-striped tr:active:nth-child(even),tr:active{color:#fff;background-color:#116cd6}thead tr:active{color:#333;background-color:#f5f5f4}th{border-right:1px solid #ddd;border-bottom:1px solid #ddd}td,th{padding:2px 15px}td:last-child,th:last-child{border-right:0}.tab-group{margin-top:-1px;display:flex;border-top:1px solid #989698;border-bottom:1px solid #989698}.tab-item{flex:1;padding:3px;font-size:12px;text-align:center;border-left:1px solid #989698;background-color:#b8b6b8;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#b8b6b8),color-stop(100%,#b0aeb0));background-image:-webkit-linear-gradient(top,#b8b6b8 0,#b0aeb0 100%);background-image:linear-gradient(to bottom,#b8b6b8 0,#b0aeb0 100%)}.tab-item:first-child{border-left:0}.tab-item.active{background-color:#d4d2d4;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#d4d2d4),color-stop(100%,#cccacc));background-image:-webkit-linear-gradient(top,#d4d2d4 0,#cccacc 100%);background-image:linear-gradient(to bottom,#d4d2d4 0,#cccacc 100%)}.tab-item .icon-close-tab:hover,.tab-item:after{background-color:rgba(0,0,0,.08)}.tab-item .icon-close-tab{position:absolute;top:50%;left:5px;width:15px;height:15px;font-size:15px;line-height:15px;text-align:center;color:#666;opacity:0;transition:opacity .1s linear,background-color .1s linear;border-radius:3px;transform:translateY(-50%);z-index:10}.tab-item:after{position:absolute;top:0;right:0;bottom:0;left:0;content:"";opacity:0;transition:opacity .1s linear;z-index:1}.tab-item:hover .icon-close-tab,.tab-item:hover:not(.active):after{opacity:1}.tab-item-fixed{flex:none;padding:3px 10px} -------------------------------------------------------------------------------- /photon/fonts/photon-entypo.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yasumichi/seapig/dd3cb12ca113ac8ba5db040d7af960398d82536f/photon/fonts/photon-entypo.eot -------------------------------------------------------------------------------- /photon/fonts/photon-entypo.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yasumichi/seapig/dd3cb12ca113ac8ba5db040d7af960398d82536f/photon/fonts/photon-entypo.ttf -------------------------------------------------------------------------------- /photon/fonts/photon-entypo.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yasumichi/seapig/dd3cb12ca113ac8ba5db040d7af960398d82536f/photon/fonts/photon-entypo.woff -------------------------------------------------------------------------------- /scripts/build-dep.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const extdir = "external"; 5 | 6 | const copyplan = [ 7 | // for ace 8 | { 9 | destdir: path.join(extdir, "ace"), 10 | srcfiles: [ 11 | 'ace-builds/LICENSE', 12 | 'ace-builds/src-min-noconflict/ace.js', 13 | 'ace-builds/src-min-noconflict/keybinding-emacs.js', 14 | 'ace-builds/src-min-noconflict/keybinding-sublime.js', 15 | 'ace-builds/src-min-noconflict/keybinding-vim.js', 16 | 'ace-builds/src-min-noconflict/mode-markdown.js', 17 | 'ace-builds/src-min-noconflict/theme-twilight.js', 18 | ] 19 | }, 20 | // for mathjax 21 | { 22 | destdir: path.join(extdir, "mathjax"), 23 | srcfiles: [ 24 | 'node_modules/mathjax/LICENSE', 25 | 'node_modules/mathjax/es5/tex-svg-full.js' 26 | ] 27 | }, 28 | // for mermaid 29 | { 30 | destdir: path.join(extdir, "mermaid"), 31 | srcfiles: [ 32 | 'node_modules/mermaid/LICENSE', 33 | 'node_modules/mermaid/dist/mermaid.min.js', 34 | ] 35 | }, 36 | // for mithril 37 | { 38 | destdir: path.join(extdir, "mithril"), 39 | srcfiles: [ 40 | 'node_modules/mithril/LICENSE', 41 | 'node_modules/mithril/mithril.min.js', 42 | ] 43 | } 44 | ]; 45 | 46 | copyplan.forEach((value) => { 47 | var destdir = value.destdir; 48 | var srcfiles = value.srcfiles; 49 | 50 | if ( fs.existsSync(destdir) == false ) { 51 | fs.mkdirSync(destdir, {recursive: true}); 52 | srcfiles.forEach((value) => { 53 | var destfile = path.join(destdir, path.basename(value)); 54 | fs.copyFileSync(value, destfile); 55 | }); 56 | } 57 | }); 58 | -------------------------------------------------------------------------------- /seapig.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yasumichi/seapig/dd3cb12ca113ac8ba5db040d7af960398d82536f/seapig.icns -------------------------------------------------------------------------------- /seapig.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yasumichi/seapig/dd3cb12ca113ac8ba5db040d7af960398d82536f/seapig.ico -------------------------------------------------------------------------------- /seapig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yasumichi/seapig/dd3cb12ca113ac8ba5db040d7af960398d82536f/seapig.png -------------------------------------------------------------------------------- /templates/github.css: -------------------------------------------------------------------------------- 1 | /* 2 | * https://gist.github.com/andyferra/2554919 3 | */ 4 | body { 5 | font-family: Helvetica, arial, sans-serif; 6 | font-size: 14px; 7 | line-height: 1.6; 8 | padding-top: 10px; 9 | padding-bottom: 10px; 10 | background-color: white; 11 | padding: 30px; } 12 | 13 | body > *:first-child { 14 | margin-top: 0 !important; } 15 | body > *:last-child { 16 | margin-bottom: 0 !important; } 17 | 18 | a { 19 | color: #4183C4; } 20 | a.absent { 21 | color: #cc0000; } 22 | a.anchor { 23 | display: block; 24 | padding-left: 30px; 25 | margin-left: -30px; 26 | cursor: pointer; 27 | position: absolute; 28 | top: 0; 29 | left: 0; 30 | bottom: 0; } 31 | 32 | h1, h2, h3, h4, h5, h6 { 33 | margin: 20px 0 10px; 34 | padding: 0; 35 | font-weight: bold; 36 | -webkit-font-smoothing: antialiased; 37 | cursor: text; 38 | position: relative; } 39 | 40 | h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, h5:hover a.anchor, h6:hover a.anchor { 41 | background: url("../../images/modules/styleguide/para.png") no-repeat 10px center; 42 | text-decoration: none; } 43 | 44 | h1 tt, h1 code { 45 | font-size: inherit; } 46 | 47 | h2 tt, h2 code { 48 | font-size: inherit; } 49 | 50 | h3 tt, h3 code { 51 | font-size: inherit; } 52 | 53 | h4 tt, h4 code { 54 | font-size: inherit; } 55 | 56 | h5 tt, h5 code { 57 | font-size: inherit; } 58 | 59 | h6 tt, h6 code { 60 | font-size: inherit; } 61 | 62 | h1 { 63 | font-size: 28px; 64 | color: black; } 65 | 66 | h2 { 67 | font-size: 24px; 68 | border-bottom: 1px solid #cccccc; 69 | color: black; } 70 | 71 | h3 { 72 | font-size: 18px; } 73 | 74 | h4 { 75 | font-size: 16px; } 76 | 77 | h5 { 78 | font-size: 14px; } 79 | 80 | h6 { 81 | color: #777777; 82 | font-size: 14px; } 83 | 84 | p, blockquote, ul, ol, dl, li, table, pre { 85 | margin: 15px 0; } 86 | 87 | body > h2:first-child { 88 | margin-top: 0; 89 | padding-top: 0; } 90 | body > h1:first-child { 91 | margin-top: 0; 92 | padding-top: 0; } 93 | body > h1:first-child + h2 { 94 | margin-top: 0; 95 | padding-top: 0; } 96 | body > h3:first-child, body > h4:first-child, body > h5:first-child, body > h6:first-child { 97 | margin-top: 0; 98 | padding-top: 0; } 99 | 100 | a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 { 101 | margin-top: 0; 102 | padding-top: 0; } 103 | 104 | h1 p, h2 p, h3 p, h4 p, h5 p, h6 p { 105 | margin-top: 0; } 106 | 107 | li p.first { 108 | display: inline-block; } 109 | 110 | ul, ol { 111 | padding-left: 30px; } 112 | 113 | ul :first-child, ol :first-child { 114 | margin-top: 0; } 115 | 116 | ul :last-child, ol :last-child { 117 | margin-bottom: 0; } 118 | 119 | dl { 120 | padding: 0; } 121 | dl dt { 122 | font-size: 14px; 123 | font-weight: bold; 124 | font-style: italic; 125 | padding: 0; 126 | margin: 15px 0 5px; } 127 | dl dt:first-child { 128 | padding: 0; } 129 | dl dt > :first-child { 130 | margin-top: 0; } 131 | dl dt > :last-child { 132 | margin-bottom: 0; } 133 | dl dd { 134 | margin: 0 0 15px; 135 | padding: 0 15px; } 136 | dl dd > :first-child { 137 | margin-top: 0; } 138 | dl dd > :last-child { 139 | margin-bottom: 0; } 140 | 141 | blockquote { 142 | border-left: 4px solid #dddddd; 143 | padding: 0 15px; 144 | color: #777777; } 145 | blockquote > :first-child { 146 | margin-top: 0; } 147 | blockquote > :last-child { 148 | margin-bottom: 0; } 149 | 150 | table { 151 | padding: 0; 152 | border-collapse: collapse; 153 | } 154 | table tr { 155 | border-top: 1px solid #cccccc; 156 | background-color: white; 157 | margin: 0; 158 | padding: 0; } 159 | table tr:nth-child(2n) { 160 | background-color: #f8f8f8; } 161 | table tr th { 162 | font-weight: bold; 163 | border: 1px solid #cccccc; 164 | text-align: left; 165 | margin: 0; 166 | padding: 6px 13px; } 167 | table tr td { 168 | border: 1px solid #cccccc; 169 | text-align: left; 170 | margin: 0; 171 | padding: 6px 13px; } 172 | table tr th :first-child, table tr td :first-child { 173 | margin-top: 0; } 174 | table tr th :last-child, table tr td :last-child { 175 | margin-bottom: 0; } 176 | 177 | img { 178 | max-width: 100%; } 179 | 180 | span.frame { 181 | display: block; 182 | overflow: hidden; } 183 | span.frame > span { 184 | border: 1px solid #dddddd; 185 | display: block; 186 | float: left; 187 | overflow: hidden; 188 | margin: 13px 0 0; 189 | padding: 7px; 190 | width: auto; } 191 | span.frame span img { 192 | display: block; 193 | float: left; } 194 | span.frame span span { 195 | clear: both; 196 | color: #333333; 197 | display: block; 198 | padding: 5px 0 0; } 199 | span.align-center { 200 | display: block; 201 | overflow: hidden; 202 | clear: both; } 203 | span.align-center > span { 204 | display: block; 205 | overflow: hidden; 206 | margin: 13px auto 0; 207 | text-align: center; } 208 | span.align-center span img { 209 | margin: 0 auto; 210 | text-align: center; } 211 | span.align-right { 212 | display: block; 213 | overflow: hidden; 214 | clear: both; } 215 | span.align-right > span { 216 | display: block; 217 | overflow: hidden; 218 | margin: 13px 0 0; 219 | text-align: right; } 220 | span.align-right span img { 221 | margin: 0; 222 | text-align: right; } 223 | span.float-left { 224 | display: block; 225 | margin-right: 13px; 226 | overflow: hidden; 227 | float: left; } 228 | span.float-left span { 229 | margin: 13px 0 0; } 230 | span.float-right { 231 | display: block; 232 | margin-left: 13px; 233 | overflow: hidden; 234 | float: right; } 235 | span.float-right > span { 236 | display: block; 237 | overflow: hidden; 238 | margin: 13px auto 0; 239 | text-align: right; } 240 | 241 | code, tt { 242 | margin: 0 2px; 243 | padding: 0 5px; 244 | white-space: nowrap; 245 | border: 1px solid #eaeaea; 246 | background-color: #f8f8f8; 247 | border-radius: 3px; } 248 | 249 | pre code { 250 | margin: 0; 251 | padding: 0; 252 | white-space: pre; 253 | border: none; 254 | background: transparent; } 255 | 256 | .highlight pre { 257 | background-color: #f8f8f8; 258 | border: 1px solid #cccccc; 259 | font-size: 13px; 260 | line-height: 19px; 261 | overflow: auto; 262 | padding: 6px 10px; 263 | border-radius: 3px; } 264 | 265 | pre { 266 | background-color: #f8f8f8; 267 | border: 1px solid #cccccc; 268 | font-size: 13px; 269 | line-height: 19px; 270 | overflow: auto; 271 | padding: 6px 10px; 272 | border-radius: 3px; } 273 | pre code, pre tt { 274 | background-color: transparent; 275 | border: none; } 276 | 277 | /* 278 | * from highlight.js 279 | */ 280 | 281 | /* 282 | 283 | github.com style (c) Vasily Polovnyov 284 | 285 | */ 286 | 287 | .hljs { 288 | display: block; 289 | overflow-x: auto; 290 | padding: 0.5em; 291 | color: #333; 292 | background: #f8f8f8; 293 | } 294 | 295 | .hljs-comment, 296 | .hljs-quote { 297 | color: #998; 298 | font-style: italic; 299 | } 300 | 301 | .hljs-keyword, 302 | .hljs-selector-tag, 303 | .hljs-subst { 304 | color: #333; 305 | font-weight: bold; 306 | } 307 | 308 | .hljs-number, 309 | .hljs-literal, 310 | .hljs-variable, 311 | .hljs-template-variable, 312 | .hljs-tag .hljs-attr { 313 | color: #008080; 314 | } 315 | 316 | .hljs-string, 317 | .hljs-doctag { 318 | color: #d14; 319 | } 320 | 321 | .hljs-title, 322 | .hljs-section, 323 | .hljs-selector-id { 324 | color: #900; 325 | font-weight: bold; 326 | } 327 | 328 | .hljs-subst { 329 | font-weight: normal; 330 | } 331 | 332 | .hljs-type, 333 | .hljs-class .hljs-title { 334 | color: #458; 335 | font-weight: bold; 336 | } 337 | 338 | .hljs-tag, 339 | .hljs-name, 340 | .hljs-attribute { 341 | color: #000080; 342 | font-weight: normal; 343 | } 344 | 345 | .hljs-regexp, 346 | .hljs-link { 347 | color: #009926; 348 | } 349 | 350 | .hljs-symbol, 351 | .hljs-bullet { 352 | color: #990073; 353 | } 354 | 355 | .hljs-built_in, 356 | .hljs-builtin-name { 357 | color: #0086b3; 358 | } 359 | 360 | .hljs-meta { 361 | color: #999; 362 | font-weight: bold; 363 | } 364 | 365 | .hljs-deletion { 366 | background: #fdd; 367 | } 368 | 369 | .hljs-addition { 370 | background: #dfd; 371 | } 372 | 373 | .hljs-emphasis { 374 | font-style: italic; 375 | } 376 | 377 | .hljs-strong { 378 | font-weight: bold; 379 | } 380 | 381 | /* 382 | * For task-list-item 383 | */ 384 | 385 | .task-list-item { 386 | list-style-type: none; 387 | } 388 | 389 | /* 390 | * Settings for PDF 391 | */ 392 | @media print { 393 | hr { 394 | visibility: hidden; 395 | page-break-after: always; 396 | } 397 | } 398 | -------------------------------------------------------------------------------- /templates/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/mathjax.md: -------------------------------------------------------------------------------- 1 | # test file for mathjax support 2 | 3 | Thanks for [@xolmon](https://qiita.com/xolmon/items/f581bf6e1dc5426c8853) 4 | 5 | ## Superscript 6 | 7 |
      8 | ```math
      9 | x^2
     10 | ```
     11 | 
    12 | ```math 13 | x^2 14 | ``` 15 | 16 | ## Subscript 17 | 18 |
     19 | ```math
     20 | x_2
     21 | ```
     22 | 
    23 | ```math 24 | x_2 25 | ``` 26 | 27 | ## Relation between energy and mass 28 | 29 |
     30 | ```math
     31 | E=mc^2
     32 | ```
     33 | 
    34 | ```math 35 | E=mc^2 36 | ``` 37 | 38 | ## Fraction 39 | 40 |
     41 | ```mathjax
     42 | \frac{1}{1-x^2}
     43 | ```
     44 | 
    45 | ```mathjax 46 | \frac{1}{1-x^2} 47 | ``` 48 | 49 | ## plus/minus and sqrt, over 50 | 51 |
     52 | ```mathjax
     53 | x = {-b \pm \sqrt{b^2-4ac} \over 2a}
     54 | ```
     55 | 
    56 | ```mathjax 57 | x = {-b \pm \sqrt{b^2-4ac} \over 2a} 58 | ``` 59 | 60 | ## Pi 61 | 62 |
     63 | ```math
     64 | \pi
     65 | ```
     66 | 
    67 | ```math 68 | \pi 69 | ``` 70 | 71 | ## Vector 72 | 73 |
     74 | ```math
     75 | \vec{a} = (a_1, a_2, \cdots, a_n)
     76 | ```
     77 | 
    78 | ```math 79 | \vec{a} = (a_1, a_2, \cdots, a_n) 80 | ``` 81 | 82 | ## Array 83 | 84 |
     85 | ```mathjax
     86 | A = \left(
     87 |     \begin{array}{ccc}
     88 |       1 & 2 & 3 \\
     89 |       4 & 5 & 6 \\
     90 |       7 & 8 & 9
     91 |     \end{array}
     92 |   \right)\\
     93 | A^T
     94 | ```
     95 | 
    96 | ```mathjax 97 | A = \left( 98 | \begin{array}{ccc} 99 | 1 & 2 & 3 \\ 100 | 4 & 5 & 6 \\ 101 | 7 & 8 & 9 102 | \end{array} 103 | \right)\\ 104 | A^T 105 | ``` 106 | 107 | ## Sum 108 | 109 |
    110 | ```mathjax
    111 | \sum_{n=1}^{100} x^2 \\
    112 | ```
    113 | 
    114 | ```mathjax 115 | \sum_{n=1}^{100} x^2 \\ 116 | ``` 117 | 118 |
    119 | ```mathjax
    120 | \sum_{n=1}^\infty\frac{1}{n^2}=\frac1{1^2}+\frac1{2^2}+\frac1{3^2}+\frac1{4^2}+\frac1{5^2}+\cdots
    121 | ```
    122 | 
    123 | ```mathjax 124 | \sum_{n=1}^\infty\frac{1}{n^2}=\frac1{1^2}+\frac1{2^2}+\frac1{3^2}+\frac1{4^2}+\frac1{5^2}+\cdots 125 | ``` 126 | 127 | ## Differential 128 | 129 |
    130 | ```math
    131 | \frac{(d^2y)}{dx^2}
    132 | ```
    133 | 
    134 | ```math 135 | \frac{(d^2y)}{dx^2} 136 | ``` 137 | 138 | ## Integral 139 | 140 |
    141 | ```math
    142 | \int f(x)dx
    143 | ```
    144 | 
    145 | ```math 146 | \int f(x)dx 147 | ``` 148 | 149 |
    150 | ```math
    151 | \int_1^\infty \frac{1}{x^2}dx
    152 | ```
    153 | 
    154 | ```math 155 | \int_1^\infty \frac{1}{x^2}dx 156 | ``` 157 | 158 | ## Limit 159 | 160 |
    161 | ```math
    162 | \lim_{x \to \infty} f(x)
    163 | ```
    164 | 
    165 | 166 | ```math 167 | \lim_{x \to \infty} f(x) 168 | ``` 169 | 170 | ## angle 171 | 172 |
    173 | ```math
    174 | 180^\circ
    175 | ```
    176 | 
    177 | ```math 178 | 180^\circ 179 | ``` 180 | 181 | ## Logarithm 182 | 183 |
    184 | ```math
    185 | log_e(x)
    186 | ```
    187 | 
    188 | 189 | ```math 190 | log_e(x) 191 | ``` 192 | 193 | ## Inequality 194 | 195 |
    196 | ```math
    197 | x\neq 0
    198 | ```
    199 | 
    200 | ```math 201 | x\neq 0 202 | ``` 203 | 204 |
    205 | ```math
    206 | 1 < x
    207 | ```
    208 | 
    209 | ```math 210 | 1 < x 211 | ``` 212 | 213 |
    214 | ```math
    215 | 1 \leq x
    216 | ```
    217 | 
    218 | ```math 219 | 1 \leq x 220 | ``` 221 | 222 |
    223 | ```math
    224 | \alpha \sim 1
    225 | ```
    226 | 
    227 | 228 | ```math 229 | \alpha \sim 1 230 | ``` 231 | 232 |
    233 | ```math
    234 | \beta \simeq 0
    235 | ```
    236 | 
    237 | 238 | ```math 239 | \beta \simeq 0 240 | ``` 241 | 242 |
    243 | ```math
    244 | \gamma \approx 10
    245 | ```
    246 | 
    247 | 248 | ```math 249 | \gamma \approx 10 250 | ``` 251 | 252 | ## Euler's formula 253 | 254 |
    255 | ```math
    256 | e^{i\theta}=\cos\theta+i\sin\theta
    257 | ```
    258 | 
    259 | ```math 260 | e^{i\theta}=\cos\theta+i\sin\theta 261 | ``` 262 | -------------------------------------------------------------------------------- /test/md2html.test.js: -------------------------------------------------------------------------------- 1 | /* for mermaid */ 2 | const jsdom = require("jsdom"); 3 | const { JSDOM } = jsdom; 4 | const { window } = new JSDOM(); 5 | global.window = window; 6 | global.SVGElement = window.SVGElement; 7 | 8 | var assert = require('assert'); 9 | const marked = require('marked'); 10 | const Md2Html = require('../js/md2html.js'); 11 | var md2html = new Md2Html(); 12 | 13 | describe('convert markdown', () => { 14 | it('convert normal syntax', () => { 15 | const header = "# Title"; 16 | const list = "- test"; 17 | const inlinecode = "``"; 18 | 19 | assert(md2html.convert(header) === marked(header)); 20 | assert(md2html.convert(list) === marked(list)); 21 | assert(md2html.convert(inlinecode) === marked(inlinecode)); 22 | }); 23 | 24 | it('convert multi byte heading', () => { 25 | const header = "# 漢字の題名"; 26 | const expect = '

    漢字の題名

    \n'; 27 | 28 | assert(md2html.convert(header) === expect); 29 | }); 30 | 31 | it('convert paragraph', () => { 32 | const markdown = "This is paragraph."; 33 | const expect = "

    This is paragraph.

    \n"; 34 | 35 | assert(md2html.convert(markdown) === expect); 36 | }); 37 | 38 | it('convert paragraph contains webview tag(test sanitize)', () => { 39 | const markdown = 'This is paragraph.This is contains webview.'; 40 | const expect = "

    This is paragraph.This is contains webview.

    \n"; 41 | 42 | assert(md2html.convert(markdown) === expect); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /test/mermaid.md: -------------------------------------------------------------------------------- 1 | # test file for mermaid rendering 2 | 3 | ```mermaid 4 | graph TD; 5 | A-->B; 6 | A-->C; 7 | B-->D; 8 | C-->D; 9 | ``` 10 | 11 | ```mermaid 12 | sequenceDiagram 13 | participant Alice 14 | participant Bob 15 | Alice->>John: Hello John, how are you? 16 | loop Healthcheck 17 | John->>John: Fight against hypochondria 18 | end 19 | Note right of John: Rational thoughts
    prevail! 20 | John-->>Alice: Great! 21 | John->>Bob: How about you? 22 | Bob-->>John: Jolly good! 23 | ``` 24 | 25 | ```mermaid 26 | gantt 27 | dateFormat YYYY-MM-DD 28 | title Adding GANTT diagram to mermaid 29 | excludes weekdays 2014-01-10 30 | 31 | section A section 32 | Completed task :done, des1, 2014-01-06,2014-01-08 33 | Active task :active, des2, 2014-01-09, 3d 34 | Future task : des3, after des2, 5d 35 | Future task2 : des4, after des3, 5d 36 | ``` 37 | 38 | ```mermaid 39 | classDiagram 40 | Class01 <|-- AveryLongClass : Cool 41 | Class03 *-- Class04 42 | Class05 o-- Class06 43 | Class07 .. Class08 44 | Class09 --> C2 : Where am i? 45 | Class09 --* C3 46 | Class09 --|> Class07 47 | Class07 : equals() 48 | Class07 : Object[] elementData 49 | Class01 : size() 50 | Class01 : int chimp 51 | Class01 : int gorilla 52 | Class08 <--> C2: Cool label 53 | ``` 54 | 55 | ```mermaid 56 | gitGraph: 57 | options 58 | { 59 | "nodeSpacing": 150, 60 | "nodeRadius": 10 61 | } 62 | end 63 | commit 64 | branch newbranch 65 | checkout newbranch 66 | commit 67 | commit 68 | checkout master 69 | commit 70 | commit 71 | merge newbranch 72 | ``` 73 | 74 | ```mermaid 75 | pie 76 | "Dogs" : 386 77 | "Cats" : 85 78 | "Rats" : 15 79 | ``` 80 | --------------------------------------------------------------------------------