mirror of
https://github.com/chinchang/web-maker.git
synced 2025-07-17 20:11:12 +02:00
add support for sass,es6,less n coffee.
This commit is contained in:
118
src/index.html
118
src/index.html
@@ -29,6 +29,16 @@
|
||||
.fr {
|
||||
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 {
|
||||
position: absolute;
|
||||
left: 0; right: 0;
|
||||
@@ -59,9 +69,9 @@
|
||||
height: 33%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
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;
|
||||
opacity: 0;
|
||||
/*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;*/
|
||||
/*opacity: 0;*/
|
||||
}
|
||||
.layout-2 .code-wrap {
|
||||
height: auto;
|
||||
@@ -74,17 +84,12 @@
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
|
||||
.code-wrap:after {
|
||||
content: attr(data-type);
|
||||
text-transform: uppercase;
|
||||
font-size: 65px;
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
color: rgba(255,255,255,0.04);
|
||||
left: 52px;
|
||||
z-index: 3;
|
||||
pointer-events: none;
|
||||
.code-wrap__header {
|
||||
padding: 5px 20px;
|
||||
background: rgba(0,0,0,0.55);
|
||||
color: #888;
|
||||
border-bottom: 1px solid rgba(0,0,0,0.3);
|
||||
font-weight: bold;
|
||||
}
|
||||
@keyframes pop-in {
|
||||
from { transform: scale(0.9); opacity: 0; }
|
||||
@@ -94,7 +99,7 @@
|
||||
/* Codemirror */
|
||||
.Codemirror {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
height: calc(100% - 25px); /* 25px for header */
|
||||
font-size: 16px;
|
||||
}
|
||||
.cm-s-monokai .CodeMirror-linenumber {
|
||||
@@ -167,6 +172,9 @@
|
||||
.mode-btn.selected svg {
|
||||
fill: rgba(255, 255, 255, 0.45);
|
||||
}
|
||||
.gutter {
|
||||
background: rgba(0,0,0,0.2);
|
||||
}
|
||||
.gutter-horizontal {
|
||||
cursor: ew-resize;
|
||||
}
|
||||
@@ -274,6 +282,49 @@
|
||||
top: 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>
|
||||
</head>
|
||||
|
||||
@@ -281,9 +332,33 @@
|
||||
<div class="main-container">
|
||||
<div class="content-wrap flex flex-grow">
|
||||
<div class="code-side" id="js-code-side">
|
||||
<div id="js-html-code" data-type="html" class="code-wrap"></div>
|
||||
<div id="js-css-code" data-type="css" class="code-wrap"></div>
|
||||
<div id="js-js-code" data-type="js" class="code-wrap"></div>
|
||||
<div id="js-html-code" data-type="html" class="code-wrap">
|
||||
<div class="code-wrap__header">HTML</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 class="demo-side" id="js-demo-side">
|
||||
<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/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="script.js"></script>
|
||||
<script src="dropdown.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
32
src/lib/babel.min.js
vendored
Normal file
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
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
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
202
src/lib/sass.js
Normal 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
813
src/lib/sass.worker.js
Normal file
File diff suppressed because one or more lines are too long
118
src/script.js
118
src/script.js
@@ -5,13 +5,26 @@
|
||||
var editur = window.editur || {};
|
||||
var version = '1.6.0';
|
||||
|
||||
var $ = document.querySelector.bind(document);
|
||||
var $all = document.querySelectorAll.bind(document);
|
||||
window.$ = document.querySelector.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
|
||||
, updateDelay = 500
|
||||
, currentLayoutMode
|
||||
, hasSeenNotifications = true
|
||||
, jsMode = JsModes.ES6
|
||||
, cssMode = CssModes.LESS
|
||||
|
||||
, frame = $('#demo-frame')
|
||||
, htmlCode = $('#js-html-code')
|
||||
, cssCode = $('#js-css-code')
|
||||
@@ -27,6 +40,8 @@
|
||||
, settingsBtn = $('#js-settings-btn')
|
||||
, notificationsBtn = $('#js-notifications-btn')
|
||||
, notificationsModal = $('#js-notifications-modal')
|
||||
, jsModelLabel = $('#js-js-mode-label')
|
||||
, cssModelLabel = $('#js-css-mode-label')
|
||||
;
|
||||
|
||||
editur.cm = {};
|
||||
@@ -46,6 +61,16 @@
|
||||
}
|
||||
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() {
|
||||
var gutters = $all('.gutter');
|
||||
@@ -59,10 +84,14 @@
|
||||
$('#js-demo-side').setAttribute('style', '');
|
||||
|
||||
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' ], {
|
||||
direction: (currentLayoutMode === 2 ? 'vertical' : 'horizontal')
|
||||
direction: (currentLayoutMode === 2 ? 'vertical' : 'horizontal'),
|
||||
minSize: 34,
|
||||
gutterSize: 6
|
||||
});
|
||||
}
|
||||
function toggleLayout(mode) {
|
||||
@@ -95,16 +124,55 @@
|
||||
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 () {
|
||||
saveCode();
|
||||
};
|
||||
|
||||
editur.setPreviewContent = function () {
|
||||
var html = editur.cm.html.getValue();
|
||||
var css = editur.cm.css.getValue();
|
||||
var js = editur.cm.js.getValue();
|
||||
|
||||
|
||||
function createPreviewFile(html, css, js) {
|
||||
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;
|
||||
@@ -131,6 +199,15 @@
|
||||
}, 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() {
|
||||
@@ -194,6 +271,8 @@
|
||||
function init () {
|
||||
var lastCode;
|
||||
|
||||
window.sass = new Sass('lib/sass.worker.js');
|
||||
|
||||
layoutBtn1.addEventListener('click', function () { saveSetting('layoutMode', 1); toggleLayout(1); return false; });
|
||||
layoutBtn2.addEventListener('click', function () { saveSetting('layoutMode', 2); toggleLayout(2); return false; });
|
||||
layoutBtn3.addEventListener('click', function () { saveSetting('layoutMode', 3); toggleLayout(3); return false; });
|
||||
@@ -234,6 +313,25 @@
|
||||
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) {
|
||||
if ((event.ctrlKey || event.metaKey) && (event.keyCode === 83)){
|
||||
event.preventDefault();
|
||||
|
Reference in New Issue
Block a user