├── .gitignore ├── LICENSE ├── README.md ├── gulpfile.js ├── package.json └── src ├── index.html └── static ├── css └── style.css ├── js └── app.js └── module ├── code-prettify ├── lang-apollo.js ├── lang-basic.js ├── lang-clj.js ├── lang-css.js ├── lang-dart.js ├── lang-erlang.js ├── lang-go.js ├── lang-hs.js ├── lang-lasso.js ├── lang-lisp.js ├── lang-llvm.js ├── lang-logtalk.js ├── lang-lua.js ├── lang-matlab.js ├── lang-ml.js ├── lang-mumps.js ├── lang-n.js ├── lang-pascal.js ├── lang-proto.js ├── lang-r.js ├── lang-rd.js ├── lang-rust.js ├── lang-scala.js ├── lang-sql.js ├── lang-swift.js ├── lang-tcl.js ├── lang-tex.js ├── lang-vb.js ├── lang-vhdl.js ├── lang-wiki.js ├── lang-xq.js ├── lang-yaml.js ├── prettify.css └── prettify.js └── html2canvas └── html2canvas.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | npm-debug.* 3 | 4 | sftp-config.json 5 | 6 | # Logs 7 | logs 8 | *.log 9 | 10 | # Compressed file 11 | *.min.js 12 | *.min.css 13 | 14 | # CDN config 15 | .cdnconf.json 16 | 17 | # Release data 18 | dist 19 | 20 | # Runtime data 21 | runtime/ 22 | pids 23 | *.pid 24 | *.seed 25 | 26 | # node-waf configuration 27 | .lock-wscript 28 | 29 | # Dependency directory 30 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 31 | node_modules/ 32 | 33 | # IDE config 34 | .idea 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Niklas von Hertzen 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Code to Image 2 | 3 | _Code to Image_ converts your blocks of code to a highlighted jpeg base64 image. And you can share it to any code-unfriendly website —— Such website doesn't support markdown or `
` tag or anything else that can make your post contains any blocks of code in it.
4 |
5 | It is much better than screen shot since you can pick a single image from **very large code files**. More than 40 programming languages can be highlighted and picked.
6 |
7 | ## Example
8 |
9 | [http://code2img.75team.com](http://code2img.75team.com/#)
10 |
11 | Paste blocks of code to textarea and **press Ctrl+D** to pick image.
12 |
13 | ## Installation
14 |
15 | ```bash
16 | git clone https://github.com/akira-cn/code-to-image.git
17 | cd code-to-image
18 | npm install
19 | ```
20 |
21 | ## Development
22 |
23 | ```bash
24 | npm start
25 | ```
26 |
27 | ## Compile & Release
28 |
29 | ```bash
30 | npm run compile
31 | ```
32 |
33 | ## Default languages
34 |
35 | Default languages included bash; C; C++; C#; HTML; Java; JavaScript; XML; Perl; Python; Ruby; PHP;
36 |
37 | ## Extensions
38 |
39 | Other languages are supported via extensions:
40 |
41 | [Apollo](http://code2img.test.h5jun.com/#apollo); [Basic](http://code2img.test.h5jun.com/#basic); [Clojure](http://code2img.test.h5jun.com/#clojure); [CSS](http://code2img.test.h5jun.com/#css); [Dart](http://code2img.test.h5jun.com/#dart); [Erlang](http://code2img.test.h5jun.com/#erlang); [Go](http://code2img.test.h5jun.com/#go); [Haskell](http://code2img.test.h5jun.com/#hs); [Lasso](http://code2img.test.h5jun.com/#lasso); [Lisp, Scheme](http://code2img.test.h5jun.com/#lisp); [Llvm](http://code2img.test.h5jun.com/#llvm); [Logtalk](http://code2img.test.h5jun.com/#logtalk); [Lua](http://code2img.test.h5jun.com/#lua); [Matlab](http://code2img.test.h5jun.com/#maltab); [MLs: F#, Ocaml,SML;](http://code2img.test.h5jun.com/#ml) [Mumps](http://code2img.test.h5jun.com/#mumps); [Nemerle](http://code2img.test.h5jun.com/#nemerle); [Pascal](http://code2img.test.h5jun.com/#pascal); [Protocol buffers](http://code2img.test.h5jun.com/#protocol); [R, S](http://code2img.test.h5jun.com/#r); [RD](http://code2img.test.h5jun.com/#rd); [Rust](http://code2img.test.h5jun.com/#rust); [Scala](http://code2img.test.h5jun.com/#scala); [SQL](http://code2img.test.h5jun.com/#sql); [Swift](http://code2img.test.h5jun.com/#swift); [TCL](http://code2img.test.h5jun.com/#tcl); [Latek](http://code2img.test.h5jun.com/#latek); [Visual Basic](http://code2img.test.h5jun.com/#vb); [VHDL](http://code2img.test.h5jun.com/#vhdl); [Wiki](http://code2img.test.h5jun.com/#wiki); [XQ](http://code2img.test.h5jun.com/#xq); [YAML](http://code2img.test.h5jun.com/#yaml)
42 |
43 | ## Thanks
44 |
45 | Thanks to [code-prettify](https://github.com/google/code-prettify) and [html2canvas](https://github.com/niklasvh/html2canvas).
46 |
47 | ## License (Multi-licensing)
48 |
49 | [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0) [LICENSE](LICENSE)
50 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var uglifyJS = require('uglify-js');
2 | var cleanCSS = require('clean-css');
3 | var fs = require('fs');
4 | var gulp = require('gulp');
5 | var through = require('through2');
6 |
7 | var config = JSON.parse(fs.readFileSync('./package.json'));
8 | var cdnconf, cdnBucket, cdnDomain;
9 |
10 | try{
11 | cdnconf = JSON.parse(fs.readFileSync('.cdnconf.json'));
12 |
13 | var qiniu = require('node-qiniu');
14 | qiniu.config(cdnconf);
15 |
16 | cdnBucket = require('node-qiniu').bucket(cdnconf.bucket);
17 | cdnDomain = cdnconf.domain;
18 | }catch(ex){
19 | cdnconf = null;
20 | }
21 |
22 | function compile(src){
23 |
24 | var query = require('path').parse(src);
25 |
26 | var name = query.name;
27 | var ext = query.ext;
28 |
29 | var path = srcToFilePath(src);
30 | var contents = '';
31 | var prePromise = Promise.resolve();
32 |
33 | if(ext === '.js'){
34 | console.log(path);
35 | contents = uglifyJS.minify(path).code;
36 | if(name === 'app'){
37 | var extensions = contents.match(/lang-[a-z]+?\.js/g);
38 | var promises = [];
39 |
40 | var prefix = '/static/module/code-prettify/';
41 |
42 | //console.log(extensions);
43 | extensions.forEach(function(extension){
44 | var src = prefix + extension;
45 | promises.push(compile(src).then(function(res){
46 | contents = contents.replace(extension, res);
47 | }));
48 | });
49 | prePromise = Promise.all(promises).then(function(){
50 | contents = contents.replace(prefix, '');
51 | });
52 | }
53 | }else if(ext === '.css'){
54 | var cssText = fs.readFileSync(path);
55 | contents = new cleanCSS().minify(cssText).styles;
56 | }
57 |
58 | var re = new RegExp(name + ext + '$');
59 | var compressed = name + '.min' + ext;
60 |
61 | path = path.replace(re, compressed);
62 |
63 | if(cdnBucket){
64 | return prePromise.then(function(){
65 | fs.writeFileSync(path, contents, 'utf-8');
66 |
67 | return new Promise(function(resolve, reject){
68 | require('checksum').file(path, function(err, sum){
69 | var cdnFile = '!' + sum.slice(0, 16) + '/' + compressed;
70 |
71 | cdnBucket.putFile(cdnFile, path, function(err, reply){
72 | if(!err){
73 | var url = cdnDomain +'/'+ reply.key;
74 | resolve(url);
75 | }else{
76 | reject(err);
77 | }
78 | });
79 | });
80 | });
81 | });
82 | }else{
83 | return prePromise.then(function(){
84 | fs.writeFileSync(path, contents, 'utf-8');
85 |
86 | return Promise.resolve(src.replace(re, compressed) + '?v=' + config.version);
87 | });
88 | }
89 | }
90 |
91 | function srcToFilePath(src){
92 | src = require('url').parse(src).pathname;
93 | return __dirname + '/src' + src;
94 | }
95 |
96 | gulp.task('resource', function() {
97 | gulp.src(['./src/**/*.min.js', './src/**/*.min.css'])
98 | .pipe(gulp.dest('./dist'));
99 | });
100 |
101 | gulp.task('default', function() {
102 | gulp.src(['./src/index.html'])
103 | .pipe(through.obj(function(file, encode, cb) {
104 | var contents = file.contents.toString(encode);
105 | var $ = require('cheerio').load(contents, {decodeEntities: false});
106 |
107 | var promises = [];
108 |
109 | var links = $('link');
110 | for(var i = 0; i < links.length; i++){
111 | var link = $(links[i]);
112 | if(link.attr('rel') === 'stylesheet'){
113 | var href = link.attr('href');
114 | if(/^\/static\//.test(href)){
115 | (function(link){
116 | promises.push(compile(href).then(function(res){
117 | link.attr('href', res);
118 | }).catch(function(err){
119 | console.log(err);
120 | }));
121 | })(link);
122 | }
123 | }
124 | }
125 |
126 | var scripts = $('script');
127 | for(var i = 0; i < scripts.length; i++){
128 | var s = $(scripts[i]);
129 |
130 | if(s.attr('type') == null
131 | || s.attr('type') === 'text/javascript'){
132 | var src = s.attr('src');
133 |
134 | if(src){
135 | if(/^\/static\//.test(src)){
136 | (function(s, src){
137 | promises.push(compile(src).then(function(res){
138 | s.attr('src', res);
139 | }).catch(function(err){
140 | console.log(err);
141 | }));
142 | })(s, src);
143 | }
144 | }
145 | }
146 | }
147 |
148 | Promise.all(promises).then(function(){
149 | contents = $.html();
150 |
151 | var HTMLMinifier = require('html-minifier').minify;
152 |
153 | var minified = HTMLMinifier(contents, {
154 | minifyCSS: true,
155 | minifyJS: true,
156 | collapseWhitespace: true,
157 | removeAttributeQuotes: true
158 | });
159 |
160 | file.contents = new Buffer(minified, encode);
161 |
162 | if(!cdnBucket) gulp.start('resource');
163 |
164 | cb(null, file, encode);
165 | });
166 |
167 | })).pipe(gulp.dest('./dist'));
168 | });
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "code-to-image",
3 | "version": "0.4.0",
4 | "description": "Convert blocks of code to a highlighted jpeg base64 image.",
5 | "main": "src/index.html",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "cd src && http-server -c-1",
9 | "compile": "rm -rf dist && gulp"
10 | },
11 | "keywords": [
12 | "code",
13 | "image",
14 | "base64",
15 | "jpeg",
16 | "html2canvas",
17 | "highlight"
18 | ],
19 | "devDependencies": {
20 | "http-server": "^0.9.0",
21 | "gulp": "~3.9.0",
22 | "through2": "~2.0.0",
23 | "cheerio": "~0.19.0",
24 | "uglify-js": "~2.6.0",
25 | "html-minifier": "~1.0.0",
26 | "clean-css": "~3.4.6",
27 | "node-qiniu": "6.2.0",
28 | "checksum": "~0.1.1"
29 | },
30 | "author": "akira-cn",
31 | "license": "Apache License 2.0"
32 | }
33 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Press Ctrl+D to get Image.
7 |
8 |
9 |
10 |
11 |
12 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/src/static/css/style.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | width: 100%;
3 | height: 100%;
4 | overflow-x: hidden;
5 | padding: 0;
6 | margin: 0;
7 | }
8 |
9 | textarea {
10 | width: 100%;
11 | height: 100%;
12 | font-size: 18px;
13 | padding: 5px 10px;
14 | }
15 |
16 | #nav {
17 | padding: 6px;
18 | line-height: 28px;
19 | }
20 |
21 | #nav img {
22 | vertical-align: middle;
23 | cursor: pointer;
24 | margin: 0 10px 6px 0;
25 | }
26 |
27 | #nav a,
28 | #nav label {
29 | text-decoration: none;
30 | margin: 0 5px;
31 | }
32 |
33 | #nav label {
34 | cursor: pointer;
35 | user-select: none;
36 | }
37 |
38 | /*github stars*/
39 | #nav iframe {
40 | position: relative;
41 | margin-left: 10px;
42 | vertical-align: middle;
43 | }
44 |
45 | ul.languages {
46 | margin-right: 20px;
47 | }
48 |
49 | ul.settings,
50 | ul.languages {
51 | padding: 0;
52 | font-size: 0;
53 | display: inline;
54 | }
55 |
56 | ul.languages li,
57 | ul.settings li {
58 | font-size: 16px;
59 | display: inline-block;
60 | }
61 |
62 | ul.languages.lang-default a[data-lang=default],
63 | ul.languages.lang-css a[data-lang=css],
64 | ul.languages.lang-erlang a[data-lang=erlang],
65 | ul.languages.lang-go a[data-lang=go],
66 | ul.languages.lang-haskell a[data-lang=haskell],
67 | ul.languages.lang-lisp a[data-lang=lisp],
68 | ul.languages.lang-lua a[data-lang=lua],
69 | ul.languages.lang-sql a[data-lang=sql],
70 | ul.languages.lang-swift a[data-lang=swift]
71 | {
72 | font-size: 20px;
73 | }
74 |
75 | ul.settings li:not(:first-child) {
76 | border-left: solid 1px #333;
77 | padding-left: 5px;
78 | }
79 |
80 | ul.settings input {
81 | display: none;
82 | }
83 |
84 | ul.settings input:checked+label {
85 | color: #f00;
86 | }
87 |
88 | #code {
89 | /*width: 1280px;*/
90 | min-width: 360px;
91 | position: absolute;
92 | font-size: 36px;
93 | left: 0;
94 | top: 0;
95 | z-index: 99;
96 | background-color: #fff;
97 | }
98 |
99 | #code pre.wrap{
100 | white-space: pre-wrap;
101 | word-wrap: break-word;
102 | }
103 |
104 | #code pre.nowrap{
105 | white-space: pre;
106 | width: 100%;
107 | }
108 |
109 | #code pre {
110 | margin: 0;
111 | padding: 0;
112 | }
113 |
114 | #code pre.w1280{
115 | min-width: 1280px;
116 | font-size: 36px;
117 | }
118 |
119 | #code pre.w720{
120 | min-width: 720px;
121 | font-size: 20px;
122 | }
123 |
124 | #code pre.w480{
125 | min-width: 480px;
126 | font-size: 14px;
127 | }
128 |
129 | #code pre.w1280.wrap{
130 | width: 1280px;
131 | }
132 |
133 | #code pre.w720.wrap{
134 | width: 720px;
135 | }
136 |
137 | #code pre.w480.wrap{
138 | width: 480px;
139 | }
140 |
141 | #code pre code{
142 | margin: 0.5em;
143 | display: inline-block;
144 | }
145 |
146 | #code div {
147 | background: rgba(0,0,0,0.5);
148 | position: absolute;
149 | display: block;
150 | }
151 |
152 | #code a.img img {
153 | position: absolute;
154 | top: 50%;
155 | left: 50%;
156 | transform: translate(-50%, -50%);
157 | }
158 |
159 | #code div a.close {
160 | color: white;
161 | position: absolute;
162 | right: 10px;
163 | top: 10px;
164 | cursor: pointer;
165 | }
--------------------------------------------------------------------------------
/src/static/js/app.js:
--------------------------------------------------------------------------------
1 | /* global jQuery, html2canvas, PR*/
2 |
3 | (function(html2canvas, PR){'use strict'
4 | var hash = location.hash.slice(1).toLowerCase(),
5 | lang;
6 |
7 | const langEl = document.querySelector('#nav .languages');
8 |
9 | if(hash){
10 | lang = hash;
11 | }
12 |
13 | const srcMap = {
14 | 'apollo': 'lang-apollo.js',
15 | 'basic': 'lang-basic.js',
16 | 'clojure': 'lang-clj.js',
17 | 'css': 'lang-css.js',
18 | 'dart': 'lang-dart.js',
19 | 'erlang': 'lang-erlang.js',
20 | 'go': 'lang-go.js',
21 | 'haskell': 'lang-hs.js',
22 | 'lasso': 'lang-lasso.js',
23 | 'lisp': 'lang-lisp.js',
24 | 'scheme': 'lang-lisp.js',
25 | 'llvm': 'lang-llvm.js',
26 | 'logtalk': 'lang-logtalk.js',
27 | 'lua': 'lang-lua.js',
28 | 'matlab': 'lang-matlab.js',
29 | 'ml': 'lang-ml.js',
30 | 'mumps': 'lang-mumps.js',
31 | 'nemerle': 'lang-n.js',
32 | 'pascal': 'lang-pascal.js',
33 | 'protocol': 'lang-proto.js',
34 | 'r': 'lang-r.js',
35 | 'rd': 'lang-rd.js',
36 | 'rust': 'lang-rust.js',
37 | 'scala': 'lang-scala.js',
38 | 'sql': 'lang-sql.js',
39 | 'swift': 'lang-swift.js',
40 | 'tcl': 'lang-tcl.js',
41 | 'latek': 'lang-tex.js',
42 | 'vb': 'lang-vb.js',
43 | 'vhdl': 'lang-vhdl.js',
44 | 'wiki': 'lang-wiki.js',
45 | 'xq': 'lang-xq.js',
46 | 'yaml': 'lang-yaml.js'
47 | };
48 |
49 | function loadPlugin(lang){
50 | var js = srcMap[lang.toLowerCase()];
51 |
52 | if(typeof js === 'string'){
53 | var script = document.createElement('script');
54 | script.src = '/static/module/code-prettify/' + js;
55 | document.body.appendChild(script);
56 | }
57 |
58 | langEl.className = 'languages lang-' + lang;
59 |
60 | //only to load js file once.
61 | srcMap[lang] = true;
62 | }
63 |
64 | if(lang) loadPlugin(lang);
65 |
66 | langEl.addEventListener('click', function(evt){
67 | var target = evt.target;
68 | var _lang = target.dataset.lang;
69 |
70 | if(target.tagName === 'A' && _lang !== 'more'){
71 | lang = _lang;
72 | if(lang === 'default') lang = '';
73 | if(lang) loadPlugin(lang);
74 | else langEl.className = 'languages lang-default';
75 | }
76 | });
77 |
78 |
79 | const codeEl = document.getElementById('code');
80 | const textCodeEl = document.getElementById('text-code');
81 |
82 | const settingVersion = '1.0';
83 |
84 | function loadSettings(){
85 | var settings = localStorage.getItem('settings') || {};
86 |
87 | if(typeof settings === 'string'){
88 | try{
89 | settings = JSON.parse(settings);
90 | document.querySelector('input#setting-theme-' + settings.theme).checked = 'checked';
91 | document.querySelector('input#setting-width-' + settings.width).checked = 'checked';
92 | document.querySelector('input#setting-format-' + settings.format).checked = 'checked';
93 | }catch(ex){
94 | console.error('settings loaded failed! ' + ex.message);
95 | settings = {};
96 | }
97 | }
98 | }
99 |
100 | loadSettings();
101 |
102 | function generateCode(text){
103 |
104 | function parseProps(propStr){
105 | var props = propStr.trim().split(';');
106 | var ret = {};
107 |
108 | for(var i = 0; i < props.length; i++){
109 | if(props[i]){
110 | var pair = props[i].split(':');
111 | ret[pair[0].trim()] = pair[1].trim();
112 | }
113 | }
114 | return ret;
115 | }
116 |
117 | var codeClass = 'prettyprint';
118 |
119 | if(lang){
120 | codeClass += ' lang-' + lang;
121 | }
122 |
123 | var settings = {
124 | theme : document.querySelector('input[name="setting-theme"]:checked').value,
125 | width: document.querySelector('input[name="setting-width"]:checked').value,
126 | format: document.querySelector('input[name="setting-format"]:checked').value
127 | };
128 |
129 | localStorage.setItem('settings', JSON.stringify(settings));
130 |
131 | codeEl.innerHTML = '' + text.replace(//g,'>') + '
';
132 |
133 | PR.prettyPrint();
134 |
135 | setTimeout(function(){
136 | var canvas = document.createElement('canvas');
137 | var context = canvas.getContext('2d');
138 |
139 | html2canvas(codeEl, {
140 | canvas: canvas,
141 | onrendered: function(canvas) {
142 | var img = new Image();
143 | img.src = canvas.toDataURL('image/jpeg');
144 |
145 | Object.assign(img.style, {
146 | 'max-width': '100%',
147 | 'max-height': '100%',
148 | 'zoom': Math.min(1.0, Math.max(0.5, 480 / img.width))
149 | });
150 |
151 | var a = document.createElement('a');
152 | a.href = img.src;
153 | a.className = 'img';
154 | a.appendChild(img);
155 |
156 | var container = document.createElement('div');
157 | container.appendChild(a);
158 |
159 | var closeBtn = document.createElement('a');
160 | closeBtn.className = 'close';
161 | closeBtn.innerHTML = 'X';
162 | container.appendChild(closeBtn);
163 |
164 | codeEl.innerHTML = '';
165 | codeEl.style.zoom = '1.0';
166 | codeEl.appendChild(container);
167 |
168 | closeBtn.addEventListener('click', function(){
169 | codeEl.innerHTML = '';
170 | });
171 |
172 | Object.assign(container.style, {
173 | width: document.documentElement.clientWidth + 'px',
174 | height: document.documentElement.clientHeight + 'px'
175 | });
176 | }
177 | });
178 | }, 0);
179 | }
180 |
181 | const codeImgEl = document.querySelector('#nav img');
182 |
183 | codeImgEl.addEventListener('click', function(){
184 | var text = textCodeEl.value;
185 | generateCode(text || 'Paste your code first!');
186 | });
187 |
188 | textCodeEl.addEventListener('keydown', function(evt){
189 | var keyCode = evt.keyCode;
190 | var target = evt.target;
191 |
192 | if(keyCode === 68 && evt.ctrlKey){
193 | evt.preventDefault(); //prevent deletion
194 | return;
195 | }
196 | if(keyCode !== 9 && keyCode !== 13 & keyCode !== 221) return;
197 |
198 | var text = target.value;
199 | var start = target.selectionStart;
200 | var end = target.selectionEnd;
201 |
202 | if(keyCode === 9) { //handle tab
203 | evt.preventDefault();
204 |
205 | // set textarea value to: text before caret + tab + text after caret
206 | target.value = text.substring(0, start)
207 | + ' '
208 | + text.substring(end);
209 |
210 | // put caret at right position again
211 | target.selectionStart = target.selectionEnd = start + 4;
212 | }else if(keyCode === 13){ //handle enter
213 | evt.preventDefault();
214 |
215 | var lines = text.substring(0, start).split('\n');
216 | var currentLine = lines[lines.length - 1];
217 | var spaces = (/^\s+/.exec(currentLine) || [''])[0];
218 |
219 | target.value = text.substring(0, start)
220 | + '\n' + spaces
221 | + text.substring(end);
222 |
223 | target.selectionStart = target.selectionEnd = start + spaces.length + 1;
224 | }else if(keyCode === 221){ //handle }
225 | evt.preventDefault();
226 |
227 | var lines = text.substring(0, start).split('\n');
228 | var currentLine = lines[lines.length - 1];
229 | var spaces = (/^\s+$/.exec(currentLine) || [''])[0];
230 | var backspace = 0;
231 |
232 | if(spaces){
233 | backspace = Math.min(spaces.length, 4);
234 | spaces = spaces.slice(0, -4);
235 | }
236 |
237 | target.value = text.substring(0, start).replace(/^\s+$/m, spaces)
238 | + '}'
239 | + text.substring(end);
240 |
241 | target.selectionStart = target.selectionEnd = start - backspace + 1;
242 | }
243 | });
244 |
245 | window.addEventListener('keydown', function(evt){
246 | if(evt.ctrlKey && evt.keyCode === 68){
247 | var text = textCodeEl.value;
248 | generateCode(text || 'Paste your code first!');
249 | }else{
250 | if(evt.keyCode === 27){
251 | codeEl.innerHTML = '';
252 | codeEl.style.zoom = '';
253 | }
254 | }
255 | });
256 |
257 | })(html2canvas, PR);
258 |
--------------------------------------------------------------------------------
/src/static/module/code-prettify/lang-apollo.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright (C) 2009 Onno Hommes.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /**
19 | * @fileoverview
20 | * Registers a language handler for the AGC/AEA Assembly Language as described
21 | * at http://virtualagc.googlecode.com
22 | *
23 | * This file could be used by goodle code to allow syntax highlight for
24 | * Virtual AGC SVN repository or if you don't want to commonize
25 | * the header for the agc/aea html assembly listing.
26 | *
27 | * @author ohommes@alumni.cmu.edu
28 | */
29 |
30 | PR['registerLangHandler'](
31 | PR['createSimpleLexer'](
32 | [
33 | // A line comment that starts with ;
34 | [PR['PR_COMMENT'], /^#[^\r\n]*/, null, '#'],
35 | // Whitespace
36 | [PR['PR_PLAIN'], /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'],
37 | // A double quoted, possibly multi-line, string.
38 | [PR['PR_STRING'], /^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/, null, '"']
39 | ],
40 | [
41 | [PR['PR_KEYWORD'], /^(?:ADS|AD|AUG|BZF|BZMF|CAE|CAF|CA|CCS|COM|CS|DAS|DCA|DCOM|DCS|DDOUBL|DIM|DOUBLE|DTCB|DTCF|DV|DXCH|EDRUPT|EXTEND|INCR|INDEX|NDX|INHINT|LXCH|MASK|MSK|MP|MSU|NOOP|OVSK|QXCH|RAND|READ|RELINT|RESUME|RETURN|ROR|RXOR|SQUARE|SU|TCR|TCAA|OVSK|TCF|TC|TS|WAND|WOR|WRITE|XCH|XLQ|XXALQ|ZL|ZQ|ADD|ADZ|SUB|SUZ|MPY|MPR|MPZ|DVP|COM|ABS|CLA|CLZ|LDQ|STO|STQ|ALS|LLS|LRS|TRA|TSQ|TMI|TOV|AXT|TIX|DLY|INP|OUT)\s/,null],
42 | [PR['PR_TYPE'], /^(?:-?GENADR|=MINUS|2BCADR|VN|BOF|MM|-?2CADR|-?[1-6]DNADR|ADRES|BBCON|[SE]?BANK\=?|BLOCK|BNKSUM|E?CADR|COUNT\*?|2?DEC\*?|-?DNCHAN|-?DNPTR|EQUALS|ERASE|MEMORY|2?OCT|REMADR|SETLOC|SUBRO|ORG|BSS|BES|SYN|EQU|DEFINE|END)\s/,null],
43 | // A single quote possibly followed by a word that optionally ends with
44 | // = ! or ?.
45 | [PR['PR_LITERAL'],
46 | /^\'(?:-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?)?/],
47 | // Any word including labels that optionally ends with = ! or ?.
48 | [PR['PR_PLAIN'],
49 | /^-*(?:[!-z_]|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?/i],
50 | // A printable non-space non-special character
51 | [PR['PR_PUNCTUATION'], /^[^\w\t\n\r \xA0()\"\\\';]+/]
52 | ]),
53 | ['apollo', 'agc', 'aea']);
54 |
--------------------------------------------------------------------------------
/src/static/module/code-prettify/lang-basic.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright (C) 2013 Peter Kofler
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | // Contributed by peter dot kofler at code minus cop dot org
19 |
20 | /**
21 | * @fileoverview
22 | * Registers a language handler for Basic.
23 | *
24 | * To use, include prettify.js and this file in your HTML page.
25 | * Then put your code in an HTML tag like
26 | *
(my BASIC code)
27 | *
28 | * @author peter dot kofler at code minus cop dot org
29 | */
30 |
31 | PR.registerLangHandler(
32 | PR.createSimpleLexer(
33 | [ // shortcutStylePatterns
34 | // "single-line-string"
35 | [PR.PR_STRING, /^(?:"(?:[^\\"\r\n]|\\.)*(?:"|$))/, null, '"'],
36 | // Whitespace
37 | [PR.PR_PLAIN, /^\s+/, null, ' \r\n\t\xA0']
38 | ],
39 | [ // fallthroughStylePatterns
40 | // A line comment that starts with REM
41 | [PR.PR_COMMENT, /^REM[^\r\n]*/, null],
42 | [PR.PR_KEYWORD, /^\b(?:AND|CLOSE|CLR|CMD|CONT|DATA|DEF ?FN|DIM|END|FOR|GET|GOSUB|GOTO|IF|INPUT|LET|LIST|LOAD|NEW|NEXT|NOT|ON|OPEN|OR|POKE|PRINT|READ|RESTORE|RETURN|RUN|SAVE|STEP|STOP|SYS|THEN|TO|VERIFY|WAIT)\b/, null],
43 | [PR.PR_PLAIN, /^[A-Z][A-Z0-9]?(?:\$|%)?/i, null],
44 | // Literals .0, 0, 0.0 0E13
45 | [PR.PR_LITERAL, /^(?:\d+(?:\.\d*)?|\.\d+)(?:e[+\-]?\d+)?/i, null, '0123456789'],
46 | [PR.PR_PUNCTUATION, /^.[^\s\w\.$%"]*/, null]
47 | // [PR.PR_PUNCTUATION, /^[-,:;!<>=\+^\/\*]+/]
48 | ]),
49 | ['basic','cbm']);
50 |
--------------------------------------------------------------------------------
/src/static/module/code-prettify/lang-clj.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license Copyright (C) 2011 Google Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | /**
18 | * @fileoverview
19 | * Registers a language handler for Clojure.
20 | *
21 | *
22 | * To use, include prettify.js and this file in your HTML page.
23 | * Then put your code in an HTML tag like
24 | * (my lisp code)
25 | * The lang-cl class identifies the language as common lisp.
26 | * This file supports the following language extensions:
27 | * lang-clj - Clojure
28 | *
29 | *
30 | * I used lang-lisp.js as the basis for this adding the clojure specific
31 | * keywords and syntax.
32 | *
33 | * "Name" = 'Clojure'
34 | * "Author" = 'Rich Hickey'
35 | * "Version" = '1.2'
36 | * "About" = 'Clojure is a lisp for the jvm with concurrency primitives and a richer set of types.'
37 | *
38 | *
39 | * I used Clojure.org Reference as
40 | * the basis for the reserved word list.
41 | *
42 | *
43 | * @author jwall@google.com
44 | */
45 |
46 | PR['registerLangHandler'](
47 | PR['createSimpleLexer'](
48 | [
49 | // clojure has more paren types than minimal lisp.
50 | ['opn', /^[\(\{\[]+/, null, '([{'],
51 | ['clo', /^[\)\}\]]+/, null, ')]}'],
52 | // A line comment that starts with ;
53 | [PR['PR_COMMENT'], /^;[^\r\n]*/, null, ';'],
54 | // Whitespace
55 | [PR['PR_PLAIN'], /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'],
56 | // A double quoted, possibly multi-line, string.
57 | [PR['PR_STRING'], /^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/, null, '"']
58 | ],
59 | [
60 | // clojure has a much larger set of keywords
61 | [PR['PR_KEYWORD'], /^(?:def|if|do|let|quote|var|fn|loop|recur|throw|try|monitor-enter|monitor-exit|defmacro|defn|defn-|macroexpand|macroexpand-1|for|doseq|dosync|dotimes|and|or|when|not|assert|doto|proxy|defstruct|first|rest|cons|defprotocol|deftype|defrecord|reify|defmulti|defmethod|meta|with-meta|ns|in-ns|create-ns|import|intern|refer|alias|namespace|resolve|ref|deref|refset|new|set!|memfn|to-array|into-array|aset|gen-class|reduce|map|filter|find|nil?|empty?|hash-map|hash-set|vec|vector|seq|flatten|reverse|assoc|dissoc|list|list?|disj|get|union|difference|intersection|extend|extend-type|extend-protocol|prn)\b/, null],
62 | [PR['PR_TYPE'], /^:[0-9a-zA-Z\-]+/]
63 | ]),
64 | ['clj']);
65 |
--------------------------------------------------------------------------------
/src/static/module/code-prettify/lang-css.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright (C) 2009 Google Inc.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /**
19 | * @fileoverview
20 | * Registers a language handler for CSS.
21 | *
22 | *
23 | * To use, include prettify.js and this file in your HTML page.
24 | * Then put your code in an HTML tag like
25 | *
26 | *
27 | *
28 | * http://www.w3.org/TR/CSS21/grammar.html Section G2 defines the lexical
29 | * grammar. This scheme does not recognize keywords containing escapes.
30 | *
31 | * @author mikesamuel@gmail.com
32 | */
33 |
34 | // This file is a call to a function defined in prettify.js which defines a
35 | // lexical scanner for CSS and maps tokens to styles.
36 |
37 | // The call to PR['registerLangHandler'] is quoted so that Closure Compiler
38 | // will not rename the call so that this language extensions can be
39 | // compiled/minified separately from one another. Other symbols defined in
40 | // prettify.js are similarly quoted.
41 |
42 | // The call is structured thus:
43 | // PR['registerLangHandler'](
44 | // PR['createSimpleLexer'](
45 | // shortcutPatterns,
46 | // fallThroughPatterns),
47 | // [languageId0, ..., languageIdN])
48 |
49 | // Langugage IDs
50 | // =============
51 | // The language IDs are typically the file extensions of source files for
52 | // that language so that users can syntax highlight arbitrary files based
53 | // on just the extension. This is heuristic, but works pretty well in
54 | // practice.
55 |
56 | // Patterns
57 | // ========
58 | // Lexers are typically implemented as a set of regular expressions.
59 | // The SimpleLexer function takes regular expressions, styles, and some
60 | // pragma-info and produces a lexer. A token description looks like
61 | // [STYLE_NAME, /regular-expression/, pragmas]
62 |
63 | // Initially, simple lexer's inner loop looked like:
64 |
65 | // while sourceCode is not empty:
66 | // try each regular expression in order until one matches
67 | // remove the matched portion from sourceCode
68 |
69 | // This was really slow for large files because some JS interpreters
70 | // do a buffer copy on the matched portion which is O(n*n)
71 |
72 | // The current loop now looks like
73 |
74 | // 1. use js-modules/combinePrefixPatterns.js to
75 | // combine all regular expressions into one
76 | // 2. use a single global regular expresion match to extract all tokens
77 | // 3. for each token try regular expressions in order until one matches it
78 | // and classify it using the associated style
79 |
80 | // This is a lot more efficient but it does mean that lookahead and lookbehind
81 | // can't be used across boundaries to classify tokens.
82 |
83 | // Sometimes we need lookahead and lookbehind and sometimes we want to handle
84 | // embedded language -- JavaScript or CSS embedded in HTML, or inline assembly
85 | // in C.
86 |
87 | // If a particular pattern has a numbered group, and its style pattern starts
88 | // with "lang-" as in
89 | // ['lang-js', /