├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── build
├── codeflask.min.js
├── codeflask.module.js
└── index.html
├── code.png
├── index.d.ts
├── logo.png
├── package.json
├── rollup.config.js
├── src
├── codeflask.js
├── styles
│ ├── editor.js
│ ├── injector.js
│ └── theme-default.js
└── utils
│ ├── css-supports.js
│ └── html-escape.js
└── test
├── e2e
├── test-app.js
└── test.html
├── test-server.js
└── wdio.conf.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | npm-debug.log
4 | package-lock.json
5 | yarn.lock
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: required
2 | language: node_js
3 | node_js:
4 | - "lts/*"
5 | addons:
6 | chrome: stable
7 | deploy:
8 | provider: npm
9 | email: $NPM_EMAIL
10 | api_key: $NPM_TOKEN
11 | on:
12 | tags: true
13 | notifications:
14 | email: false
15 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Claudio Holanda
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://www.npmjs.com/package/codeflask)
2 | [](https://travis-ci.org/kazzkiq/CodeFlask)
3 |
4 |
5 | 
6 | CodeFlask: A micro code-editor for awesome web pages.
7 |
8 |
9 |
10 |
11 |
12 |
13 | ## Installation
14 |
15 | You can install CodeFlask via npm:
16 |
17 | ```
18 | npm install codeflask
19 | ```
20 |
21 | Or use it directly in browser via cdn service:
22 |
23 | ```
24 | https://unpkg.com/codeflask/build/codeflask.min.js
25 | ```
26 |
27 | ## Usage
28 |
29 | ```js
30 | import CodeFlask from 'codeflask';
31 |
32 | const flask = new CodeFlask('#my-selector', { language: 'js' });
33 | ```
34 | You can also pass a DOM element instead of a selector:
35 | ```js
36 | import CodeFlask from 'codeflask';
37 |
38 | const editorElem = document.getElementById('editor');
39 | const flask = new CodeFlask(editorElem, { language: 'js' });
40 | ```
41 | Usage with Shadow DOM:
42 | ```js
43 | import CodeFlask from 'codeflask';
44 | ...
45 | const shadowElem = this.shadowRoot.querySelector('#editor');
46 | const flask = new CodeFlask(shadowElem, { language: 'js', styleParent: this.shadowRoot });
47 | ```
48 | ### Listening for changes in editor
49 |
50 | ```js
51 | flask.onUpdate((code) => {
52 | // do something with code here.
53 | // this will trigger whenever the code
54 | // in the editor changes.
55 | });
56 | ```
57 |
58 | ### Updating the editor programatically
59 |
60 | ```js
61 | // This will also trigger .onUpdate()
62 | flask.updateCode('const my_new_code_here = "Blabla"');
63 | ```
64 |
65 | ### Getting the current code from editor
66 |
67 | ```js
68 | const code = flask.getCode();
69 | ```
70 |
71 | ### Enabling line numbers
72 |
73 | ```js
74 | import CodeFlask from 'codeflask';
75 |
76 | const flask = new CodeFlask('#my-selector', {
77 | language: 'js',
78 | lineNumbers: true
79 | });
80 | ```
81 |
82 | ### Enabling rtl (right to left writing)
83 |
84 | ```js
85 | import CodeFlask from 'codeflask';
86 |
87 | const flask = new CodeFlask('#my-selector', {
88 | language: 'js',
89 | rtl: true
90 | });
91 | ```
92 |
93 | ### Enabling read only mode
94 |
95 | ```js
96 | import CodeFlask from 'codeflask';
97 |
98 | const flask = new CodeFlask('#my-selector', {
99 | language: 'js',
100 | readonly: true
101 | });
102 | ```
103 |
104 | ### Adding other languages support:
105 |
106 | ```js
107 | flask.addLanguage('ruby', options)
108 | ```
109 |
110 | #### For Example to add 'Ruby'
111 |
112 | ```js
113 | import Prism from 'prismjs';
114 | import CodeFlask from 'codeflask';
115 |
116 | const flask = new CodeFlask('#my-selector', {
117 | language: 'ruby',
118 | readonly: true
119 | });
120 |
121 | flask.addLanguage('ruby', Prism.languages['ruby']);
122 | ```
123 |
124 | This API is simply a proxy to add a new language to [Prism](http://prismjs.com/) itself (the code highlighter). The `options` parameter must be the same accepted in Prism. You can read more about it [here](http://prismjs.com/extending.html#language-definitions).
125 |
126 | By default, CodeFlask supports the following languages (which are also the default supported in Prism):
127 |
128 | - Markup (HTML/XML);
129 | - CSS;
130 | - C-like;
131 | - JavaScript;
132 |
133 | ### Adding your own theme to CodeFlask
134 |
135 | By default, CodeFlask comes with a simple theme made from scratch called **[CodeNoon](https://github.com/kazzkiq/CodeFlask.js/blob/master/src/styles/theme-default.js)**.
136 |
137 | You can easily override this theme with your own by writting your own CSS and adding it to your project. If that's the case, you should also disable **CodeNoon** with the `defaultTheme` option:
138 |
139 | ```js
140 | import CodeFlask from 'codeflask';
141 |
142 | const flask = new CodeFlask('#my-selector', {
143 | language: 'js',
144 | defaultTheme: false
145 | });
146 | ```
147 |
148 | # Credits & Thanks
149 |
150 | CodeFlask.js was made possible by awesome open-source projects such as [Prism.js](https://github.com/PrismJS/prism) and [Rollup](https://github.com/rollup/rollup).
151 |
--------------------------------------------------------------------------------
/build/codeflask.min.js:
--------------------------------------------------------------------------------
1 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.CodeFlask=t()}(this,function(){"use strict";var e,t,n,a='"SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace',s="\n .codeflask {\n position: absolute;\n width: 100%;\n height: 100%;\n overflow: hidden;\n }\n\n .codeflask, .codeflask * {\n box-sizing: border-box;\n }\n\n .codeflask__pre {\n pointer-events: none;\n z-index: 3;\n overflow: hidden;\n }\n\n .codeflask__textarea {\n background: none;\n border: none;\n color: "+(e="caret-color",t="#000",(CSS?CSS.supports(e,t):(n=(n=e).split("-").filter(function(e){return!!e}).map(function(e){return e[0].toUpperCase()+e.substr(1)}).join(""))[0].toLowerCase()+n.substr(1)in document.body.style)?"#fff":"#ccc")+";\n z-index: 1;\n resize: none;\n font-family: "+a+";\n -webkit-appearance: pre;\n caret-color: #111;\n z-index: 2;\n width: 100%;\n height: 100%;\n }\n\n .codeflask--has-line-numbers .codeflask__textarea {\n width: calc(100% - 40px);\n }\n\n .codeflask__code {\n display: block;\n font-family: "+a+";\n overflow: hidden;\n }\n\n .codeflask__flatten {\n padding: 10px;\n font-size: 13px;\n line-height: 20px;\n white-space: pre;\n position: absolute;\n top: 0;\n left: 0;\n overflow: auto;\n margin: 0 !important;\n outline: none;\n text-align: left;\n }\n\n .codeflask--has-line-numbers .codeflask__flatten {\n width: calc(100% - 40px);\n left: 40px;\n }\n\n .codeflask__line-highlight {\n position: absolute;\n top: 10px;\n left: 0;\n width: 100%;\n height: 20px;\n background: rgba(0,0,0,0.1);\n z-index: 1;\n }\n\n .codeflask__lines {\n padding: 10px 4px;\n font-size: 12px;\n line-height: 20px;\n font-family: 'Cousine', monospace;\n position: absolute;\n left: 0;\n top: 0;\n width: 40px;\n height: 100%;\n text-align: right;\n color: #999;\n z-index: 2;\n }\n\n .codeflask__lines__line {\n display: block;\n }\n\n .codeflask.codeflask--has-line-numbers {\n padding-left: 40px;\n }\n\n .codeflask.codeflask--has-line-numbers:before {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n width: 40px;\n height: 100%;\n background: #eee;\n z-index: 1;\n }\n";function i(e,t,n){var a=t||"codeflask-style",s=n||document.head;if(!e)return!1;if(document.getElementById(a))return!0;var i=document.createElement("style");return i.innerHTML=e,i.id=a,s.appendChild(i),!0}var r={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="};function o(e){return String(e).replace(/[&<>"'`=/]/g,function(e){return r[e]})}var l="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};var c,u=(function(e){var t="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},n=function(){var e=/\blang(?:uage)?-([\w-]+)\b/i,n=0,a=t.Prism={manual:t.Prism&&t.Prism.manual,disableWorkerMessageHandler:t.Prism&&t.Prism.disableWorkerMessageHandler,util:{encode:function(e){return e instanceof s?new s(e.type,a.util.encode(e.content),e.alias):"Array"===a.util.type(e)?e.map(a.util.encode):e.replace(/&/g,"&").replace(/e.length)return;if(!(x instanceof l)){if(f&&k!=t.length-1){if(h.lastIndex=v,!(L=h.exec(e)))break;for(var w=L.index+(g?L[1].length:0),C=L.index+L[0].length,S=k,T=v,A=t.length;S=(T+=t[S].length)&&(++k,v=T);if(t[k]instanceof l)continue;F=S-k,x=e.slice(v,T),L.index-=v}else{h.lastIndex=0;var L=h.exec(x),F=1}if(L){g&&(m=L[1]?L[1].length:0);C=(w=L.index+m)+(L=L[0].slice(m)).length;var E=x.slice(0,w),_=x.slice(C),N=[k,F];E&&(++k,v+=E.length,N.push(E));var j=new l(c,p?a.tokenize(L,p):L,b,L,f);if(N.push(j),_&&N.push(_),Array.prototype.splice.apply(t,N),1!=F&&a.matchGrammar(e,t,n,k,v,!0,c),r)break}else if(r)break}}}}},tokenize:function(e,t,n){var s=[e],i=t.rest;if(i){for(var r in i)t[r]=i[r];delete t.rest}return a.matchGrammar(e,s,t,0,0,!1),s},hooks:{all:{},add:function(e,t){var n=a.hooks.all;n[e]=n[e]||[],n[e].push(t)},run:function(e,t){var n=a.hooks.all[e];if(n&&n.length)for(var s,i=0;s=n[i++];)s(t)}}},s=a.Token=function(e,t,n,a,s){this.type=e,this.content=t,this.alias=n,this.length=0|(a||"").length,this.greedy=!!s};if(s.stringify=function(e,t,n){if("string"==typeof e)return e;if("Array"===a.util.type(e))return e.map(function(n){return s.stringify(n,t,e)}).join("");var i={type:e.type,content:s.stringify(e.content,t,n),tag:"span",classes:["token",e.type],attributes:{},language:t,parent:n};if(e.alias){var r="Array"===a.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(i.classes,r)}a.hooks.run("wrap",i);var o=Object.keys(i.attributes).map(function(e){return e+'="'+(i.attributes[e]||"").replace(/"/g,""")+'"'}).join(" ");return"<"+i.tag+' class="'+i.classes.join(" ")+'"'+(o?" "+o:"")+">"+i.content+""+i.tag+">"},!t.document)return t.addEventListener?(a.disableWorkerMessageHandler||t.addEventListener("message",function(e){var n=JSON.parse(e.data),s=n.language,i=n.code,r=n.immediateClose;t.postMessage(a.highlight(i,a.languages[s],s)),r&&t.close()},!1),t.Prism):t.Prism;var i=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return i&&(a.filename=i.src,a.manual||i.hasAttribute("data-manual")||("loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(a.highlightAll):window.setTimeout(a.highlightAll,16):document.addEventListener("DOMContentLoaded",a.highlightAll))),t.Prism}();e.exports&&(e.exports=n),void 0!==l&&(l.Prism=n),n.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype://i,cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/i,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+)/i,inside:{punctuation:[/^=/,{pattern:/(^|[^\\])["']/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/?[\da-z]{1,8};/i},n.languages.markup.tag.inside["attr-value"].inside.entity=n.languages.markup.entity,n.hooks.add("wrap",function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))}),n.languages.xml=n.languages.markup,n.languages.html=n.languages.markup,n.languages.mathml=n.languages.markup,n.languages.svg=n.languages.markup,n.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+?.*?(?:;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:/url\((?:(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,selector:/[^{}\s][^{};]*?(?=\s*\{)/,string:{pattern:/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/\B!important\b/i,function:/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:]/},n.languages.css.atrule.inside.rest=n.languages.css,n.languages.markup&&(n.languages.insertBefore("markup","tag",{style:{pattern:/(
19 |
20 |
21 |
22 |
23 | // Feel free to play with the code. :)
24 |
25 | function Hey(phrase) {
26 | phrase = phrase || "Hey";
27 | return console.log(phrase);
28 | }
29 |
30 | window.onLoad = function() {
31 | Hey();
32 | Hey("Jude");
33 | Hey("Don't make it bad.");
34 | }
35 |
46 |
47 |