UNPKG

closeheat-editor

Version:
1,684 lines (1,500 loc) 6.06 MB
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ var $, ChangeDistDirToast, Filesystem, Header, Navigation, NewApp, Promise, React, RouteHandler, Router, _, cookies, flatten, request; React = require('react'); flatten = require('flat'); _ = require('lodash'); $ = window.jQuery = window.$ = require('jquery'); request = require('request'); Promise = require('bluebird'); cookies = require('browser-cookies'); require('./materialize'); Router = require('react-router'); RouteHandler = Router.RouteHandler; Navigation = Router.Navigation; Header = require('./header'); Filesystem = require('./filesystem'); NewApp = require('./new_app'); ChangeDistDirToast = require('./change_dist_dir_toast'); module.exports = React.createClass({ getInitialState: function() { this.bindKeys(); track('loaded', { ch_initial_referrer: cookies.get('ch_initial_referrer') }); return { clean_files: _.cloneDeep(Filesystem.ls()), action_in_progress: false, first_build_done: false, show_free_hosting: false, show_change_dist_dir: !this.props.is_demo_app && this.props.first_build, dist_dir: this.props.dist_dir }; }, componentDidMount: function() { if (this.props.is_demo_app) { return this.showCodeGuide(); } }, showCodeGuide: function() { Materialize.toast("We created a simple demo website for you. Here's the code.", 10000); return setTimeout((function() { return Materialize.toast("Click <span class='guide-button'>Preview</span> to see how it looks.", 10000); }), 4000); }, showFreeHosting: function() { return this.setState({ show_free_hosting: true }); }, hideFreeHosting: function() { return this.setState({ show_free_hosting: false, free_hosting_shown: true }); }, bindKeys: function() { return $(window).bind('keydown', (function(_this) { return function(event) { if (!(event.ctrlKey || event.metaKey)) { return; } switch (String.fromCharCode(event.which).toLowerCase()) { case 's': event.preventDefault(); return _this.previewClick(); case 'e': event.preventDefault(); return _this.codeClick(); } }; })(this)); }, mixins: [Navigation], editorChange: function(path, new_content) { return Filesystem.write(path, new_content); }, codeClick: function() { track('code_clicked'); return this.transitionWithCodeModeHistory('code', '/code/*?'); }, previewClick: function() { track('preview_clicked'); if (this.state.action_in_progress) { return; } if (this.context.router.getCurrentPath().match(/^\/preview/)) { return this.buildOrRefresh(); } else { return this.transitionWithCodeModeHistory('preview', 'preview-with-history'); } }, transitionWithCodeModeHistory: function(route, with_history_route) { track('transitioned_to', { route: route }); if (_.isEmpty(this.context.router.getCurrentParams())) { return this.transitionTo(route); } else { return this.transitionTo(with_history_route, this.context.router.getCurrentParams()); } }, publishClick: function() { track('publish_clicked'); if (this.state.action_in_progress) { return; } return this.transitionWithCodeModeHistory('publish', '/publish/*?'); }, settingsClick: function() { if (this.state.action_in_progress) { return; } return this.openSettings(); }, handleError: function(msg) { track('error_happened', { message: msg }); this.setState({ error: msg }); return this.transitionWithCodeModeHistory('error', '/error/*?'); }, changedFiles: function() { return _.reject(Filesystem.ls(), (function(_this) { return function(new_file) { var clean_file; clean_file = _.find(_this.state.clean_files, function(file) { return file.path === new_file.path; }); return clean_file.content === new_file.content; }; })(this)); }, build: function() { return this.buildOrRefresh(); }, buildOrRefresh: function() { if (this.filesChanged() || !this.state.first_build_done) { return this.execBuild(); } else { return this.refreshBrowser(); } }, refreshBrowser: function() { return new Promise((function(_this) { return function(resolve, reject) { var browser_ref, ref; browser_ref = (ref = _this.refs.appRouteHandler.refs.__routeHandler__) != null ? ref.refs.browser : void 0; if (!browser_ref) { return resolve(); } browser_ref.refresh(); return resolve(); }; })(this)); }, execBuild: function() { track('build_started'); this.actionStarted(); return new Promise((function(_this) { return function(resolve, reject) { return request.post({ json: true, body: { files: _this.changedFiles() }, url: window.location.origin + "/apps/" + APP_SLUG + "/live_edit/preview" }, function(err, status, resp) { if (err) { return reject(err); } if (status.statusCode === 500) { return reject("Something bad happened in the server. Not your fault. We're fixing it."); } if (!resp.success) { return reject(resp.error); } _this.setState({ clean_files: _.cloneDeep(Filesystem.ls()), first_build_done: true }); _this.actionStopped(); track('build_finished'); return resolve(); }); }; })(this)); }, filesChanged: function() { return !_.isEmpty(this.changedFiles()); }, publishToGithub: function() { track('publish_started'); if (this.filesChanged()) { return this.build().then(this.publishToGithub)["catch"]((function(_this) { return function(err) { return _this.handleError(err); }; })(this)); } else { this.actionStarted(); return this.execPublish().then((function(_this) { return function(resp) { if (!resp.success) { return _this.handleError(resp.error); } return track('publish_to_github_finished'); }; })(this))["catch"]((function(_this) { return function(err) { return _this.handleError(err); }; })(this)); } }, waitForPublishToServer: function() { return new Promise((function(_this) { return function(resolve, reject) { return pusher_user_channel.bind('app.build', function() { track('publish_to_server_finished'); _this.actionStopped(); return resolve(); }); }; })(this)); }, execPublish: function() { return new Promise((function(_this) { return function(resolve, reject) { return request.post({ json: true, url: window.location.origin + "/apps/" + APP_SLUG + "/live_edit/publish" }, function(err, status, resp) { if (err) { return reject(err); } return resolve(resp); }); }; })(this)); }, activeMode: function() { var routes; routes = this.context.router.getCurrentRoutes(); return _.first(routes[1].name.split('-')); }, actionStarted: function() { return this.setState({ action_in_progress: true }); }, actionStopped: function() { return this.setState({ action_in_progress: false }); }, openSettings: function() { track('settings_clicked'); return this.transitionWithCodeModeHistory('settings', '/settings/*?'); }, hideChangeDistDirToast: function() { return this.setState({ show_change_dist_dir: false }); }, saveDistDir: function(dist_dir) { return new Promise((function(_this) { return function(resolve, reject) { return request.post({ json: true, url: window.location.origin + "/apps/" + APP_SLUG + "/live_edit/change_dist_dir", body: { dist_dir: dist_dir } }, function(err, status, resp) { if (err) { return reject(err); } _this.setState({ dist_dir: resp.dist_dir }); return resolve(resp); }); }; })(this)); }, saveSlug: function(slug) { return new Promise((function(_this) { return function(resolve, reject) { return request.post({ json: true, url: window.location.origin + "/apps/" + APP_SLUG + "/live_edit/change_slug", body: { slug: slug } }, function(err, status, resp) { if (err) { return reject(err); } if (!resp.success) { return reject('invalid_slug'); } return window.location.origin = _this.newEditorUrl(resp.slug); }); }; })(this)); }, newEditorUrl: function(slug) { return window.location.href = window.location.origin + "/apps/" + slug + "/live_edit" + window.location.hash; }, render: function() { return React.createElement("main", { "className": 'editor-wrapper' }, React.createElement(Header, { "action_in_progress": this.state.action_in_progress, "website_url": this.props.website_url, "active_mode": this.activeMode(), "onCodeClick": this.codeClick, "onPreviewClick": this.previewClick, "onPublishClick": this.publishClick, "onSettingsClick": this.settingsClick, "onNewWebsiteClick": this.showFreeHosting, "avatar": this.props.avatar }), React.createElement(RouteHandler, { "browser_url": this.props.browser_url, "website_url": this.props.website_url, "slug": this.props.slug, "dist_dir": this.state.dist_dir, "editorChange": this.editorChange, "build": this.build, "handleError": this.handleError, "error": this.state.error, "transitionWithCodeModeHistory": this.transitionWithCodeModeHistory, "files_changed": this.filesChanged(), "publishToGithub": this.publishToGithub, "waitForPublishToServer": this.waitForPublishToServer, "actionStopped": this.actionStopped, "saveDistDir": this.saveDistDir, "saveSlug": this.saveSlug, "hideChangeDistDirToast": this.hideChangeDistDirToast, "ref": 'appRouteHandler' }), React.createElement(NewApp, { "show": this.state.show_free_hosting, "close": this.hideFreeHosting }), React.createElement(ChangeDistDirToast, { "show": this.state.show_change_dist_dir, "dist_dir": this.state.dist_dir, "onClose": this.hideChangeDistDirToast, "onClick": this.openSettings })); } }); },{"./change_dist_dir_toast":3,"./filesystem":11,"./header":12,"./materialize":15,"./new_app":16,"bluebird":57,"browser-cookies":79,"flat":185,"jquery":244,"lodash":250,"react":489,"react-router":351,"request":500}],2:[function(require,module,exports){ var Browser, React; React = require('react'); module.exports = Browser = React.createClass({ refresh: function() { return document.getElementById('browser').src = this.props.browser_url; }, render: function() { return React.createElement("div", { "className": 'browser' }, React.createElement("iframe", { "id": 'browser', "name": 'browser-frame', "src": this.props.browser_url })); } }); },{"react":489}],3:[function(require,module,exports){ var React, _; React = require('react'); _ = require('lodash'); module.exports = React.createClass({ distDirName: function() { if (this.props.dist_dir === '/' || _.isEmpty(this.props.dist_dir)) { return 'Root (/)'; } return this.props.dist_dir; }, render: function() { if (!this.props.show) { return React.createElement("div", null); } return React.createElement("div", { "className": 'toast-container' }, React.createElement("div", { "className": 'toast custom-toast' }, React.createElement("span", null, "Current public directory for this website is ", React.createElement("b", null, this.distDirName())), React.createElement("span", { "className": 'custom-toast-buttons' }, React.createElement("span", { "className": 'btn-flat yellow-text', "onClick": this.props.onClick }, "Change public directory"), React.createElement("span", { "className": 'btn-flat blue-text text-lighten-4', "onClick": this.props.onClose }, "Leave as is")))); } }); },{"lodash":250,"react":489}],4:[function(require,module,exports){ var Link, Navigation, React, RouteHandler, Router, Tabs, _; React = require('react'); _ = require('lodash'); Router = require('react-router'); RouteHandler = Router.RouteHandler; Link = Router.Link; Navigation = Router.Navigation; Tabs = require('./tabs'); module.exports = React.createClass({ mixins: [Navigation], fullPath: function() { return this.props.params.splat; }, tabs: function() { var tabs; tabs = _.map(this.tabPaths(), (function(_this) { return function(tab_path) { var name, path, tab_data; path = tab_path.replace(/\*$/, ''); name = _.last(path.split('/')); return tab_data = { path: path, name: name, active: path === _this.activeTabPath() }; }; })(this)); return _.map(tabs, (function(_this) { return function(tab) { tab.href = _this.href(tabs, tab); tab.close_href = _this.closeHref(tabs, tab); return tab; }; })(this)); }, tabPaths: function() { if (!this.fullPath()) { return []; } return this.fullPath().split('&'); }, activeTabPath: function() { var active_with_asterix; active_with_asterix = _.find(this.tabPaths(), function(tab_path) { return _.last(tab_path) === '*'; }); if (active_with_asterix) { return active_with_asterix.slice(0, -1); } else { return this.fullPath(); } }, href: function(tabs, new_active_tab) { var new_tab_list; new_tab_list = _.map(_.cloneDeep(tabs), function(tab) { var updated_tab; updated_tab = tab; updated_tab.active = updated_tab.path === new_active_tab.path; return updated_tab; }); return this.joinTabPaths(new_tab_list); }, closeHref: function(tabs, close_tab) { var last_tab, new_tab_list; new_tab_list = _.reject(_.cloneDeep(tabs), function(tab) { return tab.path === close_tab.path; }); _.each(new_tab_list, function(tab) { return tab.active = false; }); last_tab = _.last(new_tab_list); if (last_tab) { last_tab.active = true; } return this.joinTabPaths(new_tab_list); }, joinTabPaths: function(tabs) { var tab_paths; tab_paths = _.map(tabs, function(tab) { if (tab.active) { return tab.path + '*'; } else { return tab.path; } }); return tab_paths.join('&'); }, newTabHref: function(path) { var new_active_tab, unique_tabs; new_active_tab = { path: path, active: true }; unique_tabs = _.uniqBy(_.flatten([this.tabs(), new_active_tab]), 'path'); return this.href(unique_tabs, new_active_tab); }, reuseTabHref: function(path) { var new_tabs, unique_tabs, with_active_tab; new_tabs = _.map(this.tabs(), function(tab) { if (tab.active) { tab.path = path; } return tab; }); unique_tabs = _.uniqBy(new_tabs, 'path'); with_active_tab = _.map(unique_tabs, function(tab) { if (tab.path === path) { tab.active = true; } return tab; }); return this.joinTabPaths(with_active_tab); }, checkValidPath: function() { if (!this.fullPath()) { return this.transitionTo('file', { splat: '*' }); } }, render: function() { this.checkValidPath(); return React.createElement("div", null, React.createElement("div", { "className": 'row full' }, React.createElement("div", { "className": 'col m12 full code-mode-cols' }, React.createElement(Tabs, { "tabs": this.tabs(), "new_tab_href": this.newTabHref('') }), React.createElement(RouteHandler, { "active_tab_path": this.activeTabPath(), "reuseTabHref": this.reuseTabHref, "newTabHref": this.newTabHref, "editorChange": this.props.editorChange })))); } }); },{"./tabs":24,"lodash":250,"react":489,"react-router":351}],5:[function(require,module,exports){ var $, App, CodeMode, Core, ErrorHandler, InitialLoader, PreviewMode, Publish, React, ReactDOM, Redirect, Route, Router, Settings, TabManager, md; md = require('marked'); $ = require('jquery'); React = require('react'); ReactDOM = require('react-dom'); Router = require('react-router'); Route = Router.Route; Redirect = Router.Redirect; InitialLoader = require('./initial_loader'); App = require('./app'); CodeMode = require('./code_mode'); PreviewMode = require('./preview_mode'); TabManager = require('./tab_manager'); Publish = require('./publish'); ErrorHandler = require('./error_handler'); Settings = require('./settings'); module.exports = Core = (function() { function Core(base, server) { this.base = base; this.server = server; this.initial_loader = new InitialLoader(); } Core.prototype.load = function() { return this.initial_loader.loadFilesAndData().then((function(_this) { return function(data) { _this.data = data; return Router.run(_this.routes(), function(Handler) { return ReactDOM.render(React.createElement(Handler, { "website_url": _this.data.app_domain, "slug": _this.data.slug, "avatar": _this.data.avatar, "browser_url": _this.data.browser_url, "dist_dir": _this.data.dist_dir, "is_demo_app": _this.data.is_demo_app, "first_build": _this.data.first_build }), document.getElementById('editor-container')); }); }; })(this)); }; Core.prototype.routes = function() { return React.createElement(Route, { "handler": App, "path": '/' }, React.createElement(Route, { "name": 'code', "path": '/code', "handler": CodeMode }, React.createElement(Route, { "name": 'file', "path": '/code/*?', "handler": TabManager })), React.createElement(Route, { "name": 'preview', "path": '/preview', "handler": PreviewMode }), React.createElement(Route, { "name": 'preview-with-history', "path": '/preview/*?', "handler": PreviewMode }), React.createElement(Route, { "name": 'publish', "path": '/publish', "handler": Publish }), React.createElement(Route, { "name": 'publish-with-history', "path": '/publish/*?', "handler": Publish }), React.createElement(Route, { "name": 'error', "path": '/error', "handler": ErrorHandler }), React.createElement(Route, { "name": 'error-with-history', "path": '/error/*?', "handler": ErrorHandler }), React.createElement(Route, { "name": 'settings', "path": '/settings', "handler": Settings }), React.createElement(Route, { "name": 'settings-with-history', "path": '/settings/*?', "handler": Settings }), React.createElement(Redirect, { "from": '', "to": '/code/' }), React.createElement(Redirect, { "from": "/code", "to": "/code/" })); }; return Core; })(); $(function() { return new Core(APP_DOMAIN).load(); }); },{"./app":1,"./code_mode":4,"./error_handler":7,"./initial_loader":13,"./preview_mode":17,"./publish":18,"./settings":21,"./tab_manager":23,"jquery":244,"marked":252,"react":489,"react-dom":326,"react-router":351}],6:[function(require,module,exports){ var AceEditor, React, _, brace; React = require('react'); brace = require('brace'); AceEditor = require('react-ace'); _ = require('lodash'); require('brace/mode/html'); require('brace/mode/jade'); require('brace/mode/markdown'); require('brace/mode/text'); require('brace/mode/javascript'); require('brace/mode/coffee'); require('brace/mode/jsx'); require('brace/mode/json'); require('brace/mode/css'); require('brace/mode/sass'); require('brace/theme/xcode'); require('brace/ext/searchbox'); module.exports = React.createClass({ emptySelection: function() { return { start: { row: 0, column: 0 }, end: { row: 0, column: 0 } }; }, onChange: function(new_content) { return this.props.onChange(this.props.path, new_content); }, mode: function() { var ext; ext = this.props.path.match(/\.(.*)$/)[1] || 'html'; return this.props.supported_modes[ext] || 'html'; }, restoreSettings: function(editor) { var settings; settings = window.CloseheatFileSettings[this.props.path]; if (!settings) { return editor.clearSelection(); } editor.session.selection.setSelectionRange(settings.selection); editor.session.setScrollTop(settings.scroll_top); editor.session.setScrollLeft(settings.scroll_left); settings.undo_manager.$doc = editor.session; return editor.session.setUndoManager(settings.undo_manager); }, onLoad: function(editor) { var editor_session; editor_session = editor.getSession(); editor_session.setTabSize(2); editor_session.setUseSoftTabs(true); editor.setHighlightActiveLine(false); editor_session.setUndoManager(new brace.UndoManager); return this.restoreSettings(editor); }, saveSettings: function() { var editor; editor = this.refs.editor_container.editor; return window.CloseheatFileSettings[this.props.path] = { selection: editor.getSelectionRange() || this.emptySelection(), scroll_top: editor.session.getScrollTop() || 0, scroll_left: editor.session.getScrollLeft() || 0, undo_manager: editor.session.getUndoManager() }; }, render: function() { return React.createElement(AceEditor, { "mode": this.mode(), "theme": 'xcode', "name": 'blah1', "height": 'calc(100vh - 54px - 36px)', "width": '100%', "onChange": this.onChange, "onLoad": this.onLoad, "value": this.props.value, "ref": 'editor_container', "editorProps": { $blockScrolling: true } }); } }); },{"brace":60,"brace/ext/searchbox":59,"brace/mode/coffee":61,"brace/mode/css":62,"brace/mode/html":63,"brace/mode/jade":64,"brace/mode/javascript":65,"brace/mode/json":66,"brace/mode/jsx":67,"brace/mode/markdown":68,"brace/mode/sass":69,"brace/mode/text":70,"brace/theme/xcode":71,"lodash":250,"react":489,"react-ace":325}],7:[function(require,module,exports){ var Promise, React, request; React = require('react'); Promise = require('bluebird'); request = require('request'); module.exports = React.createClass({ componentWillMount: function() { if (!this.props.error) { this.props.transitionWithCodeModeHistory('code', '/code/*?'); } return this.props.actionStopped(); }, getInitialState: function() { return {}; }, message: function() { var msg, with_n_as_enter; if (!this.props.error) { return; } msg = this.props.error.toString(); with_n_as_enter = JSON.stringify(msg).slice(1, -1); return with_n_as_enter.replace(/\\n/g, '<br>'); }, render: function() { return React.createElement("div", { "className": 'error' }, React.createElement("div", { "className": 'row' }, React.createElement("div", { "className": 'error-container col offset-s2 s8 offset-l3 l6' }, React.createElement("div", { "className": 'error-title' }, "Oops. An error occured."), React.createElement("div", { "className": 'error-content', "dangerouslySetInnerHTML": { __html: this.message() } })))); } }); },{"bluebird":57,"react":489,"request":500}],8:[function(require,module,exports){ var Navigation, React, Router; React = require('react'); Router = require('react-router'); Navigation = Router.Navigation; module.exports = React.createClass({ mixins: [Navigation], activeClass: function() { var result; result = 'tab col m2'; if (this.props.active) { result += ' tab-active'; } return result; }, onClick: function() { if (this.uneditableFile()) { return; } return this.transitionTo('file', { splat: this.props.file.href }); }, kind: function() { var ext; if (this.props.file.type === 'dir') { return 'Folder'; } ext = this.props.file.path.match(/\.([0-9a-z]+)$/i)[1]; return this.props.supported_modes[ext] || ext; }, icon: function() { if (this.props.file.type === 'dir') { return React.createElement("i", { "className": 'material-icons' }, "folder_open"); } else { return React.createElement("i", { "className": 'material-icons' }, "class"); } }, uneditableFile: function() { return this.props.file.type === 'file' && !this.props.file.editable; }, editableClass: function() { if (this.uneditableFile()) { return 'file-list-uneditable'; } }, render: function() { return React.createElement("tr", { "onClick": this.onClick, "className": this.editableClass() }, React.createElement("td", { "className": 'file-list-icon' }, this.icon()), React.createElement("td", { "className": 'file-list-name' }, this.props.file.name), React.createElement("td", { "className": 'file-list-kind' }, this.kind())); } }); },{"react":489,"react-router":351}],9:[function(require,module,exports){ var File, FileUp, Filesystem, Link, React, Router, _; React = require('react'); _ = require('lodash'); Router = require('react-router'); Link = Router.Link; Filesystem = require('./filesystem'); File = require('./file'); FileUp = require('./file_up'); module.exports = React.createClass({ folderFiles: function() { var dirs, files, ref, result; result = _.map(this.props.dir.files, (function(_this) { return function(file) { file.href = _this.props.reuseTabHref(file.path); return file; }; })(this)); ref = _.partition(result, function(f) { return f.type === 'dir'; }), dirs = ref[0], files = ref[1]; return dirs.concat(files); }, upHref: function() { var up_path; up_path = _.dropRight(this.pathParts()); return this.props.reuseTabHref(up_path); }, pathParts: function() { return (this.props.path || '').split('/'); }, render: function() { return React.createElement("div", null, React.createElement("div", { "className": 'row' }, React.createElement("div", { "className": 'col m12' }, React.createElement("ul", { "className": 'file-list-path' }, React.createElement("li", { "className": 'file-list-start' }, "Files"), _.map(this.pathParts(), function(part) { return React.createElement("li", { "key": part }, React.createElement("span", { "className": 'file-list-sep' }, "\x2F"), React.createElement("span", { "className": 'file-list-name' }, part)); })), React.createElement("table", { "className": 'file-list' }, React.createElement("tbody", null, React.createElement("tr", null, React.createElement("th", { "colSpan": 2 }, "Name"), React.createElement("th", null, "Kind")), React.createElement(FileUp, { "show": !!this.props.path, "href": this.upHref() }), _.map(this.folderFiles(), (function(_this) { return function(file) { return React.createElement(File, { "key": file.path, "file": file, "active": _this.props.active, "supported_modes": _this.props.supported_modes }); }; })(this))))))); } }); },{"./file":8,"./file_up":10,"./filesystem":11,"lodash":250,"react":489,"react-router":351}],10:[function(require,module,exports){ var Navigation, React, Router; React = require('react'); Router = require('react-router'); Navigation = Router.Navigation; module.exports = React.createClass({ mixins: [Navigation], onClick: function() { return this.transitionTo('file', { splat: this.props.href }); }, render: function() { if (!this.props.show) { return React.createElement("tr", null); } return React.createElement("tr", { "onClick": this.onClick }, React.createElement("td", null), React.createElement("td", { "colSpan": 2 }, "...")); } }); },{"react":489,"react-router":351}],11:[function(require,module,exports){ var Filesystem, _; _ = require('lodash'); module.exports = Filesystem = (function() { function Filesystem() {} Filesystem.create = function(files) { return window.fs = files; }; Filesystem.ls = function(path) { if (!path) { return window.fs; } return _.filter(window.fs, function(file) { return file.path.match(RegExp("^" + path)); }); }; Filesystem.read = function(path) { var file_on_path; file_on_path = _.find(this.ls(), function(file) { return file.path === path; }); if (file_on_path) { return file_on_path; } return { type: 'dir', path: path, files: this.dirFiles(path) }; }; Filesystem.dirFiles = function(path) { var result; result = []; _.each(this.ls(path), function(file) { var dir_path, name, relative_to_dir; relative_to_dir = file.path.replace(RegExp("^" + path + "\\/"), ''); name = _.first(relative_to_dir.split('/')); if (relative_to_dir.match('/')) { dir_path = _.isEmpty(path) ? name : [path, name].join('/'); return result.push({ type: 'dir', path: dir_path, name: name }); } else { return result.push(_.merge(file, { type: 'file', name: name })); } }); return _.uniqBy(result, 'name'); }; Filesystem.write = function(path, new_content) { var file; file = this.read(path); return file.content = new_content; }; Filesystem.isFile = function(path) { return _.find(this.ls(), function(file) { return file.path === path; }); }; return Filesystem; })(); },{"lodash":250}],12:[function(require,module,exports){ var $, Header, PublishStatus, React, ReactDOM, Tour, _, classNames; React = require('react'); ReactDOM = require('react-dom'); classNames = require('classnames'); _ = require('lodash'); PublishStatus = require('./publish_status'); Tour = require('./tour'); $ = window.jQuery = window.$ = require('jquery'); module.exports = Header = React.createClass({ getInitialState: function() { return {}; }, goToStep: function(tour_step) {}, activeModeClass: function(type, cols) { var obj; return classNames(( obj = { col: true, 'header-mode': true, 'center-align': true }, obj["" + cols] = true, obj['header-mode-active'] = this.props.active_mode === type, obj['header-in-progress'] = this.props.action_in_progress && type !== 'code', obj )); }, componentDidMount: function() { this.addTooltips(); return this.addDropdowns(); }, componentDidUpdate: function() { this.addTooltips(); return this.addDropdowns(); }, addDropdowns: function() { return $(this.refs.dropdown_button).dropdown({ hover: true, belowOrigin: true, gutter: 20, constrain_width: false }); }, addTooltips: function() { var elements; elements = _.map(['code', 'preview', 'publish', 'website_url'], (function(_this) { return function(name) { return ReactDOM.findDOMNode(_this.refs[name]); }; })(this)); return $(elements).tooltip({ delay: 100 }); }, prettyWebsiteUrl: function() { return this.props.website_url.replace('http://', ''); }, render: function() { var dashboard_url; dashboard_url = "http://app.closeheat.com/apps/" + APP_SLUG + "/"; return React.createElement("div", null, React.createElement("div", { "className": 'row header-row' }, React.createElement("div", { "className": this.activeModeClass('code', 'label-with-icon s2'), "onClick": this.props.onCodeClick, "data-tooltip": 'Ctrl+E', "ref": 'code' }, React.createElement("i", { "className": 'material-icons' }, "code"), "Code"), React.createElement("div", { "className": this.activeModeClass('preview', 'label-with-icon s2'), "onClick": this.props.onPreviewClick, "data-tooltip": 'Ctrl+S', "ref": 'preview' }, React.createElement("i", { "className": 'material-icons' }, "navigation"), "Preview"), React.createElement("div", { "className": 'header-website-url col s4 center-align label-with-icon', "ref": 'website_url', "data-tooltip": 'This is your public page URL' }, React.createElement("a", { "href": this.props.website_url, "target": '_blank', "className": 'truncate' }, this.prettyWebsiteUrl(), React.createElement("i", { "className": 'material-icons header-icon-right' }, "open_in_new"))), React.createElement("div", { "className": this.activeModeClass('publish', 's2 label-with-icon'), "onClick": this.props.onPublishClick, "data-tooltip": "Publishes changes to " + (this.prettyWebsiteUrl()), "ref": 'publish' }, React.createElement("i", { "className": 'material-icons' }, "publish"), "Publish"), React.createElement("div", { "className": 'header-support col s1 center-align' }, React.createElement("a", { "href": "mailto:support@closeheat.com?subject=I'm having a problem with the editor" }, "Support")), React.createElement("div", { "ref": 'dropdown_button', "className": 'col s1 center-align dropdown-button', "data-activates": 'avatar-dropdown' }, React.createElement("div", { "className": 'header-avatar' }, React.createElement("img", { "src": this.props.avatar })))), React.createElement("ul", { "id": 'avatar-dropdown', "className": 'dropdown-content' }, React.createElement("li", null, React.createElement("a", { "href": 'javascript:void(0);', "onClick": this.props.onSettingsClick }, "Settings")), React.createElement("li", null, React.createElement("a", { "href": 'javascript:void(0);', "onClick": this.props.onNewWebsiteClick }, "Create a New Website")), React.createElement("li", null, React.createElement("a", { "href": dashboard_url, "target": '_blank' }, "Website Dashboard"))), React.createElement(Tour, { "step": this.state.tour_step, "done": this.state.tour_done })); } }); },{"./publish_status":19,"./tour":25,"classnames":114,"jquery":244,"lodash":250,"react":489,"react-dom":326}],13:[function(require,module,exports){ var Filesystem, InitialLoader, Promise, _, request; _ = require('lodash'); request = require('request'); Promise = require('bluebird'); Filesystem = require('./filesystem'); module.exports = InitialLoader = (function() { function InitialLoader() {} InitialLoader.prototype.loadFilesAndData = function() { return this.addFiles(); }; InitialLoader.prototype.addFiles = function() { return this.getInitialData().then((function(_this) { return function(data) { window.CloseheatFileSettings = {}; Filesystem.create(data.files); return data; }; })(this))["catch"]((function(_this) { return function(err) { return alert(err); }; })(this)); }; InitialLoader.prototype.getInitialData = function() { return new Promise((function(_this) { return function(resolve, reject) { return request.get({ json: true, url: window.location.origin + "/apps/" + APP_SLUG + "/live_edit/init" }, function(err, status, resp) { if (err) { return reject(err); } return resolve(resp); }); }; })(this)); }; return InitialLoader; })(); },{"./filesystem":11,"bluebird":57,"lodash":250,"request":500}],14:[function(require,module,exports){ var React; React = require('react'); module.exports = React.createClass({ render: function() { return React.createElement("div", { "className": 'loader valign-wrapper' }, React.createElement("div", { "className": 'valign loader-container' }, React.createElement("div", { "className": 'row' }, React.createElement("div", { "className": "preloader-wrapper big active loader-spinner valign" }, React.createElement("div", { "className": "spinner-layer spinner-red-only" }, React.createElement("div", { "className": "circle-clipper left" }, React.createElement("div", { "className": "circle" })), React.createElement("div", { "className": "gap-patch" }, React.createElement("div", { "className": "circle" })), React.createElement("div", { "className": "circle-clipper right" }, React.createElement("div", { "className": "circle" }))))), React.createElement("div", { "className": 'row' }, React.createElement("div", { "className": 'action-title' }, this.props.title), React.createElement("div", { "className": 'action-title' }, this.props.subtitle)))); } }); },{"react":489}],15:[function(require,module,exports){ require('materialize-css/js/jquery.easing.1.3'); require('materialize-css/js/animation'); require('materialize-css/js/velocity.min'); require('materialize-css/js/hammer.min'); require('materialize-css/js/jquery.hammer'); require('materialize-css/js/global'); require('materialize-css/js/collapsible'); require('materialize-css/js/dropdown'); require('materialize-css/js/leanModal'); require('materialize-css/js/materialbox'); require('materialize-css/js/parallax'); require('materialize-css/js/tabs'); require('materialize-css/js/tooltip'); require('materialize-css/js/waves'); require('materialize-css/js/toasts'); require('materialize-css/js/sideNav'); require('materialize-css/js/scrollspy'); require('materialize-css/js/forms'); require('materialize-css/js/slider'); require('materialize-css/js/cards'); require('materialize-css/js/pushpin'); require('materialize-css/js/buttons'); require('materialize-css/js/transitions'); require('materialize-css/js/scrollFire'); require('materialize-css/js/date_picker/picker'); require('materialize-css/js/date_picker/picker.date'); require('materialize-css/js/character_counter'); },{"materialize-css/js/animation":253,"materialize-css/js/buttons":254,"materialize-css/js/cards":255,"materialize-css/js/character_counter":256,"materialize-css/js/collapsible":257,"materialize-css/js/date_picker/picker":259,"materialize-css/js/date_picker/picker.date":258,"materialize-css/js/dropdown":260,"materialize-css/js/forms":261,"materialize-css/js/global":262,"materialize-css/js/hammer.min":263,"materialize-css/js/jquery.easing.1.3":264,"materialize-css/js/jquery.hammer":265,"materialize-css/js/leanModal":266,"materialize-css/js/materialbox":267,"materialize-css/js/parallax":268,"materialize-css/js/pushpin":269,"materialize-css/js/scrollFire":270,"materialize-css/js/scrollspy":271,"materialize-css/js/sideNav":272,"materialize-css/js/slider":273,"materialize-css/js/tabs":274,"materialize-css/js/toasts":275,"materialize-css/js/tooltip":276,"materialize-css/js/transitions":277,"materialize-css/js/velocity.min":278,"materialize-css/js/waves":279}],16:[function(require,module,exports){ var React; React = require('react'); module.exports = React.createClass({ getInitialState: function() { return { selected: 'upload' }; }, itemClass: function(type) { var result; result = 'free-hosting-type'; if (this.state.selected === type) { result += ' free-hosting-type-selected'; } return result; }, handleSelect: function(type) { return (function(_this) { return function() { return _this.setState({ selected: type }); }; })(this); }, getHref: function() { if (this.state.selected === 'upload') { return '/apps/new/upload'; } else { return '/apps/new/templates'; } }, buttonText: function() { if (this.state.selected === 'upload') { return 'Upload my website'; } else { return 'Get my website'; } }, maybeClose: function(e) { if (e.target.className !== 'free-hosting-container') { return; } return this.props.close(); }, render: function() { if (!this.props.show) { return React.createElement("div", null); } return React.createElement("div", { "className": 'free-hosting-container', "onClick": this.maybeClose }, React.createElement("div", { "className": 'free-hosting center-align' }, React.createElement("div", { "className": 'row free-hosting-title' }, "Create a different website"), React.createElement("div", { "className": 'row' }, React.createElement("div", { "className": 'col s6' }, React.createElement("div", { "className": this.itemClass('upload'), "onClick": this.handleSelect('upload') }, React.createElement("div", { "className": 'free-hosting-type-icon' }, React.createElement("i", { "className": 'medium material-icons' }, "invert_colors")), React.createElement("div", { "className": 'free-hosting-type-title' }, "I have a website to upload"))), React.createElement("div", { "className": 'col s6' }, React.createElement("div", { "className": this.itemClass('template'), "onClick": this.handleSelect('template') }, React.createElement("div", { "className": 'free-hosting-type-icon' }, React.createElement("i", { "className": 'medium material-icons' }, "album")), React.createElement("div", { "className": 'free-hosting-type-title' }, "Use a new template"))), React.createElement("div", { "className": 'row' }, React.createElement("a", { "href": this.getHref(), "target": '_blank', "className": "btn btn-large waves-effect waves-light free-hosting-button" }, this.buttonText()))))); } }); },{"react":489}],17:[function(require,module,exports){ var Browser, Loader, React; React = require('react'); Browser = require('./browser'); Loader = require('./loader'); module.exports = React.createClass({ getInitialState: function() { return { build_finished: false }; }, componentDidMount: function() { return this.props.build().then((function(_this) { return function(resp) { return _this.setState({ build_finished: true }); }; })(this))["catch"]((function(_this) { return function(err) { return _this.props.handleError(err); }; })(this)); }, browser: function() { return React.createElement("div", null, React.createElement("div", { "className": 'row full' }, React.createElement("div", { "className": 'col browser-col full m12' }, React.createElement(Browser, { "ref": 'browser', "browser_url": this.props.browser_url })))); }, render: function() { if (this.state.build_finished) { return this.browser(); } else { return React.createElement(Loader, { "title": 'Hang in tight.', "subtitle": 'Building your page preview...' }); } } }); },{"./browser":2,"./loader":14,"react":489}],18:[function(require,module,exports){ var Loader, Promise, Published, React, request; React = require('react'); Promise = require('bluebird'); request = require('request'); Loader = require('./loader'); Published = require('./published'); module.exports = React.createClass({ getInitialState: function() { return { published_to_server: false, published_to_github: false }; }, componentDidMount: function() { return this.props.publishToGithub().then((function(_this) { return function(resp) { _this.setState({ published_to_github: true }); return _this.props.waitForPublishToServer().timeout(60000, _this.timeoutMsg()).then(function() { return _this.setState({ published_to_server: true }); }); }; })(this))["catch"]((function(_this) { return function(err) { return _this.props.handleError(err); }; })(this)); }, timeoutMsg: function() { return "Oops. Looks like we're having problems with publishing apps. <br>Click Support in the top bar!"; }, render: function() { if (this.props.files_changed) { return React.createElement(Loader, { "title": 'Building your website...' }); } else if (this.state.published_to_server) { return React.createElement(Published, { "website_url": this.props.website_url }); } else if (this.state.published_to_github) { return React.createElement(Loader, { "title": 'Your files are now in Github.', "subtitle": 'Publishing to server (~30 sec)...' }); } else { return React.createElement(Loader, { "title": 'I am publishing your landing page...' }); } } }); },{"./loader":14,"./published":20,"bluebird":57,"react":489,"request":500}],19:[function(require,module,exports){ var PublishStatus, React, classNames; React = require('react'); classNames = require('classnames'); module.exports = PublishStatus = React.createClass({ currentStage: function() { return this.props.current || 0; }, error: function(i) { if (!(this.props.error && this.currentStage() === i + 1)) { return React.createElement("span", null); } return React.createElement("div", { "className": 'stage-error' }, "App name ", this.props.error); }, render: function() { if (this.currentStage() === 0) { return React.createElement("span", { "className": 'deploy-steps' }); } return React.createElement("ul", { "className": "deploy-steps collection" }, _.map(this.props.stages, (function(_this) { return function(stage, i) { var icon_classes, li_classes; li_classes = function(_this) { return classNames({ 'collection-item': true, success: !_this.props.error && _this.currentStage() > i + 1, failure: _this.props.error && _this.currentStage() === i + 1 }); }; icon_classes = function(_this) { return classNames({ fa: true, icon: true, 'secondary-content': true, 'fa-check-circle': !_this.props.error && _this.currentStage() > i + 1, 'fa-circle-o-notch fa-spin': !_this.props.error && _this.currentStage() === i + 1, 'fa-exclamation-circle': _this.props.error && _this.currentStage() === i + 1 }); }; return React.createElement("li", { "key": stage, "className": li_classes(_this) }, React.createElement("span", { "className": 'stage-name' }, stage), React.createElement("i", { "className": icon_classes(_this) }), _this.error(i)); }; })(this))); } }); },{"classnames":114,"react":489}],20:[function(require,module,exports){ var React; React = require('react'); module.exports = React.createClass({ render: function() { return React.createElement("div", { "className": 'published valign-wrapper' }, React.createElement("div", { "className": 'valign published-container' }, React.createElement("div", { "className": 'published-icon row center-align' }, React.createElement("i", { "className": 'material-icons' }, "favorite_border")), React.createElement("div", { "className": 'row center-align' }, React.createElement("div", { "className": 'published-title' }, React.createElement("div", null, "Phew, everything is great."), React.createElement("div", null, "Your landing page has been published.")), React.createElement("a", { "href": this.props.website_url, "target": '_blank', "className": "btn btn-large waves-effect waves-light published-button" }, React.createElement("div", null, "Open my landing page", React.createElement("span", { "className": 'published-button-icon' }, React.createElement("i", { "className": 'material-icons' }, "open_in_new"))), React.createElement("div", { "className": 'published-button-subtitle' }, this.props.website_url.replace('http://', '')))))); } }); },{"react":489}],21:[function(require,module,exports){ var Promise, React, request; React = require('react'); Promise = require('bluebird'); request = require('request'); module.exports = React.createClass({ getInitialState: function() { return { dist_dir: this.props.dist_dir, slug: this.props.slug }; }, componentDidMount: function()