diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/README.md b/README.md index 96e832f..870d664 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,6 @@ -# electron-quick-start +# xkcd-simplewriter -**Clone and run for a quick way to see an Electron in action.** +![](https://blogdotxkcddotcom.files.wordpress.com/2015/09/blag_words2.png) -This is a minimal Electron application based on the [Quick Start Guide](http://electron.atom.io/docs/latest/tutorial/quick-start) within the Electron documentation. +A desktop app version of the [XKCD simplewriter](http://xkcd.com/simplewriter/) -A basic Electron application needs just these files: - -- `index.html` - A web page to render. -- `main.js` - Starts the app and creates a browser window to render HTML. -- `package.json` - Points to the app's main file and lists its details and dependencies. - -You can learn more about each of these components within the [Quick Start Guide](http://electron.atom.io/docs/latest/tutorial/quick-start). - -## To Use - -To clone and run this repository you'll need [Git](https://git-scm.com) and [Node.js](https://nodejs.org/en/download/) (which comes with [npm](http://npmjs.com)) installed on your computer. From your command line: - -```bash -# Clone this repository -$ git clone https://github.com/atom/electron-quick-start -# Go into the repository -$ cd electron-quick-start -# Install dependencies and run the app -$ npm install && npm start -``` - -Learn more about Electron and its API in the [documentation](http://electron.atom.io/docs/latest). - -#### License [MIT](LICENSE.md) diff --git a/index.html b/index.html index 726aecb..fb400a6 100644 --- a/index.html +++ b/index.html @@ -1,9 +1,9 @@ - - + + SimpleWriter

upwriter

@@ -15,23 +15,17 @@

upwriter

