1
0
mirror of https://github.com/chinchang/web-maker.git synced 2025-02-24 07:03:13 +01:00

Merge pull request #108 from chinchang/release-2.5

Release 2.5
This commit is contained in:
Kushagra Gour 2017-05-01 01:50:59 +05:30 committed by GitHub
commit 8cf23e2ad4
7 changed files with 19178 additions and 44 deletions

View File

@ -256,6 +256,7 @@
"Sass": true,
"less": true,
"stylus": true,
"atomizer": true,
"marked": true,
"jade": true,
"loadJS": true,

View File

@ -11,7 +11,7 @@
}
}
function init() {
var dropdowns = [].slice.call($all('[dropdown]'));
var dropdowns = $all('[dropdown]');
dropdowns.forEach(function (dropdown) {
dropdown.addEventListener('click', function (e) {
closeOpenDropdown(e.currentTarget);

View File

@ -17,6 +17,12 @@
<div class="main-container">
<div class="main-header">
<div class="main-header__btn-wrap fr flex flex-v-center">
<a id="runBtn" class="hide flex flex-v-center hint--rounded hint--bottom-left" aria-label="Run preview (Ctrl/⌘ + Shift + 5)" d-click="setPreviewContent">
<svg style="width: 14px; height: 14px;">
<use xlink:href="#play-icon"></use>
</svg>Run
</a>
<a id="js-add-library-btn" class="fleex-v-center hint--rounded hint--bottom-left" aria-label="Add a JS/CSS library">
Add library <span id="js-external-lib-count" style="display:none;" class="count-label"></span>
</a>
@ -66,6 +72,7 @@
<li><a data-type="css" data-mode="sass">SASS</a></li>
<li><a data-type="css" data-mode="less">LESS</a></li>
<li><a data-type="css" data-mode="stylus">Stylus</a></li>
<li><a data-type="css" data-mode="acss">Atomic CSS</a></li>
</ul>
</div>
<div class="code-wrap__header-right-options">
@ -203,7 +210,7 @@
<div class="modal" id="helpModal">
<div class="modal__content">
<h1>Web Maker<small style="font-size:14px;"> v2.4.3</small></h1>
<h1>Web Maker<small style="font-size:14px;"> v2.5.0</small></h1>
<div>
<p>Made with <span style="margin-right: 8px;">💖</span> & <span style="margin-right: 8px;">🙌</span> by <a href="https://twitter.com/chinchang457" target="_blank">Kushagra Gour</a></p>
<p>Tweet out your feature requests, comments & suggestions to <a target="_blank" href="https://twitter.com/webmakerApp">@webmakerApp</a>.</p>
@ -366,6 +373,12 @@
<input type="radio" name="keymap" value="vim" d-change="updateSetting" data-setting="keymap"> Vim
</label>
</div>
<label class="line">
<input type="checkbox" d-change="updateSetting" data-setting="refreshOnResize"> Refresh preview on resize
</label>
<label class="line">
<input type="checkbox" d-change="updateSetting" data-setting="autoPreview"> Auto-preview
</label>
<label class="line">
<input type="checkbox" d-change="updateSetting" data-setting="preserveLastCode"> Preserve last written code
</label>
@ -387,14 +400,25 @@
<div class="modal" id="notificationsModal">
<div class="modal__content">
<h1>Whats new?</h1>
<div class="notification">
<span class="notification__version">2.5.0</span>
<ul>
<li><strong>Atomic CSS</strong>: Use can now use Atomic CSS(ACSS) in your work! <a href="https://acss.io/" target="_blank">Read more about it here</a>.</li>
<li><strong>Search your saved creations</strong>: Easily search through all your saved creations by title.</li>
<li><strong>Configurable Auto-preview</strong> - You can turn off the auto preview in settings if you don't want the preview to update as you type.</li>
<li><strong>Configurable refresh on resize</strong> - You can configure whether you want the preview to refresh when you resize the preview panel.</li>
<li><strong>Bugfix</strong> - Fix indentation <a href="https://github.com/chinchang/web-maker/issues/104" target="_blank">issue</a> with custom indentation size.</li>
<li><a href="https://github.com/chinchang/web-maker/issues" target="_blank">Suggest features or report bugs.</a></li>
<li>Thank you for being a part of this community of thousands of awesome developers. If you find Web Maker helpful, <a href="https://chrome.google.com/webstore/detail/web-maker/lkfkkhfhhdkiemehlpkgjeojomhpccnh/reviews" target="_blank" class="btn">Please rate Web Maker <span class="star"></span></a> & <a href="http://twitter.com/share?url=https://webmakerapp.com/&text=Web Maker - A blazing fast %26 offline web playground! via @webmakerApp&related=webmakerApp&hashtags=web,editor,chrome,extension" target="_blank" target="_blank" class="btn">share it</a>.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.4.2</span>
<ul>
<li><strong>Improved infinite loop protection</strong>: Infinite loop protection is now faster and more reliable. And works without the need of Escodegen. Thanks to Ariya Hidayat!</li>
<li><strong>Bugfix</strong> - Default parameters not working in JavaScript is fixed.</li>
<li><a href="https://github.com/chinchang/web-maker/issues" target="_blank">Suggest features or report bugs.</a></li>
<li>Thank you for being a part of this community of thousands of awesome developers. If you find Web Maker helpful, <a href="https://chrome.google.com/webstore/detail/web-maker/lkfkkhfhhdkiemehlpkgjeojomhpccnh/reviews" target="_blank" class="btn">Please rate Web Maker <span class="star"></span></a> & <a href="http://twitter.com/share?url=https://webmakerapp.com/&text=Web Maker - A blazing fast %26 offline web playground! via @webmakerApp&related=webmakerApp&hashtags=web,editor,chrome,extension" target="_blank" target="_blank" class="btn">share it</a>.</li>
</ul>
</div>
@ -494,17 +518,18 @@
<div id="js-saved-items-pane" class="saved-items-pane">
<button class="btn saved-items-pane__close-btn" id="js-saved-items-pane-close-btn">X</button>
<div class="flex flex-v-center" style="justify-content: space-between;">
<h3>My Library <span id="savedItemCountEl"></span></h3>
<h3>My Library <span id="savedItemCountEl"></span></h3>
<div class="main-header__btn-wrap">
<a d-click="exportItems" href="" class="btn btn-icon">Export
</a>
<a d-click="onImportBtnClicked" href="" class="btn btn-icon">Import
</a>
</div>
<div class="main-header__btn-wrap">
<a d-click="exportItems" href="" class="btn btn-icon">Export
</a>
<a d-click="onImportBtnClicked" href="" class="btn btn-icon">Import
</a>
</div>
</div>
<input type="" id="searchInput" class="search-input" d-input="onSearchInputChange" placeholder="Search your creations here...">
<div id="js-saved-items-wrap" class="saved-items-pane__container">
</div>
</div>
@ -547,6 +572,11 @@
<symbol id="heart-icon" viewBox="0 0 24 24">
<path d="M12,21.35L10.55,20.03C5.4,15.36 2,12.27 2,8.5C2,5.41 4.42,3 7.5,3C9.24,3 10.91,3.81 12,5.08C13.09,3.81 14.76,3 16.5,3C19.58,3 22,5.41 22,8.5C22,12.27 18.6,15.36 13.45,20.03L12,21.35Z" />
</symbol>
<symbol id="play-icon" viewBox="0 0 24 24">
<svg>
<path d="M8,5.14V19.14L19,12.14L8,5.14Z" />
</svg>
</symbol>
</svg>
<script src="lib/codemirror/lib/codemirror.js"></script>

18997
src/lib/atomizer.browser.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -4,13 +4,15 @@ onboardModal, layoutBtn1, layoutBtn2, layoutBtn3, layoutBtn4, helpBtn, onboardMo
addLibraryModal, addLibraryModal, notificationsBtn, notificationsModal, notificationsModal,
notificationsModal, notificationsBtn, codepenBtn, saveHtmlBtn, saveBtn, settingsBtn,
onboardModal, settingsModal, notificationsBtn, onboardShowInTabOptionBtn, editorThemeLinkTag,
onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentationSizeValueEl */
onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentationSizeValueEl,
runBtn, searchInput
*/
/* eslint-disable no-extra-semi */
;(function (alertsService) {
/* eslint-enable no-extra-semi */
var scope = scope || {};
var version = '2.4.2';
var version = '2.5.0';
if (window.DEBUG) {
window.scope = scope;
@ -26,7 +28,8 @@ onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentati
SCSS: 'scss',
SASS: 'sass',
LESS: 'less',
STYLUS: 'stylus'
STYLUS: 'stylus',
ACSS: 'acss'
};
var JsModes = {
JS: 'js',
@ -47,6 +50,7 @@ onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentati
modes[CssModes.SASS] = { label: 'SASS', cmMode: 'sass', codepenVal: 'sass' };
modes[CssModes.LESS] = { label: 'LESS', cmPath: 'css', cmMode: 'text/x-less', codepenVal: 'less' };
modes[CssModes.STYLUS] = { label: 'Stylus', cmMode: 'stylus', codepenVal: 'stylus' };
modes[CssModes.ACSS] = { label: 'Atomic CSS', cmPath: 'css', cmMode: 'css', codepenVal: 'notsupported', cmDisable: true };
var updateTimer
, updateDelay = 500
@ -66,6 +70,7 @@ onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentati
, prefs = {}
, codeInPreview = { html: null, css: null, js: null }
, isSavedItemsPaneOpen = false
, editorWithFocus
// DOM nodes
, frame = $('#demo-frame')
@ -158,11 +163,13 @@ onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentati
gutterSize: 6,
sizes: getMainSplitSizesToApply(),
onDragEnd: function () {
// Running preview updation in next call stack, so that error there
// doesn't affect this dragend listener.
setTimeout(function () {
scope.setPreviewContent(true);
}, 1);
if (prefs.refreshOnResize) {
// Running preview updation in next call stack, so that error there
// doesn't affect this dragend listener.
setTimeout(function () {
scope.setPreviewContent(true);
}, 1);
}
}
});
}
@ -330,6 +337,15 @@ onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentati
savedItemsPane.classList.toggle('is-open');
}
isSavedItemsPaneOpen = savedItemsPane.classList.contains('is-open');
if (isSavedItemsPaneOpen) {
searchInput.focus();
} else {
searchInput.value = '';
// Give last focused editor, focus again
if (editorWithFocus) {
editorWithFocus.focus();
}
}
document.body.classList[isSavedItemsPaneOpen ? 'add' : 'remove']('overlay-visible');
}
@ -347,7 +363,7 @@ onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentati
d.resolve([]);
}
savedItems = savedItems || [];
savedItems = savedItems || {};
trackEvent('fn', 'fetchItems', itemIds.length);
for (let i = 0; i < itemIds.length; i++) {
@ -500,6 +516,8 @@ onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentati
});
} else if (mode === CssModes.STYLUS) {
loadJS('lib/stylus.min.js').then(setLoadedFlag);
} else if (mode === CssModes.ACSS) {
loadJS('lib/atomizer.browser.js').then(setLoadedFlag);
} else if (mode === JsModes.COFFEESCRIPT) {
loadJS('lib/coffee-script.js').then(setLoadedFlag);
} else if (mode === JsModes.ES6) {
@ -524,6 +542,7 @@ onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentati
cssMode = value;
cssModelLabel.textContent = modes[value].label;
scope.cm.css.setOption('mode', modes[value].cmMode);
scope.cm.css.setOption('readOnly', modes[value].cmDisable);
CodeMirror.autoLoadMode(scope.cm.css, modes[value].cmPath || modes[value].cmMode);
return handleModeRequirements(value);
}
@ -586,6 +605,13 @@ onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentati
}
d.resolve(result);
});
} else if (cssMode === CssModes.ACSS) {
const html = scope.cm.html.getValue();
const foundClasses = atomizer.findClassNames(html);
const finalConfig = atomizer.getConfig(foundClasses, {});
const acss = atomizer.getCss(finalConfig);
scope.cm.css.setValue(acss);
d.resolve(acss)
}
return d.promise;
@ -876,6 +902,9 @@ onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentati
}
}
});
cm.on('focus', (editor) => {
editorWithFocus = editor;
});
cm.on('change', function onChange(editor, change) {
clearTimeout(updateTimer);
@ -883,7 +912,11 @@ onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentati
// This is done so that multiple simultaneous setValue don't trigger too many preview refreshes
// and in turn too many file writes on a single file (eg. preview.html).
if (change.origin !== 'setValue') {
scope.setPreviewContent();
// Specifically checking for false so that the condition doesn't get true even
// on absent key - possible when the setting key hasn't been fetched yet.
if (prefs.autoPreview !== false) {
scope.setPreviewContent();
}
saveBtn.classList.add('is-marked');
unsavedEditCount += 1;
@ -1171,6 +1204,8 @@ onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentati
$('[data-setting=editorTheme]').value = prefs.editorTheme;
$('[data-setting=keymap][value=' + (prefs.keymap || 'sublime') + ']').checked = true;
$('[data-setting=fontSize]').value = prefs.fontSize || 16;
$('[data-setting=refreshOnResize]').checked = prefs.refreshOnResize;
$('[data-setting=autoPreview]').checked = prefs.autoPreview;
}
/**
@ -1191,6 +1226,9 @@ onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentati
trackEvent('ui', 'updatePref-' + settingName, prefs[settingName]);
}
// Show/hide RUN button based on autoPreview setting.
runBtn.classList[prefs.autoPreview ? 'add' : 'remove']('hide');
htmlCode.querySelector('.CodeMirror').style.fontSize = prefs.fontSize;
cssCode.querySelector('.CodeMirror').style.fontSize = prefs.fontSize;
jsCode.querySelector('.CodeMirror').style.fontSize = prefs.fontSize;
@ -1235,20 +1273,32 @@ onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentati
trackEvent('ui', 'saveBtnClick', currentItem.id ? 'saved' : 'new');
saveItem();
};
scope.onSearchInputChange = function (e) {
const text = e.target.value;
let el;
for (const [itemId, item] of Object.entries(savedItems)) {
el = $(`#js-saved-items-pane [data-item-id=${itemId}]`);
if (item.title.toLowerCase().indexOf(text) === -1) {
el.classList.add('hide');
} else {
el.classList.remove('hide');
}
}
};
function compileNodes() {
var nodes = [].slice.call($all('[d-click]'));
nodes.forEach(function (el) {
el.addEventListener('click', function (e) {
scope[el.getAttribute('d-click')].call(window, e)
function attachListenerForEvent(eventName) {
const nodes = $all(`[d-${eventName}]`);
nodes.forEach(function (el) {
el.addEventListener(eventName, function (e) {
scope[el.getAttribute(`d-${eventName}`)].call(window, e)
});
});
});
nodes = [].slice.call($all('[d-change]'));
nodes.forEach(function (el) {
el.addEventListener('change', function (e) {
scope[el.getAttribute('d-change')].call(window, e)
});
})
}
attachListenerForEvent('click');
attachListenerForEvent('change');
attachListenerForEvent('input');
}
function init () {
@ -1295,6 +1345,10 @@ onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentati
});
codepenBtn.addEventListener('click', function (e) {
if (cssMode === CssModes.ACSS) {
alert('Oops! CodePen doesn\'t supports Atomic CSS currently.');
return;
}
var json = {
title: 'A Web Maker experiment',
html: scope.cm.html.getValue(),
@ -1346,7 +1400,7 @@ onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentati
});
// Attach listeners on mode change menu items
var modeItems = [].slice.call($all('.js-modes-menu a'));
var modeItems = $all('.js-modes-menu a');
modeItems.forEach(function (item) {
item.addEventListener('click', function (e) {
var mode = e.currentTarget.dataset.mode;
@ -1366,7 +1420,7 @@ onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentati
});
// Collapse btn event listeners
var collapseBtns = [].slice.call($all('.js-code-collapse-btn'));
var collapseBtns = $all('.js-code-collapse-btn');
collapseBtns.forEach(function (btn) {
btn.addEventListener('click', function (e) {
var codeWrapParent = e.currentTarget.parentElement.parentElement.parentElement;
@ -1392,6 +1446,12 @@ onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentati
saveItem();
trackEvent('ui', 'saveItemKeyboardShortcut');
}
// Ctrl/⌘ + Shift + 5
if (!prefs.autoPreview && (event.ctrlKey || event.metaKey) && event.shiftKey && (event.keyCode === 53)) {
event.preventDefault();
scope.setPreviewContent();
trackEvent('ui', 'previewKeyboardShortcut');
}
// Ctrl/⌘ + O
else if ((event.ctrlKey || event.metaKey) && (event.keyCode === 79)) {
event.preventDefault();
@ -1402,25 +1462,33 @@ onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentati
closeAllOverlays();
}
if (event.keyCode === 40 && isSavedItemsPaneOpen) {
// Return if no items present.
if (!$all('.js-saved-item-tile').length) {
return;
}
selectedItemElement = $('.js-saved-item-tile.selected');
if (selectedItemElement) {
selectedItemElement.classList.remove('selected');
selectedItemElement.nextElementSibling.classList.add('selected');
selectedItemElement.nextUntil('.js-saved-item-tile:not(.hide)').classList.add('selected');
} else {
$('.js-saved-item-tile:first-child').classList.add('selected');
$('.js-saved-item-tile:not(.hide)').classList.add('selected');
}
$('.js-saved-item-tile.selected').scrollIntoView(false);
} else if (event.keyCode === 38 && isSavedItemsPaneOpen) {
if (!$all('.js-saved-item-tile').length) {
return;
}
selectedItemElement = $('.js-saved-item-tile.selected');
if (selectedItemElement) {
selectedItemElement.classList.remove('selected');
selectedItemElement.previousElementSibling.classList.add('selected');
selectedItemElement.previousUntil('.js-saved-item-tile:not(.hide)').classList.add('selected');
} else {
$('.js-saved-item-tile:first-child').classList.add('selected');
$('.js-saved-item-tile:not(.hide)').classList.add('selected');
}
$('.js-saved-item-tile.selected').scrollIntoView(false);
} else if (event.keyCode === 13 && isSavedItemsPaneOpen) {
selectedItemElement = $('.js-saved-item-tile.selected');
if (!selectedItemElement) { return; }
setTimeout(function () {
openItem(selectedItemElement.dataset.itemId);
}, 350);
@ -1491,7 +1559,9 @@ onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentati
indentSize: 2,
editorTheme: 'monokai',
keymap: 'sublime',
fontSize: 16
fontSize: 16,
refreshOnResize: false,
autoPreview: true
}, function syncGetCallback(result) {
if (result.preserveLastCode && lastCode) {
unsavedEditCount = 0;
@ -1520,6 +1590,8 @@ onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentati
prefs.editorTheme = result.editorTheme;
prefs.keymap = result.keymap;
prefs.fontSize = result.fontSize;
prefs.refreshOnResize = result.refreshOnResize;
prefs.autoPreview = result.autoPreview;
updateSettingsInUi();
scope.updateSetting();

View File

@ -25,6 +25,7 @@ h1 {
a { text-decoration: none; color: crimson; cursor: pointer; }
/*a:hover { text-decoration: underline; }*/
.hide { display: none!important; }
.flex { display: flex; }
.flex-grow { flex-grow: 1; }
.flex-v-center { align-items: center; }
@ -372,7 +373,16 @@ li.CodeMirror-hint-active {
background: none;
border: 0;
color: rgba(255,255,255,0.6);
width: calc(100vw - 400px);
width: calc(100vw - 420px);
}
.search-input {
background: rgba(255, 255, 255, 0.1);
padding: 10px 20px;
border: 0;
width: 100%;
font-size: 16px;
color: white;
border-radius: 4px;
}
.modal {
position: fixed;
@ -647,7 +657,7 @@ li.CodeMirror-hint-active {
}
.dropdown__menu > li > a {
display: block;
padding: 10px 15px;
padding: 6px 15px;
color: #333;
cursor: pointer;
}

View File

@ -2,9 +2,33 @@
window.DEBUG = document.cookie.indexOf('wmdebug') > -1;
window.$ = document.querySelector.bind(document);
window.$all = document.querySelectorAll.bind(document);
window.$all = (selector) => [...document.querySelectorAll(selector)];
var alphaNum = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
/**
* The following 2 functions are supposed to find the next/previous sibling until the
* passed `selector` is matched. But for now it actually finds the next/previous
* element of `this` element in the list of `selector` matched element inside `this`'s
* parent.
* @param Selector that should match for next siblings
* @return element Next element that mathes `selector`
*/
Node.prototype.nextUntil = function (selector) {
const siblings = [...this.parentNode.querySelectorAll(selector)];
const index = siblings.indexOf(this);
return siblings[index + 1];
};
/*
* @param Selector that should match for next siblings
* @return element Next element that mathes `selector`
*/
Node.prototype.previousUntil = function (selector) {
const siblings = [...this.parentNode.querySelectorAll(selector)];
const index = siblings.indexOf(this);
return siblings[index - 1];
};
// https://github.com/substack/semver-compare/blob/master/index.js
function semverCompare(a, b) {
var pa = a.split('.');