1
0
mirror of https://github.com/chinchang/web-maker.git synced 2025-05-16 07:09:40 +02:00
php-web-maker/src/script.js
2016-07-15 02:17:10 +05:30

485 lines
14 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* eslint-disable no-extra-semi */
;(function () {
/* eslint-enable no-extra-semi */
var editur = window.editur || {};
var version = '1.6.0';
window.$ = document.querySelector.bind(document);
window.$all = document.querySelectorAll.bind(document);
var HtmlModes = {
HTML: 'html',
MARKDOWN: 'markdown',
JADE: 'jade' // unsafe eval is put in manifest for this file
};
var CssModes = {
CSS: 'css',
SCSS: 'scss',
LESS: 'less'
};
var JsModes = {
JS: 'js',
ES6: 'es6',
COFFEESCRIPT: 'coffee'
};
var modes = {};
modes[HtmlModes.HTML] = { label: 'HTML', cmMode: 'htmlmixed', codepenVal: 'none' };
modes[HtmlModes.MARKDOWN] = { label: 'Markdown', cmMode: 'markdown', codepenVal: 'markdown' };
modes[HtmlModes.JADE] = { label: 'Jade', cmMode: 'jade', codepenVal: 'jade' };
modes[JsModes.JS] = { label: 'JS', cmMode: 'javascript', codepenVal: 'none' };
modes[JsModes.COFFEESCRIPT] = { label: 'CoffeeScript', cmMode: 'coffeescript', codepenVal: 'coffeescript' };
modes[JsModes.ES6] = { label: 'ES6 (Babel)', cmMode: 'javascript', codepenVal: 'babel' };
modes[CssModes.CSS] = { label: 'CSS', cmMode: 'css', codepenVal: 'none' };
modes[CssModes.SCSS] = { label: 'SCSS', cmMode: 'sass', codepenVal: 'scss' };
modes[CssModes.LESS] = { label: 'LESS', cmMode: 'text/x-less', codepenVal: 'less' };
var updateTimer
, updateDelay = 500
, currentLayoutMode
, hasSeenNotifications = true
, htmlMode = HtmlModes.HTML
, jsMode = JsModes.JS
, cssMode = CssModes.CSS
, frame = $('#demo-frame')
, htmlCode = $('#js-html-code')
, cssCode = $('#js-css-code')
, jsCode = $('#js-js-code')
, layoutBtn1 = $('#js-layout-btn-1')
, layoutBtn2 = $('#js-layout-btn-2')
, layoutBtn3 = $('#js-layout-btn-3')
, helpBtn = $('#js-help-btn')
, helpModal = $('#js-help-modal')
, codepenBtn = $('#js-codepen-btn')
, codepenForm = $('#js-codepen-form')
, saveHtmlBtn = $('#js-save-html')
, settingsBtn = $('#js-settings-btn')
, notificationsBtn = $('#js-notifications-btn')
, notificationsModal = $('#js-notifications-modal')
, htmlModelLabel = $('#js-html-mode-label')
, cssModelLabel = $('#js-css-mode-label')
, jsModelLabel = $('#js-js-mode-label')
;
editur.cm = {};
editur.demoFrameDocument = frame.contentDocument || frame.contentWindow.document;
// https://github.com/substack/semver-compare/blob/master/index.js
function semverCompare (a, b) {
var pa = a.split('.');
var pb = b.split('.');
for (var i = 0; i < 3; i++) {
var na = Number(pa[i]);
var nb = Number(pb[i]);
if (na > nb) { return 1; }
if (nb > na) { return -1; }
if (!isNaN(na) && isNaN(nb)) { return 1; }
if (isNaN(na) && !isNaN(nb)) { return -1; }
}
return 0;
}
function resetSplitting() {
var gutters = $all('.gutter');
for (var i = gutters.length; i--;) {
gutters[i].remove();
}
$('#js-html-code').setAttribute('style', '');
$('#js-css-code').setAttribute('style', '');
$('#js-js-code').setAttribute('style', '');
$('#js-code-side').setAttribute('style', '');
$('#js-demo-side').setAttribute('style', '');
Split(['#js-html-code', '#js-css-code', '#js-js-code'], {
direction: (currentLayoutMode === 2 ? 'horizontal' : 'vertical'),
minSize: 34,
gutterSize: 6
});
Split(['#js-code-side', '#js-demo-side' ], {
direction: (currentLayoutMode === 2 ? 'vertical' : 'horizontal'),
minSize: 34,
gutterSize: 6
});
}
function toggleLayout(mode) {
currentLayoutMode = mode;
$('#js-layout-btn-1').classList.remove('selected');
$('#js-layout-btn-2').classList.remove('selected');
$('#js-layout-btn-3').classList.remove('selected');
$('#js-layout-btn-' + mode).classList.add('selected');
document.body.classList.remove('layout-1');
document.body.classList.remove('layout-2');
document.body.classList.remove('layout-3');
document.body.classList.add('layout-' + mode);
resetSplitting();
}
function saveSetting(setting, value) {
var obj = {};
obj[setting] = value;
chrome.storage.local.set(obj, function() {
});
}
function saveCode() {
var code = {
html: editur.cm.html.getValue(),
css: editur.cm.css.getValue(),
js: editur.cm.js.getValue()
};
saveSetting('code', code);
}
/**
* Loaded the code comiler based on the mode selected
*/
function handleModeRequirements(mode) {
// Exit if already loaded
if (modes[mode].hasLoaded) { return; }
function setLoadedFlag() {
modes[mode].hasLoaded = true;
}
if (mode === HtmlModes.JADE) {
loadJS('lib/jade.js').then(setLoadedFlag);
} else if (mode === HtmlModes.MARKDOWN) {
loadJS('lib/marked.js').then(setLoadedFlag);
} else if (mode === CssModes.LESS) {
loadJS('lib/less.min.js').then(setLoadedFlag);
} else if (mode === CssModes.SCSS) {
loadJS('lib/sass.js').then(function () {
window.sass = new Sass('lib/sass.worker.js');
setLoadedFlag();
});
} else if (mode === JsModes.COFFEESCRIPT) {
loadJS('lib/coffee-script.js').then(setLoadedFlag);
} else if (mode === JsModes.ES6) {
loadJS('lib/babel.min.js').then(setLoadedFlag);
}
}
function updateHtmlMode(value) {
htmlMode = value;
htmlModelLabel.textContent = modes[value].label;
handleModeRequirements(value);
CodeMirror.autoLoadMode(editur.cm.html, modes[value].cmMode);
chrome.storage.sync.set({
htmlMode: value
}, function () {});
}
function updateCssMode(value) {
cssMode = value;
cssModelLabel.textContent = modes[value].label;
handleModeRequirements(value);
CodeMirror.autoLoadMode(editur.cm.css, modes[value].cmMode);
chrome.storage.sync.set({
cssMode: value
}, function () {});
}
function updateJsMode(value) {
jsMode = value;
jsModelLabel.textContent = modes[value].label;
handleModeRequirements(value);
CodeMirror.autoLoadMode(editur.cm.js, modes[value].cmMode);
chrome.storage.sync.set({
jsMode: value
}, function () {});
}
// computeHtml, computeCss & computeJs evaluate the final code according
// to whatever mode is selected and resolve the returned promise with the code.
function computeHtml() {
var d = deferred();
var code = editur.cm.html.getValue();
if (htmlMode === HtmlModes.HTML) {
d.resolve(code);
} else if (htmlMode === HtmlModes.MARKDOWN) {
d.resolve(marked(code));
} else if (htmlMode === HtmlModes.JADE) {
d.resolve(jade.render(code));
}
return d.promise;
}
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();
};
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;
var blob = new Blob([ html ], {type: "text/plain;charset=UTF-8"});
function errorHandler() { console.log(arguments); }
window.webkitRequestFileSystem(window.TEMPORARY, 1024 * 1024 * 5, function(fs){
fs.root.getFile('preview.html', {create: true}, function(fileEntry) {
fileEntry.createWriter(function(fileWriter) {
function onWriteComplete() {
if (fileWritten) {
frame.src = 'filesystem:chrome-extension://' + chrome.i18n.getMessage('@@extension_id') + '/temporary/' + 'preview.html';
}
else {
fileWritten = true;
fileWriter.seek(0);
fileWriter.write(blob);
}
}
fileWriter.onwriteend = onWriteComplete;
fileWriter.truncate(0)
}, errorHandler);
}, errorHandler);
}, errorHandler);
}
editur.setPreviewContent = function () {
var htmlPromise = computeHtml();
var cssPromise = computeCss();
var jsPromise = computeJs();
Promise.all([htmlPromise, cssPromise, jsPromise]).then(function (result) {
createPreviewFile(result[0], result[1], result[2]);
});
};
function saveFile() {
var htmlPromise = computeHtml();
var cssPromise = computeCss();
var jsPromise = computeJs();
Promise.all([htmlPromise, cssPromise, jsPromise]).then(function (result) {
var html = result[0],
css = result[1],
js = result[2];
var fileContent = '<html><head>\n<style>\n'
+ css + '\n</style>\n</head>\n<body>\n'
+ html + '\n<script>\n' + js + '\n</script>\n\n</body>\n</html>';
var d = new Date();
var fileName = [ 'web-maker', d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds() ].join('-');
fileName += '.html';
var a = document.createElement('a');
var blob = new Blob([ fileContent ], {type: "text/html;charset=UTF-8"});
a.href = window.URL.createObjectURL(blob);
a.download = fileName;
a.style.display = 'none';
document.body.appendChild(a);
a.click();
a.remove();
});
}
function initEditor(element, options) {
var cm = CodeMirror(element, {
mode: options.mode,
lineNumbers: true,
lineWrapping: true,
autofocus: options.autofocus || false,
autoCloseBrackets: true,
matchBrackets: true,
tabMode: 'indent',
keyMap: 'sublime',
theme: 'monokai',
// cursorScrollMargin: '20', has issue with scrolling
profile: options.profile || ''
});
cm.on('change', function onChange() {
clearTimeout(updateTimer);
updateTimer = setTimeout(function () {
editur.setPreviewContent();
}, updateDelay);
});
return cm;
}
editur.cm.html = initEditor(htmlCode, {
mode: 'htmlmixed',
profile: 'xhtml'
});
emmetCodeMirror(editur.cm.html);
editur.cm.css = initEditor(cssCode, {
mode: 'css'
});
editur.cm.js = initEditor(jsCode, {
mode: 'javascript'
});
function init () {
var lastCode;
CodeMirror.modeURL = "lib/codemirror/mode/%N/%N.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; });
helpBtn.addEventListener('click', function () {
helpModal.classList.toggle('is-modal-visible');
return false;
});
notificationsBtn.addEventListener('click', function () {
notificationsModal.classList.toggle('is-modal-visible');
if (notificationsModal.classList.contains('is-modal-visible') && !hasSeenNotifications) {
hasSeenNotifications = true;
notificationsBtn.classList.remove('has-new');
chrome.storage.sync.set({
lastSeenVersion: version
}, function () {});
}
return false;
});
codepenBtn.addEventListener('click', function (e) {
var json = {
title: 'A Web Maker experiment',
html: editur.cm.html.getValue(),
css: editur.cm.css.getValue(),
js: editur.cm.js.getValue(),
html_pre_processor: modes[htmlMode].codepenVal,
css_pre_processor: modes[cssMode].codepenVal,
js_pre_processor: modes[jsMode].codepenVal
};
json = JSON.stringify(json)
.replace(/"/g, "&quot;")
.replace(/'/g, "&apos;")
codepenForm.querySelector('input').value = json;
codepenForm.submit();
e.preventDefault();
});
saveHtmlBtn.addEventListener('click', function () {
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 === 'html' ? htmlMode : (type === 'css' ? cssMode : jsMode);
if (currentMode !== mode) {
if (type === 'html') {
updateHtmlMode(mode);
} else if (type === 'js') {
updateJsMode(mode);
} else if (type === 'css') {
updateCssMode(mode);
}
}
});
});
window.addEventListener('keydown', function (event) {
if ((event.ctrlKey || event.metaKey) && (event.keyCode === 83)){
event.preventDefault();
saveFile();
}
});
window.addEventListener('click', function(e) {
if (typeof e.target.className === 'string' && e.target.className.indexOf('modal-overlay') !== -1) {
helpModal.classList.remove('is-modal-visible');
notificationsModal.classList.remove('is-modal-visible');
}
});
settingsBtn.addEventListener('click', function() {
if (!chrome.runtime.openOptionsPage) {
// New way to open options pages, if supported (Chrome 42+).
// Bug: https://bugs.chromium.org/p/chromium/issues/detail?id=601997
// Until this bug fixes, use the
// fallback.
chrome.runtime.openOptionsPage();
} else {
// Fallback.
chrome.tabs.create({
url: 'chrome://extensions?options=' + chrome.i18n.getMessage('@@extension_id')
});
}
return false;
});
chrome.storage.local.get({
layoutMode: 1,
code: ''
}, function localGetCallback(result) {
toggleLayout(result.layoutMode);
if (result.code) {
lastCode = result.code;
}
});
// Get synced `preserveLastCode` setting to get back last code (or not).
chrome.storage.sync.get({
preserveLastCode: true,
htmlMode: 'html',
jsMode: 'js',
cssMode: 'css'
}, function syncGetCallback(result) {
if (result.preserveLastCode && lastCode) {
editur.cm.html.setValue(lastCode.html);
editur.cm.css.setValue(lastCode.css);
editur.cm.js.setValue(lastCode.js);
editur.cm.html.refresh();
editur.cm.css.refresh();
editur.cm.js.refresh();
}
updateHtmlMode(result.htmlMode);
updateJsMode(result.jsMode);
updateCssMode(result.cssMode);
});
// Check for new version notifications
chrome.storage.sync.get({
lastSeenVersion: ''
}, function syncGetCallback(result) {
// console.log(result, hasSeenNotifications, version);
if (!result.lastSeenVersion || semverCompare(result.lastSeenVersion, version) === -1) {
notificationsBtn.classList.add('has-new');
hasSeenNotifications = false;
}
});
}
init();
})();