├── vim ├── common.js ├── data │ ├── guide │ ├── inject │ ├── options │ ├── devtools │ └── icons │ │ ├── 128.png │ │ ├── 16.png │ │ ├── 256.png │ │ ├── 32.png │ │ ├── 48.png │ │ ├── 512.png │ │ └── 64.png ├── devtools │ ├── index.js │ └── index.html ├── config.js └── manifest.json ├── notepad++ ├── common.js ├── data │ ├── guide │ ├── inject │ ├── options │ ├── devtools │ └── icons │ │ ├── 128.png │ │ ├── 16.png │ │ ├── 256.png │ │ ├── 32.png │ │ ├── 48.png │ │ └── 64.png ├── devtools │ ├── index.js │ └── index.html ├── config.js └── manifest.json ├── sublime ├── common.js ├── data │ ├── guide │ ├── devtools │ ├── inject │ ├── options │ └── icons │ │ ├── 16.png │ │ ├── 32.png │ │ ├── 48.png │ │ ├── 64.png │ │ ├── 128.png │ │ ├── 256.png │ │ └── 512.png ├── devtools │ ├── index.js │ └── index.html ├── config.js └── manifest.json └── common ├── data ├── options │ ├── matched.js │ ├── matched.json │ ├── index.html │ └── index.js ├── guide │ ├── info.svg │ ├── success.svg │ ├── error.svg │ ├── index.js │ └── index.html ├── inject │ ├── inspect.css │ └── inspect.js └── devtools │ ├── index.html │ └── index.js └── common.js /vim/common.js: -------------------------------------------------------------------------------- 1 | ../common/common.js -------------------------------------------------------------------------------- /notepad++/common.js: -------------------------------------------------------------------------------- 1 | ../common/common.js -------------------------------------------------------------------------------- /sublime/common.js: -------------------------------------------------------------------------------- 1 | ../common/common.js -------------------------------------------------------------------------------- /vim/data/guide: -------------------------------------------------------------------------------- 1 | ../../common/data/guide/ -------------------------------------------------------------------------------- /sublime/data/guide: -------------------------------------------------------------------------------- 1 | ../../common/data/guide/ -------------------------------------------------------------------------------- /vim/data/inject: -------------------------------------------------------------------------------- 1 | ../../common/data/inject/ -------------------------------------------------------------------------------- /vim/data/options: -------------------------------------------------------------------------------- 1 | ../../common/data/options/ -------------------------------------------------------------------------------- /notepad++/data/guide: -------------------------------------------------------------------------------- 1 | ../../common/data/guide/ -------------------------------------------------------------------------------- /notepad++/data/inject: -------------------------------------------------------------------------------- 1 | ../../common/data/inject/ -------------------------------------------------------------------------------- /notepad++/data/options: -------------------------------------------------------------------------------- 1 | ../../common/data/options/ -------------------------------------------------------------------------------- /sublime/data/devtools: -------------------------------------------------------------------------------- 1 | ../../common/data/devtools/ -------------------------------------------------------------------------------- /sublime/data/inject: -------------------------------------------------------------------------------- 1 | ../../common/data/inject/ -------------------------------------------------------------------------------- /sublime/data/options: -------------------------------------------------------------------------------- 1 | ../../common/data/options/ -------------------------------------------------------------------------------- /vim/data/devtools: -------------------------------------------------------------------------------- 1 | ../../common/data/devtools/ -------------------------------------------------------------------------------- /notepad++/data/devtools: -------------------------------------------------------------------------------- 1 | ../../common/data/devtools/ -------------------------------------------------------------------------------- /common/data/options/matched.js: -------------------------------------------------------------------------------- 1 | ../../../../_/matched/matched.js -------------------------------------------------------------------------------- /common/data/options/matched.json: -------------------------------------------------------------------------------- 1 | ../../../../_/matched/matched.json -------------------------------------------------------------------------------- /vim/data/icons/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/belaviyo/edit-as-html/HEAD/vim/data/icons/128.png -------------------------------------------------------------------------------- /vim/data/icons/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/belaviyo/edit-as-html/HEAD/vim/data/icons/16.png -------------------------------------------------------------------------------- /vim/data/icons/256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/belaviyo/edit-as-html/HEAD/vim/data/icons/256.png -------------------------------------------------------------------------------- /vim/data/icons/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/belaviyo/edit-as-html/HEAD/vim/data/icons/32.png -------------------------------------------------------------------------------- /vim/data/icons/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/belaviyo/edit-as-html/HEAD/vim/data/icons/48.png -------------------------------------------------------------------------------- /vim/data/icons/512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/belaviyo/edit-as-html/HEAD/vim/data/icons/512.png -------------------------------------------------------------------------------- /vim/data/icons/64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/belaviyo/edit-as-html/HEAD/vim/data/icons/64.png -------------------------------------------------------------------------------- /sublime/data/icons/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/belaviyo/edit-as-html/HEAD/sublime/data/icons/16.png -------------------------------------------------------------------------------- /sublime/data/icons/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/belaviyo/edit-as-html/HEAD/sublime/data/icons/32.png -------------------------------------------------------------------------------- /sublime/data/icons/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/belaviyo/edit-as-html/HEAD/sublime/data/icons/48.png -------------------------------------------------------------------------------- /sublime/data/icons/64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/belaviyo/edit-as-html/HEAD/sublime/data/icons/64.png -------------------------------------------------------------------------------- /notepad++/data/icons/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/belaviyo/edit-as-html/HEAD/notepad++/data/icons/128.png -------------------------------------------------------------------------------- /notepad++/data/icons/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/belaviyo/edit-as-html/HEAD/notepad++/data/icons/16.png -------------------------------------------------------------------------------- /notepad++/data/icons/256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/belaviyo/edit-as-html/HEAD/notepad++/data/icons/256.png -------------------------------------------------------------------------------- /notepad++/data/icons/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/belaviyo/edit-as-html/HEAD/notepad++/data/icons/32.png -------------------------------------------------------------------------------- /notepad++/data/icons/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/belaviyo/edit-as-html/HEAD/notepad++/data/icons/48.png -------------------------------------------------------------------------------- /notepad++/data/icons/64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/belaviyo/edit-as-html/HEAD/notepad++/data/icons/64.png -------------------------------------------------------------------------------- /sublime/data/icons/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/belaviyo/edit-as-html/HEAD/sublime/data/icons/128.png -------------------------------------------------------------------------------- /sublime/data/icons/256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/belaviyo/edit-as-html/HEAD/sublime/data/icons/256.png -------------------------------------------------------------------------------- /sublime/data/icons/512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/belaviyo/edit-as-html/HEAD/sublime/data/icons/512.png -------------------------------------------------------------------------------- /sublime/devtools/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | if (chrome.devtools.panels.elements.createSidebarPane) { 4 | chrome.devtools.panels.elements.createSidebarPane('Sublime Text', sidebar => { 5 | sidebar.setPage('/data/devtools/index.html'); 6 | }); 7 | } 8 | -------------------------------------------------------------------------------- /vim/devtools/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | if (chrome.devtools.panels.elements.createSidebarPane) { 4 | chrome.devtools.panels.elements.createSidebarPane(chrome.runtime.getManifest().name, sidebar => { 5 | sidebar.setPage('/data/devtools/index.html'); 6 | }); 7 | } 8 | -------------------------------------------------------------------------------- /notepad++/devtools/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | if (chrome.devtools.panels.elements.createSidebarPane) { 4 | const name = chrome.runtime.getManifest().name; 5 | chrome.devtools.panels.elements.createSidebarPane(name, sidebar => { 6 | sidebar.setPage('/data/devtools/index.html'); 7 | }); 8 | } 9 | -------------------------------------------------------------------------------- /vim/devtools/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /sublime/devtools/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /notepad++/devtools/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /common/data/guide/info.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /notepad++/config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const config = {}; 4 | 5 | config.id = 'com.add0n.native_client'; 6 | 7 | config.command = () => new Promise(resolve => { 8 | chrome.storage.local.get({ 9 | Mac: 'open -a "Notepad++" %path;', 10 | Lin: '/opt/notepadpp/notepadpp %path;', 11 | Win: '"%ProgramFiles(x86)%\\Notepad++\\notepad++.exe" %path;' 12 | }, prefs => { 13 | resolve(prefs[navigator.platform.substr(0, 3)]); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /sublime/config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const config = {}; 4 | 5 | config.id = 'com.add0n.native_client'; 6 | 7 | config.command = () => new Promise(resolve => { 8 | chrome.storage.local.get({ 9 | Mac: 'open -a "Sublime Text" %path;', 10 | Lin: '/opt/sublime_text/sublime_text %path;', 11 | Win: '"%ProgramFiles%\\Sublime Text 3\\subl.exe" %path;' 12 | }, prefs => { 13 | resolve(prefs[navigator.platform.substr(0, 3)]); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /common/data/inject/inspect.css: -------------------------------------------------------------------------------- 1 | .inspectEditor { 2 | border: dashed 1px #222831; 3 | position: absolute; 4 | pointer-events: none; 5 | box-sizing: border-box; 6 | z-index: 2147483647; 7 | } 8 | .inspectEditor:before { 9 | box-sizing: border-box; 10 | content: attr(data-value); 11 | color: #EEEEEE; 12 | background-color: #222831; 13 | font-size: 11px; 14 | font-weight: bold; 15 | white-space: nowrap; 16 | margin-top: -20px; 17 | float: right; 18 | padding: 3px 5px; 19 | } 20 | -------------------------------------------------------------------------------- /vim/config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const config = {}; 4 | 5 | config.id = 'com.add0n.native_client'; 6 | 7 | config.command = () => new Promise(resolve => { 8 | chrome.storage.local.get('command', prefs => { 9 | if (prefs.command) { 10 | return resolve(prefs.command); 11 | } 12 | resolve({ 13 | Mac: 'open -a "MacVim" %path;', 14 | Lin: '/usr/local/bin/gvim %path;', 15 | Win: '"%ProgramFiles(x86)%\\Vim\\vim81\\gvim.exe" %path;' 16 | }[navigator.platform.substr(0, 3)]); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /common/data/options/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |A system-level command to open the external text editor
12 |17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /common/data/guide/success.svg: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /common/data/guide/error.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /common/data/devtools/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |For the extension to execute external commands (start the external text editor and exchange content) one extra step is required. Please download, unzip and install this minimal native client.
109 |./install.shinstall.bat fileThe installer script copies a few files to two different locations for your browser to be able to detect this native client (paths of these directories are being printed based on your OS and configuration). If you already have NodeJS in your system, the installed version of NodeJS will be used. So please make sure you have an up-to-date version of NodeJS installed. If you don't have this application, the portable version will be used. Read more here.
119 |To completely remove this native client, run ./uninstall.shuninstall.bat.
To make sure the native client is accessible, click on the "Check Connection" button. If you still get this page even when the "Check Button" reports successful connection, it means the application cannot be accessed (application's path is not correct in the options page). If the path to the executable is correct and the native client is connected, you can debug the connection by enabling console logs.
121 |There is no need for administration permission for the native client to operate.
122 | 123 | 130 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /common/common.js: -------------------------------------------------------------------------------- 1 | /* globals config */ 2 | 'use strict'; 3 | 4 | function notify(message) { 5 | chrome.notifications.create({ 6 | title: chrome.runtime.getManifest().name, 7 | type: 'basic', 8 | iconUrl: '/data/icons/48.png', 9 | message 10 | }); 11 | } 12 | 13 | chrome.browserAction.onClicked.addListener(tab => { 14 | chrome.tabs.insertCSS(tab.id, { 15 | allFrames: true, 16 | matchAboutBlank: true, 17 | runAt: 'document_start', 18 | file: '/data/inject/inspect.css' 19 | }, () => { 20 | if (chrome.runtime.lastError) { 21 | notify(chrome.runtime.lastError.message); 22 | } 23 | else { 24 | chrome.tabs.executeScript(tab.id, { 25 | allFrames: true, 26 | matchAboutBlank: true, 27 | runAt: 'document_start', 28 | file: '/data/inject/inspect.js' 29 | }); 30 | } 31 | }); 32 | }); 33 | 34 | function editor(request, observe) { 35 | const native = chrome.runtime.connectNative(config.id); 36 | native.onDisconnect.addListener(() => observe()); 37 | native.onMessage.addListener(observe); 38 | native.postMessage({ 39 | permissions: ['crypto', 'fs', 'path', 'os'], 40 | args: [request.content, request.ext], 41 | script: ` 42 | const crypto = require('crypto'); 43 | const fs = require('fs'); 44 | 45 | const [content, ext] = args; 46 | 47 | const filename = require('path').join( 48 | require('os').tmpdir(), 49 | 'editor-' + crypto.randomBytes(4).readUInt32LE(0) + '.' + ext 50 | ); 51 | fs.writeFile(filename, content, e => { 52 | if (e) { 53 | push({ 54 | method: 'error', 55 | error: e.message 56 | }); 57 | close(); 58 | } 59 | else { 60 | push({ 61 | method: 'file-created', 62 | filename 63 | }); 64 | fs.watchFile(filename, event => { 65 | fs.readFile(filename, 'utf8', (e, content) => { 66 | if (e) { 67 | push({ 68 | type: 'error', 69 | error: e.message 70 | }); 71 | } 72 | else { 73 | push({ 74 | method: 'file-changed', 75 | content, 76 | event 77 | }); 78 | } 79 | }); 80 | }); 81 | } 82 | }); 83 | ` 84 | }); 85 | return native; 86 | } 87 | 88 | chrome.runtime.onMessage.addListener((request, sender) => { 89 | if (request.method === 'bounce-release') { 90 | chrome.tabs.sendMessage(sender.tab.id, { 91 | method: 'release' 92 | }); 93 | } 94 | }); 95 | 96 | const panels = {}; 97 | chrome.tabs.onRemoved.addListener(tabId => delete panels[tabId]); 98 | 99 | chrome.runtime.onConnect.addListener(devToolsConnection => { 100 | if (devToolsConnection.name === 'devtools-panel') { 101 | return devToolsConnection.onMessage.addListener(request => { 102 | if (request.method === 'tabId') { 103 | panels[request.tabId] = devToolsConnection; 104 | devToolsConnection.onDisconnect.addListener(() => { 105 | delete panels[request.tabId]; 106 | }); 107 | } 108 | }); 109 | } 110 | const connectListener = request => { 111 | const id = devToolsConnection.sender.tab.id; 112 | const log = msg => panels[id] ? panels[id].postMessage({ 113 | method: 'log', 114 | msg 115 | }) : ''; 116 | if (request.method === 'edit-with') { 117 | const native = editor(request, res => { 118 | if (!res) { 119 | const lastError = chrome.runtime.lastError; 120 | let msg = 'The native client is not installed or the native application exited with an error.'; 121 | if (lastError) { 122 | msg += ' -- ' + lastError.message; 123 | } 124 | notify(msg); 125 | chrome.tabs.create({ 126 | url: '/data/guide/index.html' 127 | }); 128 | } 129 | else if (res.method === 'error') { 130 | notify(res.error); 131 | } 132 | else if (res.method === 'file-created') { 133 | log('Temporary file is created at ' + res.filename); 134 | config.command().then(command => { 135 | chrome.runtime.sendNativeMessage(config.id, { 136 | permissions: ['child_process'], 137 | args: [command.replace('%path;', res.filename)], 138 | script: String.raw` 139 | const {exec} = require('child_process'); 140 | const command = args[0].replace(/%([^%]+)%/g, (_, n) => env[n]); 141 | exec(command, (error, stdout, stderr) => { 142 | push({error, stdout, stderr}); 143 | close(); 144 | }); 145 | ` 146 | }, res => { 147 | if (res.stderr) { 148 | notify(res.stderr); 149 | } 150 | }); 151 | }); 152 | } 153 | else if (res.method === 'file-changed') { 154 | log('File content is changed'); 155 | devToolsConnection.postMessage({ 156 | method: 'file-changed', 157 | content: res.content 158 | }); 159 | } 160 | }); 161 | connectListener.natives.push(native); 162 | } 163 | }; 164 | connectListener.natives = []; 165 | // add the listener 166 | devToolsConnection.onMessage.addListener(connectListener); 167 | // disconnect 168 | devToolsConnection.onDisconnect.addListener(() => { 169 | connectListener.natives.forEach(n => n.disconnect()); 170 | devToolsConnection.onMessage.removeListener(connectListener); 171 | }); 172 | }); 173 | 174 | // context menu 175 | { 176 | const callback = () => { 177 | chrome.contextMenus.create({ 178 | id: 'edit-with', 179 | title: chrome.runtime.getManifest().name, 180 | contexts: ['editable'] 181 | }); 182 | }; 183 | chrome.runtime.onInstalled.addListener(callback); 184 | chrome.runtime.onStartup.addListener(callback); 185 | } 186 | chrome.contextMenus.onClicked.addListener((info, tab) => { 187 | chrome.tabs.executeScript(tab.id, { 188 | frameId: info.frameId, 189 | runAt: 'document_start', 190 | matchAboutBlank: true, 191 | code: `{ 192 | const target = document.activeElement; 193 | const background = chrome.runtime.connect({ 194 | name: 'context-menu' 195 | }); 196 | background.postMessage({ 197 | method: 'edit-with', 198 | content: target.value, 199 | ext: 'txt' 200 | }); 201 | background.onMessage.addListener(request => { 202 | if (request.method === 'file-changed') { 203 | target.value = request.content; 204 | } 205 | }); 206 | }` 207 | }); 208 | }); 209 | /* FAQs & Feedback */ 210 | { 211 | const {onInstalled, setUninstallURL, getManifest} = chrome.runtime; 212 | const {name, version} = getManifest(); 213 | const page = getManifest().homepage_url; 214 | if (navigator.webdriver !== true) { 215 | onInstalled.addListener(({reason, previousVersion}) => { 216 | chrome.storage.local.get({ 217 | 'faqs': true, 218 | 'last-update': 0 219 | }, prefs => { 220 | if (reason === 'install' || (prefs.faqs && reason === 'update')) { 221 | const doUpdate = (Date.now() - prefs['last-update']) / 1000 / 60 / 60 / 24 > 45; 222 | if (doUpdate && previousVersion !== version) { 223 | chrome.tabs.create({ 224 | url: page + '&version=' + version + 225 | (previousVersion ? '&p=' + previousVersion : '') + 226 | '&type=' + reason, 227 | active: reason === 'install' 228 | }); 229 | chrome.storage.local.set({'last-update': Date.now()}); 230 | } 231 | } 232 | }); 233 | }); 234 | setUninstallURL(page + '&rd=feedback&name=' + encodeURIComponent(name) + '&version=' + version); 235 | } 236 | } 237 | --------------------------------------------------------------------------------