1
0
mirror of https://github.com/chinchang/web-maker.git synced 2025-04-07 12:22:31 +02:00

remove old files

This commit is contained in:
Kushagra Gour 2018-06-15 23:22:23 +05:30
parent dcd1cd80d4
commit f5d2b5d1a7
27 changed files with 0 additions and 10387 deletions

@ -1,37 +0,0 @@
/* global ga */
// eslint-disable-next-line max-params
window.trackEvent = function(category, action, label, value) {
if (window.DEBUG) {
utils.log('trackevent', category, action, label, value);
return;
}
if (window.ga) {
ga('send', 'event', category, action, label, value);
}
};
// if online, load after sometime
if (navigator.onLine && !window.DEBUG) {
/* eslint-disable */
// prettier-ignore
setTimeout(function() {
(function(i,s,o,g,r,a,m){
i['GoogleAnalyticsObject']=r;
i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
if (location.href.indexOf('chrome-extension://') === -1) {
ga('create', 'UA-87786708-1');
} else {
ga('create', 'UA-87786708-1', {'cookieDomain': 'none'});
// required for chrome extension protocol
ga('set', 'checkProtocolTask', function(){ /* nothing */ });
}
ga('send', 'pageview');
}, 100);
/* eslint-enable */
}

@ -1,34 +0,0 @@
window.logout = function logout() {
firebase.auth().signOut();
};
function login(providerName) {
var provider;
if (providerName === 'facebook') {
provider = new firebase.auth.FacebookAuthProvider();
} else if (providerName === 'twitter') {
provider = new firebase.auth.TwitterAuthProvider();
} else if (providerName === 'google') {
provider = new firebase.auth.GoogleAuthProvider();
provider.addScope('https://www.googleapis.com/auth/userinfo.profile');
} else {
provider = new firebase.auth.GithubAuthProvider();
}
return firebase
.auth()
.signInWithPopup(provider)
.then(function() {
window.trackEvent('fn', 'loggedIn', providerName);
// Save to recommend next time
window.db.local.set({ lastAuthProvider: providerName });
})
.catch(function(error) {
utils.log(error);
if (error.code === 'auth/account-exists-with-different-credential') {
alert(
'You have already signed up with the same email using different social login'
);
}
});
}
window.login = login;

146
src/db.js

@ -1,146 +0,0 @@
(() => {
const FAUX_DELAY = 1;
var db;
var dbPromise;
var local = {
get: (obj, cb) => {
const retVal = {};
if (typeof obj === 'string') {
retVal[obj] = JSON.parse(window.localStorage.getItem(obj));
setTimeout(() => cb(retVal), FAUX_DELAY);
} else {
Object.keys(obj).forEach(key => {
const val = window.localStorage.getItem(key);
retVal[key] =
val === undefined || val === null ? obj[key] : JSON.parse(val);
});
setTimeout(() => cb(retVal), FAUX_DELAY);
}
},
set: (obj, cb) => {
Object.keys(obj).forEach(key => {
window.localStorage.setItem(key, JSON.stringify(obj[key]));
});
/* eslint-disable consistent-return */
setTimeout(() => {
if (cb) {
return cb();
}
}, FAUX_DELAY);
/* eslint-enable consistent-return */
}
};
const dbLocalAlias = chrome && chrome.storage ? chrome.storage.local : local;
const dbSyncAlias = chrome && chrome.storage ? chrome.storage.sync : local;
async function getDb() {
if (dbPromise) {
return dbPromise;
}
utils.log('Initializing firestore');
dbPromise = new Promise((resolve, reject) => {
if (db) {
return resolve(db);
}
return firebase
.firestore()
.enablePersistence()
.then(function() {
// Initialize Cloud Firestore through firebase
db = firebase.firestore();
utils.log('firebase db ready', db);
resolve(db);
})
.catch(function(err) {
reject(err.code);
if (err.code === 'failed-precondition') {
// Multiple tabs open, persistence can only be enabled
// in one tab at a a time.
alert(
"Opening Web Maker web app in multiple tabs isn't supported at present and it seems like you already have it opened in another tab. Please use in one tab."
);
window.trackEvent('fn', 'multiTabError');
} else if (err.code === 'unimplemented') {
// The current browser does not support all of the
// features required to enable persistence
// ...
}
});
});
return dbPromise;
}
async function getUserLastSeenVersion() {
const d = deferred();
// Will be chrome.storage.sync in extension environment,
// otherwise will fallback to localstorage
dbSyncAlias.get(
{
lastSeenVersion: ''
},
result => {
d.resolve(result.lastSeenVersion);
}
);
return d.promise;
// Might consider getting actual value from remote db.
// Not critical right now.
}
async function setUserLastSeenVersion(version) {
// Setting the `lastSeenVersion` in localStorage(sync for extension) always
// because next time we need to fetch it irrespective of the user being
// logged in or out quickly from local storage.
dbSyncAlias.set(
{
lastSeenVersion: version
},
function() {}
);
if (window.user) {
const remoteDb = await getDb();
remoteDb
.doc(`users/${window.user.uid}`)
.update({ lastSeenVersion: version });
}
}
async function getUser(userId) {
const remoteDb = await getDb();
return remoteDb
.doc(`users/${userId}`)
.get()
.then(doc => {
if (!doc.exists)
return remoteDb.doc(`users/${userId}`).set({}, { merge: true });
const user = doc.data();
Object.assign(window.user, user);
return user;
});
}
// Fetch user settings.
// This isn't hitting the remote db because remote settings
// get fetch asynchronously (in user/) and update the envioronment.
function getSettings(defaultSettings) {
const d = deferred();
// Will be chrome.storage.sync in extension environment,
// otherwise will fallback to localstorage
dbSyncAlias.get(defaultSettings, result => {
d.resolve(result);
});
return d.promise;
}
window.db = {
getDb,
getUser,
getUserLastSeenVersion,
setUserLastSeenVersion,
getSettings,
local: dbLocalAlias,
sync: dbSyncAlias
};
})();

@ -1,14 +0,0 @@
(function() {
window.deferred = function() {
var d = {};
var promise = new Promise(function(resolve, reject) {
d.resolve = resolve;
d.reject = reject;
});
// Add the native promise as a key on deferred object.
d.promise = promise;
// Also move all props/methods of native promise on the deferred obj.
return Object.assign(d, promise);
};
})();

@ -1,30 +0,0 @@
// Dropdown.js
(function($all) {
var openDropdown;
// Closes all dropdowns except the passed one.
function closeOpenDropdown(except) {
if (openDropdown && (!except || except !== openDropdown)) {
openDropdown.classList.remove('open');
openDropdown = null;
}
}
function init() {
var dropdowns = $all('[dropdown]');
dropdowns.forEach(function(dropdown) {
dropdown.addEventListener('click', function(e) {
closeOpenDropdown(e.currentTarget);
e.currentTarget.classList.toggle('open');
openDropdown = e.currentTarget;
e.stopPropagation();
});
});
document.addEventListener('click', function() {
closeOpenDropdown();
});
}
init();
})($all);

@ -1,133 +0,0 @@
<html>
<head>
<meta charset="utf-8">
<title>Web Maker</title>
<link rel="icon" href="icon-128.png">
<meta name=viewport content="width=device-width, initial-scale=1">
<style>
/* Critically acclaimed CSS */
.saved-items-pane {
position: fixed;
right: 0;
top: 0;
bottom: 0;
width: 450px;
transform: translateX(100%);
}
.modal {
visibility: hidden;
}
</style>
<!-- build:css vendor.css -->
<link rel="stylesheet" href="lib/codemirror/lib/codemirror.css">
<link rel="stylesheet" href="lib/codemirror/addon/hint/show-hint.css">
<link rel="stylesheet" href="lib/codemirror/addon/fold/foldgutter.css">
<link rel="stylesheet" href="lib/codemirror/addon/dialog/dialog.css">
<link rel="stylesheet" href="lib/hint.min.css">
<link rel="stylesheet" href="lib/inlet.css">
<!-- endbuild -->
<link rel="stylesheet" id="editorThemeLinkTag" href="lib/codemirror/theme/monokai.css"></link>
<!-- build:css style.css -->
<link rel="stylesheet" href="style.css">
<!-- endbuild -->
<style id="fontStyleTemplate" type="template">
@font-face { font-family: 'fontname'; font-style: normal; font-weight: 400; src: url(fontname.ttf) format('truetype'); unicode-range:
U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD,
U+F000; } .Codemirror pre { font-family: 'fontname', monospace; }
</style>
<style type="text/css" id="fontStyleTag">
@font-face {
font-family: 'FiraCode';
font-style: normal;
font-weight: 400;
src: url(FiraCode.ttf) format('truetype');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
}
.Codemirror pre {
font-family: 'FiraCode', monospace;
}
</style>
</head>
<body>
<div class="modal" id="onboardModal">
<div class="modal__content" d-html="partials/onboard-modal.html"></div>
</div>
<div class="alerts-container" id="js-alerts-container"></div>
<!-- build:js vendor.js -->
<script src="lib/codemirror/lib/codemirror.js"></script>
<script src="lib/codemirror/addon/edit/matchbrackets.js"></script>
<script src="lib/codemirror/addon/edit/matchtags.js"></script>
<script src="lib/codemirror/addon/edit/closebrackets.js"></script>
<script src="lib/codemirror/addon/edit/closetag.js"></script>
<script src="lib/codemirror/addon/comment/comment.js"></script>
<script src="lib/codemirror/addon/fold/foldcode.js"></script>
<script src="lib/codemirror/addon/fold/foldgutter.js"></script>
<script src="lib/codemirror/addon/fold/xml-fold.js"></script>
<script src="lib/codemirror/addon/fold/indent-fold.js"></script>
<script src="lib/codemirror/addon/fold/comment-fold.js"></script>
<script src="lib/codemirror/addon/fold/brace-fold.js"></script>
<script src="lib/codemirror/addon/mode/loadmode.js"></script>
<script src="lib/codemirror/addon/hint/show-hint.js"></script>
<script src="lib/codemirror/addon/hint/javascript-hint.js"></script>
<script src="lib/codemirror/addon/hint/xml-hint.js"></script>
<script src="lib/codemirror/addon/hint/html-hint.js"></script>
<script src="lib/codemirror/addon/hint/css-hint.js"></script>
<script src="lib/codemirror/addon/selection/active-line.js"></script>
<script src="lib/codemirror/addon/search/searchcursor.js"></script>
<script src="lib/codemirror/addon/search/search.js"></script>
<script src="lib/codemirror/addon/dialog/dialog.js"></script>
<script src="lib/codemirror/addon/search/jump-to-line.js"></script>
<script src="lib/codemirror/mode/xml/xml.js"></script>
<script src="lib/codemirror/mode/javascript/javascript.js"></script>
<script src="lib/codemirror/mode/css/css.js"></script>
<script src="lib/codemirror/mode/htmlmixed/htmlmixed.js"></script>
<script src="lib/codemirror/keymap/sublime.js"></script>
<script src="lib/codemirror/keymap/vim.js"></script>
<script src="lib/emmet.js"></script>
<script src="lib/code-blast.js"></script>
<script src="lib/split.js"></script>
<script src="lib/inlet.min.js"></script>
<script src="lib/esprima.js"></script>
<script src="lib/firebase.js"></script>
<script src="lib/firebase-firestore.js"></script>
<!-- endbuild -->
<!-- build:js script.js -->
<script src="service-worker-registration.js"></script>
<script src="utils.js"></script>
<script src="db.js"></script>
<script src="auth.js"></script>
<script src="analytics.js"></script>
<script src="deferred.js"></script>
<script src="loader.js"></script>
<script src="notifications.js"></script>
<script src="library-list.js"></script>
<script src="textarea-autocomplete.js"></script>
<script src="itemService.js"></script>
<script src="script.js"></script>
<script src="dropdown.js"></script>
<!-- endbuild -->
</body>
</html>

@ -1,233 +0,0 @@
(() => {
window.itemService = {
async getItem(id) {
var remoteDb = await window.db.getDb();
return remoteDb
.doc(`items/${id}`)
.get()
.then(doc => {
return doc.data();
});
},
async getUserItemIds() {
if (window.user) {
return new Promise(resolve => {
resolve(window.user.items || {});
});
}
var remoteDb = await window.db.getDb();
return remoteDb
.doc(`users/${window.user.uid}`)
.get()
.then(doc => {
if (!doc.exists) {
return {};
}
return doc.data().items;
});
},
async getAllItems() {
var t=Date.now()
var d = deferred();
let itemIds = await this.getUserItemIds();
itemIds = Object.getOwnPropertyNames(itemIds || {});
utils.log('itemids', itemIds);
if (!itemIds.length) {
d.resolve([]);
}
var remoteDb = await window.db.getDb();
const items = [];
remoteDb
.collection('items')
.where('createdBy', '==', window.user.uid)
.onSnapshot(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
items.push(doc.data());
});
utils.log('Items fetched in ', Date.now()-t, 'ms')
d.resolve(items);
}, function() {
d.resolve([])
});
return d.promise;
},
async setUser() {
const remoteDb = await window.db.getDb();
return remoteDb.doc(`users/${window.user.uid}`).set({
items: {}
});
},
async setItem(id, item) {
const d = deferred();
var remotePromise;
// TODO: check why we need to save locally always?
const obj = {
[id]: item
};
db.local.set(obj, () => {
// Is extension OR is app but logged out OR is logged in but offline
// If logged in but offline, resolve immediately so
// that you see the feedback msg immediately and not wait for
// later sync.
if (window.IS_EXTENSION || !window.user || !navigator.onLine) {
d.resolve();
}
});
// If `id` is `code`, this is a call on unloadbefore to save the last open thing.
// Do not presist that on remote.
if (id === 'code') {
// No deferred required here as this gets called on unloadbefore
return false;
}
if (window.user) {
var remoteDb = await window.db.getDb();
utils.log(`Starting to save item ${id}`);
item.createdBy = window.user.uid;
remotePromise = remoteDb
.collection('items')
.doc(id)
.set(item, {
merge: true
})
.then(arg => {
utils.log('Document written', arg);
d.resolve();
})
.catch(d.reject);
}
return window.user && navigator.onLine ? remotePromise : d.promise;
},
/**
* Saves the passed items in the database.
* @param {Array} items to be saved in DB
*/
saveItems(items) {
var d = deferred();
// When not logged in
if (!window.user) {
// save new items
window.db.local.set(items, d.resolve);
// Push in new item IDs
window.db.local.get(
{
items: {}
},
function(result) {
/* eslint-disable guard-for-in */
for (var id in items) {
result.items[id] = true;
}
window.db.local.set({
items: result.items
});
/* eslint-enable guard-for-in */
}
);
} else {
window.db.getDb().then(remoteDb => {
const batch = remoteDb.batch();
/* eslint-disable guard-for-in */
for (var id in items) {
items[id].createdBy = window.user.uid;
batch.set(remoteDb.doc(`items/${id}`), items[id]);
batch.update(remoteDb.doc(`users/${window.user.uid}`), {
[`items.${id}`]: true
});
// Set these items on our cached user object too
window.user.items = window.user.items || {};
window.user.items[id] = true;
}
batch.commit().then(d.resolve);
/* eslint-enable guard-for-in */
});
}
return d.promise;
},
async removeItem(id) {
// When not logged in
if (!window.user) {
var d = deferred();
db.local.remove(id, d.resolve);
return d.promise;
}
const remoteDb = await window.db.getDb();
utils.log(`Starting to save item ${id}`);
return remoteDb
.collection('items')
.doc(id)
.delete()
.then(arg => {
utils.log('Document removed', arg);
})
.catch(error => utils.log(error));
},
async setItemForUser(itemId) {
// When not logged in
if (!window.user) {
return window.db.local.get(
{
items: {}
},
function(result) {
result.items[itemId] = true;
window.db.local.set({
items: result.items
});
}
);
}
const remoteDb = await window.db.getDb();
return remoteDb
.collection('users')
.doc(window.user.uid)
.update({
[`items.${itemId}`]: true
})
.then(arg => {
utils.log(`Item ${itemId} set for user`, arg);
window.user.items = window.user.items || {};
window.user.items[itemId] = true;
})
.catch(error => utils.log(error));
},
async unsetItemForUser(itemId) {
// When not logged in
if (!window.user) {
return window.db.local.get(
{
items: {}
},
function(result) {
delete result.items[itemId];
db.local.set({
items: result.items
});
}
);
}
const remoteDb = await window.db.getDb();
return remoteDb
.collection('users')
.doc(window.user.uid)
.update({
[`items.${itemId}`]: firebase.firestore.FieldValue.delete()
})
.then(arg => {
delete window.user.items[itemId];
utils.log(`Item ${itemId} unset for user`, arg);
})
.catch(error => utils.log(error));
}
};
})();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,569 +0,0 @@
// The programming goals of Split.js are to deliver readable, understandable and
// maintainable code, while at the same time manually optimizing for tiny minified file size,
// browser compatibility without additional requirements, graceful fallback (IE8 is supported)
// and very few assumptions about the user's page layout.
//
// Make sure all browsers handle this JS library correctly with ES5.
// More information here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode
'use strict';
// A wrapper function that does a couple things:
//
// 1. Doesn't pollute the global namespace. This is important for a library.
// 2. Allows us to mount the library in different module systems, as well as
// directly in the browser.
(function() {
// Save the global `this` for use later. In this case, since the library only
// runs in the browser, it will refer to `window`. Also, figure out if we're in IE8
// or not. IE8 will still render correctly, but will be static instead of draggable.
//
// Save a couple long function names that are used frequently.
// This optimization saves around 400 bytes.
var global = this
, isIE8 = global.attachEvent && !global[addEventListener]
, document = global.document
, addEventListener = 'addEventListener'
, removeEventListener = 'removeEventListener'
, getBoundingClientRect = 'getBoundingClientRect'
// This library only needs two helper functions:
//
// The first determines which prefixes of CSS calc we need.
// We only need to do this once on startup, when this anonymous function is called.
//
// Tests -webkit, -moz and -o prefixes. Modified from StackOverflow:
// http://stackoverflow.com/questions/16625140/js-feature-detection-to-detect-the-usage-of-webkit-calc-over-calc/16625167#16625167
, calc = (function () {
var el
, prefixes = ["", "-webkit-", "-moz-", "-o-"]
for (var i = 0; i < prefixes.length; i++) {
el = document.createElement('div')
el.style.cssText = "width:" + prefixes[i] + "calc(9px)"
if (el.style.length) {
return prefixes[i] + "calc"
}
}
})()
// The second helper function allows elements and string selectors to be used
// interchangeably. In either case an element is returned. This allows us to
// do `Split(elem1, elem2)` as well as `Split('#id1', '#id2')`.
, elementOrSelector = function (el) {
if (typeof el === 'string' || el instanceof String) {
return document.querySelector(el)
} else {
return el
}
}
// The main function to initialize a split. Split.js thinks about each pair
// of elements as an independant pair. Dragging the gutter between two elements
// only changes the dimensions of elements in that pair. This is key to understanding
// how the following functions operate, since each function is bound to a pair.
//
// A pair object is shaped like this:
//
// {
// a: DOM element,
// b: DOM element,
// aMin: Number,
// bMin: Number,
// dragging: Boolean,
// parent: DOM element,
// isFirst: Boolean,
// isLast: Boolean,
// direction: 'horizontal' | 'vertical'
// }
//
// The basic sequence:
//
// 1. Set defaults to something sane. `options` doesn't have to be passed at all.
// 2. Initialize a bunch of strings based on the direction we're splitting.
// A lot of the behavior in the rest of the library is paramatized down to
// rely on CSS strings and classes.
// 3. Define the dragging helper functions, and a few helpers to go with them.
// 4. Define a few more functions that "balance" the entire split instance.
// Split.js tries it's best to cope with min sizes that don't add up.
// 5. Loop through the elements while pairing them off. Every pair gets an
// `pair` object, a gutter, and special isFirst/isLast properties.
// 6. Actually size the pair elements, insert gutters and attach event listeners.
// 7. Balance all of the pairs to accomodate min sizes as best as possible.
, Split = function (ids, options) {
var dimension
, i
, clientDimension
, clientAxis
, position
, gutterClass
, paddingA
, paddingB
, pairs = []
// 1. Set defaults to something sane. `options` doesn't have to be passed at all,
// so create an options object if none exists. Pixel values 10, 100 and 30 are
// arbitrary but feel natural.
options = typeof options !== 'undefined' ? options : {}
if (typeof options.gutterSize === 'undefined') options.gutterSize = 10
if (typeof options.minSize === 'undefined') options.minSize = 100
if (typeof options.snapOffset === 'undefined') options.snapOffset = 30
if (typeof options.direction === 'undefined') options.direction = 'horizontal'
// 2. Initialize a bunch of strings based on the direction we're splitting.
// A lot of the behavior in the rest of the library is paramatized down to
// rely on CSS strings and classes.
if (options.direction == 'horizontal') {
dimension = 'width'
clientDimension = 'clientWidth'
clientAxis = 'clientX'
position = 'left'
gutterClass = 'gutter gutter-horizontal'
paddingA = 'paddingLeft'
paddingB = 'paddingRight'
if (!options.cursor) options.cursor = 'ew-resize'
} else if (options.direction == 'vertical') {
dimension = 'height'
clientDimension = 'clientHeight'
clientAxis = 'clientY'
position = 'top'
gutterClass = 'gutter gutter-vertical'
paddingA = 'paddingTop'
paddingB = 'paddingBottom'
if (!options.cursor) options.cursor = 'ns-resize'
}
// 3. Define the dragging helper functions, and a few helpers to go with them.
// Each helper is bound to a pair object that contains it's metadata. This
// also makes it easy to store references to listeners that that will be
// added and removed.
//
// Even though there are no other functions contained in them, aliasing
// this to self saves 50 bytes or so since it's used so frequently.
//
// The pair object saves metadata like dragging state, position and
// event listener references.
//
// startDragging calls `calculateSizes` to store the inital size in the pair object.
// It also adds event listeners for mouse/touch events,
// and prevents selection while dragging so avoid the selecting text.
var startDragging = function (e) {
// Alias frequently used variables to save space. 200 bytes.
var self = this
, a = self.a
, b = self.b
// Call the onDragStart callback.
if (!self.dragging && options.onDragStart) {
options.onDragStart()
}
// Don't actually drag the element. We emulate that in the drag function.
e.preventDefault()
// Set the dragging property of the pair object.
self.dragging = true
// Create two event listeners bound to the same pair object and store
// them in the pair object.
self.move = drag.bind(self)
self.stop = stopDragging.bind(self)
// All the binding. `window` gets the stop events in case we drag out of the elements.
global[addEventListener]('mouseup', self.stop)
global[addEventListener]('touchend', self.stop)
global[addEventListener]('touchcancel', self.stop)
self.parent[addEventListener]('mousemove', self.move)
self.parent[addEventListener]('touchmove', self.move)
// Disable selection. Disable!
a[addEventListener]('selectstart', noop)
a[addEventListener]('dragstart', noop)
b[addEventListener]('selectstart', noop)
b[addEventListener]('dragstart', noop)
a.style.userSelect = 'none'
a.style.webkitUserSelect = 'none'
a.style.MozUserSelect = 'none'
a.style.pointerEvents = 'none'
b.style.userSelect = 'none'
b.style.webkitUserSelect = 'none'
b.style.MozUserSelect = 'none'
b.style.pointerEvents = 'none'
// Set the cursor, both on the gutter and the parent element.
// Doing only a, b and gutter causes flickering.
self.gutter.style.cursor = options.cursor
self.parent.style.cursor = options.cursor
// Cache the initial sizes of the pair.
calculateSizes.call(self)
}
// stopDragging is very similar to startDragging in reverse.
, stopDragging = function () {
var self = this
, a = self.a
, b = self.b
if (self.dragging && options.onDragEnd) {
options.onDragEnd()
}
self.dragging = false
// Remove the stored event listeners. This is why we store them.
global[removeEventListener]('mouseup', self.stop)
global[removeEventListener]('touchend', self.stop)
global[removeEventListener]('touchcancel', self.stop)
self.parent[removeEventListener]('mousemove', self.move)
self.parent[removeEventListener]('touchmove', self.move)
// Delete them once they are removed. I think this makes a difference
// in memory usage with a lot of splits on one page. But I don't know for sure.
delete self.stop
delete self.move
a[removeEventListener]('selectstart', noop)
a[removeEventListener]('dragstart', noop)
b[removeEventListener]('selectstart', noop)
b[removeEventListener]('dragstart', noop)
a.style.userSelect = ''
a.style.webkitUserSelect = ''
a.style.MozUserSelect = ''
a.style.pointerEvents = ''
b.style.userSelect = ''
b.style.webkitUserSelect = ''
b.style.MozUserSelect = ''
b.style.pointerEvents = ''
self.gutter.style.cursor = ''
self.parent.style.cursor = ''
}
// drag, where all the magic happens. The logic is really quite simple:
//
// 1. Ignore if the pair is not dragging.
// 2. Get the offset of the event.
// 3. Snap offset to min if within snappable range (within min + snapOffset).
// 4. Actually adjust each element in the pair to offset.
//
// ---------------------------------------------------------------------
// | | <- this.aMin || this.bMin -> | |
// | | | <- this.snapOffset || this.snapOffset -> | | |
// | | | || | | |
// | | | || | | |
// ---------------------------------------------------------------------
// | <- this.start this.size -> |
, drag = function (e) {
var offset
if (!this.dragging) return
// Get the offset of the event from the first side of the
// pair `this.start`. Supports touch events, but not multitouch, so only the first
// finger `touches[0]` is counted.
if ('touches' in e) {
offset = e.touches[0][clientAxis] - this.start
} else {
offset = e[clientAxis] - this.start
}
// If within snapOffset of min or max, set offset to min or max.
// snapOffset buffers aMin and bMin, so logic is opposite for both.
// Include the appropriate gutter sizes to prevent overflows.
if (offset <= this.aMin + options.snapOffset + this.aGutterSize) {
offset = this.aMin + this.aGutterSize
} else if (offset >= this.size - (this.bMin + options.snapOffset + this.bGutterSize)) {
offset = this.size - (this.bMin + this.bGutterSize)
}
// Actually adjust the size.
adjust.call(this, offset)
// Call the drag callback continously. Don't do anything too intensive
// in this callback.
if (options.onDrag) {
options.onDrag()
}
}
// Cache some important sizes when drag starts, so we don't have to do that
// continously:
//
// `size`: The total size of the pair. First element + second element + first gutter + second gutter.
// `percentage`: The percentage between 0-100 that the pair occupies in the parent.
// `start`: The leading side of the first element.
//
// ------------------------------------------------ - - - - - - - - - - -
// | aGutterSize -> ||| | |
// | ||| | |
// | ||| | |
// | ||| <- bGutterSize | |
// ------------------------------------------------ - - - - - - - - - - -
// | <- start size -> | parentSize -> |
, calculateSizes = function () {
// Figure out the parent size minus padding.
var computedStyle = global.getComputedStyle(this.parent)
, parentSize = this.parent[clientDimension] - parseFloat(computedStyle[paddingA]) - parseFloat(computedStyle[paddingB])
this.size = this.a[getBoundingClientRect]()[dimension] + this.b[getBoundingClientRect]()[dimension] + this.aGutterSize + this.bGutterSize
this.percentage = Math.min(this.size / parentSize * 100, 100)
this.start = this.a[getBoundingClientRect]()[position]
}
// Actually adjust the size of elements `a` and `b` to `offset` while dragging.
// calc is used to allow calc(percentage + gutterpx) on the whole split instance,
// which allows the viewport to be resized without additional logic.
// Element a's size is the same as offset. b's size is total size - a size.
// Both sizes are calculated from the initial parent percentage, then the gutter size is subtracted.
, adjust = function (offset) {
this.a.style[dimension] = calc + '(' + (offset / this.size * this.percentage) + '% - ' + this.aGutterSize + 'px)'
this.b.style[dimension] = calc + '(' + (this.percentage - (offset / this.size * this.percentage)) + '% - ' + this.bGutterSize + 'px)'
}
// 4. Define a few more functions that "balance" the entire split instance.
// Split.js tries it's best to cope with min sizes that don't add up.
// At some point this should go away since it breaks out of the calc(% - px) model.
// Maybe it's a user error if you pass uncomputable minSizes.
, fitMin = function () {
var self = this
, a = self.a
, b = self.b
if (a[getBoundingClientRect]()[dimension] < self.aMin) {
a.style[dimension] = (self.aMin - self.aGutterSize) + 'px'
b.style[dimension] = (self.size - self.aMin - self.aGutterSize) + 'px'
} else if (b[getBoundingClientRect]()[dimension] < self.bMin) {
a.style[dimension] = (self.size - self.bMin - self.bGutterSize) + 'px'
b.style[dimension] = (self.bMin - self.bGutterSize) + 'px'
}
}
, fitMinReverse = function () {
var self = this
, a = self.a
, b = self.b
if (b[getBoundingClientRect]()[dimension] < self.bMin) {
a.style[dimension] = (self.size - self.bMin - self.bGutterSize) + 'px'
b.style[dimension] = (self.bMin - self.bGutterSize) + 'px'
} else if (a[getBoundingClientRect]()[dimension] < self.aMin) {
a.style[dimension] = (self.aMin - self.aGutterSize) + 'px'
b.style[dimension] = (self.size - self.aMin - self.aGutterSize) + 'px'
}
}
, balancePairs = function (pairs) {
for (var i = 0; i < pairs.length; i++) {
calculateSizes.call(pairs[i])
fitMin.call(pairs[i])
}
for (i = pairs.length - 1; i >= 0; i--) {
calculateSizes.call(pairs[i])
fitMinReverse.call(pairs[i])
}
}
, setElementSize = function (el, size, gutterSize) {
// Split.js allows setting sizes via numbers (ideally), or if you must,
// by string, like '300px'. This is less than ideal, because it breaks
// the fluid layout that `calc(% - px)` provides. You're on your own if you do that,
// make sure you calculate the gutter size by hand.
if (typeof size !== 'string' && !(size instanceof String)) {
if (!isIE8) {
size = calc + '(' + size + '% - ' + gutterSize + 'px)'
} else {
size = options.sizes[i] + '%'
}
}
el.style[dimension] = size
}
// No-op function to prevent default. Used to prevent selection.
, noop = function () { return false }
// All DOM elements in the split should have a common parent. We can grab
// the first elements parent and hope users read the docs because the
// behavior will be whacky otherwise.
, parent = elementOrSelector(ids[0]).parentNode
// Set default options.sizes to equal percentages of the parent element.
if (!options.sizes) {
var percent = 100 / ids.length
options.sizes = []
for (i = 0; i < ids.length; i++) {
options.sizes.push(percent)
}
}
// Standardize minSize to an array if it isn't already. This allows minSize
// to be passed as a number.
if (!Array.isArray(options.minSize)) {
var minSizes = []
for (i = 0; i < ids.length; i++) {
minSizes.push(options.minSize)
}
options.minSize = minSizes
}
// 5. Loop through the elements while pairing them off. Every pair gets a
// `pair` object, a gutter, and isFirst/isLast properties.
//
// Basic logic:
//
// - Starting with the second element `i > 0`, create `pair` objects with
// `a = ids[i - 1]` and `b = ids[i]`
// - Set gutter sizes based on the _pair_ being first/last. The first and last
// pair have gutterSize / 2, since they only have one half gutter, and not two.
// - Create gutter elements and add event listeners.
// - Set the size of the elements, minus the gutter sizes.
//
// -----------------------------------------------------------------------
// | i=0 | i=1 | i=2 | i=3 |
// | | isFirst | | isLast |
// | pair 0 pair 1 pair 2 |
// | | | | |
// -----------------------------------------------------------------------
for (i = 0; i < ids.length; i++) {
var el = elementOrSelector(ids[i])
, isFirstPair = (i == 1)
, isLastPair = (i == ids.length - 1)
, size = options.sizes[i]
, gutterSize = options.gutterSize
, pair
, parentFlexDirection = window.getComputedStyle(parent).flexDirection
, temp
if (i > 0) {
// Create the pair object with it's metadata.
pair = {
a: elementOrSelector(ids[i - 1]),
b: el,
aMin: options.minSize[i - 1],
bMin: options.minSize[i],
dragging: false,
parent: parent,
isFirst: isFirstPair,
isLast: isLastPair,
direction: options.direction
}
// For first and last pairs, first and last gutter width is half.
pair.aGutterSize = options.gutterSize
pair.bGutterSize = options.gutterSize
if (isFirstPair) {
pair.aGutterSize = options.gutterSize / 2
}
if (isLastPair) {
pair.bGutterSize = options.gutterSize / 2
}
// if the parent has a reverse flex-direction, switch the pair elements.
if (parentFlexDirection === 'row-reverse' || parentFlexDirection === 'column-reverse') {
temp = pair.a;
pair.a = pair.b;
pair.b = temp;
}
}
// Determine the size of the current element. IE8 is supported by
// staticly assigning sizes without draggable gutters. Assigns a string
// to `size`.
//
// IE9 and above
if (!isIE8) {
// Create gutter elements for each pair.
if (i > 0) {
var gutter = document.createElement('div')
gutter.className = gutterClass
gutter.style[dimension] = options.gutterSize + 'px'
gutter[addEventListener]('mousedown', startDragging.bind(pair))
gutter[addEventListener]('touchstart', startDragging.bind(pair))
parent.insertBefore(gutter, el)
pair.gutter = gutter
}
// Half-size gutters for first and last elements.
if (i === 0 || i == ids.length - 1) {
gutterSize = options.gutterSize / 2
}
}
// Set the element size to our determined size.
setElementSize(el, size, gutterSize)
// After the first iteration, and we have a pair object, append it to the
// list of pairs.
if (i > 0) {
pairs.push(pair)
}
}
// Balance the pairs to try to accomodate min sizes.
balancePairs(pairs)
return {
setSizes: function (sizes) {
for (var i = 0; i < sizes.length; i++) {
if (i > 0) {
var pair = pairs[i - 1]
setElementSize(pair.a, sizes[i - 1], pair.aGutterSize)
setElementSize(pair.b, sizes[i], pair.bGutterSize)
}
}
},
collapse: function (i) {
var pair
if (i === pairs.length) {
pair = pairs[i - 1]
calculateSizes.call(pair)
adjust.call(pair, pair.size - Math.max(pair.bGutterSize, pair.aMin))
} else {
pair = pairs[i]
calculateSizes.call(pair)
adjust.call(pair, Math.max(pair.aGutterSize, pair.aMin))
}
},
destroy: function () {
for (var i = 0; i < pairs.length; i++) {
pairs[i].parent.removeChild(pairs[i].gutter)
pairs[i].a.style[dimension] = ''
pairs[i].b.style[dimension] = ''
}
}
}
}
// Play nicely with module systems, and the browser too if you include it raw.
if (typeof exports !== 'undefined') {
if (typeof module !== 'undefined' && module.exports) {
exports = module.exports = Split
}
exports.Split = Split
} else {
global.Split = Split
}
// Call our wrapper function with the current global. In this case, `window`.
}).call(window);

