├── .gitignore ├── static └── bg-8-full.jpg ├── src ├── polyfills.ts ├── deferred.ts ├── utils.ts └── index.ts ├── tsconfig.json ├── typings.json ├── index.html ├── webpack.config.js ├── package.json ├── LICENSE.md ├── test ├── spawn1.txt ├── spawn2.txt └── example.txt ├── dist ├── live-coder.min.js ├── polyfills.min.js └── live-coder.min.js.map └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | typings -------------------------------------------------------------------------------- /static/bg-8-full.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jscriptcoder/live-coder/HEAD/static/bg-8-full.jpg -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | import 'core-js/es6/promise'; 2 | import 'core-js/modules/es6.object.assign'; 3 | import 'whatwg-fetch'; -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5" 4 | }, 5 | "exclude": [ 6 | "node_modules" 7 | ] 8 | } -------------------------------------------------------------------------------- /typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "live-coder", 3 | "dependencies": {}, 4 | "globalDependencies": { 5 | "es2015-object": "registry:env/es2015-object#1.0.0+20160526151700", 6 | "es2015-promise": "registry:env/es2015-promise#1.0.0+20160526151700" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/deferred.ts: -------------------------------------------------------------------------------- 1 | export class Deferred { 2 | public promise: Promise; 3 | public resolve: {(value?: T): void}; 4 | public reject: {(error?: any): void}; 5 | 6 | constructor() { 7 | this.promise = new Promise((resolve: {(value?: T): void}, reject: {(error?: any): void}) => { 8 | this.resolve = resolve; 9 | this.reject = reject; 10 | }); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ..:: Live Coding ::.. 6 | 7 | 8 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | 3 | module.exports = { 4 | entry: { 5 | 'polyfills': './src/polyfills.ts', 6 | 'live-coder': './src/index.ts' 7 | }, 8 | output: { 9 | library: 'Live', 10 | filename: 'dist/[name].min.js' 11 | }, 12 | resolve: { 13 | extensions: ['', '.ts', '.js'] 14 | }, 15 | module: { 16 | loaders: [ 17 | {test: /\.ts/, loader: 'ts-loader'} 18 | ] 19 | }, 20 | plugins: [ 21 | new webpack.optimize.UglifyJsPlugin() 22 | ], 23 | devtool: 'source-map' 24 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "live-coder", 3 | "version": "1.0.0", 4 | "description": "live coding simulation", 5 | "main": "src/index.ts", 6 | "scripts": { 7 | "postinstall": "typings install", 8 | "build": "webpack", 9 | "start": "live-server", 10 | "prestart": "npm run build" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/jscriptcoder/live-coder.git" 15 | }, 16 | "author": "Francisco Ramos ", 17 | "license": "MIT", 18 | "bugs": { 19 | "url": "https://github.com/jscriptcoder/live-coder/issues" 20 | }, 21 | "homepage": "https://github.com/jscriptcoder/live-coder#readme", 22 | "devDependencies": { 23 | "live-server": "^1.1.0", 24 | "ts-loader": "^1.2.0", 25 | "typescript": "^2.0.9", 26 | "typings": "^2.0.0", 27 | "uglify-js": "^2.7.4", 28 | "webpack": "^1.13.3" 29 | }, 30 | "dependencies": { 31 | "core-js": "^2.4.1", 32 | "es6-shim": "^0.35.1", 33 | "whatwg-fetch": "^2.0.1" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017-present Francisco Ramos 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 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | import { Deferred } from './deferred'; 2 | 3 | export type AnyPromise = Promise; 4 | 5 | export function asyncLoop(fn: {(): AnyPromise}, condition: {(): boolean}, delay?: number): AnyPromise { 6 | const deferred = new Deferred(); 7 | 8 | const loop = (): void => { 9 | if (condition()) { 10 | fn() 11 | .then(() => { 12 | if (delay) { 13 | setTimeout(loop, delay); 14 | } else { 15 | loop(); 16 | } 17 | }) 18 | .catch(() => deferred.reject()); 19 | } else { 20 | deferred.resolve(); 21 | } 22 | }; 23 | 24 | loop(); 25 | 26 | return deferred.promise; 27 | } 28 | 29 | export function asyncForOf(fn: {(value: T): AnyPromise}, array: T[], delay?: number): AnyPromise { 30 | let index: number = 0; 31 | const length: number = array.length; 32 | let value: any; 33 | 34 | const conditionLoop = (): boolean => index < length; 35 | const bodyLoop = () => { 36 | const value = array[index]; 37 | const promise = fn(value); 38 | index++; 39 | return promise; 40 | }; 41 | 42 | return asyncLoop(bodyLoop, conditionLoop, delay); 43 | } 44 | 45 | export function waitForDom(): AnyPromise { 46 | return new Promise((resolve: Function) => { 47 | if (/comp|inter|loaded/.test(document.readyState)){ 48 | resolve(); 49 | } else { 50 | document.addEventListener('DOMContentLoaded', () => resolve() ); 51 | } 52 | }); 53 | } 54 | -------------------------------------------------------------------------------- /test/spawn1.txt: -------------------------------------------------------------------------------- 1 | --- css:apply --- 2 | .spawn1__display { 3 | background-color: rgba(0, 0, 0, 0.8); 4 | color: white; 5 | margin: 0; 6 | padding: 4px; 7 | overflow: auto; 8 | width: 600px; 9 | max-height: 200px; 10 | } 11 | 12 | --- html:div.spawn1-display-container --- 13 |
14 | 15 |
16 |
17 |
18 |
19 |
20 | 21 |
22 | 23 |
24 |
25 | --- apply --- 26 | 27 | --- js --- 28 | var s1Display = document.querySelector('.spawn1__display'); 29 | var s1DisplayBody = document.querySelector('.spawn1-display-body'); 30 | s1DisplayBody.appendChild(s1Display); 31 | --- apply --- 32 | 33 | --- css:apply --- 34 | .spawn1-display-container { 35 | position: absolute; 36 | top: 300px; 37 | left: 20px; 38 | border-top-left-radius: 6px; 39 | border-top-right-radius: 6px; 40 | box-shadow: 0px 0px 15px 1px rgba(0,0,0,0.75); 41 | } 42 | 43 | .spawn1-display-header { 44 | height: 30px; 45 | background-color: white; 46 | border-top-left-radius: 6px; 47 | border-top-right-radius: 6px; 48 | display: flex; 49 | align-items: center; 50 | } 51 | 52 | --- html:div.spawn1-display-header__title:apply --- 53 | spawn1@jscriptcoder 54 | 55 | --- css:apply --- 56 | .spawn1-display-header__title { 57 | color: black; 58 | font-family: monospace; 59 | font-size: 14px; 60 | font-weight: bold; 61 | } 62 | 63 | .spawn1-display-header__actions { 64 | display: flex; 65 | justify-content: space-between; 66 | align-items: center; 67 | margin: 0 8px; 68 | } 69 | 70 | .spawn1-display-header__actions > div { 71 | width: 16px; 72 | height: 16px; 73 | border-radius: 8px; 74 | margin: 0 2px; 75 | } 76 | 77 | .spawn1-display-header__actions .close { background-color: #df6961; } 78 | .spawn1-display-header__actions .minimize { background-color: #f2bc57; } 79 | .spawn1-display-header__actions .maximize { background-color: #6bb358; } -------------------------------------------------------------------------------- /test/spawn2.txt: -------------------------------------------------------------------------------- 1 | --- css:apply --- 2 | .spawn2__display { 3 | background-color: rgba(255, 255, 255, 0.8); 4 | color: black; 5 | margin: 0; 6 | padding: 4px; 7 | overflow: auto; 8 | width: 600px; 9 | max-height: 200px; 10 | } 11 | 12 | --- html:div.spawn2-display-container --- 13 |
14 | 15 |
16 |
17 |
18 |
19 |
20 | 21 |
22 | 23 |
24 |
25 | --- apply --- 26 | 27 | --- js --- 28 | var s1Display = document.querySelector('.spawn2__display'); 29 | var s1DisplayBody = document.querySelector('.spawn2-display-body'); 30 | s1DisplayBody.appendChild(s1Display); 31 | --- apply --- 32 | 33 | --- css:apply --- 34 | .spawn2-display-container { 35 | position: absolute; 36 | top: 20px; 37 | left: 20px; 38 | border-top-left-radius: 6px; 39 | border-top-right-radius: 6px; 40 | box-shadow: 0px 0px 15px 1px rgba(0,0,0,0.75); 41 | } 42 | 43 | .spawn2-display-header { 44 | height: 30px; 45 | background: linear-gradient(180deg, #666464 0%, #3D3B3B 100%); 46 | border-top-left-radius: 6px; 47 | border-top-right-radius: 6px; 48 | display: flex; 49 | align-items: center; 50 | } 51 | 52 | --- html:div.spawn2-display-header__title:apply --- 53 | spawn2@jscriptcoder 54 | 55 | --- css:apply --- 56 | .spawn2-display-header__title { 57 | color: white; 58 | font-family: monospace; 59 | font-size: 14px; 60 | font-weight: bold; 61 | } 62 | 63 | .spawn2-display-header__actions { 64 | display: flex; 65 | justify-content: space-between; 66 | align-items: center; 67 | margin: 0 8px; 68 | } 69 | 70 | .spawn2-display-header__actions > div { 71 | width: 16px; 72 | height: 16px; 73 | background: linear-gradient(180deg, #9E9E9E 0%, #5a5a5a 100%); 74 | border-radius: 8px; 75 | margin: 0 2px; 76 | font-size: 10px; 77 | text-align: center; 78 | line-height: 16px; 79 | color: #424242; 80 | } 81 | 82 | .spawn2-display-header__actions .close { 83 | background: linear-gradient(180deg, #f78867 0%, #b72b00 100%); 84 | } -------------------------------------------------------------------------------- /dist/live-coder.min.js: -------------------------------------------------------------------------------- 1 | var Live=function(e){function t(r){if(n[r])return n[r].exports;var i=n[r]={exports:{},id:r,loaded:!1};return e[r].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){"use strict";var r=n(1),i=n(2),o=function(){function e(t){void 0===t&&(t={}),this.config=Object.assign({},e.DEFAULT_CONFIG,t),this.domReady=i.waitForDom(),this.paused=new r.Deferred,this.isPaused=!0,this.init()}return e.isElementAttached=function(e){return!!e.parentElement},e.appendIfApply=function(t,n,r){t&&n&&"apply"===t.toLowerCase()&&!e.isElementAttached(n)&&r&&r.appendChild(n)},e.prototype.init=function(){var e=this;this.domReady.then(function(){e.$runner=document.getElementsByTagName("head")[0]||document.body,e.$defContainer=e.createElement(e.config.defaultContainer),e.$body=document.body,e.$display=e.getDisplay(),e.config.pauseOnClick&&(e.togglePauseListener=e.togglePause.bind(e),document.addEventListener("click",e.togglePauseListener)),e.config.paused?e.pause():e.resume()})},e.prototype.evalElement=function(e){this.$runner.appendChild(e)},e.prototype.togglePause=function(){this.isPaused?this.resume():this.pause()},e.prototype.createElement=function(e,t,n){void 0===t&&(t={});for(var r=document.createElement(e),i=0,o=Object.keys(t);i` element. 14 | 15 | **--- html**: will add the following html in the `` element (see **CoderConfig** below). 16 | 17 | **--- js**: will add the following javascript code in a `