UNPKG

hatchyt

Version:
703 lines (604 loc) 27.6 kB
/******/ (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