1
0
mirror of https://github.com/chinchang/web-maker.git synced 2025-07-11 00:56:25 +02:00

add support for sass,es6,less n coffee.

This commit is contained in:
Kushagra Gour
2016-07-14 01:54:43 +05:30
parent ded1b100a8
commit 45aa1d1e7d
7 changed files with 1290 additions and 28 deletions

View File

@ -29,6 +29,16 @@
.fr { .fr {
float: right; float: right;
} }
.caret {
display: inline-block;
width: 0;
height: 0;
border: 6px solid transparent;
border-top-color: currentColor;
position: relative;
top: 5px;
margin-left: 7px;
}
.main-container { .main-container {
position: absolute; position: absolute;
left: 0; right: 0; left: 0; right: 0;
@ -59,9 +69,9 @@
height: 33%; height: 33%;
overflow: hidden; overflow: hidden;
position: relative; position: relative;
animation: pop-in 0.4s cubic-bezier(.71,1.7,.77,1.24) forwards 0.2s; /*animation: pop-in 0.4s cubic-bezier(.71,1.7,.77,1.24) forwards 0.2s;*/
animation: pop-in 0.4s ease forwards 0.2s; /*animation: pop-in 0.4s ease forwards 0.2s;*/
opacity: 0; /*opacity: 0;*/
} }
.layout-2 .code-wrap { .layout-2 .code-wrap {
height: auto; height: auto;
@ -74,17 +84,12 @@
animation-delay: 0.4s; animation-delay: 0.4s;
} }
.code-wrap:after { .code-wrap__header {
content: attr(data-type); padding: 5px 20px;
text-transform: uppercase; background: rgba(0,0,0,0.55);
font-size: 65px; color: #888;
display: block; border-bottom: 1px solid rgba(0,0,0,0.3);
position: absolute; font-weight: bold;
top: 4px;
color: rgba(255,255,255,0.04);
left: 52px;
z-index: 3;
pointer-events: none;
} }
@keyframes pop-in { @keyframes pop-in {
from { transform: scale(0.9); opacity: 0; } from { transform: scale(0.9); opacity: 0; }
@ -94,7 +99,7 @@
/* Codemirror */ /* Codemirror */
.Codemirror { .Codemirror {
width: 100%; width: 100%;
height: 100%; height: calc(100% - 25px); /* 25px for header */
font-size: 16px; font-size: 16px;
} }
.cm-s-monokai .CodeMirror-linenumber { .cm-s-monokai .CodeMirror-linenumber {
@ -167,6 +172,9 @@
.mode-btn.selected svg { .mode-btn.selected svg {
fill: rgba(255, 255, 255, 0.45); fill: rgba(255, 255, 255, 0.45);
} }
.gutter {
background: rgba(0,0,0,0.2);
}
.gutter-horizontal { .gutter-horizontal {
cursor: ew-resize; cursor: ew-resize;
} }
@ -274,6 +282,49 @@
top: 2px; top: 2px;
left: 2px; left: 2px;
} }
.btn-group {
position: relative;
}
.btn-group {
cursor: pointer;
}
.dropdown__menu {
position: absolute;
top: 100%;
left: 0;
padding: 0;
margin: 0;
min-width: 200px;
display: block;
list-style: none;
border-radius: 4px;
overflow: hidden;
opacity: 0;
visibility: hidden;
transition: 0.3s ease;
transform: translateY(10px);
z-index: 5;
background: white;
}
.dropdown__menu > li > a {
display: block;
padding: 15px;
color: #333;
cursor: pointer;
}
.dropdown__menu > li > a:hover {
background: #ff8c00;
color: white;
}
.dropdown__menu > li:not(:last-child) {
border-bottom: 1px solid rgba(0,0,0,0.05);
}
.open .dropdown__menu {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
</style> </style>
</head> </head>
@ -281,9 +332,33 @@
<div class="main-container"> <div class="main-container">
<div class="content-wrap flex flex-grow"> <div class="content-wrap flex flex-grow">
<div class="code-side" id="js-code-side"> <div class="code-side" id="js-code-side">
<div id="js-html-code" data-type="html" class="code-wrap"></div> <div id="js-html-code" data-type="html" class="code-wrap">
<div id="js-css-code" data-type="css" class="code-wrap"></div> <div class="code-wrap__header">HTML</div>
<div id="js-js-code" data-type="js" class="code-wrap"></div> </div>
<div id="js-css-code" data-type="css" class="code-wrap">
<div class="code-wrap__header">
<div class="btn-group" dropdown>
<span id="js-css-mode-label">CSS</span><span class="caret"></span>
<ul class="js-modes-menu dropdown__menu">
<li><a data-mode-type="css" data-mode="css">CSS</a></li>
<li><a data-mode-type="css" data-mode="scss">SCSS</a></li>
<li><a data-mode-type="css" data-mode="less">LESS</a></li>
</ul>
</div>
</div>
</div>
<div id="js-js-code" data-type="js" class="code-wrap">
<div class="code-wrap__header">
<div class="btn-group" dropdown>
<span id="js-js-mode-label">JS</span><span class="caret"></span>
<ul class="js-modes-menu dropdown__menu">
<li><a data-mode-type="js" data-mode="js">JS</a></li>
<li><a data-mode-type="js" data-mode="coffee">CoffeeScript</a></li>
<li><a data-mode-type="js" data-mode="es6">ES6 (Babel)</a></li>
</ul>
</div>
</div>
</div>
</div> </div>
<div class="demo-side" id="js-demo-side"> <div class="demo-side" id="js-demo-side">
<iframe src="about://blank" frameborder="0" id="demo-frame"></iframe> <iframe src="about://blank" frameborder="0" id="demo-frame"></iframe>
@ -429,8 +504,15 @@
<script src="lib/codemirror/keymap/sublime.js"></script> <script src="lib/codemirror/keymap/sublime.js"></script>
<script src="lib/emmet.js"></script> <script src="lib/emmet.js"></script>
<script src="lib/sass.js"></script>
<script src="lib/less.min.js"></script>
<script src="lib/babel.min.js"></script>
<script src="lib/coffee-script.js"></script>
<script src="lib/split.js"></script> <script src="lib/split.js"></script>
<script src="script.js"></script> <script src="script.js"></script>
<script src="dropdown.js"></script>
</body> </body>
</html> </html>

32
src/lib/babel.min.js vendored Normal file

File diff suppressed because one or more lines are too long

12
src/lib/coffee-script.js Normal file

File diff suppressed because one or more lines are too long

23
src/lib/less.min.js vendored Normal file

File diff suppressed because one or more lines are too long

202
src/lib/sass.js Normal file
View File

@ -0,0 +1,202 @@
/*! sass.js - v0.9.10 (9a781bf) - built 2016-04-24
providing libsass 3.3.6 (3ae9a20)
via emscripten 1.36.1 (d5085ed)
*/
(function (root, factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
define([], factory);
} else if (typeof exports === 'object') {
module.exports = factory();
} else {
root.Sass = factory();
}
}(this, function () {/*global document*/
// identify the path sass.js is located at in case we're loaded by a simple
// <script src="path/to/sass.js"></script>
// this path can be used to identify the location of
// * sass.worker.js from sass.js
// * libsass.js.mem from sass.sync.js
// see https://github.com/medialize/sass.js/pull/32#issuecomment-103142214
// see https://github.com/medialize/sass.js/issues/33
var SASSJS_RELATIVE_PATH = (function() {
'use strict';
// in Node things are rather simple
if (typeof __dirname !== 'undefined') {
return __dirname;
}
// we can only run this test in the browser,
// so make sure we actually have a DOM to work with.
if (typeof document === 'undefined' || !document.getElementsByTagName) {
return null;
}
// http://www.2ality.com/2014/05/current-script.html
var currentScript = document.currentScript || (function() {
var scripts = document.getElementsByTagName('script');
return scripts[scripts.length - 1];
})();
var path = currentScript && currentScript.src;
if (!path) {
return null;
}
// [worker] make sure we're not running in some concatenated thing
if (path.slice(-8) === '/sass.js') {
return path.slice(0, -8);
}
// [sync] make sure we're not running in some concatenated thing
if (path.slice(-13) === '/sass.sync.js') {
return path.slice(0, -13);
}
return null;
})() || '.';
/*global Worker, SASSJS_RELATIVE_PATH*/
'use strict';
var noop = function(){};
var slice = [].slice;
// defined upon first Sass.initialize() call
var globalWorkerUrl;
function Sass(workerUrl) {
if (!workerUrl && !globalWorkerUrl) {
/*jshint laxbreak:true */
throw new Error(
'Sass needs to be initialized with the URL of sass.worker.js - '
+ 'either via Sass.setWorkerUrl(url) or by new Sass(url)'
);
/*jshint laxbreak:false */
}
if (!globalWorkerUrl) {
globalWorkerUrl = workerUrl;
}
// bind all functions
// we're doing this because we used to have a single hard-wired instance that allowed
// [].map(Sass.removeFile) and we need to maintain that for now (at least until 1.0.0)
for (var key in this) {
if (typeof this[key] === 'function') {
this[key] = this[key].bind(this);
}
}
this._callbacks = {};
this._worker = new Worker(workerUrl || globalWorkerUrl);
this._worker.addEventListener('message', this._handleWorkerMessage, false);
}
// allow setting the workerUrl before the first Sass instance is initialized,
// where registering the global workerUrl would've happened automatically
Sass.setWorkerUrl = function(workerUrl) {
globalWorkerUrl = workerUrl;
};
Sass.style = {
nested: 0,
expanded: 1,
compact: 2,
compressed: 3
};
Sass.comments = {
'none': 0,
'default': 1
};
Sass.prototype = {
style: Sass.style,
comments: Sass.comments,
destroy: function() {
this._worker && this._worker.terminate();
this._worker = null;
this._callbacks = {};
this._importer = null;
},
_handleWorkerMessage: function(event) {
if (event.data.command) {
this[event.data.command](event.data.args);
}
this._callbacks[event.data.id] && this._callbacks[event.data.id](event.data.result);
delete this._callbacks[event.data.id];
},
_dispatch: function(options, callback) {
if (!this._worker) {
throw new Error('Sass worker has been terminated');
}
options.id = 'cb' + Date.now() + Math.random();
this._callbacks[options.id] = callback;
this._worker.postMessage(options);
},
_importerInit: function(args) {
// importer API done callback pushing results
// back to the worker
var done = function done(result) {
this._worker.postMessage({
command: '_importerFinish',
args: [result]
});
}.bind(this);
try {
this._importer(args[0], done);
} catch(e) {
done({ error: e.message });
throw e;
}
},
importer: function(importerCallback, callback) {
if (typeof importerCallback !== 'function' && importerCallback !== null) {
throw new Error('importer callback must either be a function or null');
}
// callback is executed in the main EventLoop
this._importer = importerCallback;
// tell worker to activate importer callback
this._worker.postMessage({
command: 'importer',
args: [Boolean(importerCallback)]
});
callback && callback();
},
};
var commands = 'writeFile readFile listFiles removeFile clearFiles lazyFiles preloadFiles options compile compileFile';
commands.split(' ').forEach(function(command) {
Sass.prototype[command] = function() {
var callback = slice.call(arguments, -1)[0];
var args = slice.call(arguments, 0, -1);
if (typeof callback !== 'function') {
args.push(callback);
callback = noop;
}
this._dispatch({
command: command,
args: args
}, callback);
};
});
// automatically set the workerUrl in case we're loaded by a simple
// <script src="path/to/sass.js"></script>
// see https://github.com/medialize/sass.js/pull/32#issuecomment-103142214
Sass.setWorkerUrl(SASSJS_RELATIVE_PATH + '/sass.worker.js');
return Sass;
}));

813
src/lib/sass.worker.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -5,13 +5,26 @@
var editur = window.editur || {}; var editur = window.editur || {};
var version = '1.6.0'; var version = '1.6.0';
var $ = document.querySelector.bind(document); window.$ = document.querySelector.bind(document);
var $all = document.querySelectorAll.bind(document); window.$all = document.querySelectorAll.bind(document);
var JsModes = {
JS: 'js',
ES6: 'es6',
COFFEESCRIPT: 'coffee'
};
var CssModes = {
CSS: 'js',
SCSS: 'scss',
LESS: 'less'
};
var updateTimer var updateTimer
, updateDelay = 500 , updateDelay = 500
, currentLayoutMode , currentLayoutMode
, hasSeenNotifications = true , hasSeenNotifications = true
, jsMode = JsModes.ES6
, cssMode = CssModes.LESS
, frame = $('#demo-frame') , frame = $('#demo-frame')
, htmlCode = $('#js-html-code') , htmlCode = $('#js-html-code')
, cssCode = $('#js-css-code') , cssCode = $('#js-css-code')
@ -27,6 +40,8 @@
, settingsBtn = $('#js-settings-btn') , settingsBtn = $('#js-settings-btn')
, notificationsBtn = $('#js-notifications-btn') , notificationsBtn = $('#js-notifications-btn')
, notificationsModal = $('#js-notifications-modal') , notificationsModal = $('#js-notifications-modal')
, jsModelLabel = $('#js-js-mode-label')
, cssModelLabel = $('#js-css-mode-label')
; ;
editur.cm = {}; editur.cm = {};
@ -46,6 +61,16 @@
} }
return 0; return 0;
} }
function deferred() {
var d = {};
var promise = new Promise(function (resolve, reject) {
d.resolve = resolve;
d.reject = reject;
});
d.promise = promise;
return Object.assign(d, promise);
}
function resetSplitting() { function resetSplitting() {
var gutters = $all('.gutter'); var gutters = $all('.gutter');
@ -59,10 +84,14 @@
$('#js-demo-side').setAttribute('style', ''); $('#js-demo-side').setAttribute('style', '');
Split(['#js-html-code', '#js-css-code', '#js-js-code'], { Split(['#js-html-code', '#js-css-code', '#js-js-code'], {
direction: (currentLayoutMode === 2 ? 'horizontal' : 'vertical') direction: (currentLayoutMode === 2 ? 'horizontal' : 'vertical'),
minSize: 34,
gutterSize: 6
}); });
Split(['#js-code-side', '#js-demo-side' ], { Split(['#js-code-side', '#js-demo-side' ], {
direction: (currentLayoutMode === 2 ? 'vertical' : 'horizontal') direction: (currentLayoutMode === 2 ? 'vertical' : 'horizontal'),
minSize: 34,
gutterSize: 6
}); });
} }
function toggleLayout(mode) { function toggleLayout(mode) {
@ -95,16 +124,55 @@
saveSetting('code', code); saveSetting('code', code);
} }
function updateCssMode(value) {
cssMode = value;
cssModelLabel.textContent = value;
editur.cm.css.setOption('mode', value);
}
function updateJsMode(value) {
jsMode = value;
jsModelLabel.textContent = value;
editur.cm.js.setOption('mode', value);
}
function computeHtml() {
return editur.cm.html.getValue();
}
function computeCss() {
var d = deferred();
var code = editur.cm.css.getValue();
if (cssMode === CssModes.CSS) {
d.resolve(code);
} else if (cssMode === CssModes.SCSS) {
sass.compile(code, function(result) {
d.resolve(result.text);
});
} else if (cssMode === CssModes.LESS) {
less.render(code).then(function (result) {
d.resolve(result.css);
});
}
return d.promise;
}
function computeJs() {
var d = deferred();
var code = editur.cm.js.getValue();
if (jsMode === JsModes.JS) {
d.resolve(code);
} else if (jsMode === JsModes.COFFEESCRIPT) {
d.resolve(CoffeeScript.compile(code, {bare: true}));
} else if (jsMode === JsModes.ES6) {
d.resolve(Babel.transform(editur.cm.js.getValue(), { presets: ['es2015'] }).code);
}
return d.promise;
}
window.onunload = function () { window.onunload = function () {
saveCode(); saveCode();
}; };
editur.setPreviewContent = function () { function createPreviewFile(html, css, js) {
var html = editur.cm.html.getValue();
var css = editur.cm.css.getValue();
var js = editur.cm.js.getValue();
html = '<html>\n<head>\n<style>\n' + css + '\n</style>\n</head>\n<body>\n' + html + '\n<script>\n' + js + '\n</script></body>\n</html>'; html = '<html>\n<head>\n<style>\n' + css + '\n</style>\n</head>\n<body>\n' + html + '\n<script>\n' + js + '\n</script></body>\n</html>';
var fileWritten = false; var fileWritten = false;
@ -131,6 +199,15 @@
}, errorHandler); }, errorHandler);
}, errorHandler); }, errorHandler);
}, errorHandler); }, errorHandler);
}
editur.setPreviewContent = function () {
var html = computeHtml();
var cssPromise = css = computeCss();
var js = computeJs();
Promise.all([html, cssPromise, js]).then(function (result) {
createPreviewFile(result[0], result[1], result[2]);
});
}; };
function saveFile() { function saveFile() {
@ -194,6 +271,8 @@
function init () { function init () {
var lastCode; var lastCode;
window.sass = new Sass('lib/sass.worker.js');
layoutBtn1.addEventListener('click', function () { saveSetting('layoutMode', 1); toggleLayout(1); return false; }); layoutBtn1.addEventListener('click', function () { saveSetting('layoutMode', 1); toggleLayout(1); return false; });
layoutBtn2.addEventListener('click', function () { saveSetting('layoutMode', 2); toggleLayout(2); return false; }); layoutBtn2.addEventListener('click', function () { saveSetting('layoutMode', 2); toggleLayout(2); return false; });
layoutBtn3.addEventListener('click', function () { saveSetting('layoutMode', 3); toggleLayout(3); return false; }); layoutBtn3.addEventListener('click', function () { saveSetting('layoutMode', 3); toggleLayout(3); return false; });
@ -234,6 +313,25 @@
saveFile(); saveFile();
}); });
// Attach listeners on mode change menu items
var modeItems = [].slice.call($all('.js-modes-menu a'));
modeItems.forEach(function (item) {
item.addEventListener('click', function (e) {
var mode = e.currentTarget.dataset.mode;
var type = e.currentTarget.dataset.type;
var currentMode = type === 'js' ? jsMode : cssMode;
if (currentMode !== mode) {
if (type = 'js') {
updateJsMode(mode);
} else {
updateCssMode(mode);
}
}
});
});
updateJsMode(jsMode);
updateCssMode(cssMode);
window.addEventListener('keydown', function (event) { window.addEventListener('keydown', function (event) {
if ((event.ctrlKey || event.metaKey) && (event.keyCode === 83)){ if ((event.ctrlKey || event.metaKey) && (event.keyCode === 83)){
event.preventDefault(); event.preventDefault();