├── start.cmd ├── icon.png ├── edit.cmd ├── favicon.ico ├── screenshot.png ├── app ├── images │ ├── livewire-logo.png │ └── diagonal-lines.png ├── modules │ ├── results │ │ ├── renderTransformer │ │ │ ├── afterRenderRules.js │ │ │ ├── index.js │ │ │ └── beforeRenderRules.js │ │ ├── asciidoc-worker.js │ │ ├── markdown.js │ │ ├── contentInspector │ │ │ └── index.js │ │ ├── pick-inline-macro.js │ │ ├── asciidoc.js │ │ └── index.js │ ├── config │ │ ├── index.js │ │ ├── packageJsonReader.js │ │ ├── docsConfig.js │ │ └── productConfigurationReader.js │ ├── menu │ │ ├── file.js │ │ ├── view.js │ │ ├── help.js │ │ ├── context.js │ │ └── index.js │ ├── formats │ │ ├── grammar │ │ │ └── asciidoc │ │ │ │ └── include │ │ │ │ └── index.js │ │ ├── markdown.js │ │ ├── asciidoc.js │ │ └── index.js │ ├── editor │ │ ├── fileNameCleaner.js │ │ ├── spellcheck │ │ │ ├── dictionaryProvider.js │ │ │ ├── customDictionary.js │ │ │ ├── defaultDictionary.js │ │ │ ├── index.js │ │ │ └── shouldCheckWord.js │ │ ├── dialogs │ │ │ ├── metadata │ │ │ │ ├── template.html │ │ │ │ └── index.js │ │ │ ├── links │ │ │ │ ├── template.html │ │ │ │ └── index.js │ │ │ ├── images │ │ │ │ └── index.js │ │ │ └── index.js │ │ ├── clipboard.js │ │ ├── buildflags.js │ │ ├── formatting.js │ │ └── index.js │ ├── help │ │ ├── shortcuts.js │ │ └── index.js │ ├── global │ │ ├── drag-drop-open.js │ │ └── index.js │ ├── persistence │ │ ├── saveAsHtml-before-save-rules.js │ │ └── index.js │ ├── toolbars │ │ ├── formatting │ │ │ └── index.js │ │ └── tabs │ │ │ └── index.js │ ├── buildFlags │ │ └── index.js │ ├── messenger │ │ └── index.js │ ├── files │ │ ├── metadata-cleanup-rules.js │ │ └── index.js │ ├── dialogs │ │ └── index.js │ └── footer │ │ └── index.js ├── vendor │ ├── typo │ │ └── dictionaries │ │ │ └── en_US │ │ │ ├── en_US.dic │ │ │ ├── README.md │ │ │ └── en_US.aff │ └── asciidoctor.js │ │ └── asciidoctor-pick-inline-macro.js ├── bower.json ├── config.js ├── package.json ├── data │ ├── index.js │ └── metadata │ │ ├── tags.json │ │ └── controls.json ├── index.js ├── index.html ├── index.css └── index.less ├── .gitignore ├── .vscode ├── tasks.json └── launch.json ├── gulpfile.js ├── main-process ├── context-menus │ ├── addToDictionary.js │ ├── spellingSuggestions.js │ └── index.js └── application-menus │ └── index.js ├── package.json ├── index.js └── readme.md /start.cmd: -------------------------------------------------------------------------------- 1 | REM :: Starts Livewire via npm 2 | 3 | npm start -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Infragistics/livewire/HEAD/icon.png -------------------------------------------------------------------------------- /edit.cmd: -------------------------------------------------------------------------------- 1 | REM :: Opens project in Visual Studio Code 2 | 3 | code . 4 | exit -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Infragistics/livewire/HEAD/favicon.ico -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Infragistics/livewire/HEAD/screenshot.png -------------------------------------------------------------------------------- /app/images/livewire-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Infragistics/livewire/HEAD/app/images/livewire-logo.png -------------------------------------------------------------------------------- /app/images/diagonal-lines.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Infragistics/livewire/HEAD/app/images/diagonal-lines.png -------------------------------------------------------------------------------- /app/modules/results/renderTransformer/afterRenderRules.js: -------------------------------------------------------------------------------- 1 | module = module.exports; 2 | 3 | module.rules = [ 4 | 5 | ]; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | bower_components 3 | releases 4 | presentation-commands 5 | _installers 6 | _debug.js 7 | version.json -------------------------------------------------------------------------------- /app/vendor/typo/dictionaries/en_US/en_US.dic: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Infragistics/livewire/HEAD/app/vendor/typo/dictionaries/en_US/en_US.dic -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "command": "gulp", 4 | "isShellCommand": true, 5 | "args": [ 6 | "--no-color" 7 | ], 8 | "tasks": [] 9 | } -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp'); 2 | const less = require('gulp-less'); 3 | 4 | gulp.task('less', function () { 5 | return gulp.src('./app/index.less') 6 | .pipe(less()) 7 | .pipe(gulp.dest('./app')); 8 | }); -------------------------------------------------------------------------------- /app/vendor/typo/dictionaries/en_US/README.md: -------------------------------------------------------------------------------- 1 | 2006-02-07 release. 2 | 3 | --- 4 | 5 | This dictionary is based on a subset of the original English wordlist created by Kevin Atkinson for Pspell and Aspell and thus is covered by his original LGPL license. The affix file is a heavily modified version of the original english.aff file which was released as part of Geoff Kuenning's Ispell and as such is covered by his BSD license. 6 | 7 | Thanks to both authors for their wonderful work. -------------------------------------------------------------------------------- /app/modules/config/index.js: -------------------------------------------------------------------------------- 1 | /*jslint node: true */ 2 | /*jshint esversion: 6 */ 3 | 4 | const path = require('path'); 5 | const { remote } = require('electron'); 6 | 7 | let config = null; 8 | 9 | var docsConfig = require('./docsConfig'); 10 | 11 | module.exports.get = function () { 12 | 13 | if (config === null) { 14 | config = require(path.resolve(__dirname, '../../config.js')); 15 | config.userDataPath = remote.app.getPath('userData'); 16 | docsConfig.init(config); 17 | } 18 | 19 | return config; 20 | }; -------------------------------------------------------------------------------- /app/modules/results/renderTransformer/index.js: -------------------------------------------------------------------------------- 1 | module = module.exports; 2 | 3 | const path = require('path'); 4 | const beforeRenderRules = require(path.resolve(__dirname, './beforeRenderRules.js')); 5 | const afterRenderRules = require(path.resolve(__dirname, './afterRenderRules.js')); 6 | 7 | module.beforeRender = (source, productConfiguration) => { 8 | return beforeRenderRules.apply(source, productConfiguration); 9 | }; 10 | 11 | module.afterRender = (source, productConfiguration) => { 12 | return source; 13 | }; -------------------------------------------------------------------------------- /app/modules/menu/file.js: -------------------------------------------------------------------------------- 1 | 2 | const path = require('path'); 3 | const { remote } = require('electron'); 4 | const app = remote.app; 5 | const messenger = require(path.resolve(__dirname, '../messenger')); 6 | 7 | // most of the file menu collaborates directly with the ACE editor, 8 | // therefore you will find the rest of the implementation in 9 | // modules/editor/persistence.js 10 | 11 | messenger.subscribe.menu('quit', function () { 12 | let quit = confirm('Are you sure you want to close Livewire?'); 13 | if (quit) { 14 | app.quit(); 15 | } 16 | }); -------------------------------------------------------------------------------- /main-process/context-menus/addToDictionary.js: -------------------------------------------------------------------------------- 1 | /*jslint node: true */ 2 | /*jshint esversion: 6 */ 3 | 4 | const { MenuItem } = require('electron'); 5 | 6 | module.exports.create = (values, menu, sender) => { 7 | menu.insert(0, new MenuItem({ type: 'separator' })); 8 | 9 | values.forEach((item) => { 10 | menu.insert(0, new MenuItem({ 11 | label: item, 12 | click: () => { 13 | sender.send('editor-context-menu-add-to-dictionary', { }); 14 | } 15 | })); 16 | }); 17 | 18 | return menu; 19 | }; -------------------------------------------------------------------------------- /main-process/context-menus/spellingSuggestions.js: -------------------------------------------------------------------------------- 1 | /*jslint node: true */ 2 | /*jshint esversion: 6 */ 3 | 4 | const { MenuItem } = require('electron'); 5 | 6 | module.exports.create = (values, menu, sender) => { 7 | menu.insert(0, new MenuItem({ type: 'separator' })); 8 | 9 | values.forEach((suggestion) => { 10 | menu.insert(0, new MenuItem({ 11 | label: suggestion, 12 | click: () => { 13 | sender.send('editor-context-menu-replace-mispelling', { replacementWord: suggestion }); 14 | } 15 | })); 16 | }); 17 | 18 | return menu; 19 | }; -------------------------------------------------------------------------------- /app/modules/config/packageJsonReader.js: -------------------------------------------------------------------------------- 1 | module = module.exports; 2 | 3 | const path = require('path'); 4 | const fs = require('fs'); 5 | 6 | var config = null; 7 | 8 | module.get = () => { 9 | return new Promise((success, reject) => { 10 | if(config) { 11 | success(config); 12 | } else { 13 | fs.readFile(path.resolve(__dirname, '../../../package.json'), 'utf8', (err, data) => { 14 | if(err) { 15 | reject(); 16 | } else { 17 | config = JSON.parse(data); 18 | success(config); 19 | } 20 | }); 21 | } 22 | }); 23 | }; -------------------------------------------------------------------------------- /app/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "electric-mark", 3 | "main": "index.js", 4 | "version": "0.0.1", 5 | "authors": [ 6 | "Craig Shoemaker " 7 | ], 8 | "description": "Electron Markdown editor", 9 | "keywords": [ 10 | "electron", 11 | "markdown" 12 | ], 13 | "license": "MIT", 14 | "ignore": [ 15 | "**/.*", 16 | "node_modules", 17 | "bower_components", 18 | "test", 19 | "tests" 20 | ], 21 | "dependencies": { 22 | "ace-min-noconflict": "~1.1.9", 23 | "bootstrap": "~3.3.5", 24 | "font-awesome": "~4.4.0", 25 | "postal.js": "2.0.4", 26 | "asciidoctor.js": "1.5.2", 27 | "typeahead.js": "~0.11.1" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/config.js: -------------------------------------------------------------------------------- 1 | /*jslint node: true */ 2 | /*jshint esversion: 6 */ 3 | 4 | let config = { 5 | urls: { 6 | repository : 'https://github.com/infragistics/livewire', 7 | installers : 'https://github.com/infragistics/livewire/wiki/installers', 8 | version : 'http://download.infragistics.com/users/livewire/version.json' 9 | }, 10 | defaultFormat: 'asciidoc', 11 | cultures: { 12 | ja: { 13 | defaultTOCLabel: 'このトピックの内容', 14 | test: (source) => /[ぁ-ゔゞァ-・ヽヾ゛゜ー]/g.test(source) 15 | }, 16 | en: { 17 | defaultTOCLabel: 'In This Topic', 18 | test: (source) => !config.cultures.ja.test(source) 19 | }, 20 | detect: (source) => config.cultures.ja.test(source) ? 'ja' : 'en' 21 | } 22 | }; 23 | 24 | module.exports = config; -------------------------------------------------------------------------------- /app/modules/formats/grammar/asciidoc/include/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const INCLUDE_SUPPORT_DEPTH = 4; 5 | 6 | var includeFile = (asciidoc, sourceFolder) => { 7 | var filePath; 8 | 9 | asciidoc = asciidoc.replace(/include::(.*?)\[\]/gi, (match, g) => { 10 | filePath = path.resolve(sourceFolder, g); 11 | if(fs.existsSync(filePath)){ 12 | match = fs.readFileSync(filePath, 'utf8').trim(); 13 | } 14 | return match; 15 | }); 16 | 17 | return asciidoc; 18 | }; 19 | 20 | module.exports.apply = (asciidoc, sourceFolder) => { 21 | 22 | for (var i = 0; i < INCLUDE_SUPPORT_DEPTH; i++) { 23 | asciidoc = includeFile(asciidoc, sourceFolder); 24 | } 25 | 26 | return asciidoc; 27 | }; -------------------------------------------------------------------------------- /app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "livewire-renderer", 3 | "version": "0.0.1", 4 | "description": "", 5 | "main": "../index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "echo Do not run \"npm start\" from this location. Move up to the root directory first.", 9 | "postinstall": "bower install" 10 | }, 11 | "keywords": [ 12 | "asciidoc", 13 | "electron", 14 | "markdown" 15 | ], 16 | "author": "Craig Shoemaker ", 17 | "license": "MIT", 18 | "devDependencies": { 19 | "bower": "^1.8.0" 20 | }, 21 | "dependencies": { 22 | "asciidoctor.js": "^1.5.2", 23 | "cheerio": "^0.19.0", 24 | "lodash": "4.17.4", 25 | "marked": "^0.3.6", 26 | "node-uuid": "^1.4.3", 27 | "xml2js": "^0.4.17" 28 | } 29 | } -------------------------------------------------------------------------------- /app/modules/editor/fileNameCleaner.js: -------------------------------------------------------------------------------- 1 | /* Copied from Tripwire */ 2 | module = module.exports; 3 | 4 | var replaceUnderscoreWithDash = function(name){ 5 | return name.replace(/_/g,'-'); 6 | }; 7 | 8 | var replaceSpaceWithDash = function(name){ 9 | return name.replace(/\s/g,'-'); 10 | }; 11 | 12 | var stripOrderingNumbers = function(name){ 13 | 14 | var nameParts = name.split('_'); 15 | 16 | if(nameParts.length > 0 && !isNaN(nameParts[0])){ 17 | nameParts.shift(); 18 | name = nameParts.join('_'); 19 | } 20 | 21 | if(name[0] === '~'){ 22 | name = name.substring(1); 23 | } 24 | 25 | return name; 26 | }; 27 | 28 | module.clean = function(fileName){ 29 | fileName = stripOrderingNumbers(fileName); 30 | fileName = replaceSpaceWithDash(fileName); 31 | fileName = replaceUnderscoreWithDash(fileName); 32 | return fileName; 33 | }; -------------------------------------------------------------------------------- /app/modules/menu/view.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const { remote } = require('electron'); 3 | const app = remote.app; 4 | const messenger = require(path.resolve(__dirname, '../messenger')); 5 | 6 | var handlers = { 7 | 8 | quit: function (data, envelope) { 9 | var quit = confirm('Are you sure you want to close this application?'); 10 | if (quit) { 11 | app.quit(); 12 | } 13 | }, 14 | 15 | reload: function () { 16 | remote.getCurrentWindow().reload(); 17 | }, 18 | 19 | devToolsToggle: function () { 20 | remote.getCurrentWindow().toggleDevTools(); 21 | } 22 | }; 23 | 24 | messenger.subscribe.menu('reload', handlers.reload); 25 | messenger.subscribe.menu('devToolsToggle', handlers.devToolsToggle); 26 | messenger.subscribe.menu('fullScreenToggle', handlers.fullScreenToggle); 27 | messenger.subscribe.menu('autoHideMenu', handlers.autoHideMenu); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "livewire", 3 | "version": "1.2.0", 4 | "description": "Simple Web Content Editor", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "electron .", 9 | "release-win64": "electron-packager . Livewire --platform=win32 --arch=x64 --out=../releases", 10 | "release": "electron-packager . Livewire --platform=all --arch=all --out=../releases", 11 | "postinstall": "cd app && npm install" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/infragistics/livewire.git" 16 | }, 17 | "keywords": [ 18 | "asciidoc", 19 | "electron", 20 | "markdown" 21 | ], 22 | "author": "Craig Shoemaker ", 23 | "license": "MIT", 24 | "devDependencies": { 25 | "electron": "^1.4.14", 26 | "electron-packager": "^7.0.0", 27 | "gulp": "^3.9.1", 28 | "gulp-less": "^3.1.0" 29 | } 30 | } -------------------------------------------------------------------------------- /app/modules/editor/spellcheck/dictionaryProvider.js: -------------------------------------------------------------------------------- 1 | /*jslint node: true */ 2 | /*jshint esversion: 6 */ 3 | /* global Typo */ 4 | 5 | const path = require('path') 6 | , fs = require('fs'); 7 | 8 | module.exports.get = (lang) => { 9 | return new Promise((resolve, reject) => { 10 | 11 | const filePaths = { 12 | dictionary: path.resolve(__dirname, `../../../vendor/typo/dictionaries/en_US/${lang}.dic`), 13 | aff: path.resolve(__dirname, `../../../vendor/typo/dictionaries/en_US/${lang}.aff`) 14 | }; 15 | 16 | fs.readFile(filePaths.dictionary, 'utf8', (dictionaryError, dictionaryData) => { 17 | if(dictionaryError) reject(dictionaryError); 18 | 19 | fs.readFile(filePaths.aff, 'utf8', (affError, affData) => { 20 | if(affError) reject(affError); 21 | 22 | const typo = new Typo(lang, affData, dictionaryData); 23 | resolve(typo); 24 | }); 25 | }); 26 | }); 27 | }; -------------------------------------------------------------------------------- /app/modules/results/asciidoc-worker.js: -------------------------------------------------------------------------------- 1 | /* global Opal */ 2 | 3 | /* 4 | The AsciiDoctor.js conversion must be in this web worker because 5 | the ways that AsciiDoctor.js (likely the Opal objects) change 6 | global prototypes adversely affect the Ace editor's performance. 7 | 8 | By splitting the conversion process into this worker, the 9 | execution is in a separate context (with separate globals) 10 | and does not degrade the performance of the editor. 11 | */ 12 | 13 | importScripts('../../bower_components/asciidoctor.js/dist/asciidoctor-all.js'); 14 | 15 | var options = Opal.hash2( 16 | ['doctype', 'attributes'], 17 | { 18 | doctype: 'article', // inline 19 | attributes: ['showtitle'] 20 | }); 21 | 22 | var handlers = { 23 | message: function(e){ 24 | if(e.data && e.data.source && e.data.source.length > 0){ 25 | var html = Opal.Asciidoctor.$convert(e.data.source, options); 26 | postMessage({html: html }); 27 | } 28 | } 29 | }; 30 | 31 | addEventListener('message', handlers.message, true); -------------------------------------------------------------------------------- /app/modules/help/shortcuts.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | { "shortcut": "new AsciiDoc", "description": "CmdOrCtrl + n" }, 3 | { "shortcut": "new Markdown", "description": "CmdOrCtrl + shift + n" }, 4 | { "shortcut": "header 1", "description": "CmdOrCtrl + 1" }, 5 | { "shortcut": "header 2", "description": "CmdOrCtrl + 2" }, 6 | { "shortcut": "header 3", "description": "CmdOrCtrl + 3" }, 7 | { "shortcut": "bold", "description": "CmdOrCtrl + b" }, 8 | { "shortcut": "italic", "description": "CmdOrCtrl + i" }, 9 | { "shortcut": "image", "description": "CmdOrCtrl + shift + b" }, 10 | { "shortcut": "link", "description": "CmdOrCtrl + k" }, 11 | { "shortcut": "inline code", "description": "CmdOrCtrl + d" }, 12 | { "shortcut": "quote", "description": "CmdOrCtrl + /" }, 13 | { "shortcut": "unordered list item", "description": "CmdOrCtrl + ." }, 14 | { "shortcut": "ordered list item", "description": "CmdOrCtrl + ," }, 15 | { "shortcut": "horizontal rule", "description": "CmdOrCtrl + -" }, 16 | { "shortcut": "save", "description": "CmdOrCtrl + s" }, 17 | { "shortcut": "save as", "description": "CmdOrCtrl + shift + s" }, 18 | { "shortcut": "save as HTML", "description": "CmdOrCtrl + shift + h" } 19 | ]; -------------------------------------------------------------------------------- /app/modules/editor/dialogs/metadata/template.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/modules/menu/help.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const messenger = require(path.resolve(__dirname, '../messenger')); 3 | const { shell } = require('electron'); 4 | const config = require(path.resolve(__dirname, '../config')).get(); 5 | const dialogs = require('../dialogs'); 6 | const packageJsonReader = require(path.resolve(__dirname, '../config/packageJsonReader.js')); 7 | 8 | let handlers = { 9 | issues: function () { 10 | shell.openExternal(config.urls.repository + '/issues'); 11 | }, 12 | about: function () { 13 | 14 | let version = null; 15 | const fs = require('fs'); 16 | 17 | let showAboutDialog = (version) => { 18 | dialogs.messageBox({ 19 | title: 'About', 20 | message: `Livewire 21 | 22 | 23 | Version: ${version} 24 | GitHub: http://github.com/infragistics/livewire` 25 | }); 26 | }; 27 | 28 | if(!version) { 29 | packageJsonReader.get().then((config) => { 30 | version = config.version; 31 | showAboutDialog(version); 32 | }); 33 | } else { 34 | showAboutDialog(version) 35 | } 36 | } 37 | }; 38 | 39 | messenger.subscribe.menu('issues', handlers.issues); 40 | messenger.subscribe.menu('about', handlers.about); -------------------------------------------------------------------------------- /app/modules/results/markdown.js: -------------------------------------------------------------------------------- 1 | module = module.exports; 2 | 3 | var marked = require('marked'); 4 | var renderer = new marked.Renderer(); 5 | var basePath = ''; 6 | var path = require('path'); 7 | var messenger = require(path.resolve(__dirname, '../messenger')); 8 | 9 | messenger.subscribe.file('pathChanged', function (data, envelope) { 10 | basePath = data.basePath; 11 | }); 12 | 13 | renderer.table = function (header, body) { 14 | return '\n' + header + '\n' + body + '\n
'; 15 | }; 16 | 17 | renderer.image = function (href, title, text) { 18 | var value = '[image: ' + href + ']'; 19 | 20 | if (basePath.length > 0) { 21 | value = ''; 27 | } 28 | 29 | return value; 30 | }; 31 | 32 | marked.setOptions({ 33 | renderer: renderer, 34 | gfm: true, 35 | tables: true 36 | }); 37 | 38 | var _renderer = function(content, callback){ 39 | var html = marked(content); 40 | callback({ html: html }); 41 | }; 42 | 43 | module.get = function (initialBasePath) { 44 | basePath = initialBasePath; 45 | return _renderer; 46 | }; -------------------------------------------------------------------------------- /app/modules/editor/clipboard.js: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | module = module.exports; 4 | 5 | const { clipboard } = require('electron'); 6 | 7 | var path = require('path'); 8 | var messenger = require(path.resolve(__dirname, '../messenger')); 9 | var editor = null; 10 | var key = 'editor.copied.text' 11 | 12 | module.init = function (editorInstance) { 13 | editor = editorInstance; 14 | }; 15 | 16 | var copySelectedText = function () { 17 | var range = editor.getSelectionRange(); 18 | var text = editor.session.getTextRange(range).replace(/\n/g, "\r\n"); //"\r\n" will make sure new lines are handled across all operating systems and editors 19 | clipboard.writeText(text, key); 20 | return range; 21 | }; 22 | 23 | var handlers = { 24 | 25 | cut: function (data, envelope) { 26 | var range = copySelectedText(); 27 | editor.getSession().remove(range); 28 | }, 29 | 30 | copy: function (data, envelope) { 31 | copySelectedText(); 32 | }, 33 | 34 | paste: function (data, envelope) { 35 | var text = clipboard.readText(key); 36 | editor.insert(text); 37 | } 38 | }; 39 | 40 | messenger.subscribe.contextMenu('cut', handlers.cut); 41 | messenger.subscribe.contextMenu('copy', handlers.copy); 42 | messenger.subscribe.contextMenu('paste', handlers.paste); 43 | -------------------------------------------------------------------------------- /app/modules/global/drag-drop-open.js: -------------------------------------------------------------------------------- 1 | /*jslint node: true */ 2 | /*jshint esversion: 6 */ 3 | 4 | const path = require('path'); 5 | const formats = require(path.resolve(__dirname, '../formats')); 6 | const messenger = require(path.resolve(__dirname, '../messenger')); 7 | 8 | window.ondragover = function(e) { 9 | e.preventDefault(); 10 | e.dataTransfer.dropEffect = 'link'; 11 | return false; 12 | }; 13 | 14 | window.ondrop = function(e) { 15 | e.preventDefault(); 16 | 17 | let filePaths = []; 18 | let supportedFileExtensions = formats.getSupportedFileExtensions(); 19 | 20 | let message = [].concat(supportedFileExtensions); // clone array 21 | message[message.length -1] = `or ${message[message.length -1]}`; 22 | message = message.join(', '); 23 | 24 | [].forEach.call(e.dataTransfer.files, (file) => { 25 | let extension = path.extname(file.name).replace('.', ''); 26 | if(supportedFileExtensions.includes(extension)) { 27 | filePaths.push(file.path); 28 | } else { 29 | alert(`Can not open file: '${file.name}'. 30 | 31 | The file type '${extension}' is unsupported. Please try to open files with the following extensions: ${message}.`); 32 | } 33 | }); 34 | 35 | if(filePaths.length > 0) { 36 | messenger.publish.menu('open', filePaths); 37 | } 38 | 39 | return false; 40 | }; -------------------------------------------------------------------------------- /app/modules/editor/dialogs/links/template.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /main-process/context-menus/index.js: -------------------------------------------------------------------------------- 1 | /*jslint node: true */ 2 | /*jshint esversion: 6 */ 3 | 4 | const { BrowserWindow, Menu, MenuItem, ipcMain } = require('electron'); 5 | const path = require('path'); 6 | 7 | const createDefaultMenu = (sender) => { 8 | let menu = new Menu(); 9 | 10 | menu.append(new MenuItem({ 11 | label: 'Cut', 12 | accelerator: 'CmdOrCtrl+Z', 13 | click: () => sender.send('editor-context-menu-cut') 14 | })); 15 | 16 | menu.append(new MenuItem({ 17 | label: 'Copy', 18 | accelerator: 'CmdOrCtrl+C', 19 | click: () => sender.send('editor-context-menu-copy') 20 | })); 21 | 22 | menu.append(new MenuItem({ 23 | label: 'Paste', 24 | accelerator: 'CmdOrCtrl+V', 25 | click: () => sender.send('editor-context-menu-paste') 26 | })); 27 | 28 | return menu; 29 | }; 30 | 31 | 32 | ipcMain.on('show-editor-context-menu', (e, args) => { 33 | const win = BrowserWindow.fromWebContents(e.sender); 34 | let menu = {}; 35 | 36 | if(args.dynamicMenus && args.dynamicMenus.length > 0) { 37 | let menus = args.dynamicMenus.reverse(); 38 | menu = createDefaultMenu(e.sender); 39 | menus.forEach((dynamicMenu) => { 40 | let _menu = require(path.resolve(__dirname, `./${dynamicMenu.name}.js`)); 41 | menu = _menu.create(dynamicMenu.values, menu, e.sender); 42 | }); 43 | } else { 44 | menu = createDefaultMenu(e.sender); 45 | } 46 | 47 | menu.popup(win); 48 | }); -------------------------------------------------------------------------------- /app/modules/results/contentInspector/index.js: -------------------------------------------------------------------------------- 1 | /*jslint node: true */ 2 | /*jshint esversion: 6 */ 3 | 4 | module = module.exports 5 | 6 | const path = require('path'); 7 | const messenger = require(path.resolve(__dirname, '../../messenger')); 8 | 9 | var _source = ''; 10 | var _fileInfo = {}; 11 | 12 | var inspectionRules = [ 13 | { 14 | description: 'detect Infragistics help documentation topic', 15 | apply: () => { 16 | var hasBuildFlags = false, hasMetadata = false, hasBuildVariables = false, hasPickMacro = false; 17 | 18 | hasMetadata = _fileInfo.metadata; 19 | hasBuildVariables = /{.*?}/.test(_source); 20 | hasBuildFlags = /ifdef::.*\[/.test(_source); 21 | hasPickMacro = /pick:\[(.*?)"]/.test(_source); 22 | 23 | if(hasMetadata || hasBuildVariables || hasBuildFlags || hasPickMacro) { 24 | messenger.publish.metadata('isInfragisticsDocumentationFile'); 25 | } else { 26 | messenger.publish.metadata('isNotInfragisticsDocumentationFile'); 27 | } 28 | } 29 | } 30 | ]; 31 | 32 | module.inspect = (source, fileInfo) => { 33 | _source = source; 34 | _fileInfo = fileInfo; 35 | 36 | if(_source.length > 0) { 37 | inspectionRules.forEach((rule) => { 38 | rule.apply(); 39 | }); 40 | } 41 | }; -------------------------------------------------------------------------------- /app/modules/formats/markdown.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: "Markdown", 3 | defaultContent: "# Markdown", 4 | extensions: ["md", "markdown", "mdtp"], 5 | defaultExtension: "md", 6 | shortcuts: { 7 | bold: { left : "**", right : "**" }, 8 | italic: { left : "_", right : "_" }, 9 | image: { left : "![", right : "]({0})", cursorOffset: { value: 1, fromLeft: false } }, 10 | link: { left : "[", right : "]({0})" }, 11 | code: { left : "`", right : "`" }, 12 | h1: { left : "# ", right : "", cursorOffset: { wrapAtBeginningOfLine: true } }, 13 | h2: { left : "## ", right : "", cursorOffset: { wrapAtBeginningOfLine: true } }, 14 | h3: { left : "### ", right : "", cursorOffset: { wrapAtBeginningOfLine: true } }, 15 | quote: { left : "> ", right : "", cursorOffset: { wrapAtBeginningOfLine: true } }, 16 | ordered: { left : "1. ", right : "", cursorOffset: { wrapAtBeginningOfLine: true } }, 17 | unordered: { left : "- ", right : "", cursorOffset: { wrapAtBeginningOfLine: true } }, 18 | hr: { left : "\n\n---\n\n", right : "" }, 19 | comment: { left : "\n\n" } 20 | }, 21 | wrapTextInComment: (text) => { 22 | return `\n\n`; 23 | }, 24 | metadataPatterns: { 25 | full: /\