diff --git a/README.md b/README.md
index 11e2d9a1..4e1eee87 100644
--- a/README.md
+++ b/README.md
@@ -1,150 +1,40 @@
-[](https://www.npmjs.com/package/codeflask)
-[](https://travis-ci.org/kazzkiq/CodeFlask)
-
-
- 
- CodeFlask: A micro code-editor for awesome web pages.
-
-
-
-
-
-
-## Installation
-
-You can install CodeFlask via npm:
-
-```
-npm install codeflask
-```
-
-Or use it directly in browser via cdn service:
-
-```
-https://unpkg.com/codeflask/build/codeflask.min.js
-```
-
-## Usage
-
-```js
-import CodeFlask from 'codeflask';
-
-const flask = new CodeFlask('#my-selector', { language: 'js' });
-```
-You can also pass a DOM element instead of a selector:
-```js
-import CodeFlask from 'codeflask';
-
-const editorElem = document.getElementById('editor');
-const flask = new CodeFlask(editorElem, { language: 'js' });
-```
-Usage with Shadow DOM:
-```js
-import CodeFlask from 'codeflask';
-...
-const shadowElem = this.shadowRoot.querySelector('#editor');
-const flask = new CodeFlask(shadowElem, { language: 'js', styleParent: this.shadowRoot });
-```
-### Listening for changes in editor
-
-```js
-flask.onUpdate((code) => {
- // do something with code here.
- // this will trigger whenever the code
- // in the editor changes.
-});
-```
-
-### Updating the editor programatically
-
-```js
-// This will also trigger .onUpdate()
-flask.updateCode('const my_new_code_here = "Blabla"');
-```
-
-### Getting the current code from editor
-
-```js
-const code = flask.getCode();
-```
-
-### Enabling line numbers
-
-```js
-import CodeFlask from 'codeflask';
-
-const flask = new CodeFlask('#my-selector', {
- language: 'js',
- lineNumbers: true
-});
-```
-
-### Enabling rtl (right to left writing)
-
-```js
-import CodeFlask from 'codeflask';
-
-const flask = new CodeFlask('#my-selector', {
- language: 'js',
- rtl: true
-});
-```
-
-### Enabling read only mode
-
-```js
-import CodeFlask from 'codeflask';
-
-const flask = new CodeFlask('#my-selector', {
- language: 'js',
- readonly: true
-});
-```
-
-### Adding other languages support:
-
-```js
-flask.addLanguage('ruby', options)
-```
-
-#### For Example to add 'Ruby'
-
-```js
-import Prism from 'prismjs';
-import CodeFlask from 'codeflask';
-
-const flask = new CodeFlask('#my-selector', {
- language: 'ruby',
- readonly: true
-});
-
-flask.addLanguage('ruby', Prism.languages['ruby']);
-```
-
-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).
-
-By default, CodeFlask supports the following languages (which are also the default supported in Prism):
-
-- Markup (HTML/XML);
-- CSS;
-- C-like;
-- JavaScript;
-
-### Adding your own theme to CodeFlask
-
-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)**.
-
-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:
-
-```js
-import CodeFlask from 'codeflask';
-
-const flask = new CodeFlask('#my-selector', {
- language: 'js',
- defaultTheme: false
-});
-```
-
-# Credits & Thanks
-
-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).
+# CodeFlask Mod
+
+```bash
+npm i '@acarl005/codeflask'
+```
+
+I modified [CodeFlask](https://github.com/kazzkiq/CodeFlask) to be able to...
+
+1. Make PrismJS a peer dependency
+1. Attach (and remove) custom event listeners to the editor
+1. Support the [Line Highlight](https://prismjs.com/plugins/line-highlight/) plugin in PrismJS
+1. Fix this issue: kazzkiq/CodeFlask#69
+1. Fix bugs with tab hotkey for indentation
+1. Make the self-closing characters configurable
+
+```javascript
+import CodeFlask from "codeflask"
+import Prism from "prismjs"
+
+const flask = new CodeFlask(editor, Prism, {
+ language: "js",
+ selfClosingCharacters: ['(', '[', '{', "'", '"'],
+ customEventListeners: {
+ "keydown": e => {
+ if (e.key == "Enter") {
+ e.preventDefault()
+ e.stopImmediatePropagation()
+ // do custom stuff
+ }
+ }
+ }
+})
+
+flask.highlightLines("4-7")
+```
+
+PrismJS is highly customizable.
+It actually offers custom builds with more plugins that you can opt into.
+This is an awesome and rare feature b/c you can minimize the bundle by omitting unneeded functionality.
+Therefore, it should be a peer dependency, b/c CodeFlask can't know which build with which plugins you'll need.
diff --git a/build/codeflask.min.js b/build/codeflask.min.js
index faa1b340..b8715681 100644
--- a/build/codeflask.min.js
+++ b/build/codeflask.min.js
@@ -1 +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:/(