@ -1,153 +0,0 @@
window.jsLibs = [
{
url: 'https://code.jquery.com/jquery-3.2.1.min.js',
label: 'jQuery',
type: 'js'
},
{
url: 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js',
label: 'Bootstrap 3',
type: 'js'
},
{
url:
'https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js',
label: 'Bootstrap 4',
type: 'js'
},
{
url:
'https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/js/foundation.min.js',
label: 'Foundation',
type: 'js'
},
{
url: 'https://semantic-ui.com/dist/semantic.min.js',
label: 'Semantic UI',
type: 'js'
},
{
url: 'https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.min.js',
label: 'Angular',
type: 'js'
},
{
url:
'https://cdnjs.cloudflare.com/ajax/libs/react/16.2.0/umd/react.production.min.js',
label: 'React',
type: 'js'
},
{
url:
'https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.2.0/umd/react-dom.production.min.js',
label: 'React DOM',
type: 'js'
},
{
url: 'https://unpkg.com/vue/dist/vue.min.js',
label: 'Vue.js',
type: 'js'
},
{
url: 'https://cdnjs.cloudflare.com/ajax/libs/three.js/89/three.min.js',
label: 'Three.js',
type: 'js'
},
{
url: 'https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js',
label: 'D3',
type: 'js'
},
{
url:
'https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js',
label: 'Underscore',
type: 'js'
},
{
url: 'https://cdnjs.cloudflare.com/ajax/libs/gsap/1.20.3/TweenMax.min.js',
label: 'Greensock TweenMax',
type: 'js'
},
{
url: 'https://cdnjs.cloudflare.com/ajax/libs/uikit/2.27.5/js/uikit.min.js',
label: 'UIkit 2',
type: 'js'
},
{
url:
'https://cdnjs.cloudflare.com/ajax/libs/uikit/3.0.0-beta.42/js/uikit.min.js',
label: 'UIkit 3',
type: 'js'
}
];
window.cssLibs = [
{
url:
'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css',
label: 'Bootstrap 3',
type: 'css'
},
{
url:
'https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css',
label: 'Bootstrap 4',
type: 'css'
},
{
url:
'https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/css/foundation.min.css',
label: 'Foundation',
type: 'css'
},
{
url: 'https://semantic-ui.com/dist/semantic.min.css',
label: 'Semantic UI',
type: 'css'
},
{
url: 'https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.1/css/bulma.min.css',
label: 'Bulma',
type: 'css'
},
{
url: 'https://cdnjs.cloudflare.com/ajax/libs/hint.css/2.5.0/hint.min.css',
label: 'Hint.css',
type: 'css'
},
{
url: 'https://cdn.jsdelivr.net/npm/tailwindcss/dist/tailwind.min.css',
label: 'Tailwind.css',
type: 'css'
},
{
url:
'https://cdnjs.cloudflare.com/ajax/libs/uikit/2.27.5/css/uikit.min.css',
label: 'UIkit 2',
type: 'css'
},
{
url:
'https://cdnjs.cloudflare.com/ajax/libs/uikit/3.0.0-beta.42/css/uikit.min.css',
label: 'UIkit 3',
type: 'css'
},
{
url:
'https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css',
label: 'Animate.css',
type: 'css'
},
{
url:
'https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css',
label: 'FontAwesome 4',
type: 'css'
},
{
url: 'https://use.fontawesome.com/releases/v5.0.10/css/all.css',
label: 'FontAwesome 5',
type: 'css'
}
];