+ diff --git a/main.css b/main.css index cac98f4..95461bf 100644 --- a/main.css +++ b/main.css @@ -6,6 +6,7 @@ body { line-height: 36px; font-family: monospace; } + #editor-wrapper { margin: 0; position: absolute; @@ -15,6 +16,7 @@ body { right: 0; background: #F45C1A; } + #editor { margin: 0; position: absolute; @@ -28,20 +30,25 @@ body { color: #444; -webkit-transition: bottom .4s ease-in; } + .ace_gutter { display: none } + .ace_disallowed, .ace_disallowed + .ace_suffix { color: #F45C1A } + h1 { visibility: hidden } + #erroneous { position: absolute; bottom: 0; } + #erroneous a { color: #D0EACC; display: inline-block; diff --git a/main.js b/main.js index f5755a2..275aec2 100644 --- a/main.js +++ b/main.js @@ -1,9 +1,12 @@ 'use strict'; +const fs = require('fs'); const electron = require('electron'); const app = electron.app; const BrowserWindow = electron.BrowserWindow; // Module to create native browser window. -const ipcMain = electron.ipcMain; +const dialog = electron.dialog; +const Menu = electron.Menu; +const MenuItem = electron.MenuItem; // Report crashes to our server. electron.crashReporter.start(); @@ -16,8 +19,7 @@ function createMainWindow() { // Create the browser window. const win = new BrowserWindow({ width: 800, - height: 600, - title: 'simplewriter' + height: 600 }); // and load the index.html of the app. @@ -30,10 +32,148 @@ function createMainWindow() { // when you should delete the corresponding element. mainWindow = null; }); - return win; } +function setMenu() { + let template = [ + { + label: 'File', + submenu: [ + { + label: 'Open..', + accelerator: 'CmdOrCtrl+O', + click(item, focusedWindow) { + dialog.showOpenDialog(fileNames => { + if(fileNames === undefined) return; + let fileName = fileNames[0]; + fs.readFile(fileName, 'utf-8', (err, data) => { + mainWindow.webContents.send('setText', data); + }); + }); + } + }, + { + label: 'Save As..', + accelerator: 'CmdOrCtrl+S', + click(item, focusedWindow) { + dialog.showSaveDialog(fileName => { + if(fileName === undefined) return; + let arg = mainWindow.webContents.send('getText', ''); + fs.writeFile(fileName, arg, err => {}); + }); + } + } + ] + }, + { + label: 'View', + submenu: [ + { + label: 'Reload', + accelerator: 'CmdOrCtrl+R', + click(item, focusedWindow) { + if(focusedWindow) focusedWindow.reload(); + } + }, + { + label: 'Toggle Full Screen', + accelerator: (() => (process.platform == 'darwin') ? 'Ctrl+Command+F' : 'F11')(), + click(item, focusedWin) { + if(focusedWin) focusedWin.setFullScreen(!focusedWin.isFullScreen()); + } + }, + { + label: 'Toggle Developer Tools', + accelerator: (() => (process.platform == 'darwin') ? 'Alt+Command+I' : 'Ctrl+Shift+I')(), + click(item, focusedWindow) { + if(focusedWindow) focusedWindow.toggleDevTools(); + } + }, + ] + }, + { + label: 'Window', + role: 'window', + submenu: [ + { + label: 'Minimize', + accelerator: 'CmdOrCtrl+M', + role: 'minimize' + }, + { + label: 'Close', + accelerator: 'CmdOrCtrl+W', + role: 'close' + }, + ] + }, + { + label: 'Help', + role: 'help', + submenu: [ + { + label: 'Learn More', + click() { + electron.shell.openExternal('http://electron.atom.io'); + } + }, + ] + }, + ]; + + if (process.platform == 'darwin') { + let name = app.getName(); + template.unshift({ + label: name, + submenu: [ + { + label: `About ${name}`, + role: 'about' + }, + { + type: 'separator' + }, + { + label: `Hide ${name}`, + accelerator: 'Command+H', + role: 'hide' + }, + { + label: 'Hide Others', + accelerator: 'Command+Shift+H', + role: 'hideothers' + }, + { + label: 'Show All', + role: 'unhide' + }, + { + type: 'separator' + }, + { + label: 'Quit', + accelerator: 'Command+Q', + click() { app.quit(); } + }, + ] + }); + // Window menu. + template[3].submenu.push( + { + type: 'separator' + }, + { + label: 'Bring All to Front', + role: 'front' + } + ); + } + + let menu = Menu.buildFromTemplate(template); + Menu.setApplicationMenu(menu); +} + // Quit when all windows are closed. app.on('window-all-closed', () => { // On OS X it is common for applications and their menu bar @@ -51,4 +191,5 @@ app.on('activate', () => { app.on('ready', () => { mainWindow = createMainWindow(); -}); + setMenu(); +}); \ No newline at end of file diff --git a/mode-upwriter.js b/mode-upwriter.js index 4475162..7b305b9 100644 --- a/mode-upwriter.js +++ b/mode-upwriter.js @@ -1,97 +1,93 @@ define("ace/mode/upwriter_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) { -"use strict"; + "use strict"; -var oop = require("../lib/oop"); -var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; - -var UpwriterHighlightRules = function() { + const oop = require("../lib/oop"); + const TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + const UpwriterHighlightRules = function() { // regexp must not have capturing parentheses. Use (?:) instead. // regexps are ordered -> the first match is used - - this.$rules = - { - "start": [ + this.$rules = { + "start": [ { - "token" : "suffix", - "regex" : "['’][a-zA-Z]+" + "token" : "suffix", + "regex" : "['’][a-zA-Z]+" }, { - "token" : "allowed", - "regex" : "\\b(?:" + window.__WORDS + ")\\b", - "caseInsensitive": true + "token" : "allowed", + "regex" : "\\b(?:" + window.__WORDS + ")\\b", + "caseInsensitive": true }, { - "token" : "disallowed", - "regex" : "[a-zA-Z]+" + "token" : "disallowed", + "regex" : "[a-zA-Z]+" } - ] -} - -}; + ] + } + }; -oop.inherits(UpwriterHighlightRules, TextHighlightRules); + oop.inherits(UpwriterHighlightRules, TextHighlightRules); -exports.UpwriterHighlightRules = UpwriterHighlightRules; + exports.UpwriterHighlightRules = UpwriterHighlightRules; }); define("ace/mode/upwriter",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/upwriter_highlight_rules"], function(require, exports, module) { -"use strict"; + "use strict"; -var oop = require("../lib/oop"); -var TextMode = require("./text").Mode; -var UpwriterHighlightRules = require("./upwriter_highlight_rules").UpwriterHighlightRules; + const oop = require("../lib/oop"); + const TextMode = require("./text").Mode; + const UpwriterHighlightRules = require("./upwriter_highlight_rules").UpwriterHighlightRules; -var Mode = function() { + let Mode = function() { this.HighlightRules = UpwriterHighlightRules; -}; -oop.inherits(Mode, TextMode); - -Mode.prototype.$id = "ace/mode/upwriter"; - -// // optimized, hence ugly for loops -// Mode.prototype.getFirstDisallowed = function(editor) { -// var session = editor.getSession(); -// var i, j, line, first, lines = session.doc.getAllLines(); -// outer: for (i = 0; i < lines.length; i++) { -// line = session.getTokens(i); -// for (j = 0; j < line.length; j++) { -// if (line[j].type === "disallowed") { -// first = line[j].value; -// break outer; -// } -// } -// } -// return first; -// }; - -Mode.prototype.getDisallowed = function (editor) { - var session = editor.getSession(); - return Object.keys(Array.apply(this, Array(session.doc.getAllLines().length)).reduce(function(m, _nil, i) { - session.getTokens(i).forEach(function(token) { - if (token.type === "disallowed") m[token.value] = true; - }); - return m; - }, {})); -} - - -Mode.prototype.onRecalculateAllowed = function(editor, cb) { - var self = this; - editor.getSession().on('change', debounce(function() { - cb(self.getDisallowed(editor)); - }, 500)); -}; - -exports.Mode = Mode; - -function debounce(fn, delay) { - return function() { - fn.args = arguments; - fn.timeout_id && clearTimeout(fn.timeout_id); - fn.timeout_id = setTimeout(function() { return fn.apply(fn, fn.args); }, delay); }; -} + oop.inherits(Mode, TextMode); + + Mode.prototype.$id = "ace/mode/upwriter"; + + // // optimized, hence ugly for loops + // Mode.prototype.getFirstDisallowed = function(editor) { + // var session = editor.getSession(); + // var i, j, line, first, lines = session.doc.getAllLines(); + // outer: for (i = 0; i < lines.length; i++) { + // line = session.getTokens(i); + // for (j = 0; j < line.length; j++) { + // if (line[j].type === "disallowed") { + // first = line[j].value; + // break outer; + // } + // } + // } + // return first; + // }; + + Mode.prototype.getDisallowed = function(editor) { + let session = editor.getSession(); + return Object.keys(Array.apply(this, Array(session.doc.getAllLines().length)).reduce(function(m, _nil, i) { + session.getTokens(i).forEach(function(token) { + if (token.type === "disallowed") m[token.value] = true; + }); + return m; + }, {})); + }; + + + Mode.prototype.onRecalculateAllowed = function(editor, cb) { + let self = this; + editor.getSession().on('change', debounce(function() { + cb(self.getDisallowed(editor)); + }, 500)); + }; + + exports.Mode = Mode; + + function debounce(fn, delay) { + return function() { + fn.args = arguments; + fn.timeout_id && clearTimeout(fn.timeout_id); + fn.timeout_id = setTimeout(function() { return fn.apply(fn, fn.args); }, delay); + }; + } }); \ No newline at end of file diff --git a/package.json b/package.json index 3dcf3c2..e8f5438 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { "name": "xkcd-simplewriter", + "productName": "SimpleWriter", "version": "1.0.0", "description": "An Electron App of the XKCD Simple Writer", "main": "main.js", @@ -27,5 +28,6 @@ "homepage": "https://github.com/tcyrus/xkcd-simplewriter#readme", "devDependencies": { "electron-prebuilt": "^0.34.0" - } + }, + "dependencies": {} }