├── .gitignore ├── EmacsClient.app.zip ├── LICENSE ├── README.md ├── background.js ├── capture.js ├── manifest.json ├── options.html ├── options.js └── popup.html /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore temporary files: 2 | *~ 3 | \#*\# 4 | /Org-mode-unicorn.svg 5 | /org-mode-unicorn.png 6 | -------------------------------------------------------------------------------- /EmacsClient.app.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sprig/org-capture-extension/3911377933619a24562730dc8b353424f8809d9e/EmacsClient.app.zip -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2017 Konstantin Kliakhandler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Org Capture Extension 2 | 3 | This is an extension for Google Chrome (tm) and Firefox (tm) which adds a "Capture" button, sending the site address, title, and selected text (if any) to emacs via org-protocol, see the [Org-Mode site] for instructions for setting that up org-protocol. The extentsion itself is available at the [Chrome App Store]. 4 | 5 | # Improvements 6 | 7 | - Adding options for selecting the exact structure of the links that are constructed (e.g. for the benefit of people with '///' problems). 8 | - There is always room to improve. Open a ticket with your ideas. 9 | 10 | # Example Usage 11 | [![Example Usage Video](https://img.youtube.com/vi/zKDHto-4wsU/0.jpg)](https://www.youtube.com/watch?v=zKDHto-4wsU) 12 | ![Example Usage Screenshot](https://dl.dropboxusercontent.com/s/x2xjgg7bnwuj6uv/Screenshot.png) 13 | 14 | # Problems? Please [click here](#troubleshooting) or scroll to the bottom. 15 | 16 | # Detailed setup instructions 17 | 18 | ## Install the extension 19 | 20 | Either via the [Chrome App Store] or by dragging the extension folder to the "Extensions" tab in Chrome. If the latter is the chosen procedure then one needs to enable developer mode first, if I'm not mistaken. Note that if you choose to have a local-install, then you need to choose some icon and name it org-mode-unicorn.png, placing it in the extension's folder. Or, you can name it anything you want, but then you need to update manifest.json. 21 | 22 | _Note_: The first time you use the extension, Chrome will ask you allow it to run ```open ....``` (on OSX) or ```xdg-open ...``` (on Linux), or ??? (On Windows). Those are the standard system mechanisms for dispatching a file/URL to the appropriate handler, so you should accept the request. 23 | 24 | ## Set up org-protocol 25 | 26 | Detailed instructions available at [Org-Mode site]. 27 | 28 | The gist of it is to make your system recognize emacsclient as the handler of ```org-protocol://``` links. In addition, one needs to set up emacs to load org-protocol and to set up capture templates. 29 | 30 | ### Register emacsclient as the ```org-protocol``` handler 31 | 32 | #### Under Linux 33 | 34 | ``` bash 35 | cat > "${HOME}/.local/share/applications/org-protocol.desktop" << EOF 36 | [Desktop Entry] 37 | Name=org-protocol 38 | Exec=emacsclient %u 39 | Type=Application 40 | Terminal=false 41 | Categories=System; 42 | MimeType=x-scheme-handler/org-protocol; 43 | EOF 44 | ``` 45 | 46 | And then, for GTK-based DE: 47 | ``` bash 48 | update-desktop-database ~/.local/share/applications/ 49 | ``` 50 | 51 | For KDE5: 52 | ``` bash 53 | kbuildsycoca5 54 | xdg-mime default org-protocol.desktop x-scheme-handler/org-protocol 55 | ``` 56 | ##### For KDE4 57 | ###### Note: This is a workaround to issue #16 - See comment [here](https://github.com/sprig/org-capture-extension/issues/16#issuecomment-305050310) 58 | 59 | Create the file 60 | */usr/local/bin/emacs-capture* 61 | ```sh 62 | #!/bin/bash 63 | 64 | # HACK: workaround for a kde-open bug (feature?) that might have 65 | # eaten a colon from our argument, om nom nom 66 | argv=() 67 | for arg in "$@"; do 68 | re='s_^org-protocol:/+capture:?/+_org-protocol://capture://_' 69 | argv+=("$(echo -n "$arg" | sed -Ez "$re")") 70 | done 71 | 72 | # Note: feel free to add any other arguments you want, 73 | # e.g. emacsclient --alternate-editor= -c "${argv[@]}" 74 | emacsclient "${argv[@]}" 75 | ``` 76 | And the file 77 | 78 | *$HOME/.local/share/applications/emacs-capture.desktop* 79 | ```desktop 80 | #!/usr/bin/env xdg-open 81 | [Desktop Entry] 82 | Name=Emacs Client 83 | Exec=emacs-capture "%u" 84 | Icon=emacs-icon 85 | Type=Application 86 | Terminal=false 87 | MimeType=x-scheme-handler/org-protocol; 88 | ``` 89 | 90 | Finally, run 91 | 92 | ``` bash 93 | kbuildsycoca4 94 | sudo update-desktop-database 95 | ``` 96 | 97 | #### Under OSX 98 | 99 | Start Applescript Editor. Paste the following snippet: 100 | 101 | ``` applescript 102 | on emacsclient(input) 103 | do shell script "/Applications/Emacs.app/Contents/MacOS/bin-x86_64-10_9/emacsclient -n -c -a \"/Applications/Emacs.app/Contents/MacOS/Emacs\" '" & input & "'" 104 | end emacsclient 105 | 106 | on open location input 107 | emacsclient(input) 108 | end open location 109 | 110 | on open inputs 111 | repeat with raw_input in inputs 112 | set input to POSIX path of raw_input 113 | emacsclient(input) 114 | end repeat 115 | end open 116 | 117 | on run 118 | do shell script emacsclient("") 119 | end run 120 | ``` 121 | 122 | Adjust the paths and save it (with 'type' as Application) under ```/Applications/EmacsClient.app``` (or whatever else you choose). 123 | Edit (with Xcode) the file ```/Applications/Emacsclient.app/Contents/Info.plist``` 124 | 125 | And add there the following: 126 | ``` plist 127 | CFBundleURLTypes 128 | 129 | 130 | CFBundleURLName 131 | org-protocol 132 | CFBundleURLSchemes 133 | 134 | org-protocol 135 | 136 | 137 | 138 | ``` 139 | 140 | and 141 | ``` plist 142 | CFBundleDocumentTypes 143 | 144 | 145 | CFBundleTypeExtensions 146 | 147 | * 148 | 149 | CFBundleTypeName 150 | All 151 | CFBundleTypeOSTypes 152 | 153 | **** 154 | 155 | CFBundleTypeRole 156 | Viewer 157 | 158 | 159 | ``` 160 | 161 | and restart the desktop. You can also download [EmacsClient.app.zip], which I prepared in advance, if you are lazy. 162 | 163 | ##### Install EmacsClient.app with homebrew cask 164 | 165 | If you have Homebrew and [Homebrew-Cask](https://caskroom.github.io/) installed, you can also install [EmacsClient.app.zip] with `brew cask install emacsclient` 166 | 167 | ##### Frame Visibility 168 | 169 | Under some setups the emacs frame does not appear on top. @dangom [proposes a workaround using hammerspoon](https://github.com/sprig/org-capture-extension/issues/46#issuecomment-379498419): 170 | 171 | Add the following to your init.lua: 172 | 173 | ```lua 174 | function emacsclientWatcher(appName, eventType, appObject) 175 | if (eventType == hs.application.watcher.activated) then 176 | if (appName == "Emacsclient") then 177 | -- Bring Emacs to Front 178 | hs.osascript.applescript('tell application "Emacs" to activate') 179 | end 180 | end 181 | end 182 | appWatcher = hs.application.watcher.new(emacsclientWatcher) 183 | appWatcher:start() 184 | ``` 185 | 186 | #### Under Windows 187 | 188 | Open the Registry Editor (Win-R, then type `regedit`). Within `HKEY_CLASSES_ROOT`, add a key called `org-protocol`. Within `org-protocol`, set the data for the string value with the name `(Default)` to be `URL:org-protocol`, add another string value with name `URL Protocol` and no data, and add a key called `shell`. 189 | 190 | Within `shell`, create a key called `open`. 191 | 192 | Within `open`, create a key called `command`. 193 | 194 | Within `command`, set the data for the string value with the name `(Default)` to `"C:\the\path\to\your\emacsclientw.exe" "%1"`, updating the path to point to your Emacs installation. 195 | 196 | If you get stuck, see [this guide to registering a protocol handler](https://msdn.microsoft.com/en-us/library/aa767914\(v=vs.85\).aspx) and look at how registries are set up for other protocol handlers (`skype`, `ftp`, etc.). Most of your pre-existing protocol handlers have more config than you need. 197 | 198 | ### Set up handlers in emacs 199 | 200 | If some text is selected before the button is clicked, then the following is sent to emacs: 201 | ``` 202 | org-protocol://capture:/p///selection> 203 | ``` 204 | 205 | If nothing is selected, then instead the following is sent: 206 | ``` 207 | org-protocol://capture:/L/<url>/<title> 208 | ``` 209 | 210 | This means that you need to have appropriate capture templates for "L" and for "p". Example templates below: 211 | 212 | ```lisp 213 | (setq org-capture-templates `( 214 | ("p" "Protocol" entry (file+headline ,(concat org-directory "notes.org") "Inbox") 215 | "* %^{Title}\nSource: %u, %c\n #+BEGIN_QUOTE\n%i\n#+END_QUOTE\n\n\n%?") 216 | ("L" "Protocol Link" entry (file+headline ,(concat org-directory "notes.org") "Inbox") 217 | "* %? [[%:link][%:description]] \nCaptured On: %U") 218 | )) 219 | ``` 220 | 221 | 222 | _Hint:_ You can put code in capture handlers via %() blocks. I use this mechanism to automatically close the newly crated frame in the L template. If anyone cares to know, I'll add the details. Another example use is below. 223 | 224 | [*Note*](https://github.com/sprig/org-capture-extension/issues/37): The `L` template above would break for links to pages having `[` and `]` characters in their page titles - notably ArXiv. To mitigae this, you can use the improved template, contributed by [Vincent Picaud](https://www.github.com/vincent-picaud): 225 | 226 | ```lisp 227 | (defun transform-square-brackets-to-round-ones(string-to-transform) 228 | "Transforms [ into ( and ] into ), other chars left unchanged." 229 | (concat 230 | (mapcar #'(lambda (c) (if (equal c ?[) ?\( (if (equal c ?]) ?\) c))) string-to-transform)) 231 | ) 232 | 233 | (setq org-capture-templates `( 234 | ("p" "Protocol" entry (file+headline ,(concat org-directory "notes.org") "Inbox") 235 | "* %^{Title}\nSource: %u, %c\n #+BEGIN_QUOTE\n%i\n#+END_QUOTE\n\n\n%?") 236 | ("L" "Protocol Link" entry (file+headline ,(concat org-directory "notes.org") "Inbox") 237 | "* %? [[%:link][%(transform-square-brackets-to-round-ones \"%:description\")]]\n") 238 | )) 239 | ``` 240 | 241 | #### Example: closins the frame after a capture 242 | 243 | If you wish to automatically close the emacs frame after a capture, add the following template: 244 | 245 | ```lisp 246 | ("L" "Protocol Link" entry (file+headline ,(concat org-directory "notes.org") "Inbox") 247 | "* %? [[%:link][%:description]] %(progn (setq kk/delete-frame-after-capture 2) \"\")\nCaptured On: %U" 248 | :empty-lines 1) 249 | ``` 250 | 251 | and in the initialization of org-mode put: 252 | 253 | ```lisp 254 | ;; Kill the frame if one was created for the capture 255 | (defvar kk/delete-frame-after-capture 0 "Whether to delete the last frame after the current capture") 256 | 257 | (defun kk/delete-frame-if-neccessary (&rest r) 258 | (cond 259 | ((= kk/delete-frame-after-capture 0) nil) 260 | ((> kk/delete-frame-after-capture 1) 261 | (setq kk/delete-frame-after-capture (- kk/delete-frame-after-capture 1))) 262 | (t 263 | (setq kk/delete-frame-after-capture 0) 264 | (delete-frame)))) 265 | 266 | (advice-add 'org-capture-finalize :after 'kk/delete-frame-if-neccessary) 267 | (advice-add 'org-capture-kill :after 'kk/delete-frame-if-neccessary) 268 | (advice-add 'org-capture-refile :after 'kk/delete-frame-if-neccessary) 269 | ``` 270 | 271 | # Troubleshooting 272 | 273 | Is the extension not working as you expect? i.e., is it "broken"? You need to do some investigative 274 | legwork. And if you open a ticket, provide enough information to help solve the problem! 275 | 276 | Please describe your setup. Linux? Version. OSX? Version. Emacs? Version. org-mode? Version. Chrome? Version. How did 277 | you get your system to send org-protocol links to emacs? Please provide the relevant capture templates. 278 | 279 | Please find the simplest URL for which it fails (does it work on a simple address that contain only 280 | alphanumeric characters and periods? and backslashes? and query parameters? and escaped characters? 281 | etc.). Then open the developer console and look for the debug message that the extension gives and 282 | add it to the ticket. 283 | 284 | Open a terminal and run $open "COPIED-URL" (do not skip the quotes, unless what you are pasting 285 | already has quotes around it). $open is simply open if you are on OSX and xdg-open if on 286 | linux. COPIED-URL is obviously the url you pasted here in step 1. Does it work? Congrats, you found 287 | where the problem is not (i.e. inside chrome). No? Does $open org-"protocol://capture:/p/a/b" work? 288 | No? Again you found where the problem lies not. Otherwise proceed to step 3. 289 | 290 | Call up the line you ran in the terminal with the non-working url. it will be of the form open 291 | "org-protocol://capture:/<letter>/PIECE1/PIECE2/ with PIECE2 usually being longer and more complex 292 | if you selected any text, and PIECE1 otherwise. Please edit the url until it is as short as possible 293 | while still breaking (Note, % should always be proceeded by two digits/letters in the ranges 0-9 and 294 | A-F so do not leave a percent sign with a single symbol following). You can probably trim one of the 295 | pieces to be just one character. Add to the ticket the smallest breaking URL. 296 | 297 | Try sending said URL directly to emacsclient, for good measure. Does it work? Again, congrats. If 298 | you are using OSX, make sure that the emacsclient which you call is the correct one! 299 | 300 | ### P.S. 301 | It is of course fine to ask for help with problems in your config as well. 302 | 303 | # License 304 | This repository is licensed as MIT license, see the LICENSE file for details. 305 | 306 | [Org-Mode site]: http://orgmode.org/worg/org-contrib/org-protocol.html 307 | [Chrome App Store]: https://chrome.google.com/webstore/detail/org-capture/kkkjlfejijcjgjllecmnejhogpbcigdc 308 | [EmacsClient.app.zip]: https://github.com/sprig/org-capture-extension/raw/master/EmacsClient.app.zip 309 | -------------------------------------------------------------------------------- /background.js: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2015-2017 Konstantin Kliakhandler // 3 | // // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy // 5 | // of this software and associated documentation files (the "Software"), to deal // 6 | // in the Software without restriction, including without limitation the rights // 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // 8 | // copies of the Software, and to permit persons to whom the Software is // 9 | // furnished to do so, subject to the following conditions: // 10 | // // 11 | // The above copyright notice and this permission notice shall be included in // 12 | // all copies or substantial portions of the Software. // 13 | // // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // 20 | // THE SOFTWARE. // 21 | /////////////////////////////////////////////////////////////////////////////////// 22 | 23 | 24 | chrome.runtime.onInstalled.addListener(function (details) { 25 | if (details.reason == "install") 26 | chrome.storage.sync.set( 27 | { 28 | selectedTemplate: 'p', 29 | unselectedTemplate: 'L', 30 | useNewStyleLinks: true, 31 | debug: false, 32 | overlay: true 33 | }); 34 | else if ((details.reason == "update" && details.previousVersion.startsWith("0.1"))) 35 | chrome.storage.sync.set( 36 | { 37 | selectedTemplate: 'p', 38 | unselectedTemplate: 'L', 39 | useNewStyleLinks: false, 40 | debug: false, 41 | overlay: true 42 | }); 43 | }); 44 | 45 | chrome.browserAction.onClicked.addListener(function (tab) { 46 | chrome.tabs.executeScript({file: "capture.js"}); 47 | }); 48 | -------------------------------------------------------------------------------- /capture.js: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2015-2017 Konstantin Kliakhandler // 3 | // // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy // 5 | // of this software and associated documentation files (the "Software"), to deal // 6 | // in the Software without restriction, including without limitation the rights // 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // 8 | // copies of the Software, and to permit persons to whom the Software is // 9 | // furnished to do so, subject to the following conditions: // 10 | // // 11 | // The above copyright notice and this permission notice shall be included in // 12 | // all copies or substantial portions of the Software. // 13 | // // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // 20 | // THE SOFTWARE. // 21 | /////////////////////////////////////////////////////////////////////////////////// 22 | 23 | 24 | (function () { 25 | 26 | 27 | class Capture { 28 | 29 | createCaptureURI() { 30 | var protocol = "capture"; 31 | var template = (this.selection_text != "" ? this.selectedTemplate : this.unselectedTemplate); 32 | if (this.useNewStyleLinks) 33 | return "org-protocol://"+protocol+"?template="+template+'&url='+this.encoded_url+'&title='+this.escaped_title+'&body='+this.selection_text; 34 | else 35 | return "org-protocol://"+protocol+":/"+template+'/'+this.encoded_url+'/'+this.escaped_title+'/'+this.selection_text; 36 | } 37 | 38 | constructor() { 39 | this.window = window; 40 | this.document = document; 41 | this.location = location; 42 | 43 | this.selection_text = escapeIt(window.getSelection().toString()); 44 | this.encoded_url = encodeURIComponent(location.href); 45 | this.escaped_title = escapeIt(document.title); 46 | 47 | } 48 | 49 | capture() { 50 | var uri = this.createCaptureURI(); 51 | 52 | if (this.debug) { 53 | logURI(uri); 54 | } 55 | 56 | location.href = uri; 57 | 58 | if (this.overlay) { 59 | toggleOverlay(); 60 | } 61 | } 62 | 63 | captureIt(options) { 64 | if (chrome.runtime.lastError) { 65 | alert("Could not capture url. Error loading options: " + chrome.runtime.lastError.message); 66 | return; 67 | } 68 | 69 | if (this.selection_text) { 70 | this.template = this.selectedTemplate; 71 | this.protocol = this.selectedProtocol; 72 | } else { 73 | this.template = this.unselectedTemplate; 74 | this.protocol = this.unselectedProtocol; 75 | } 76 | 77 | for(var k in options) this[k] = options[k]; 78 | this.capture(); 79 | } 80 | } 81 | 82 | 83 | function replace_all(str, find, replace) { 84 | return str.replace(new RegExp(find, 'g'), replace); 85 | } 86 | 87 | function escapeIt(text) { 88 | return replace_all(replace_all(replace_all(encodeURIComponent(text), "[(]", escape("(")), 89 | "[)]", escape(")")), 90 | "[']" ,escape("'")); 91 | } 92 | 93 | function logURI(uri) { 94 | window.console.log("Capturing the following URI with new org-protocol: ", uri); 95 | return uri; 96 | } 97 | 98 | function toggleOverlay() { 99 | var outer_id = "org-capture-extension-overlay"; 100 | var inner_id = "org-capture-extension-text"; 101 | if (! document.getElementById(outer_id)) { 102 | var outer_div = document.createElement("div"); 103 | outer_div.id = outer_id; 104 | 105 | var inner_div = document.createElement("div"); 106 | inner_div.id = inner_id; 107 | inner_div.innerHTML = "Captured"; 108 | 109 | outer_div.appendChild(inner_div); 110 | document.body.appendChild(outer_div); 111 | 112 | var css = document.createElement("style"); 113 | css.type = "text/css"; 114 | // noinspection JSAnnotator 115 | css.innerHTML = `#org-capture-extension-overlay { 116 | position: fixed; /* Sit on top of the page content */ 117 | display: none; /* Hidden by default */ 118 | width: 100%; /* Full width (cover the whole page) */ 119 | height: 100%; /* Full height (cover the whole page) */ 120 | top: 0; 121 | left: 0; 122 | right: 0; 123 | bottom: 0; 124 | background-color: rgba(0,0,0,0.2); /* Black background with opacity */ 125 | z-index: 1; /* Specify a stack order in case you're using a different order for other elements */ 126 | cursor: pointer; /* Add a pointer on hover */ 127 | } 128 | 129 | #org-capture-extension-text{ 130 | position: absolute; 131 | top: 50%; 132 | left: 50%; 133 | font-size: 50px; 134 | color: white; 135 | transform: translate(-50%,-50%); 136 | -ms-transform: translate(-50%,-50%); 137 | }`; 138 | document.body.appendChild(css); 139 | } 140 | 141 | function on() { 142 | document.getElementById(outer_id).style.display = "block"; 143 | } 144 | 145 | function off() { 146 | document.getElementById(outer_id).style.display = "none"; 147 | } 148 | 149 | on(); 150 | setTimeout(off, 200); 151 | 152 | } 153 | 154 | 155 | var capture = new Capture(); 156 | var f = function (options) {capture.captureIt(options)}; 157 | chrome.storage.sync.get(null, f); 158 | })(); 159 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | "name": "Org Capture", 4 | "version": "0.2.1", 5 | "description": "A helper for capturing things via org-protocol in emacs: First, set up: http://orgmode.org/worg/org-contrib/org-protocol.html", 6 | "homepage_url": "https://github.com/sprig/org-capture-extension", 7 | 8 | "background": { 9 | "persistent": false, 10 | "scripts": ["background.js"] 11 | }, 12 | 13 | "permissions": ["activeTab", "storage"], 14 | 15 | "options_ui": { 16 | "page": "options.html" 17 | }, 18 | 19 | "browser_action": { 20 | "default_icon": "org-mode-unicorn.png" 21 | }, 22 | 23 | "commands": { 24 | "_execute_browser_action": { 25 | "description": "Capture current page with org-capture", 26 | "suggested_key": { 27 | "default": "Ctrl+Shift+L", 28 | "mac": "Command+Shift+L" 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /options.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <title>Org Capture Settings 5 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 20 | 21 | 22 | 25 | 28 | 29 | 30 | 33 | 36 | 37 | 38 | 41 | 44 | 45 | 46 | 49 | 52 | 54 |
15 | Get notified after captures? 16 | 18 | 19 |
23 | Selected Template 24 | 26 | 27 |
31 | Unselected Template 32 | 34 | 35 |
39 | Use New-Style links? (Recommended for Org-Mode 9.0+) 40 | 42 | 43 |
47 | Debug (will produce logging messages to console) 48 | 50 | 51 | Note: You will have to enable "Preserve Log" in the console in order to see the logged messages. 53 |
55 | 56 |
57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /options.js: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2015-2017 Konstantin Kliakhandler // 3 | // // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy // 5 | // of this software and associated documentation files (the "Software"), to deal // 6 | // in the Software without restriction, including without limitation the rights // 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // 8 | // copies of the Software, and to permit persons to whom the Software is // 9 | // furnished to do so, subject to the following conditions: // 10 | // // 11 | // The above copyright notice and this permission notice shall be included in // 12 | // all copies or substantial portions of the Software. // 13 | // // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // 20 | // THE SOFTWARE. // 21 | /////////////////////////////////////////////////////////////////////////////////// 22 | 23 | 24 | // Saves options to chrome.storage.sync. 25 | function save_options() { 26 | var selTemp = document.getElementById('selTemplate').value; 27 | var unselTemp = document.getElementById('unselTemplate').value; 28 | var NewStyleP = document.getElementById('useNewStyle').checked; 29 | var debugP = document.getElementById('debug').checked; 30 | var overlayP = document.getElementById('overlay').checked; 31 | 32 | chrome.storage.sync.set({ 33 | selectedTemplate: selTemp, 34 | unselectedTemplate: unselTemp, 35 | useNewStyleLinks: NewStyleP, 36 | debug: debugP, 37 | overlay: overlayP 38 | }, function() { 39 | // Update status to let user know options were saved. 40 | var status = document.getElementById('status'); 41 | status.textContent = 'Options saved.'; 42 | setTimeout(function() { 43 | status.textContent = ''; 44 | }, 750); 45 | }); 46 | } 47 | 48 | // Restores select box and checkbox state using the preferences 49 | // stored in chrome.storage. 50 | function restore_options() { 51 | // Use default value color = 'red' and likesColor = true. 52 | chrome.storage.sync.get({ 53 | selectedTemplate: 'p', 54 | unselectedTemplate: 'L', 55 | useNewStyleLinks: true, 56 | debug: false, 57 | overlay: true 58 | }, function(options) { 59 | document.getElementById('unselTemplate').value = options.unselectedTemplate; 60 | document.getElementById('selTemplate').value = options.selectedTemplate; 61 | document.getElementById('useNewStyle').checked = options.useNewStyleLinks; 62 | document.getElementById('debug').checked = options.debug; 63 | document.getElementById('overlay').checked = options.overlay; 64 | }); 65 | } 66 | document.addEventListener('DOMContentLoaded', restore_options); 67 | document.getElementById('save').addEventListener('click', 68 | save_options); 69 | -------------------------------------------------------------------------------- /popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | captured! 7 | 8 | 9 | --------------------------------------------------------------------------------