hatchyt
Version:
Hatch your next idea.
703 lines (604 loc) • 27.6 kB
JavaScript
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
var _editor = __webpack_require__(1);
var _editor2 = _interopRequireDefault(_editor);
var _utilities = __webpack_require__(3);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// (function(){
var defaultStyles = [{ id: 1, name: 'Normalize', uri: '//cdnjs.cloudflare.com/ajax/libs/normalize/3.0.3/normalize.min.css' }, { id: 2, name: 'PureCSS', uri: '//yui.yahooapis.com/pure/0.6.0/pure-min.css' }, { id: 0, name: 'Bootstrap', uri: '//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css' }, { id: 3, name: 'Foundation', uri: '//cdnjs.cloudflare.com/ajax/libs/foundation/6.0.1/css/foundation.min.css' }, { id: 4, name: '960', uri: '//cdnjs.cloudflare.com/ajax/libs/960gs/0/960.min.css' }, { id: 5, name: 'Bootstrap 4', uri: '//maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.2/css/bootstrap.min.css' }, { id: 5, name: 'Milligram', uri: '//cdnjs.cloudflare.com/ajax/libs/milligram/1.1.0/milligram.min.css' }];
var defaultScripts = [{ id: 0, name: 'jQuery', uri: '//code.jquery.com/jquery-2.2.0.min.js' }, { id: 1, name: 'React', dependencies: [4], uri: '//cdnjs.cloudflare.com/ajax/libs/react/0.14.3/react.min.js' }, { id: 2, name: 'Bootstrap', dependencies: [0], uri: '//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js' }, { id: 3, name: 'Google Analytics', input: 'Enter your GA ID:', dependencies: [] }, { id: 4, name: 'React DOM', dependencies: [1], uri: '//cdnjs.cloudflare.com/ajax/libs/react/0.14.3/react-dom.min.js' }, { id: 5, name: 'Underscore', dependencies: [], uri: '//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js' }, { id: 6, name: 'Foundation', dependencies: [0], uri: '//cdnjs.cloudflare.com/ajax/libs/foundation/6.0.1/js/foundation.min.js' }, { id: 6, name: 'Bootstrap 4', dependencies: [0], uri: '//maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.2/js/bootstrap.min.js' }];
site.config = JSON.parse(site.config);
var unsavedChanges;
var frame = document.getElementById('frame').contentWindow.document;
function confirmDelete(e) {
if (!window.confirm('Are you sure you want to delete this site? This will delete all tracking and signup information as well!')) {
return false;
} else {
window.location = 'delete';
}
}
function textFromTemplates(editor) {
var templates = JSON.parse(editor.templates).filter(function (x) {
return x.checked;
});
return templates.map(function (x) {
return x.text;
}).join('');
}
function update(e) {
var head = '<!doctype html><head>';
var styles = '<style type="text/css">body{background-color:white;}form._h-sign input[name="name"]{display: none;}</style>';
var script = '<script type="text/javascript">';
var body = '<body>';
body += htmlEditor.mirror.getValue();
script += scriptEditor.mirror.getValue();
body += (0, _utilities.thirdPartyScripts)(scriptEditor.settings);
styles += (0, _utilities.thirdPartyStyles)(cssEditor.settings);
styles += '<style type="text/css">' + textFromTemplates(cssEditor) + cssEditor.mirror.getValue() + '</style>';
frame.open();
frame.write(head + styles + '</head>' + body + script + '</script></body></html>');
frame.close();
unsavedChanges = true;
}
function mergeOptions(custom, key, original) {
// merges the users custom selections with the originals
if (!custom || !custom[key]) return original;
return original.map(function (o) {
return custom[key].find(function (c) {
return c.id === o.id;
}) || o;
}).concat(custom[key].filter(function (x) {
return x.custom;
}));
}
var title = document.getElementById('title');
var scriptEditor = new _editor2.default(document.getElementById('javascript'), {
id: 'scripts',
mode: 'javascript',
value: site.script || '',
title: 'JavaScript Library',
extraKeys: { 'Cmd-Enter': update },
configMenu: mergeOptions(site.config, 'extraScripts', defaultScripts),
templates: mergeOptions(site.config, 'scriptTemplates', defaultTemplates.filter(function (x) {
return x.name.startsWith('scripts');
}).map(function (x) {
x.name = x.name.substr(8);return x;
}))
});
var htmlEditor = new _editor2.default(document.getElementById('markup'), {
// id: 'markup',
mode: 'xml',
htmlMode: true,
value: site.markup || ''
});
var cssEditor = new _editor2.default(document.getElementById('style'), {
id: 'styles',
mode: 'css',
title: 'CSS Library',
value: site.style || '',
extraKeys: { 'Cmd-Enter': update },
lineWrapping: true,
templates: mergeOptions(site.config, 'cssTemplates', defaultTemplates.filter(function (x) {
return x.name.startsWith('styles');
}).map(function (x) {
x.name = x.name.substr(7);return x;
})),
configMenu: mergeOptions(site.config, 'extraCSS', defaultStyles)
});
if (console.debug) console.debug('Site debug loaded:', site);
cssEditor.mirror.setSize('100%', 500 - 18);
function publish(evnt) {
var targetElement = event.target;
var form = new FormData();
targetElement.classList.add('loading');
form.append('markup', htmlEditor.mirror.getValue());
form.append('stylesheet', cssEditor.mirror.getValue());
form.append('script', scriptEditor.mirror.getValue());
form.append('title', title.value);
form.append('id', document.getElementById('site-id').value);
form.append('domain', document.getElementById('site-domain').value);
// build the configuration settings
var config = {
extraScripts: JSON.parse(scriptEditor.settings).filter(function (x) {
return x.checked;
}),
extraCSS: JSON.parse(cssEditor.settings).filter(function (x) {
return x.checked;
}),
cssTemplates: JSON.parse(cssEditor.templates).filter(function (x) {
return x.checked;
}),
scriptTemplates: JSON.parse(scriptEditor.templates).filter(function (x) {
return x.checked;
})
};
form.append('config', JSON.stringify(config));
// send them to the server
var request = new XMLHttpRequest();
var now = new Date();
request.open('post', '/publish/');
request.send(form);
request.onreadystatechange = restore;
unsavedChanges = false;
function restore() {
var text = request.responseText;
var later = new Date();
if (later - now < 3000) {
setTimeout(function () {
targetElement.classList.remove('loading');
}, 500);
} else {
console.log('!');
targetElement.classList.remove('loading');
}
}
}
function fullscreen() {
var elem = document.getElementById("frame");
if (elem.requestFullscreen) {
elem.requestFullscreen();
} else if (elem.msRequestFullscreen) {
elem.msRequestFullscreen();
} else if (elem.mozRequestFullScreen) {
elem.mozRequestFullScreen();
} else if (elem.webkitRequestFullscreen) {
elem.webkitRequestFullscreen();
}
}
var checkChanges = function checkChanges(e) {
var result = unsavedChanges ? 'You have unsaved changes. Are you sure you want to exit?' : null;
if (result) {
e.returnValue = result;
return result;
}
};
document.getElementById('delete').setAttribute('href', 'javascript:(' + confirmDelete.toString() + '())');
scriptEditor.mirror.on('blur', update);
cssEditor.mirror.on('blur', update);
htmlEditor.mirror.on('blur', update);
htmlEditor.mirror.on('keyup', update);
htmlEditor.addButton({
text: 'Insert Signup Form',
callback: function callback(e) {
this.mirror.replaceSelection('\n<form class="_h-sign" data-_h-success="">\n\t<input name="email" placeholder="email@example.com" type="text" /><input name="name" type="text" />\n\t<input type="submit" value="Submit" />\n</form>\n');
update();
}
});
window.addEventListener('beforeunload', checkChanges);
update();
window.publish = publish; //make this global for inline
unsavedChanges = false;
// }());
//# sourceMappingURL=editor.js.map
/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); // wraps a code
//mirror editor with some UI
Object.defineProperty(exports, "__esModule", {
value: true
});
var _configMenu = __webpack_require__(2);
var _configMenu2 = _interopRequireDefault(_configMenu);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Editor = (function () {
function Editor(container, options) {
_classCallCheck(this, Editor);
this.options = options;
this._id = options.id;
this.toolbar = document.createElement('div');
this.toolbar.classList.add('toolbar');
container.appendChild(this.toolbar);
this.mirror = CodeMirror(container, options);
if (options.configMenu) {
this.addButton({ className: 'choices', id: options.id });
}
if (options.templates) {
this.addButton({ text: 'Save Template', callback: this.saveTemplate });
}
}
_createClass(Editor, [{
key: 'saveTemplate',
value: function saveTemplate(e) {
var request = new XMLHttpRequest();
var form = new FormData();
var name = prompt('Enter name to save template as:');
if (!name) return;
form.append('name', [this._id, name].join('-'));
form.append('text', this.mirror.getValue());
request.open('post', '/template/');
request.send(form);
}
}, {
key: 'addButton',
value: function addButton(options) {
var _button$classList;
var button = document.createElement('div');
var classes = options.className ? [options.className] : ['btn', 'small'];
(_button$classList = button.classList).add.apply(_button$classList, classes);
if (options.id) {
ReactDOM.render(React.createElement(_configMenu2.default, { id: options.id, choices: this.options.configMenu, templates: this.options.templates, title: this.options.title || this.options.mode }), button);
}
if (options.callback) {
button.addEventListener(options.on || 'click', options.callback.bind(this));
}
if (options.text) {
var text = document.createTextNode(options.text);
button.appendChild(text);
}
this.toolbar.appendChild(button);
}
}, {
key: 'settings',
get: function get() {
return document.getElementById('config-menu-' + this._id).value;
}
}, {
key: 'templates',
get: function get() {
return document.getElementById('config-templates-' + this._id).value;
}
}]);
return Editor;
})();
exports.default = Editor;
//# sourceMappingURL=editor.js.map
/***/ },
/* 2 */
/***/ function(module, exports) {
'use strict';
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
Object.defineProperty(exports, "__esModule", {
value: true
});
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
// Automatically bind all handlers to the component.
function autoBind(context) {
for (var _len = arguments.length, handlers = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
handlers[_key - 1] = arguments[_key];
}
if (handlers.length === 0) {
var proto = Object.getPrototypeOf(context);
handlers = Object.getOwnPropertyNames(proto).filter(function (x) {
return x.startsWith('handle');
}).map(function (x) {
return context[x];
}); // map all properties begining with handle to their function
}
handlers.forEach(function (h) {
return context[h.name] = h.bind(context);
});
}
var configMenu = (function (_React$Component) {
_inherits(configMenu, _React$Component);
function configMenu(props) {
_classCallCheck(this, configMenu);
var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(configMenu).call(this, props));
autoBind(_this);
var loadedItems = props.choices || JSON.parse(localStorage.getItem('items') || []);
var loadedTemplates = props.templates || [];
_this.state = { items: loadedItems, templates: loadedTemplates, enabled: false };
return _this;
}
_createClass(configMenu, [{
key: 'render',
value: function render() {
var _this2 = this;
var vendors = this.state.items.map(function (obj, index) {
return React.createElement(CheckItem, { id: _this2.props.id + obj.id,
deleteHandler: _this2.handleRemove.bind(_this2, index),
clickHandler: _this2.handleClick.bind(_this2, index),
key: index,
isInline: obj.inline,
isChecked: obj.checked,
isCustom: obj.custom,
text: obj.name
});
});
var templates = this.state.templates.map(function (obj, index) {
return React.createElement(CheckItem, { id: _this2.props.id + obj.id,
key: 't_' + index,
text: obj.name,
clickHandler: _this2.handleTemplateClick.bind(_this2, index),
isChecked: obj.checked
});
});
var classes = classNames({
checked: this.props.isChecked
});
return React.createElement(
'div',
{ className: "thingList " + (this.state.enabled ? "" : "closed") },
React.createElement(
'div',
{ className: 'config-menu btn small', onClick: this.handleToggle },
React.createElement('span', { className: "icon " + (this.state.enabled ? "icon-triangle-down" : "closed icon-triangle-right") }),
this.props.title
),
React.createElement(
'table',
{ className: 'someThings' },
React.createElement(
'thead',
null,
React.createElement(
'tr',
null,
React.createElement(
'th',
null,
React.createElement(
'span',
{ onClick: this.handleSwap },
'<->'
)
),
React.createElement(
'th',
{ className: 'hidden' },
'Inline'
)
)
),
React.createElement(
'tbody',
{ className: classNames({ vendor: true, hidden: this.state.showTemplates }) },
vendors,
React.createElement(
'tr',
null,
React.createElement(
'td',
null,
React.createElement('input', { onKeyDown: this.handleCustom, type: 'text', placeholder: 'http://custom.uri' })
)
)
),
React.createElement(
'tbody',
{ className: classNames({ templates: true, hidden: !this.state.showTemplates }) },
templates
)
),
React.createElement('input', { id: "config-menu-" + this.props.id, name: this.props.id, type: 'hidden', value: JSON.stringify(this.state.items) }),
React.createElement('input', { id: "config-templates-" + this.props.id, name: this.props.id, type: 'hidden', value: JSON.stringify(this.state.templates) })
);
}
}, {
key: 'handleRemove',
value: function handleRemove(id, evnt) {
var confirmed = confirm('Are you sure you want to delete this script?');
if (confirmed) {
var items = this.state.items;
items.splice(id, 1);
this.save({ items: items });
}
}
}, {
key: 'handleCustom',
value: function handleCustom(evnt) {
if (evnt.keyCode !== 13) return true;
var items = this.state.items;
items.push({ id: items.length, name: evnt.target.value, custom: true, checked: true });
this.save({ items: items });
evnt.target.value = '';
}
}, {
key: 'handleToggle',
value: function handleToggle(evnt) {
this.setState({ enabled: !this.state.enabled });
}
}, {
key: 'handleSwap',
value: function handleSwap(evnt) {
this.setState({ showTemplates: !this.state.showTemplates });
}
}, {
key: 'handleTemplateClick',
value: function handleTemplateClick(index, evnt) {
this.handleClick(index, evnt, 'templates');
}
}, {
key: 'handleClick',
value: function handleClick(index, evnt, key) {
var items = this.state[key] || this.state.items;
var item = items[index];
if (evnt.target.classList.contains('inline')) {
item.inline = !item.inline;
if (item.inline) {
item.checked = true;
}
} else {
// toggle item selection
item.checked = !item.checked;
// check for user-input
if (item.input && item.checked) {
item.value = prompt(item.input, item.value || "");
if (!item.value) item.checked = false;
}
if (item.dependencies && item.checked) {
item.dependencies.forEach(function (x) {
return items[x].checked = true;
});
} else if (!item.checked) {
item.inline = false;
// check all other items for dependcey
items.forEach(function (x) {
if (x.dependencies && x.dependencies.indexOf(item.id) > -1) {
x.checked = false;
x.inline = false;
}
});
}
}
// update object with dynamic name (items/templates)
var u = {};
if (!key) {
key = 'items';
}
u[key] = items;
this.save(u);
}
}, {
key: 'save',
value: function save(update) {
this.setState(update);
var stringifiedItems = JSON.stringify(this.state.items);
localStorage.setItem('items', stringifiedItems);
}
}]);
return configMenu;
})(React.Component);
exports.default = configMenu;
configMenu.defaultProps = {
items: [],
title: "A list of things!",
enabled: false,
inline: false,
showTemplates: false
};
configMenu.propTypes = {
'items': React.PropTypes.array,
'enabled': React.PropTypes.bool.isRequired,
'inline': React.PropTypes.bool.isRequired,
'input': React.PropTypes.string,
'value': React.PropTypes.string,
'showTemplates': React.PropTypes.bool.isRequired
};
var CheckItem = (function (_React$Component2) {
_inherits(CheckItem, _React$Component2);
function CheckItem() {
_classCallCheck(this, CheckItem);
return _possibleConstructorReturn(this, Object.getPrototypeOf(CheckItem).apply(this, arguments));
}
_createClass(CheckItem, [{
key: 'render',
value: function render() {
var classes = classNames({
checked: this.props.isChecked
});
return React.createElement(
'tr',
{ className: classes },
React.createElement(
'td',
null,
React.createElement('input', { type: 'checkbox', onChange: this.props.clickHandler, checked: this.props.isChecked, id: this.props.id }),
React.createElement(
'label',
{ htmlFor: this.props.id },
this.props.text
)
),
React.createElement(
'td',
{ className: 'text-center hidden' },
React.createElement('input', { type: 'checkbox', onChange: this.props.clickHandler, className: 'inline', id: 'inline_' + this.props.id, checked: this.props.isInline }),
React.createElement(Trasher, { id: this.props.id, deleteHandler: this.props.deleteHandler, active: this.props.isCustom })
)
);
}
}]);
return CheckItem;
})(React.Component);
var Trasher = (function (_React$Component3) {
_inherits(Trasher, _React$Component3);
function Trasher() {
_classCallCheck(this, Trasher);
return _possibleConstructorReturn(this, Object.getPrototypeOf(Trasher).apply(this, arguments));
}
_createClass(Trasher, [{
key: 'render',
value: function render() {
if (!this.props.active) return React.createElement('div', { className: 'spacer' });
return React.createElement('span', { onClick: this.props.deleteHandler, className: 'icon-trashcan' });
}
}]);
return Trasher;
})(React.Component);
//# sourceMappingURL=configMenu.js.map
/***/ },
/* 3 */
/***/ function(module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.thirdPartyScripts = thirdPartyScripts;
exports.thirdPartyStyles = thirdPartyStyles;
// extras the third party scripts from the settings
// returns a string of script tags
function thirdPartyScripts(config) {
var parsed = JSON.parse(config) || [];
if (!config) {
return '';
}
return parsed.filter(function (s) {
return s.checked;
}).map(function (s) {
return '<script type="text/javascript" src="' + (s.custom ? s.name : s.uri) + '"></script>';
}).join('');
}
function thirdPartyStyles(config) {
var parsed = JSON.parse(config) || [];
if (!config) {
return '';
}
return parsed.filter(function (s) {
return s.checked;
}).map(function (s) {
return '<link rel="stylesheet" type="text/css" href="' + (s.custom ? s.name : s.uri) + '">';
}).join('');
}
//# sourceMappingURL=utilities.js.map
/***/ }
/******/ ]);
//# sourceMappingURL=editor.packed.js.map