@ -1,14 +0,0 @@
(function(w) {
window.loadJS = function(src) {
var d = deferred();
var ref = w.document.getElementsByTagName('script')[0];
var script = w.document.createElement('script');
script.src = src;
script.async = true;
ref.parentNode.insertBefore(script, ref);
script.onload = function() {
d.resolve();
};
return d.promise;
};
})(window);

@ -1,21 +0,0 @@
(function() {
const noticationContainerEL = $('#js-alerts-container');
var hideTimeout;
function addNotification(msg) {
// var n = document.createElement('div');
// div.textContent = msg;
// noticationContainerEL.appendChild(n);
noticationContainerEL.textContent = msg;
noticationContainerEL.classList.add('is-active');
clearTimeout(hideTimeout);
hideTimeout = setTimeout(function() {
noticationContainerEL.classList.remove('is-active');
}, 2000);
}
window.alertsService = {
add: addNotification
};
})();

@ -1,16 +0,0 @@
<a d-click="onModalCloseBtnClick" href="" aria-label="Close modal" title="Close" class="js-modal__close-btn modal__close-btn">
<svg>
<use xlink:href="#cross-icon"></use>
</svg>
</a>
<h2>Import your creations in your account</h2>
<div>
<p>You have <span id="oldSavedCreationsCountEl"></span> creations saved in your local machine. Do you want to import those creations in your account so they are more secure and accessible anywhere?</p>
<p>It's okay if you don't want to. You can simply logout and access them anytime on this browser.</p>
<div class="flex flex-h-end">
<button d-click="dontAskToImportAnymore" class="btn">Don't ask me again</button>
<button d-click="importCreationsAndSettingsIntoApp" class="btn btn--primary ml-1">Yes, please import</button>
</div>
</div>

