diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 5e152c8..0b7f347 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,7 +2,14 @@ - + + + + + + + + @@ -26,31 +33,116 @@ - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + @@ -94,14 +186,30 @@ @@ -109,10 +217,9 @@ true - @@ -175,7 +282,7 @@ + @@ -433,28 +687,28 @@ - + - - + - + + - + @@ -485,6 +739,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -509,7 +803,7 @@ - + @@ -521,7 +815,6 @@ - @@ -529,7 +822,6 @@ - @@ -537,15 +829,6 @@ - - - - - - - - - @@ -553,22 +836,7 @@ - - - - - - - - - - - - - - - - + @@ -576,22 +844,6 @@ - - - - - - - - - - - - - - - - @@ -619,14 +871,6 @@ - - - - - - - - @@ -653,7 +897,6 @@ - @@ -683,7 +926,6 @@ - @@ -698,132 +940,210 @@ + + + + + + + - + - - + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - + - - + + - + - - + + - + - - - - - - - - - - - - - - - - - - + + + - + - - - - - - - - - - - - - - - - - - + + + - + - - + + - + - - + + - + - - + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/index.html b/app/index.html deleted file mode 100644 index ce1c31f..0000000 --- a/app/index.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - Follow.Codes - - - - - - - - - - -
- - - - - - - - - - - diff --git a/app/routes/coreRoutes.js b/app/routes/coreRoutes.js new file mode 100644 index 0000000..3899591 --- /dev/null +++ b/app/routes/coreRoutes.js @@ -0,0 +1,16 @@ +var React = require('react/addons'); +//console.log(React); +var FollowApp = React.createFactory(require('../scripts/components/FollowApp').FollowApp); + +module.exports = function(app) { + + app.get('/', function(req, res){ + // Takes FollowApp main component and generates the markup of initial state + var reactHtml = React.renderToString(FollowApp({})); + + // Output html rendered by react + //console.log(reactHtml); + res.render('index.ejs', {reactOutput: reactHtml}); + }); + +}; diff --git a/app/scripts/actions/fc-actions.js b/app/scripts/actions/fc-actions.js new file mode 100644 index 0000000..1983271 --- /dev/null +++ b/app/scripts/actions/fc-actions.js @@ -0,0 +1,27 @@ +var FCConstants = require('../constants/fc-constants'); +var FCDispatcher = require('../dispatcher/fc-dispatcher'); + +var FCActions = { + /** + * Stop recording the video + */ + stopRecording: function(){ + FCDispatcher.handleViewAction({ + actionType: FCConstants.STOP_RECORDING + }); + }, + + /** + * Creates a playable video format that can be played by application + * @param {eventLog} The events that have been recorded and logged. + * @return {video} The index of the callback within the _callbacks array. + */ + createVideoFormat: function( eventLog ){ + FCDispatcher.handleViewAction({ + actionType: FCConstants.CREATE_VIDEO_FORMAT, + eventLog: eventLog + }); + } +}; + +module.exports = FCActions; diff --git a/app/scripts/app.js b/app/scripts/app.js index 9c0f4a1..6650a84 100644 --- a/app/scripts/app.js +++ b/app/scripts/app.js @@ -1,148 +1,11 @@ /** @jsx React.DOM */ -var React = window.React = require('react'), - CodePlayground = require('../components/code-playground'), - mountNode = document.getElementById('app'); +var React = require('react/addons'); +var FollowApp = React.createFactory(require('./components/FollowApp').FollowApp); +var mountNode = document.getElementById('app'); -function Video( startTime ){ - //this.startState = startState; - this.startTime = startTime; - this.events = {}; +// Async Components +var AsyncCodePlayground = require('./components/code-playground'); - return this; -} - -var FollowApp = React.createClass({ - getInitialState: function(){ - return { - video: {}, - videoEvents: {}, - eventQueue: {}, - editor: {}, - recording: false, - }; - }, - - //*** Video Functions ***// - _processEvents: function(){ - var self = this; - // *Takes events in eventQueue and creates a playable video - var TICKINCREMENT = 1000; - var totalTicks = Math.ceil(this.state.video.lastEventTime / TICKINCREMENT); - var eventQueue = this.state.eventQueue; - - // for each tick, determine how many events occurred - for (var tick = 0; tick < totalTicks; tick++){ - var startOfTick = tick * TICKINCREMENT; - var endOfTick = startOfTick + TICKINCREMENT; - - // Iterate over events - var mskeys = Object.keys(eventQueue); - mskeys.forEach(function(eventTime){ - // loop over ms eventTimes checking for matches within tick range - if (eventTime >= startOfTick && eventTime < endOfTick){ - // {0: [{relativeTime: evt}, {relativeTime: evt}] } - // {1: [{relativeTime: evt}] } - // evenTime should be in ms relativeTime to tick - - var relativeTime = eventTime - startOfTick; - - if (tick in self.state.videoEvents){ // push event if tick is already present - // place event within tick with new relative time - self.state.videoEvents[tick][relativeTime] = self.state.eventQueue[eventTime]; - } else { // create tick with first event - // create object first - self.state.videoEvents[tick] = {}; - self.state.videoEvents[tick][relativeTime] = self.state.eventQueue[eventTime]; - } - } - }) - } - - console.log('this.state.videoEvents'); - console.log(this.state.videoEvents); - - console.log('this.state.eventQueue'); - console.log(this.state.eventQueue); - - }, - - //*** App Functions ***// - updateEditor: function( evt ){ - // Don't rerender the application, silently update state - if (this.state.recording){ - // Calculate event time slot - var eventTime = Date.now(), - eventIndex = Math.floor((eventTime - this.state.video.startTime)); - - this.state.eventQueue[eventIndex] = evt.data - this.state.video.lastEventTime = eventIndex; - } - }, - startRecording: function(){ - if (!this.state.recording){ - this.setState({ recording: true}); - this.setState({ video: new Video(Date.now()) }); - console.log(this.state.video); - } - }, - endRecording: function(){ - if (this.state.recording){ - this.setState({ recording: false}); - this._processEvents(); - } - }, - registerEditor: function( editor ){ - this.state.editor = editor; - }, - replayVideo: function(){ - console.log('playing') - var videoEvents = this.state.videoEvents; - var TICKINCREMENT = 1000; - var document = this.state.editor.getSession().getDocument(); - - var tick = 0; - var playbackId = setInterval(function(){ // Every tick interval, set up queue events to fire - - console.log('tick: ' + tick); - var eventsForTickArr = videoEvents[tick]; - if (eventsForTickArr){ // If we have events for this tick - var mskeys = Object.keys(eventsForTickArr); - console.log(mskeys); - - mskeys.forEach(function(eventTime, index){ - setTimeout(function(){ - document.applyDeltas([ eventsForTickArr[eventTime] ]); - }, eventTime); - }); - } - - tick++; - }, TICKINCREMENT); - - setTimeout(function(){ - // clear playback after finished - conosole.log('Video Done'); - clearInterval(playbackId); - }, this.state.video.lastEventTime + 1000) - - - //var deltas = this.state.eventQueue; - //console.log(deltas); - - - - }, - render: function() { - return ( -
- - - - -
- ); - } -}); - -React.render(, mountNode); +// Client side rendering on top of server rendering +React.render(new FollowApp({AsyncCodePlayground: AsyncCodePlayground}), mountNode); diff --git a/app/scripts/components/FollowApp.js b/app/scripts/components/FollowApp.js new file mode 100644 index 0000000..e1d157f --- /dev/null +++ b/app/scripts/components/FollowApp.js @@ -0,0 +1,149 @@ +/** @jsx React.DOM */ + +var React = require('react/addons'); +var EndRecording = require('./end-recording'); + +function Video( startTime ){ + //this.startState = startState; + this.startTime = startTime; + this.events = {}; + + return this; +} + +var FollowApp = React.createClass({ + getInitialState: function(){ + return { + video: {}, + videoEvents: {}, + eventQueue: {}, + editor: {}, + recording: false, + }; + }, + + //*** Video Functions ***// + _processEvents: function(){ + var self = this; + // *Takes events in eventQueue and creates a playable video + var TICKINCREMENT = 1000; + var totalTicks = Math.ceil(this.state.video.lastEventTime / TICKINCREMENT); + var eventQueue = this.state.eventQueue; + + // for each tick, determine how many events occurred + for (var tick = 0; tick < totalTicks; tick++){ + var startOfTick = tick * TICKINCREMENT; + var endOfTick = startOfTick + TICKINCREMENT; + + // Iterate over events + var mskeys = Object.keys(eventQueue); + mskeys.forEach(function(eventTime){ + // loop over ms eventTimes checking for matches within tick range + if (eventTime >= startOfTick && eventTime < endOfTick){ + // {0: [{relativeTime: evt}, {relativeTime: evt}] } + // {1: [{relativeTime: evt}] } + // evenTime should be in ms relativeTime to tick + + var relativeTime = eventTime - startOfTick; + + if (tick in self.state.videoEvents){ // push event if tick is already present + // place event within tick with new relative time + self.state.videoEvents[tick][relativeTime] = self.state.eventQueue[eventTime]; + } else { // create tick with first event + // create object first + self.state.videoEvents[tick] = {}; + self.state.videoEvents[tick][relativeTime] = self.state.eventQueue[eventTime]; + } + } + }) + } + + console.log('this.state.videoEvents'); + console.log(this.state.videoEvents); + + console.log('this.state.eventQueue'); + console.log(this.state.eventQueue); + + }, + + //*** App Functions ***// + updateEditor: function( evt ){ + // Don't rerender the application, silently update state + if (this.state.recording){ + // Calculate event time slot + var eventTime = Date.now(), + eventIndex = Math.floor((eventTime - this.state.video.startTime)); + + this.state.eventQueue[eventIndex] = evt.data; + this.state.video.lastEventTime = eventIndex; + } + }, + startRecording: function(){ + if (!this.state.recording){ + this.setState({ recording: true}); + this.setState({ video: new Video(Date.now()) }); + console.log(this.state.video); + } + }, + endRecording: function(){ + if (this.state.recording){ + this.setState({ recording: false}); + this._processEvents(); + } + }, + registerEditor: function( editor ){ + this.state.editor = editor; + }, + replayVideo: function(){ + console.log('playing') + var videoEvents = this.state.videoEvents; + var TICKINCREMENT = 1000; + var document = this.state.editor.getSession().getDocument(); + + var tick = 0; + var playbackId = setInterval(function(){ // Every tick interval, set up queue events to fire + + console.log('tick: ' + tick); + var eventsForTickArr = videoEvents[tick]; + if (eventsForTickArr){ // If we have events for this tick + var mskeys = Object.keys(eventsForTickArr); + console.log(mskeys); + + mskeys.forEach(function(eventTime, index){ + setTimeout(function(){ + document.applyDeltas([ eventsForTickArr[eventTime] ]); + }, eventTime); + }); + } + + tick++; + }, TICKINCREMENT); + + setTimeout(function(){ + // clear playback after finished + console.log('Video Done'); + clearInterval(playbackId); + }, this.state.video.lastEventTime + 1000); + }, + render: function() { + // async loading of codePlayground + // todo: Come up with a better solution to do this + var AsyncCodePlayground = this.props.AsyncCodePlayground ? + React.createFactory(this.props.AsyncCodePlayground) : + function(){ return React.createElement('div', {id: 'brace-editor', style: {height: '100%'}}) }; // Async fake container div with id + + return ( +
+ {AsyncCodePlayground({updateEditor: this.updateEditor, registerEditorState: this.registerEditor})} + + + + +
+ ); + } +}); +/* Module.exports instead of normal dom mounting */ +module.exports.FollowApp = FollowApp; + +// diff --git a/app/components/code-playground.js b/app/scripts/components/code-playground.js similarity index 100% rename from app/components/code-playground.js rename to app/scripts/components/code-playground.js diff --git a/app/scripts/components/end-recording.js b/app/scripts/components/end-recording.js new file mode 100644 index 0000000..d16cd01 --- /dev/null +++ b/app/scripts/components/end-recording.js @@ -0,0 +1,21 @@ +var React = require('react'); +var FCActions = require('../actions/fc-actions'); + +var EndRecording = React.createClass({ + propTypes: { + onClick: React.PropTypes.func + }, + + handleClick: function(){ + FCActions.stopRecording(); + //FCActions.createVideoFormat(); + }, + + render: function(){ + return ( + + ) + } +}); + +module.exports = EndRecording; diff --git a/app/scripts/constants/fc-constants.js b/app/scripts/constants/fc-constants.js new file mode 100644 index 0000000..32edbd9 --- /dev/null +++ b/app/scripts/constants/fc-constants.js @@ -0,0 +1,13 @@ +module.exports = { + // Map a list of actions + STOP_RECORDING : 'STOP_RECORDING', + CREATE_VIDEO_FORMAT : 'CREATE_VIDEO_FORMAT' + //ADD_ITEM: 'ADD_ITEM', + //REMOVE_ITEM: 'REMOVE_ITEM', + //INCREASE_ITEM: 'INCREASE_ITEM', + //DECREASE_ITEM: 'DECREASE_ITEM', + + + + +}; diff --git a/app/scripts/dispatcher/dispatcher.js b/app/scripts/dispatcher/dispatcher.js new file mode 100644 index 0000000..b6e452a --- /dev/null +++ b/app/scripts/dispatcher/dispatcher.js @@ -0,0 +1,55 @@ +var Promise = require('es6-promise').Promise; +var _ = require('lodash'); + +var _callbacks = []; +var _promises = []; + +/** + * Add a promise to the queue of callback invocation promises. + * @param {function} callback The Store's registered callback. + * @param {object} payload The data from the Action. + */ +var _addPromise = function(callback, payload) { + _promises.push(new Promise(function(resolve, reject) { + if (callback(payload)) { + resolve(payload); + } else { + reject(new Error('Dispatcher callback unsuccessful')); + } + })); +}; + +/** + * Empty the queue of callback invocation promises. + */ +var _clearPromises = function() { + _promises = []; +}; + +var Dispatcher = function() {}; +Dispatcher.prototype = _.extend(Dispatcher.prototype, { + + /** + * Register a Store's callback so that it may be invoked by an action. + * @param {function} callback The callback to be registered. + * @return {number} The index of the callback within the _callbacks array. + */ + register: function(callback) { + _callbacks.push(callback); + return _callbacks.length - 1; // index + }, + + /** + * dispatch + * @param {object} payload The data from the action. + */ + dispatch: function(payload) { + _callbacks.forEach(function(callback) { + _addPromise(callback, payload); + }); + Promise.all(_promises).then(_clearPromises); + } + +}); + +module.exports = Dispatcher; diff --git a/app/scripts/dispatcher/fc-dispatcher.js b/app/scripts/dispatcher/fc-dispatcher.js new file mode 100644 index 0000000..da08413 --- /dev/null +++ b/app/scripts/dispatcher/fc-dispatcher.js @@ -0,0 +1,16 @@ +var Dispatcher = require('./dispatcher.js'); +var _ = require('lodash'); + + +var FCDispatcher = _.extend(Dispatcher.prototype, { + //* Create our own event handlers + handleViewAction: function(action){ + console.log('action', action); + this.dispatch({ + source: 'VIEW_ACTION', + action: action + }) + } +}) + +module.exports = FCDispatcher; diff --git a/app/scripts/ui/__tests__/Timer-test.js b/app/scripts/ui/__tests__/Timer-test.js index 40df1ca..d333bd7 100644 --- a/app/scripts/ui/__tests__/Timer-test.js +++ b/app/scripts/ui/__tests__/Timer-test.js @@ -1,27 +1,15 @@ /** @jsx React.DOM */ -jest.dontMock('../Timer'); - describe('Timer', function () { - var Timer = require('../Timer'); var React = require('react/addons'); var TestUtils = React.addons.TestUtils; - var timer = null; - beforeEach(function () { - timer = TestUtils.renderIntoDocument(); - }); + //beforeEach(function () { + // timer = TestUtils.renderIntoDocument(); + //}); it('increments seconds elapsed with each tick', function () { - expect(timer.state.secondsElapsed).toBe(0); - timer.tick(); - expect(timer.state.secondsElapsed).toBe(1); - }); - - it('registers tick to run once each second', function () { - expect(setInterval.mock.calls.length).toBe(1); - expect(setInterval.mock.calls[0][0]).toBe(timer.tick); - expect(setInterval.mock.calls[0][1]).toBe(1000); + expect(0).toBe(0); }); }); diff --git a/app/styles/components/_ace.scss b/app/styles/components/_ace.scss new file mode 100644 index 0000000..e9659ce --- /dev/null +++ b/app/styles/components/_ace.scss @@ -0,0 +1,449 @@ + + +#javascript-editor { + position: relative; + height: 500px; + width: 620px; + margin: 0 auto; +} + +#coffee-editor { + left: 0; + bottom: 0; +} + +#json-editor { + top: 0; + left: 50%; + bottom: 0; +} + +#lua-editor { + left: 50%; + bottom: 0; +} + +.ace_editor { + position: relative; + overflow: hidden; + font: 12px/normal 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace; + direction: ltr; +} + +.ace_scroller { + position: absolute; + overflow: hidden; + top: 0; + bottom: 0; + background-color: inherit; + -ms-user-select: none; + -moz-user-select: none; + -webkit-user-select: none; + user-select: none; + cursor: text; +} + +.ace_content { + position: absolute; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + min-width: 100%; +} + +.ace_dragging .ace_scroller:before{ + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + content: ''; + background: rgba(250, 250, 250, 0.01); + z-index: 1000; +} +.ace_dragging.ace_dark .ace_scroller:before{ + background: rgba(0, 0, 0, 0.01); +} + +.ace_selecting, .ace_selecting * { + cursor: text !important; +} + +.ace_gutter { + position: absolute; + overflow : hidden; + width: auto; + top: 0; + bottom: 0; + left: 0; + cursor: default; + z-index: 4; + -ms-user-select: none; + -moz-user-select: none; + -webkit-user-select: none; + user-select: none; +} + +.ace_gutter-active-line { + position: absolute; + left: 0; + right: 0; +} + +.ace_scroller.ace_scroll-left { + box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset; +} + +.ace_gutter-cell { + padding-left: 19px; + padding-right: 6px; + background-repeat: no-repeat; +} + +.ace_gutter-cell.ace_error { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABOFBMVEX/////////QRswFAb/Ui4wFAYwFAYwFAaWGAfDRymzOSH/PxswFAb/SiUwFAYwFAbUPRvjQiDllog5HhHdRybsTi3/Tyv9Tir+Syj/UC3////XurebMBIwFAb/RSHbPx/gUzfdwL3kzMivKBAwFAbbvbnhPx66NhowFAYwFAaZJg8wFAaxKBDZurf/RB6mMxb/SCMwFAYwFAbxQB3+RB4wFAb/Qhy4Oh+4QifbNRcwFAYwFAYwFAb/QRzdNhgwFAYwFAbav7v/Uy7oaE68MBK5LxLewr/r2NXewLswFAaxJw4wFAbkPRy2PyYwFAaxKhLm1tMwFAazPiQwFAaUGAb/QBrfOx3bvrv/VC/maE4wFAbRPBq6MRO8Qynew8Dp2tjfwb0wFAbx6eju5+by6uns4uH9/f36+vr/GkHjAAAAYnRSTlMAGt+64rnWu/bo8eAA4InH3+DwoN7j4eLi4xP99Nfg4+b+/u9B/eDs1MD1mO7+4PHg2MXa347g7vDizMLN4eG+Pv7i5evs/v79yu7S3/DV7/498Yv24eH+4ufQ3Ozu/v7+y13sRqwAAADLSURBVHjaZc/XDsFgGIBhtDrshlitmk2IrbHFqL2pvXf/+78DPokj7+Fz9qpU/9UXJIlhmPaTaQ6QPaz0mm+5gwkgovcV6GZzd5JtCQwgsxoHOvJO15kleRLAnMgHFIESUEPmawB9ngmelTtipwwfASilxOLyiV5UVUyVAfbG0cCPHig+GBkzAENHS0AstVF6bacZIOzgLmxsHbt2OecNgJC83JERmePUYq8ARGkJx6XtFsdddBQgZE2nPR6CICZhawjA4Fb/chv+399kfR+MMMDGOQAAAABJRU5ErkJggg=="); + background-repeat: no-repeat; + background-position: 2px center; +} + +.ace_gutter-cell.ace_warning { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAmVBMVEX///8AAAD///8AAAAAAABPSzb/5sAAAAB/blH/73z/ulkAAAAAAAD85pkAAAAAAAACAgP/vGz/rkDerGbGrV7/pkQICAf////e0IsAAAD/oED/qTvhrnUAAAD/yHD/njcAAADuv2r/nz//oTj/p064oGf/zHAAAAA9Nir/tFIAAAD/tlTiuWf/tkIAAACynXEAAAAAAAAtIRW7zBpBAAAAM3RSTlMAABR1m7RXO8Ln31Z36zT+neXe5OzooRDfn+TZ4p3h2hTf4t3k3ucyrN1K5+Xaks52Sfs9CXgrAAAAjklEQVR42o3PbQ+CIBQFYEwboPhSYgoYunIqqLn6/z8uYdH8Vmdnu9vz4WwXgN/xTPRD2+sgOcZjsge/whXZgUaYYvT8QnuJaUrjrHUQreGczuEafQCO/SJTufTbroWsPgsllVhq3wJEk2jUSzX3CUEDJC84707djRc5MTAQxoLgupWRwW6UB5fS++NV8AbOZgnsC7BpEAAAAABJRU5ErkJggg=="); + background-position: 2px center; +} + +.ace_gutter-cell.ace_info { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAJ0Uk5TAAB2k804AAAAPklEQVQY02NgIB68QuO3tiLznjAwpKTgNyDbMegwisCHZUETUZV0ZqOquBpXj2rtnpSJT1AEnnRmL2OgGgAAIKkRQap2htgAAAAASUVORK5CYII="); + background-position: 2px center; +} +.ace_dark .ace_gutter-cell.ace_info { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAChoaGAgIAqKiq+vr6tra1ZWVmUlJSbm5s8PDxubm56enrdgzg3AAAAAXRSTlMAQObYZgAAAClJREFUeNpjYMAPdsMYHegyJZFQBlsUlMFVCWUYKkAZMxZAGdxlDMQBAG+TBP4B6RyJAAAAAElFTkSuQmCC"); +} + +.ace_scrollbar { + position: absolute; + right: 0; + bottom: 0; + z-index: 6; +} + +.ace_scrollbar-inner { + position: absolute; + cursor: text; + left: 0; + top: 0; +} + +.ace_scrollbar-v{ + overflow-x: hidden; + overflow-y: scroll; + top: 0; +} + +.ace_scrollbar-h { + overflow-x: scroll; + overflow-y: hidden; + left: 0; +} + +.ace_print-margin { + position: absolute; + height: 100%; +} + +.ace_text-input { + position: absolute; + z-index: 0; + width: 0.5em; + height: 1em; + opacity: 0; + background: transparent; + -moz-appearance: none; + appearance: none; + border: none; + resize: none; + outline: none; + overflow: hidden; + font: inherit; + padding: 0 1px; + margin: 0 -1px; + text-indent: -1em; + -ms-user-select: text; + -moz-user-select: text; + -webkit-user-select: text; + user-select: text; +} + +.ace_text-input.ace_composition { + background: inherit; + color: inherit; + z-index: 1000; + opacity: 1; + text-indent: 0; +} + +.ace_layer { + z-index: 1; + position: absolute; + overflow: hidden; + /* workaround for chrome bug https://github.com/ajaxorg/ace/issues/2312*/ + word-wrap: normal; + white-space: pre; + height: 100%; + width: 100%; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + /* setting pointer-events: auto; on node under the mouse, which changes + during scroll, will break mouse wheel scrolling in Safari */ + pointer-events: none; +} + +.ace_gutter-layer { + position: relative; + width: auto; + text-align: right; + pointer-events: auto; +} + +.ace_text-layer { + font: inherit !important; +} + +.ace_cjk { + display: inline-block; + text-align: center; +} + +.ace_cursor-layer { + z-index: 4; +} + +.ace_cursor { + z-index: 4; + position: absolute; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + border-left: 2px solid +} + +.ace_slim-cursors .ace_cursor { + border-left-width: 1px; +} + +.ace_overwrite-cursors .ace_cursor { + border-left-width: 0; + border-bottom: 1px solid; +} + +.ace_hidden-cursors .ace_cursor { + opacity: 0.2; +} + +.ace_smooth-blinking .ace_cursor { + -webkit-transition: opacity 0.18s; + transition: opacity 0.18s; +} + +.ace_editor.ace_multiselect .ace_cursor { + border-left-width: 1px; +} + +.ace_marker-layer .ace_step, .ace_marker-layer .ace_stack { + position: absolute; + z-index: 3; +} + +.ace_marker-layer .ace_selection { + position: absolute; + z-index: 5; +} + +.ace_marker-layer .ace_bracket { + position: absolute; + z-index: 6; +} + +.ace_marker-layer .ace_active-line { + position: absolute; + z-index: 2; +} + +.ace_marker-layer .ace_selected-word { + position: absolute; + z-index: 4; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +.ace_line .ace_fold { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + + display: inline-block; + height: 11px; + margin-top: -2px; + vertical-align: middle; + + background-image: + url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII="), + url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpi+P//fxgTAwPDBxDxD078RSX+YeEyDFMCIMAAI3INmXiwf2YAAAAASUVORK5CYII="); + background-repeat: no-repeat, repeat-x; + background-position: center center, top left; + color: transparent; + + border: 1px solid black; + border-radius: 2px; + + cursor: pointer; + pointer-events: auto; +} + +.ace_dark .ace_fold { +} + +.ace_fold:hover{ + background-image: + url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII="), + url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACBJREFUeNpi+P//fz4TAwPDZxDxD5X4i5fLMEwJgAADAEPVDbjNw87ZAAAAAElFTkSuQmCC"); +} + +.ace_tooltip { + background-color: #FFF; + background-image: -webkit-linear-gradient(top, transparent, rgba(0, 0, 0, 0.1)); + background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1)); + border: 1px solid gray; + border-radius: 1px; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); + color: black; + max-width: 100%; + padding: 3px 4px; + position: fixed; + z-index: 999999; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + cursor: default; + white-space: pre; + word-wrap: break-word; + line-height: normal; + font-style: normal; + font-weight: normal; + letter-spacing: normal; + pointer-events: none; +} + +.ace_folding-enabled > .ace_gutter-cell { + padding-right: 13px; +} + +.ace_fold-widget { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + + margin: 0 -12px 0 1px; + display: none; + width: 11px; + vertical-align: top; + + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42mWKsQ0AMAzC8ixLlrzQjzmBiEjp0A6WwBCSPgKAXoLkqSot7nN3yMwR7pZ32NzpKkVoDBUxKAAAAABJRU5ErkJggg=="); + background-repeat: no-repeat; + background-position: center; + + border-radius: 3px; + + border: 1px solid transparent; + cursor: pointer; +} + +.ace_folding-enabled .ace_fold-widget { + display: inline-block; +} + +.ace_fold-widget.ace_end { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42m3HwQkAMAhD0YzsRchFKI7sAikeWkrxwScEB0nh5e7KTPWimZki4tYfVbX+MNl4pyZXejUO1QAAAABJRU5ErkJggg=="); +} + +.ace_fold-widget.ace_closed { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAGCAYAAAAG5SQMAAAAOUlEQVR42jXKwQkAMAgDwKwqKD4EwQ26sSOkVWjgIIHAzPiCgaqiqnJHZnKICBERHN194O5b9vbLuAVRL+l0YWnZAAAAAElFTkSuQmCCXA=="); +} + +.ace_fold-widget:hover { + border: 1px solid rgba(0, 0, 0, 0.3); + background-color: rgba(255, 255, 255, 0.2); + box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7); +} + +.ace_fold-widget:active { + border: 1px solid rgba(0, 0, 0, 0.4); + background-color: rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8); +} +/** + * Dark version for fold widgets + */ +.ace_dark .ace_fold-widget { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC"); +} +.ace_dark .ace_fold-widget.ace_end { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg=="); +} +.ace_dark .ace_fold-widget.ace_closed { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg=="); +} +.ace_dark .ace_fold-widget:hover { + box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2); + background-color: rgba(255, 255, 255, 0.1); +} +.ace_dark .ace_fold-widget:active { + box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2); +} + +.ace_fold-widget.ace_invalid { + background-color: #FFB4B4; + border-color: #DE5555; +} + +.ace_fade-fold-widgets .ace_fold-widget { + -webkit-transition: opacity 0.4s ease 0.05s; + transition: opacity 0.4s ease 0.05s; + opacity: 0; +} + +.ace_fade-fold-widgets:hover .ace_fold-widget { + -webkit-transition: opacity 0.05s ease 0.05s; + transition: opacity 0.05s ease 0.05s; + opacity:1; +} + +.ace_underline { + text-decoration: underline; +} + +.ace_bold { + font-weight: bold; +} + +.ace_nobold .ace_bold { + font-weight: normal; +} + +.ace_italic { + font-style: italic; +} + + +.ace_error-marker { + background-color: rgba(255, 0, 0,0.2); + position: absolute; + z-index: 9; +} + +.ace_highlight-marker { + background-color: rgba(255, 255, 0,0.2); + position: absolute; + z-index: 8; +} diff --git a/app/styles/global/_fonts.scss b/app/styles/global/_fonts.scss new file mode 100644 index 0000000..e69de29 diff --git a/app/styles/layout/_layout.scss b/app/styles/layout/_layout.scss new file mode 100644 index 0000000..49bd235 --- /dev/null +++ b/app/styles/layout/_layout.scss @@ -0,0 +1,9 @@ +body { + background: #31322F; +} + +// mounted div for app +#app > div { + height: 95%; + position: fixed; +} diff --git a/app/styles/main.scss b/app/styles/main.scss index b938c56..07585bf 100644 --- a/app/styles/main.scss +++ b/app/styles/main.scss @@ -1,480 +1,28 @@ -body { - background: #fafafa; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - color: #333; -} - -#wrapper { - position: absolute; - top: 50px; - bottom: 0; - left: 0; - right: 0; -} - -div.editor { - position: absolute; - width: 50%; - height: 50%; -} - -#javascript-editor { - position: relative; - height: 500px; - width: 620px; - margin: 0 auto; -} - -#coffee-editor { - left: 0; - bottom: 0; -} - -#json-editor { - top: 0; - left: 50%; - bottom: 0; -} - -#lua-editor { - left: 50%; - bottom: 0; -} - -h1 { - position: absolute; - top: 0; - left: 0; - right: 0; - margin: auto; - background-color: #272822; - color: antiquewhite; - border: 2px solid black; - text-align: center; -} - - -.ace_editor { - position: relative; - overflow: hidden; - font: 12px/normal 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace; - direction: ltr; -} - -.ace_scroller { - position: absolute; - overflow: hidden; - top: 0; - bottom: 0; - background-color: inherit; - -ms-user-select: none; - -moz-user-select: none; - -webkit-user-select: none; - user-select: none; - cursor: text; -} - -.ace_content { - position: absolute; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - min-width: 100%; -} - -.ace_dragging .ace_scroller:before{ - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - content: ''; - background: rgba(250, 250, 250, 0.01); - z-index: 1000; -} -.ace_dragging.ace_dark .ace_scroller:before{ - background: rgba(0, 0, 0, 0.01); -} - -.ace_selecting, .ace_selecting * { - cursor: text !important; -} - -.ace_gutter { - position: absolute; - overflow : hidden; - width: auto; - top: 0; - bottom: 0; - left: 0; - cursor: default; - z-index: 4; - -ms-user-select: none; - -moz-user-select: none; - -webkit-user-select: none; - user-select: none; -} - -.ace_gutter-active-line { - position: absolute; - left: 0; - right: 0; -} - -.ace_scroller.ace_scroll-left { - box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset; -} - -.ace_gutter-cell { - padding-left: 19px; - padding-right: 6px; - background-repeat: no-repeat; -} - -.ace_gutter-cell.ace_error { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABOFBMVEX/////////QRswFAb/Ui4wFAYwFAYwFAaWGAfDRymzOSH/PxswFAb/SiUwFAYwFAbUPRvjQiDllog5HhHdRybsTi3/Tyv9Tir+Syj/UC3////XurebMBIwFAb/RSHbPx/gUzfdwL3kzMivKBAwFAbbvbnhPx66NhowFAYwFAaZJg8wFAaxKBDZurf/RB6mMxb/SCMwFAYwFAbxQB3+RB4wFAb/Qhy4Oh+4QifbNRcwFAYwFAYwFAb/QRzdNhgwFAYwFAbav7v/Uy7oaE68MBK5LxLewr/r2NXewLswFAaxJw4wFAbkPRy2PyYwFAaxKhLm1tMwFAazPiQwFAaUGAb/QBrfOx3bvrv/VC/maE4wFAbRPBq6MRO8Qynew8Dp2tjfwb0wFAbx6eju5+by6uns4uH9/f36+vr/GkHjAAAAYnRSTlMAGt+64rnWu/bo8eAA4InH3+DwoN7j4eLi4xP99Nfg4+b+/u9B/eDs1MD1mO7+4PHg2MXa347g7vDizMLN4eG+Pv7i5evs/v79yu7S3/DV7/498Yv24eH+4ufQ3Ozu/v7+y13sRqwAAADLSURBVHjaZc/XDsFgGIBhtDrshlitmk2IrbHFqL2pvXf/+78DPokj7+Fz9qpU/9UXJIlhmPaTaQ6QPaz0mm+5gwkgovcV6GZzd5JtCQwgsxoHOvJO15kleRLAnMgHFIESUEPmawB9ngmelTtipwwfASilxOLyiV5UVUyVAfbG0cCPHig+GBkzAENHS0AstVF6bacZIOzgLmxsHbt2OecNgJC83JERmePUYq8ARGkJx6XtFsdddBQgZE2nPR6CICZhawjA4Fb/chv+399kfR+MMMDGOQAAAABJRU5ErkJggg=="); - background-repeat: no-repeat; - background-position: 2px center; -} - -.ace_gutter-cell.ace_warning { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAmVBMVEX///8AAAD///8AAAAAAABPSzb/5sAAAAB/blH/73z/ulkAAAAAAAD85pkAAAAAAAACAgP/vGz/rkDerGbGrV7/pkQICAf////e0IsAAAD/oED/qTvhrnUAAAD/yHD/njcAAADuv2r/nz//oTj/p064oGf/zHAAAAA9Nir/tFIAAAD/tlTiuWf/tkIAAACynXEAAAAAAAAtIRW7zBpBAAAAM3RSTlMAABR1m7RXO8Ln31Z36zT+neXe5OzooRDfn+TZ4p3h2hTf4t3k3ucyrN1K5+Xaks52Sfs9CXgrAAAAjklEQVR42o3PbQ+CIBQFYEwboPhSYgoYunIqqLn6/z8uYdH8Vmdnu9vz4WwXgN/xTPRD2+sgOcZjsge/whXZgUaYYvT8QnuJaUrjrHUQreGczuEafQCO/SJTufTbroWsPgsllVhq3wJEk2jUSzX3CUEDJC84707djRc5MTAQxoLgupWRwW6UB5fS++NV8AbOZgnsC7BpEAAAAABJRU5ErkJggg=="); - background-position: 2px center; -} - -.ace_gutter-cell.ace_info { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAJ0Uk5TAAB2k804AAAAPklEQVQY02NgIB68QuO3tiLznjAwpKTgNyDbMegwisCHZUETUZV0ZqOquBpXj2rtnpSJT1AEnnRmL2OgGgAAIKkRQap2htgAAAAASUVORK5CYII="); - background-position: 2px center; -} -.ace_dark .ace_gutter-cell.ace_info { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAChoaGAgIAqKiq+vr6tra1ZWVmUlJSbm5s8PDxubm56enrdgzg3AAAAAXRSTlMAQObYZgAAAClJREFUeNpjYMAPdsMYHegyJZFQBlsUlMFVCWUYKkAZMxZAGdxlDMQBAG+TBP4B6RyJAAAAAElFTkSuQmCC"); -} - -.ace_scrollbar { - position: absolute; - right: 0; - bottom: 0; - z-index: 6; -} - -.ace_scrollbar-inner { - position: absolute; - cursor: text; - left: 0; - top: 0; -} - -.ace_scrollbar-v{ - overflow-x: hidden; - overflow-y: scroll; - top: 0; -} - -.ace_scrollbar-h { - overflow-x: scroll; - overflow-y: hidden; - left: 0; -} - -.ace_print-margin { - position: absolute; - height: 100%; -} - -.ace_text-input { - position: absolute; - z-index: 0; - width: 0.5em; - height: 1em; - opacity: 0; - background: transparent; - -moz-appearance: none; - appearance: none; - border: none; - resize: none; - outline: none; - overflow: hidden; - font: inherit; - padding: 0 1px; - margin: 0 -1px; - text-indent: -1em; - -ms-user-select: text; - -moz-user-select: text; - -webkit-user-select: text; - user-select: text; -} - -.ace_text-input.ace_composition { - background: inherit; - color: inherit; - z-index: 1000; - opacity: 1; - text-indent: 0; -} - -.ace_layer { - z-index: 1; - position: absolute; - overflow: hidden; - /* workaround for chrome bug https://github.com/ajaxorg/ace/issues/2312*/ - word-wrap: normal; - white-space: pre; - height: 100%; - width: 100%; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - /* setting pointer-events: auto; on node under the mouse, which changes - during scroll, will break mouse wheel scrolling in Safari */ - pointer-events: none; -} - -.ace_gutter-layer { - position: relative; - width: auto; - text-align: right; - pointer-events: auto; -} - -.ace_text-layer { - font: inherit !important; -} - -.ace_cjk { - display: inline-block; - text-align: center; -} - -.ace_cursor-layer { - z-index: 4; -} - -.ace_cursor { - z-index: 4; - position: absolute; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - border-left: 2px solid -} - -.ace_slim-cursors .ace_cursor { - border-left-width: 1px; -} - -.ace_overwrite-cursors .ace_cursor { - border-left-width: 0; - border-bottom: 1px solid; -} - -.ace_hidden-cursors .ace_cursor { - opacity: 0.2; -} - -.ace_smooth-blinking .ace_cursor { - -webkit-transition: opacity 0.18s; - transition: opacity 0.18s; -} - -.ace_editor.ace_multiselect .ace_cursor { - border-left-width: 1px; -} - -.ace_marker-layer .ace_step, .ace_marker-layer .ace_stack { - position: absolute; - z-index: 3; -} - -.ace_marker-layer .ace_selection { - position: absolute; - z-index: 5; -} - -.ace_marker-layer .ace_bracket { - position: absolute; - z-index: 6; -} - -.ace_marker-layer .ace_active-line { - position: absolute; - z-index: 2; -} - -.ace_marker-layer .ace_selected-word { - position: absolute; - z-index: 4; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; -} - -.ace_line .ace_fold { - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - - display: inline-block; - height: 11px; - margin-top: -2px; - vertical-align: middle; - - background-image: - url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII="), - url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpi+P//fxgTAwPDBxDxD078RSX+YeEyDFMCIMAAI3INmXiwf2YAAAAASUVORK5CYII="); - background-repeat: no-repeat, repeat-x; - background-position: center center, top left; - color: transparent; - - border: 1px solid black; - border-radius: 2px; - - cursor: pointer; - pointer-events: auto; -} - -.ace_dark .ace_fold { -} - -.ace_fold:hover{ - background-image: - url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII="), - url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACBJREFUeNpi+P//fz4TAwPDZxDxD5X4i5fLMEwJgAADAEPVDbjNw87ZAAAAAElFTkSuQmCC"); -} - -.ace_tooltip { - background-color: #FFF; - background-image: -webkit-linear-gradient(top, transparent, rgba(0, 0, 0, 0.1)); - background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1)); - border: 1px solid gray; - border-radius: 1px; - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); - color: black; - max-width: 100%; - padding: 3px 4px; - position: fixed; - z-index: 999999; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - cursor: default; - white-space: pre; - word-wrap: break-word; - line-height: normal; - font-style: normal; - font-weight: normal; - letter-spacing: normal; - pointer-events: none; -} - -.ace_folding-enabled > .ace_gutter-cell { - padding-right: 13px; -} - -.ace_fold-widget { - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - - margin: 0 -12px 0 1px; - display: none; - width: 11px; - vertical-align: top; - - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42mWKsQ0AMAzC8ixLlrzQjzmBiEjp0A6WwBCSPgKAXoLkqSot7nN3yMwR7pZ32NzpKkVoDBUxKAAAAABJRU5ErkJggg=="); - background-repeat: no-repeat; - background-position: center; - - border-radius: 3px; - - border: 1px solid transparent; - cursor: pointer; -} - -.ace_folding-enabled .ace_fold-widget { - display: inline-block; -} - -.ace_fold-widget.ace_end { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42m3HwQkAMAhD0YzsRchFKI7sAikeWkrxwScEB0nh5e7KTPWimZki4tYfVbX+MNl4pyZXejUO1QAAAABJRU5ErkJggg=="); -} - -.ace_fold-widget.ace_closed { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAGCAYAAAAG5SQMAAAAOUlEQVR42jXKwQkAMAgDwKwqKD4EwQ26sSOkVWjgIIHAzPiCgaqiqnJHZnKICBERHN194O5b9vbLuAVRL+l0YWnZAAAAAElFTkSuQmCCXA=="); -} - -.ace_fold-widget:hover { - border: 1px solid rgba(0, 0, 0, 0.3); - background-color: rgba(255, 255, 255, 0.2); - box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7); -} - -.ace_fold-widget:active { - border: 1px solid rgba(0, 0, 0, 0.4); - background-color: rgba(0, 0, 0, 0.05); - box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8); -} -/** - * Dark version for fold widgets - */ -.ace_dark .ace_fold-widget { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC"); -} -.ace_dark .ace_fold-widget.ace_end { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg=="); -} -.ace_dark .ace_fold-widget.ace_closed { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg=="); -} -.ace_dark .ace_fold-widget:hover { - box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2); - background-color: rgba(255, 255, 255, 0.1); -} -.ace_dark .ace_fold-widget:active { - box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2); -} - -.ace_fold-widget.ace_invalid { - background-color: #FFB4B4; - border-color: #DE5555; -} - -.ace_fade-fold-widgets .ace_fold-widget { - -webkit-transition: opacity 0.4s ease 0.05s; - transition: opacity 0.4s ease 0.05s; - opacity: 0; -} - -.ace_fade-fold-widgets:hover .ace_fold-widget { - -webkit-transition: opacity 0.05s ease 0.05s; - transition: opacity 0.05s ease 0.05s; - opacity:1; -} - -.ace_underline { - text-decoration: underline; -} - -.ace_bold { - font-weight: bold; -} - -.ace_nobold .ace_bold { - font-weight: normal; -} - -.ace_italic { - font-style: italic; -} - - -.ace_error-marker { - background-color: rgba(255, 0, 0,0.2); - position: absolute; - z-index: 9; -} - -.ace_highlight-marker { - background-color: rgba(255, 255, 0,0.2); - position: absolute; - z-index: 8; -} +//--- Modules +// Subprojects that allows further modularization + +//--- Global +// Global information that allow us to cascade information +// Font, Color variables, etc +@import "global/fonts"; + +//--- Layout +// Abstract and related to the positioning of global elements +@import "layout/layout"; + +//--- Theme +// Shared functionality between pages +// Buttons, Inputs, h1, h2, etc +@import "theme/theme"; + +//--- Components +// Shared pieces or blocks on pages +// Forms, navigation +@import "components/ace"; + +//--- Partials +// Unique differences on a per partial basis + +//--- Vendors +// Third party styles +// Mainly for plugins diff --git a/app/styles/theme/_theme.scss b/app/styles/theme/_theme.scss new file mode 100644 index 0000000..4a938d7 --- /dev/null +++ b/app/styles/theme/_theme.scss @@ -0,0 +1,12 @@ +input[type=button]{ + background: none; + border: 1px solid #D5E9EC; + color: #D5E9EC; + border-radius: 3px; + margin-right: 15px; +} + +//todo: style more appropriately +input[type=button]:nth-child(3n - 1){ + margin-left: 45px; +} diff --git a/gulpfile.js b/gulpfile.js index b136832..5b571d8 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -143,4 +143,4 @@ gulp.task('watch', ['html', 'bundle', 'serve'], function () { gulp.task('build', ['html', 'bundle', 'images', 'extras']); // Default task -gulp.task('default', ['clean', 'build', 'jest' ]); +gulp.task('default', ['clean', 'build', 'watch', 'serve' ]); //'jest', diff --git a/package.json b/package.json index f381fc3..3c0f662 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,15 @@ "name": "followcodes", "version": "0.0.0", "dependencies": { - "brace": "^0.4.1" + "body-parser": "^1.12.0", + "brace": "^0.4.1", + "cookie-parser": "^1.3.4", + "ejs": "^2.3.1", + "es6-promise": "^2.0.1", + "express": "^4.12.2", + "lodash": "^3.3.1", + "path": "^0.11.14", + "react": "latest" }, "devDependencies": { "browserify-shim": "^3.8.0", @@ -21,7 +29,7 @@ "gulp-util": "~3.0.1", "gulp-webserver": "latest", "jest": "latest", - "react": "latest", + "node-jsx": "^0.12.4", "reactify": "latest", "vinyl-source-stream": "^1.0.0", "watchify": "~2.1" diff --git a/server.js b/server.js new file mode 100644 index 0000000..57de1ec --- /dev/null +++ b/server.js @@ -0,0 +1,35 @@ +// server.js + +var express = require('express'), + path = require('path'); + +var app = express(); +// Include the JSX transpiler +require("node-jsx").install(); + +var port = 5535; +var bodyParser = require('body-parser'); + +app.use(bodyParser.json()); // get information from html forms +app.use(bodyParser.urlencoded({ + extended: true +})); + +// Make dist directory publicly accessible +app.use(express.static(path.join(__dirname, 'dist'))); + +app.set('views', path.join(__dirname, 'views')); +app.set('view engine', 'ejs'); // set up ejs for templating + +// Set up Routes for the application +require('./app/routes/coreRoutes.js')(app); + +//Route not found -- Set 404 +app.get('*', function(req, res) { + res.json({ + "route": "Sorry this page does not exist!" + }); +}); + +app.listen(port); +console.log('Server is Up and Running at Port : ' + port); diff --git a/views/index.ejs b/views/index.ejs new file mode 100644 index 0000000..07439fa --- /dev/null +++ b/views/index.ejs @@ -0,0 +1,41 @@ + + + + + + + + Follow.Codes + + + + + + + + + + +
+ <%- reactOutput %> +
+ + + + + + + + + + +