@ -1,520 +0,0 @@
<a d-click="onModalCloseBtnClick" href="" aria-label="Close notifications" title="Close" class="js-modal__close-btn modal__close-btn">
<svg>
<use xlink:href="#cross-icon"></use>
</svg>
</a>
<h1>Whats new?</h1>
<div class="notification">
<span class="notification__version">3.2.0</span>
<ul>
<li>
<strong>🚀 Loop timeout setting</strong>: You now have a setting to tweak the maximum timeout of a loop iteration before it's marked as infinite loop.
</li>
<li><strong>♿️ Accessibility</strong>: Modals now have proper keyboard navigation integrated.</li>
<li><strong>♿️ Accessibility</strong>: Color contrast improvements.</li>
<li>🚀 Popular libraries list updated. Thanks
<a href="https://github.com/diomed" target="_blank">@diomed</a> & <a href="https://github.com/leninalbertolp" target="_blank">@leninalbertolp</a>
</li>
<li>
<strong>🔧 Bugfix</strong>: Modal take up appropriate width instead of spanning full width.
</li>
<br>
<li>
<strong>🚀 Announcement</strong>: Hi! I am Kushagra Gour (creator of Web Maker) and I have launched a
<a href="https://patreon.com/kushagra"
target="_blank">Patreon campaign</a>. If you love Web Maker, consider pledging to
<a href="https://patreon.com/kushagra" target="_blank">support me</a> :)</li>
<li>
<a href="https://github.com/chinchang/web-maker/issues" target="_blank">Suggest features or report bugs.</a>
</li>
<li>Web Maker now has more than 50K weekly active users! Thank you for being a part of this community 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>&nbsp;
<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>&nbsp;
<a aria-label="Support the developer" d-click="openSupportDeveloperModal" data-event-action="supportDeveloperChangelogBtnClick"
class="btn btn-icon">Support the developer</a>
</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">3.1.1</span>
<ul>
<li>
<strong>Bugfix</strong>: Fix the "Run" button not refreshing the preview after release 3.0.4.
</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">3.1.0</span>
<ul>
<li>
<strong>Mobile Support (app only).</strong>: Make the Web Maker app usable on mobile. This is only for web app as Chrome extensions don't run on mobile.
</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">3.0.4</span>
<ul>
<li>
<strong>Bugfix</strong>: Guarantee code doesn't execute when "auto preview" is off.</li>
<li>Add link to our new
<a href="https://web-maker.slack.com" target="_blank">Slack channel</a> 🤗.
</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">3.0.3</span>
<ul>
<li>
<strong>Bugfix (extension)</strong>: "Save as HTML" file saves with correct extension.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">3.0.1</span>
<ul>
<li>After months of work, here is Web Maker 3.0.
<a href="https://medium.com/web-maker/web-maker-3-0-is-here-f158a40eeaee"
target="_blank">Read the blog post about it</a>.</li>
<li>Web Maker is no more just a Chrome extension, it is also available as web app that runs offline just like the extension!
Checkout it out ->
<a href="https://webmakerapp.com/app/" target="_blank">https://webmakerapp.com/app/</a>.</li>
<li>Now use Web Maker web app on any modern browser (tested with Chrome and Firefox).</li>
<li>
<strong>User Accounts</strong> - The much requested user accounts are here. Now maintain your account and store all your creations
in the cloud and access them anywhere anytime.</li>
<li>
<strong>New layout mode</strong> - One more layout mode, that lets you align all the panes vertically.</li>
<li>
<strong>No more restriction on scripts (Web app only)</strong> - If you are using the web app, there is no more a restriction
to load scripts from only specific domains. Load any script!</li>
<li>
<strong>Inline scripts (Web app only)</strong> - The restriction of writing JavaScript only in JS pane is also removed.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.9.7</span>
<ul>
<li>
<a href="https://tailwindcss.com/" target="_blank">Tailwind CSS</a> added to popular CSS libraries list. Thanks
<a href="https://github.com/diomed" target="_blank">diomed</a>.</li>
<li>Popular libraries list updated. Thanks
<a href="https://github.com/diomed" target="_blank">diomed</a>.</li>
<li>
<strong>Dev</strong>: Bug fixes and code refactoring to make things simple. Thanks
<a href="https://github.com/iamandrewluca"
target="_blank">iamandrewluca</a>.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.9.6</span>
<ul>
<li>
<strong>Bugfix</strong>: Fix close buttons not working in notifications and keyboard shortcuts modal.</li>
<li>
<strong>Bugfix</strong>: Fix keyboard shortcut to see keyboard shortcuts :) Thanks
<a href="https://github.com/ClassicOldSong"
target="_blank">ClassicOldSong</a>.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.9.5</span>
<ul>
<li>
<a href="https://medium.com/web-maker/release-2-9-5-add-library-search-pane-collapsing-ux-improvements-more-1085216c1301"
target="_blank">Read blog post about this release.</a>
</li>
<li>
<strong>Keyboard shortcuts panel</strong>: Add a list of all keyboard shotcuts. Access with
<code> Ctrl/⌘ + Shift + ?</code> or click keyboard button in footer.</li>
<li>
<strong>Add external library</strong>: Better UX for searching third party libraries.</li>
<li>
<strong>Improvement</strong>: Code panes now go fullscreen when double-clicked on their headers - which is much more intuitive
behavior based on feedback from lot of developers.</li>
<li>
<strong>Improvement</strong>: Add
<code>allowfullscreen</code> attribute on iframes. Thanks
<a href="https://github.com/ClassicOldSong" target="_blank">ClassicOldSong</a>.</li>
<li>
<strong>Bugfix</strong> - Stop screenlog.js from showing up in the exported HTML.</li>
<li>Popular external libraries list updated. Thanks
<a href="https://github.com/jlapitan" target="_blank">jlapitan</a>.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.9.4</span>
<ul>
<li>
<strong>Improvement</strong>: Atomic CSS (Atomizer) has been updated to latest version. Now you can do things like psuedo elements.
Learn More.</li>
<li>
<strong>Bugfix</strong> - Logging circular objects is now possible. It won't show in the Web Maker console, but will show fine
in browser's console.</li>
<li>
<strong>Bugfix</strong> - Console's z-index issue has been fixed.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.9.3</span>
<ul>
<li>Choose the save location while exporting your saved creations. Now easily sync them to your Dropbox or any cloud storage.</li>
<li>All modals inside the app now have a close button.</li>
<li>Checkbox that showed on clicking a boolean value is now removed. Thanks
<a href="https://github.com/gauravmuk" target="_blank">Gaurav Nanda</a>.</li>
<li>
<strong>Bugfix</strong> - Screenshots on retina device are now correct. Thanks
<a href="https://github.com/AshBardhan" target="_blank">Ashish Bardhan</a>.</li>
<li>
<strong>Bugfix</strong> - Double console log in detached mode fixed.</li>
<li>
<strong>Bugfix</strong> - Console.clear now works in detached mode too.</li>
<li>
<strong>Bugfix</strong> - DOCTYPE added in preview.</li>
<li>
<strong>Bugfix</strong> - Typo correction in README. Thanks
<a href="https://github.com/AdilMah" target="_blank">Adil Mahmood</a>.</li>
<li>gstatic.com is available to load external JavaScripts from.</li>
<li>Popular libraries list updated. Thanks
<a href="https://github.com/diomed" target="_blank">diomed</a>.</li>
<li>Added
<a href="https://github.com/chinchang/web-maker/blob/master/CONTRIBUTING.md" target="_blank">contribution guidelines</a> in the Github repository.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.9.2</span>
<ul>
<li>Minor bug fixes.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.9.1</span>
<ul>
<li>
<a href="https://medium.com/web-maker/v2-9-lots-of-goodies-bd1e939571f6" target="_blank">Read blog post about last release.</a>
</li>
<li>Use Ctrl/Cmd+D to select next occurence of matching selection.</li>
<li>Improve onboard experience.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.9.0</span>
<ul>
<li>
<a href="https://medium.com/web-maker/v2-9-lots-of-goodies-bd1e939571f6" target="_blank">Read blog post about this release.</a>
</li>
<li>
<strong>Detached Preview</strong> - Yes, you read that correct! You can now detach your preview and send it to your secondary
monitor.
</li>
<li>
<strong>Find & Replace</strong> - Long awaited, now its there. Ctrl/Cmd+f to find and add Alt to replace.</li>
<li>
<strong>Atomic CSS (Atomizer) configurations</strong> - Add custom config for Atomic CSS.
<a href="https://github.com/acss-io/atomizer#api"
target="_blank">Read more</a>.</li>
<li>
<strong>Light mode</strong> - This new setting makes Web Maker drop some heavy effects like blur etc to gain more performance.
Thanks
<a href="https://github.com/iamandrewluca" target="_blank">Andrew</a>.</li>
<li>
<strong>Preserve logs setting</strong> - Choose whether or not to preserve logs across preview refreshes. Thanks
<a href="https://github.com/BasitAli"
target="_blank">Basit</a>.</li>
<li>
<strong>Line wrap setting</strong> - As the name says.</li>
<li>Semantic UI added to popular libraries.</li>
<li>Bootstrap, Vue, UI-Kit and more updated to latest versions in popular libraries.</li>
<li>UX improvements in settings UI</li>
<li>
<strong>Bugfix</strong> - Trigger preview refresh anytime with Ctrl/⌘ + Shift + 5. Even with auto-preview on.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.8.1</span>
<ul>
<li>Vue.js & UIKit version updated to latest version in 'Add Library' list.</li>
<li>UTF-8 charset added to preview HTML to support universal characters.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.8.0</span>
<ul>
<li>
<a href="https://medium.com/web-maker/release-v2-8-is-out-f44e6ea5d9c4" target="_blank">Read blog post about this release.</a>
</li>
<li>
<strong>Auto Save</strong> - Your creations now auto-save after your first manual save. This is configurable from settings.
</li>
<li>
<strong>Base2Tone-Meadow Editor Theme</strong> - First user contributed theme. Thanks to Diomed.</li>
<li>
<strong>Use System Fonts</strong> - You can now use any of your existing system fonts in the editor!</li>
<li>
<strong>Matching Tag Highlight</strong> - Cursor over any HTML tag would highlight the matching pair tag.</li>
<li>Auto-completion suggestion can now be switched off from settings.</li>
<li>
<strong>Improvement</strong> - Stop white flicker in editor when the app opens.
</li>
<li>
<strong>Bugfix</strong> - Add Babel Polyfill to enable use of next-gen built-ins like Promise or WeakMap.
</li>
<li>Vue.js version updated to 2.4.0 in popular library list.</li>
<li>Downloads permission is optional. Asked only when you take screenshot.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.7.2</span>
<ul>
<li>
<strong>External Libraries</strong> - Add Foundation.js and update UIKit 3 to latest beta.</li>
<li>
<strong>rawgit.com</strong> &
<strong>wzrd.in</strong> domains are now allowed for loading external libraries from.</li>
<li>Minor booting speed improvements</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.7.1</span>
<ul>
<li>
<strong>Framer.js support</strong> - You can now load the latest framer.js library from
<a href="https://builds.framerjs.com/"
target="_blank">framer builds page</a> and start coding framer prototypes.</li>
<li>
<strong>Bugfix</strong>: Edit on CodePen is back in action.</li>
<li>
<strong>Bugfix</strong>: Autocompletion menu doesn't show on cut and paste now.</li>
<li>
<strong>Bugfix</strong>: Updated & fixed urls of some common external libraries to latest versions. UIKit3 & Bootstrap 4α are
now in the list.</li>
<li>Preprocessor selector are now more accessible.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.7.0</span>
<ul>
<li>
<strong>Fork any creation!</strong>: Now you can fork any existing creation of yours to start a new work based on it. One big
use case of this feature is "Templates"!
<a target="_blank" href="https://kushagragour.in/blog/2017/05/web-maker-fork-templates/?utm_source=webmakerapp&utm_medium=referral">Read more about it</a>.</li>
<li>
<strong>Fonts 😍 </strong>: Super-awesome 4 fonts (mostly with ligature support) now available to choose from. Fira Code is the
default font now.</li>
<li>Updated most used external libraries to latest versions.</li>
<li>
<strong>Bugfix</strong>: Add missing Bootstrap JS file to most used external libraries list.</li>
<li>Several other minor bugfixes and improvements to make Web Maker awesome!</li>
<li>Great news to share with you - Web Maker has been featured on the Chrome Webstore homepage! Thanks for all the love :)</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.6.1</span>
<ul>
<li>
<strong>Bugfix</strong>: Emojis vanishing while exporting to Codepen has been fixed.</li>
<li>
<strong>Bugfix</strong>:
<code>console.clear()</code> now doesn't error and clears the inbuilt console.</li>
<li>
<strong>Bugfix</strong>: External libraries added to the creation are exported as well to Codepen.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.6.0</span>
<ul>
<li>
<strong>The "Console"</strong>: The most awaited feature is here! There is now an inbuilt console to see your logs, errors and
for quickly evaluating JavaScript code inside your preview. Enjoy! I also a
<a href="https://kushagragour.in/blog/2017/05/web-maker-console-is-here/?utm_source=webmakerapp&utm_medium=referral"
target="_blank">blog post about it</a>.</li>
<li>Number slider which popped on clicking any number in the code has been removed due to poor user experience.</li>
<li>Minor usability improvements.</li>
</ul>
</div>
<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>
</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>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.4.0</span>
<ul>
<li>
<strong>Import/Export</strong>: Your creations are most important. Now export all your creations into a single file as a backup
that can be imported anytime & anywhere.</li>
<li>
<strong>Editor themes</strong>: You have been heard. Now you can choose from a huge list of wonderful editor themes!</li>
<li>
<strong>Identation settings</strong>: Not a spaces fan? Switch to tabs and set your indentation size.</li>
<li>
<strong>Vim key bindings</strong>: Rejoice Vim lovers!</li>
<li>
<strong>Code blast</strong>: Why don't you try coding with this switched on from the settings? Go on...</li>
<li>
<strong>Important</strong>: Due to security policy changes from Chrome 57 onwards, Web Maker now allows loading external JavaScript
libraries only from certain whitelisted domains (localhost, https://ajax.googleapis.com, https://code.jquery.com, https://cdnjs.cloudflare.com,
https://unpkg.com, https://maxcdn.com, https://cdn77.com, https://maxcdn.bootstrapcdn.com, https://cdn.jsdelivr.net/)</li>
<li>Save button now highlights when you have unsaved changes.</li>
<li>Jade is now called Pug. Just a name change.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.3.2</span>
<ul>
<li>Update Babel to support latest and coolest ES6 features.</li>
<li>Improve onboarding experience at first install.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.3.1</span>
<ul>
<li>
<strong>Bugfix</strong> - Splitting of code and preview panes is remembered by the editor.</li>
<li>Title of the creation is used for the file name when saving as HTML.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.3.0</span>
<ul>
<li>
<strong>Add Library Autocompletion</strong> - Just start typing the name of library and you'll be shown matching libraries from
cdnjs.</li>
<li>
<strong>Preview Screenshot Capture</strong> - Want to grab a nice screenshot of your creation. You have it! Click and capture.</li>
<li>
<strong>Auto Indent Code</strong> - Select your code and hit Shift-Tab to auto-indent it!</li>
<li>
<strong>Keyboard Navigation in Saved List</strong> - Now select your creation using arrow keys and hit ENTER to open it.</li>
<li>Highlight active line in code panes.</li>
<li>
<strong>Bugfix</strong> - Fix in generated title of new creation.</li>
<li>
<strong>Bugfix</strong> - HTML autocompletion is manual triggered now with Ctrl+Space.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.2.0</span>
<ul>
<li>
<strong>Code Autocompletion</strong> - See code suggestions while you type!</li>
<li>
<strong>Full Screen Preview</strong> - Checkout your creation in a full-screen layout.</li>
<li>
<strong>SASS</strong> - SASS support added for CSS.</li>
<li>
<strong>Faster CSS update</strong> - Preview updates instantly without refresh when just CSS is changed.</li>
<li>
<strong>Bugfix</strong> - Indentation fixed while going on new line.</li>
<li>
<strong>Bugfix</strong> - Works even in Chrome Canary now. Though libraries can be added only through CDNs.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.1.0</span>
<ul>
<li>
<strong>TypeScript</strong> - Now you can code in TypeScript too!</li>
<li>
<strong>Stylus Preprocessor</strong> - Stylus supported adding for CSS.</li>
<li>
<strong>Code Folding</strong> - Collapse large code blocks for easy editing.</li>
<li>
<strong>Bugfix</strong> - Support JSX in JavaScript.</li>
<li>Better onboarding for first time users.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.0.0</span>
<ul>
<li>
<strong>Save and Load</strong> - Long pending and super-useful, now you can save your creations and resume them anytime later.</li>
<li>
<strong>Insert JS & CSS</strong> - Load popular JavaScript & CSS libraries in your work without writing any code.</li>
<li>
<strong>Collapsed Panes</strong> - Collapse/uncollapse code panes with a single click. Your pane configuration is even saved with
every creation!</li>
<li>
<strong>Quick color & number change</strong> - Click on any color or number and experiment with quick values using a slider.</li>
<li>
<strong>Linting</strong> - See your code errors right where you are coding.</li>
<li>No more browser hang due to infinite loops!</li>
<!-- <li><a href="https://kushagragour.in/blog/web-maker-2">Read more about this big release</a></li> -->
</ul>
</div>
<div class="notification">
<span class="notification__version">1.7.0</span>
<ul>
<li>
<strong>Preprocessors!</strong> - Enjoy a whole list of preprocessors for HTML(Jade & markdown), CSS(SCSS & LESS) and JavaScript(CoffeeScript
& Babel).</li>
<li>More awesome font for code.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">1.6.0</span>
<ul>
<li>You can now configure Web-Maker to not replace new tab page from the settings. It is always accessible from the icon in
the top-right.</li>
<li>Download current code as HTML file with Ctrl/⌘ + S keyboard shortcut.</li>
<li>New notifications panel added so you are always aware of the new changes in Web-Maker.</li>
</ul>
</div>

@ -1,73 +0,0 @@
<a d-click="onModalCloseBtnClick" href="" aria-label="Close help modal" title="Close" class="js-modal__close-btn modal__close-btn">
<svg>
<use xlink:href="#cross-icon"></use>
</svg>
</a>
<h1>
<div class="web-maker-with-tag">Web Maker</div>
<small style="font-size:14px;"> v3.2.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>
<a href="/docs" target="_blank">Read the documentation</a>.
</p>
<p>Tweet out your feature requests, comments & suggestions to
<a target="_blank" href="https://twitter.com/webmakerApp">@webmakerApp</a>.</p>
<p>Like this extension? Please
<a href="https://chrome.google.com/webstore/detail/web-maker/lkfkkhfhhdkiemehlpkgjeojomhpccnh/reviews" target="_blank">rate it here</a>.</p>
<p>
<button aria-label="Support the developer" d-click="openSupportDeveloperModal" data-event-action="supportDeveloperHelpBtnClick"
class="btn btn-icon">
<svg>
<use xlink:href="#gift-icon"></use>
</svg>Support the developer</button>
<a aria-label="Rate Web Maker" href="https://chrome.google.com/webstore/detail/web-maker/lkfkkhfhhdkiemehlpkgjeojomhpccnh/reviews"
target="_blank" class="btn btn-icon">
<svg>
<use xlink:href="#heart-icon"></use>
</svg>Share Web Maker</a>
<a aria-label="Chat" href="https://web-maker.slack.com" target="_blank" class="btn btn-icon">
<svg>
<use xlink:href="#chat-icon"></use>
</svg>Chat</a>
<a aria-label="Report a Bug" href="https://github.com/chinchang/web-maker/issues" target="_blank" class="btn btn-icon">
<svg>
<use xlink:href="#bug-icon"></use>
</svg>Report a bug</a>
</p>
<p>
<h3>Awesome libraries used</h3>
<ul>
<li>
<a target="_blank" href="https://kushagragour.in/lab/hint/">Hint.css</a> &
<a target="_blank" href="https://github.com/chinchang/screenlog.js">Screenlog.js</a> - By me :)</li>
<li>
<a target="_blank" href="https://nathancahill.github.io/Split.js/">Split.js</a> - Nathan Cahill</li>
<li>
<a target="_blank" href="https://codemirror.net/">Codemirror</a> - Marijn Haverbeke</li>
<li>
<a target="_blank" href="https://emmet.io/">Emmet</a> - Sergey Chikuyonok</li>
<li>
<a target="_blank" href="http://esprima.org/">Esprima</a> - Ariya Hidayat</li>
<li>
<a target="_blank" href="https://github.com/enjalot/Inlet">Inlet</a> - Ian Johnson</li>
<li>
<a target="_blank" href="https://webmakerapp.com/">Web Maker!</a> - whhat!</li>
</ul>
</p>
<p>
<h3>License</h3>
"Web Maker" is
<a target="_blank" href="https://github.com/chinchang/web-maker">open-source</a> under the
<a href="https://opensource.org/licenses/MIT" target="_blank">MIT License</a>.
</p>
</div>

@ -1,106 +0,0 @@
<a d-click="onModalCloseBtnClick" href="" aria-label="Close keyboard shortcuts modal" title="Close" class="js-modal__close-btn modal__close-btn">
<svg>
<use xlink:href="#cross-icon"></use>
</svg>
</a>
<h1>Keyboard Shortcuts</h1>
<div class="flex">
<div>
<h2>Global</h2>
<p>
<span class="kbd-shortcut__keys">
Ctrl/⌘ + Shift + ?
</span>
<span class="kbd-shortcut__details">See keyboard shortcuts</span>
</p>
<p>
<span class="kbd-shortcut__keys">
Ctrl/⌘ + Shift + 5
</span>
<span class="kbd-shortcut__details">Refresh preview</span>
</p>
<p>
<span class="kbd-shortcut__keys">
Ctrl/⌘ + S
</span>
<span class="kbd-shortcut__details">Save current creations</span>
</p>
<p>
<span class="kbd-shortcut__keys">
Ctrl/⌘ + O
</span>
<span class="kbd-shortcut__details">Open list of saved creations</span>
</p>
<p>
<span class="kbd-shortcut__keys">
Ctrl + L
</span>
<span class="kbd-shortcut__details">Clear console (works when console input is focused)</span>
</p>
<p>
<span class="kbd-shortcut__keys">
Esc
</span>
<span class="kbd-shortcut__details">Close saved creations panel & modals</span>
</p>
</div>
<div class="ml-2">
<h2>Editor</h2>
<p>
<span class="kbd-shortcut__keys">
Ctrl/⌘ + F
</span>
<span class="kbd-shortcut__details">Find</span>
</p>
<p>
<span class="kbd-shortcut__keys">
Ctrl/⌘ + G
</span>
<span class="kbd-shortcut__details">Select next match</span>
</p>
<p>
<span class="kbd-shortcut__keys">
Ctrl/⌘ + Shift + G
</span>
<span class="kbd-shortcut__details">Select previous match</span>
</p>
<p>
<span class="kbd-shortcut__keys">
Ctrl/⌘ + Opt/Alt + F
</span>
<span class="kbd-shortcut__details">Find & replace</span>
</p>
<p>
<span class="kbd-shortcut__keys">
Shift + Tab
</span>
<span class="kbd-shortcut__details">Realign code</span>
</p>
<p>
<span class="kbd-shortcut__keys">
Ctrl/⌘ + ]
</span>
<span class="kbd-shortcut__details">Indent code right</span>
</p>
<p>
<span class="kbd-shortcut__keys">
Ctrl/⌘ + [
</span>
<span class="kbd-shortcut__details">Indent code left</span>
</p>
<p>
<span class="kbd-shortcut__keys">
Tab
</span>
<span class="kbd-shortcut__details">Emmet code completion <a href="https://emmet.io/" target="_blank">Read more</a></span>
</p>
<p>
<span class="kbd-shortcut__keys">
Ctrl/⌘ + /
</span>
<span class="kbd-shortcut__details">Single line comment</span>
</p>
</div>
</div>

@ -1,40 +0,0 @@
<a d-click="onModalCloseBtnClick" href="" aria-label="Close Login modal" title="Close" class="js-modal__close-btn modal__close-btn">
<svg>
<use xlink:href="#cross-icon"></use>
</svg>
</a>
<h2>Login / Signup</h2>
<div>
<p>
<button
d-click="login"
class="social-login-btn social-login-btn--github btn btn-icon btn--big full-width hint--right hint--always"
data-auth-provider="github"
data-hint="You logged in with Github last time">
<svg><use xlink:href="#github-icon"></use></svg>Login with Github
</button>
</p>
<p>
<button
d-click="login"
class="social-login-btn social-login-btn--google btn btn-icon btn--big full-width hint--right hint--always"
data-auth-provider="google"
data-hint="You logged in with Google last time">
<svg><use xlink:href="#google-icon"></use></svg>Login with Google
</button>
</p>
<p class="mb-2">
<button
d-click="login"
class="social-login-btn social-login-btn--facebook btn btn-icon btn--big full-width hint--right hint--always"
data-auth-provider="facebook"
data-hint="You logged in with Facebook last time">
<svg><use xlink:href="#fb-icon"></use></svg>Login with Facebook
</button>
</p>
<p>
Join a community of 50,000+ Developers
</p>
</div>

@ -1,73 +0,0 @@
<div class="tac">
<svg width="130px" height="50px" aria-hidden="true">
<use xlink:href="#logo" />
</svg>
<h1 style="margin-top:20px">Welcome to Web Maker<span class="show-when-app"> 3.0 (beta)</span></h1>
</div>
<div class="flex" style="margin-top:40px;">
<div class="onboard-step show-when-app">
<div class="tac">
<svg class="onboard-step__icon" viewBox="0 0 24 24">
<path d="M13.64,21.97C13.14,22.21 12.54,22 12.31,21.5L10.13,16.76L7.62,18.78C7.45,18.92 7.24,19 7,19A1,1 0 0,1 6,18V3A1,1 0 0,1 7,2C7.24,2 7.47,2.09 7.64,2.23L7.65,2.22L19.14,11.86C19.57,12.22 19.62,12.85 19.27,13.27C19.12,13.45 18.91,13.57 18.7,13.61L15.54,14.23L17.74,18.96C18,19.46 17.76,20.05 17.26,20.28L13.64,21.97Z"
/>
</svg>
</div>
<p>
Open Web Maker anytime by visiting <a>https://webmakerapp.com/app/</a> - Even when you are offline! It just works! 😱 <strong>Drag the following bookmarklet</strong> on your bookmark bar to create a quick access shortcut:
<a class="ml-1 bookmarklet" href="https://webmakerapp.com/app/">
<svg width="20" height="20" aria-hidden="true">
<use xlink:href="#logo" />
</svg>
Web Maker
</a>
</p>
</div>
<div class="onboard-step show-when-extension">
<div class="tac">
<svg class="onboard-step__icon" viewBox="0 0 24 24">
<path d="M13.64,21.97C13.14,22.21 12.54,22 12.31,21.5L10.13,16.76L7.62,18.78C7.45,18.92 7.24,19 7,19A1,1 0 0,1 6,18V3A1,1 0 0,1 7,2C7.24,2 7.47,2.09 7.64,2.23L7.65,2.22L19.14,11.86C19.57,12.22 19.62,12.85 19.27,13.27C19.12,13.45 18.91,13.57 18.7,13.61L15.54,14.23L17.74,18.96C18,19.46 17.76,20.05 17.26,20.28L13.64,21.97Z"
/>
</svg>
</div>
<p>
Open Web Maker anytime by clicking the
<svg class="relative" style="top:5px;" width="40" height="30">
<use xlink:href="#logo" />
</svg> button in top-right side of your browser.
</p>
</div>
<div class="onboard-step">
<div class="tac">
<svg class="onboard-step__icon" viewBox="0 0 24 24">
<use xlink:href="#settings-icon"></use>
</svg>
</div>
<p>
Configure and customize settings by clicking the gear icon (
<svg style="width:18px;height:18px;position:relative;top:3px;fill:#888"
viewBox="0 0 24 24">
<use xlink:href="#settings-icon"></use>
</svg>) in bottom right of the app.
</p>
</div>
<div class="onboard-step">
<div class="tac">
<svg class="onboard-step__icon" style="stroke-width:0.3px;">
<use xlink:href="#twitter-icon"></use>
</svg>
</div>
<p>
Follow <a href="https://twitter.com/intent/follow?screen_name=webmakerApp" targe="_blank">@webmakerApp</a> to know about the new upcoming
features!
</p>
</div>
</div>
<p class="tac show-when-app">
If you are an existing Chrome extension user, you can import your creations from there to here. <a href="https://medium.com/web-maker/importing-exporting-your-creations-d92e7de5c3dc" target="_blank">Learn how to export/import</a>.
</p>
<p class="tac">
<button class="btn btn--primary" d-click="closeAllOverlays">Lets start!</button>
</p>

@ -1,22 +0,0 @@
<a d-click="onModalCloseBtnClick" href="" aria-label="Close modal" title="Close" class="js-modal__close-btn modal__close-btn">
<svg>
<use xlink:href="#cross-icon"></use>
</svg>
</a>
<div class="tac">
<h1>Support the Developer</h1>
<p>Hi, <a href="https://kushagragour.in" target="_blank">Kushagra</a> here! Web Maker is a free and open-source project. To keep myself motivated for working on such open-source and free <a href="https://kushagragour.in/lab/" target="_blank">side projects</a>, I am accepting donations. Your pledge, no matter how small, will act as an appreciation towards my work and keep me going forward making Web Maker more awesome🔥. So please consider donating. 🙏🏼 (could be as small as $1/month).
</p>
<div class="flex flex-h-center" id="onboardDontShowInTabOptionBtn" d-click="onDontShowInTabClicked">
<a class="onboard-selection" href="https://patreon.com/kushagra" target="_blank" aria-label="Make a monthly pledge on Patreon">
<img src="patreon.png" height="60" alt="Become a patron image">
<h3 class="onboard-selection-text">Make a monthly pledge on Patreon</h3>
</a>
</div>
<a href="https://www.paypal.me/kushagragour" target="_blank" aria-label="Make a one time donation on Paypal">
Or, make a one time donation
</a>
</div>

Binary file not shown.

Before

(image error) Size: 6.4 KiB

@ -1,31 +0,0 @@
// Console header drag resize logic
var consoleHeaderDragStartY;
var consoleInitialHeight;
function onConsoleHeaderDrag(e) {
consoleEl.style.height =
consoleInitialHeight + consoleHeaderDragStartY - e.pageY + 'px';
}
$('.js-console__header').addEventListener('mousedown', e => {
consoleHeaderDragStartY = e.pageY;
consoleInitialHeight = consoleEl.getBoundingClientRect().height;
$('#demo-frame').classList.add('pointer-none');
window.addEventListener('mousemove', onConsoleHeaderDrag);
});
$('.js-console__header').addEventListener('mouseup', () => {
window.removeEventListener('mousemove', onConsoleHeaderDrag);
$('#demo-frame').classList.remove('pointer-none');
});
window.addEventListener('focusin', e => {
if (document.body.classList.contains('overlay-visible')) {
const modal = $('.is-modal-visible');
if (!modal) {
return;
}
if (!modal.contains(e.target)) {
e.preventDefault();
modal.querySelector('.js-modal__close-btn').focus();
}
}
});

File diff suppressed because it is too large Load Diff

@ -1,154 +0,0 @@
// textarea-autocomplete.js
(function() {
class TextareaAutoComplete {
constructor(textarea, options) {
this.t = textarea;
this.filter = options.filter;
this.selectedCallback = options.selectedCallback;
var wrap = document.createElement('div');
wrap.classList.add('btn-group');
textarea.parentElement.insertBefore(wrap, textarea);
wrap.insertBefore(textarea, null);
this.list = document.createElement('ul');
this.list.classList.add('dropdown__menu');
this.list.classList.add('autocomplete-dropdown');
wrap.insertBefore(this.list, null);
this.loader = document.createElement('div');
this.loader.classList.add('loader');
this.loader.classList.add('autocomplete__loader');
this.loader.style.display = 'none';
wrap.insertBefore(this.loader, null);
// after list is insrted into the DOM, we put it in the body
// fixed at same position
setTimeout(() => {
requestIdleCallback(() => {
document.body.appendChild(this.list);
this.list.style.position = 'fixed';
});
}, 100);
this.t.addEventListener('input', e => this.onInput(e));
this.t.addEventListener('keydown', e => this.onKeyDown(e));
this.t.addEventListener('blur', e => this.closeSuggestions(e));
this.list.addEventListener('mousedown', e => this.onListMouseDown(e));
}
get currentLineNumber() {
return this.t.value.substr(0, this.t.selectionStart).split('\n').length;
}
get currentLine() {
var line = this.currentLineNumber;
return this.t.value.split('\n')[line - 1];
}
closeSuggestions() {
this.list.classList.remove('is-open');
this.isShowingSuggestions = false;
}
getList(input) {
var url = 'https://api.cdnjs.com/libraries?search=';
return fetch(url + input).then(response => {
return response.json().then(json => json.results);
});
}
replaceCurrentLine(val) {
var lines = this.t.value.split('\n');
lines.splice(this.currentLineNumber - 1, 1, val);
this.t.value = lines.join('\n');
}
onInput() {
var currentLine = this.currentLine;
if (currentLine) {
if (
currentLine.indexOf('/') !== -1 ||
currentLine.match(/https*:\/\//)
) {
return;
}
clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
this.loader.style.display = 'block';
this.getList(currentLine).then(arr => {
this.loader.style.display = 'none';
if (!arr.length) {
this.closeSuggestions();
return;
}
this.list.innerHTML = '';
if (this.filter) {
/* eslint-disable no-param-reassign */
arr = arr.filter(this.filter);
}
for (var i = 0; i < Math.min(arr.length, 10); i++) {
this.list.innerHTML += `<li data-url="${arr[i].latest}"><a>${arr[
i
].name}</a></li>`;
}
this.isShowingSuggestions = true;
if (!this.textareaBounds) {
this.textareaBounds = this.t.getBoundingClientRect();
this.list.style.top = this.textareaBounds.bottom + 'px';
this.list.style.left = this.textareaBounds.left + 'px';
this.list.style.width = this.textareaBounds.width + 'px';
}
this.list.classList.add('is-open');
});
}, 500);
}
}
onKeyDown(event) {
var selectedItemElement;
if (!this.isShowingSuggestions) {
return;
}
if (event.keyCode === 27) {
this.closeSuggestions();
event.stopPropagation();
}
if (event.keyCode === 40 && this.isShowingSuggestions) {
selectedItemElement = this.list.querySelector('.selected');
if (selectedItemElement) {
selectedItemElement.classList.remove('selected');
selectedItemElement.nextElementSibling.classList.add('selected');
} else {
this.list.querySelector('li:first-child').classList.add('selected');
}
this.list.querySelector('.selected').scrollIntoView(false);
event.preventDefault();
} else if (event.keyCode === 38 && this.isShowingSuggestions) {
selectedItemElement = this.list.querySelector('.selected');
if (selectedItemElement) {
selectedItemElement.classList.remove('selected');
selectedItemElement.previousElementSibling.classList.add('selected');
} else {
this.list.querySelector('li:first-child').classList.add('selected');
}
this.list.querySelector('.selected').scrollIntoView(false);
event.preventDefault();
} else if (event.keyCode === 13 && this.isShowingSuggestions) {
selectedItemElement = this.list.querySelector('.selected');
this.selectSuggestion(selectedItemElement.dataset.url);
this.closeSuggestions();
}
}
onListMouseDown(event) {
var target = event.target;
if (target.parentElement.dataset.url) {
this.selectSuggestion(target.parentElement.dataset.url);
}
}
selectSuggestion(value) {
if (this.selectedCallback) {
this.selectedCallback.call(null, value);
} else {
this.replaceCurrentLine(value);
}
this.closeSuggestions();
}
}
window.TextareaAutoComplete = TextareaAutoComplete;
})();

@ -1,229 +0,0 @@
(function() {
window.DEBUG = document.cookie.indexOf('wmdebug') > -1;
window.$ = document.querySelector.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];
};
// Safari doesn't have this!
window.requestIdleCallback =
window.requestIdleCallback ||
function(fn) {
setTimeout(fn, 10);
};
/*
* @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('.');
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 generateRandomId(len) {
var length = len || 10;
var id = '';
for (var i = length; i--; ) {
id += alphaNum[~~(Math.random() * alphaNum.length)];
}
return id;
}
function onButtonClick(btn, listener) {
btn.addEventListener('click', function buttonClickListener(e) {
listener(e);
return false;
});
}
function log() {
if (window.DEBUG) {
console.log(...arguments);
}
}
/**
* Adds timed limit on the loops found in the passed code.
* Contributed by Ariya Hidayat!
* @param code {string} Code to be protected from infinite loops.
*/
function addInfiniteLoopProtection(code, { timeout }) {
var loopId = 1;
var patches = [];
var varPrefix = '_wmloopvar';
var varStr = 'var %d = Date.now();\n';
var checkStr = `\nif (Date.now() - %d > ${timeout}) { window.top.previewException(new Error("Infinite loop")); break;}\n`;
esprima.parse(code, { tolerant: true, range: true, jsx: true }, function(
node
) {
switch (node.type) {
case 'DoWhileStatement':
case 'ForStatement':
case 'ForInStatement':
case 'ForOfStatement':
case 'WhileStatement':
var start = 1 + node.body.range[0];
var end = node.body.range[1];
var prolog = checkStr.replace('%d', varPrefix + loopId);
var epilog = '';
if (node.body.type !== 'BlockStatement') {
// `while(1) doThat()` becomes `while(1) {doThat()}`
prolog = '{' + prolog;
epilog = '}';
--start;
}
patches.push({ pos: start, str: prolog });
patches.push({ pos: end, str: epilog });
patches.push({
pos: node.range[0],
str: varStr.replace('%d', varPrefix + loopId)
});
++loopId;
break;
default:
break;
}
});
/* eslint-disable no-param-reassign */
patches
.sort(function(a, b) {
return b.pos - a.pos;
})
.forEach(function(patch) {
code = code.slice(0, patch.pos) + patch.str + code.slice(patch.pos);
});
/* eslint-disable no-param-reassign */
return code;
}
function getHumanDate(timestamp) {
var d = new Date(timestamp);
var retVal =
d.getDate() +
' ' +
[
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
][d.getMonth()] +
' ' +
d.getFullYear();
return retVal;
}
// create a one-time event
function once(node, type, callback) {
// create event
node.addEventListener(type, function(e) {
// remove event
e.target.removeEventListener(type, arguments.callee);
// call handler
return callback(e);
});
}
function downloadFile(fileName, blob) {
function downloadWithAnchor() {
var a = document.createElement('a');
a.href = window.URL.createObjectURL(blob);
a.download = fileName;
a.style.display = 'none';
document.body.appendChild(a);
a.click();
a.remove();
}
if (window.IS_EXTENSION) {
chrome.downloads.download(
{
url: window.URL.createObjectURL(blob),
filename: fileName,
saveAs: true
},
() => {
// If there was an error, just download the file using ANCHOR method.
if (chrome.runtime.lastError) {
downloadWithAnchor();
}
}
);
} else {
downloadWithAnchor();
}
}
window.utils = {
semverCompare,
generateRandomId,
onButtonClick,
addInfiniteLoopProtection,
getHumanDate,
log,
once,
downloadFile
};
window.chrome = window.chrome || {};
window.chrome.i18n = { getMessage: () => {} };
window.IS_EXTENSION = !!window.chrome.extension;
if (window.IS_EXTENSION) {
document.body.classList.add('is-extension');
} else {
document.body.classList.add('is-app');
}
})();