├── .eslintrc.json ├── .gitignore ├── .jscsrc ├── .jshintrc ├── .tern-project ├── .tx └── config ├── AUTHORS.md ├── CHANGELOG.md ├── LICENSE.md ├── Makefile ├── README.md ├── addon ├── .editorconfig ├── LICENSE.md ├── bootstrap.js ├── chrome.manifest ├── chrome │ ├── content │ │ └── zutilo │ │ │ ├── keyconfig_adapted.js │ │ │ ├── keys.js │ │ │ ├── preferences.js │ │ │ ├── preferences.xhtml │ │ │ ├── readme.xul │ │ │ ├── zoteroOverlay.js │ │ │ ├── zutilo.js │ │ │ └── zutiloChrome.js │ └── locale │ │ ├── de │ │ └── zutilo │ │ │ └── zutilo.properties │ │ ├── en-US │ │ └── zutilo │ │ │ └── zutilo.properties │ │ ├── es │ │ └── zutilo │ │ │ └── zutilo.properties │ │ ├── fr │ │ └── zutilo │ │ │ └── zutilo.properties │ │ └── zh-CN │ │ └── zutilo │ │ └── zutilo.properties ├── install.rdf ├── locale │ ├── de │ │ └── zutilo.ftl │ ├── en-US │ │ └── zutilo.ftl │ ├── es │ │ └── zutilo.ftl │ ├── fr │ │ └── zutilo.ftl │ └── zh-CN │ │ └── zutilo.ftl ├── manifest.json ├── zutilo.png └── zutilo64.png ├── assets ├── Screen_shot_address_bar_icon_menu.png ├── Screen_shot_content_area_context_menu.png ├── Screen_shot_item_menu.png └── Screen_shot_preferences_ui.png ├── deploy ├── .gitignore ├── config.yaml ├── update.rdf └── updates.json ├── docs ├── BUGS.md ├── COMMANDS.md ├── DEVELOPERS.md └── USAGE.md ├── i18n ├── de │ └── readme │ │ ├── AUTHORS.md │ │ ├── CHANGELOG.md │ │ ├── LICENSE.md │ │ ├── README.md │ │ └── docs │ │ ├── BUGS.md │ │ ├── COMMANDS.md │ │ ├── DEVELOPERS.md │ │ └── USAGE.md ├── en-US │ └── readme │ │ ├── AUTHORS.md │ │ ├── CHANGELOG.md │ │ ├── LICENSE.md │ │ ├── README.md │ │ └── docs │ │ ├── BUGS.md │ │ ├── COMMANDS.md │ │ ├── DEVELOPERS.md │ │ └── USAGE.md ├── es │ └── readme │ │ ├── AUTHORS.md │ │ ├── CHANGELOG.md │ │ ├── LICENSE.md │ │ ├── README.md │ │ └── docs │ │ ├── BUGS.md │ │ ├── COMMANDS.md │ │ ├── DEVELOPERS.md │ │ └── USAGE.md ├── fr │ └── readme │ │ ├── AUTHORS.md │ │ ├── CHANGELOG.md │ │ ├── LICENSE.md │ │ ├── README.md │ │ └── docs │ │ ├── BUGS.md │ │ ├── COMMANDS.md │ │ ├── DEVELOPERS.md │ │ └── USAGE.md └── zh-CN │ └── readme │ ├── AUTHORS.md │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ └── docs │ ├── BUGS.md │ ├── COMMANDS.md │ ├── DEVELOPERS.md │ └── USAGE.md ├── jsconfig.json ├── package-lock.json ├── package.json ├── scripts ├── git_hooks │ ├── copy_docs_to_locale.py │ ├── pre-commit │ └── setup_hooks.sh ├── substitute_relative_links └── update_non_english.py └── zotero7_todo.txt /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "es6": true, 4 | "node": true 5 | }, 6 | "extends": "eslint:recommended", 7 | "globals": { 8 | "Atomics": "readonly", 9 | "SharedArrayBuffer": "readonly" 10 | }, 11 | "parserOptions": { 12 | "ecmaVersion": 2018 13 | }, 14 | "rules": { 15 | "accessor-pairs": "error", 16 | "array-bracket-newline": "off", 17 | "array-bracket-spacing": [ 18 | "error", 19 | "never" 20 | ], 21 | "array-callback-return": "error", 22 | "array-element-newline": "off", 23 | "arrow-body-style": "error", 24 | "arrow-parens": "error", 25 | "arrow-spacing": "error", 26 | "block-scoped-var": "off", 27 | "block-spacing": [ 28 | "error", 29 | "never" 30 | ], 31 | "brace-style": "off", 32 | "callback-return": "error", 33 | "camelcase": "off", 34 | "capitalized-comments": "off", 35 | "class-methods-use-this": "off", 36 | "comma-dangle": "error", 37 | "comma-spacing": [ 38 | "error", 39 | { 40 | "after": true, 41 | "before": false 42 | } 43 | ], 44 | "comma-style": [ 45 | "error", 46 | "last" 47 | ], 48 | "complexity": "off", 49 | "computed-property-spacing": [ 50 | "error", 51 | "never" 52 | ], 53 | "consistent-return": "off", 54 | "consistent-this": "error", 55 | "curly": "off", 56 | "default-case": "off", 57 | "dot-location": "off", 58 | "dot-notation": [ 59 | "error", 60 | { 61 | "allowKeywords": true 62 | } 63 | ], 64 | "eol-last": "error", 65 | "eqeqeq": "off", 66 | "func-call-spacing": "error", 67 | "func-name-matching": "error", 68 | "func-names": "off", 69 | "func-style": "off", 70 | "function-paren-newline": "off", 71 | "generator-star-spacing": "off", 72 | "global-require": "error", 73 | "guard-for-in": "off", 74 | "handle-callback-err": "error", 75 | "id-blacklist": "error", 76 | "id-length": "off", 77 | "id-match": "error", 78 | "implicit-arrow-linebreak": "error", 79 | "indent": "off", 80 | "indent-legacy": "off", 81 | "init-declarations": "off", 82 | "jsx-quotes": "error", 83 | "key-spacing": "error", 84 | "keyword-spacing": "off", 85 | "line-comment-position": "off", 86 | "linebreak-style": [ 87 | "error", 88 | "unix" 89 | ], 90 | "lines-around-comment": "off", 91 | "lines-around-directive": "off", 92 | "lines-between-class-members": "error", 93 | "max-classes-per-file": "off", 94 | "max-depth": "off", 95 | "max-len": ["error", { "code": 520, "ignoreComments": true }], 96 | "max-lines": "off", 97 | "max-lines-per-function": "off", 98 | "max-nested-callbacks": "error", 99 | "max-params": "off", 100 | "max-statements": "off", 101 | "max-statements-per-line": "off", 102 | "multiline-comment-style": "off", 103 | "multiline-ternary": "off", 104 | "new-parens": "off", 105 | "newline-after-var": "off", 106 | "newline-before-return": "off", 107 | "newline-per-chained-call": "error", 108 | "no-alert": "error", 109 | "no-array-constructor": "error", 110 | "no-await-in-loop": "off", 111 | "no-bitwise": "error", 112 | "no-buffer-constructor": "error", 113 | "no-caller": "error", 114 | "no-catch-shadow": "error", 115 | "no-confusing-arrow": "error", 116 | "no-console": "error", 117 | "no-continue": "off", 118 | "no-div-regex": "error", 119 | "no-duplicate-imports": "error", 120 | "no-else-return": "off", 121 | "no-empty-function": "off", 122 | "no-eq-null": "error", 123 | "no-eval": "error", 124 | "no-extend-native": "error", 125 | "no-extra-bind": "error", 126 | "no-extra-label": "error", 127 | "no-extra-parens": "off", 128 | "no-floating-decimal": "error", 129 | "no-implicit-coercion": "error", 130 | "no-implicit-globals": "error", 131 | "no-implied-eval": "error", 132 | "no-inline-comments": "off", 133 | "no-inner-declarations": [ 134 | "error", 135 | "functions" 136 | ], 137 | "no-invalid-this": "off", 138 | "no-iterator": "error", 139 | "no-label-var": "error", 140 | "no-labels": "error", 141 | "no-lone-blocks": "error", 142 | "no-lonely-if": "off", 143 | "no-loop-func": "error", 144 | "no-magic-numbers": "off", 145 | "no-mixed-operators": "error", 146 | "no-mixed-requires": "error", 147 | "no-multi-assign": "off", 148 | "no-multi-spaces": "off", 149 | "no-multi-str": "error", 150 | "no-multiple-empty-lines": "error", 151 | "no-native-reassign": "error", 152 | "no-negated-condition": "error", 153 | "no-negated-in-lhs": "error", 154 | "no-nested-ternary": "error", 155 | "no-new": "error", 156 | "no-new-func": "error", 157 | "no-new-object": "error", 158 | "no-new-require": "error", 159 | "no-new-wrappers": "error", 160 | "no-octal-escape": "error", 161 | "no-param-reassign": "off", 162 | "no-path-concat": "error", 163 | "no-plusplus": "off", 164 | "no-process-env": "error", 165 | "no-process-exit": "error", 166 | "no-proto": "error", 167 | "no-prototype-builtins": "off", 168 | "no-restricted-globals": "error", 169 | "no-restricted-imports": "error", 170 | "no-restricted-modules": "error", 171 | "no-restricted-properties": "error", 172 | "no-restricted-syntax": "error", 173 | "no-return-assign": "error", 174 | "no-return-await": "error", 175 | "no-script-url": "error", 176 | "no-self-compare": "error", 177 | "no-sequences": "error", 178 | "no-shadow": "off", 179 | "no-spaced-func": "error", 180 | "no-sync": "error", 181 | "no-tabs": [ 182 | "error", 183 | { 184 | "allowIndentationTabs": true 185 | } 186 | ], 187 | "no-template-curly-in-string": "error", 188 | "no-ternary": "off", 189 | "no-throw-literal": "error", 190 | "no-trailing-spaces": "error", 191 | "no-undef-init": "error", 192 | "no-undefined": "off", 193 | "no-underscore-dangle": "off", 194 | "no-unmodified-loop-condition": "error", 195 | "no-unneeded-ternary": "error", 196 | "no-unused-expressions": "error", 197 | "no-unused-vars": [ "error", { "argsIgnorePattern": "^_" } ], 198 | "no-use-before-define": "off", 199 | "no-useless-call": "error", 200 | "no-useless-computed-key": "error", 201 | "no-useless-concat": "error", 202 | "no-useless-constructor": "error", 203 | "no-useless-rename": "error", 204 | "no-useless-return": "error", 205 | "no-var": "off", 206 | "no-void": "error", 207 | "no-warning-comments": "off", 208 | "no-whitespace-before-property": "error", 209 | "nonblock-statement-body-position": "error", 210 | "object-curly-newline": "error", 211 | "object-curly-spacing": "off", 212 | "object-shorthand": "off", 213 | "one-var": "off", 214 | "one-var-declaration-per-line": [ 215 | "error", 216 | "initializations" 217 | ], 218 | "operator-assignment": "off", 219 | "operator-linebreak": [ 220 | "error", 221 | "after" 222 | ], 223 | "padded-blocks": "off", 224 | "padding-line-between-statements": "error", 225 | "prefer-arrow-callback": "off", 226 | "prefer-const": "off", 227 | "prefer-destructuring": "off", 228 | "prefer-named-capture-group": "off", 229 | "prefer-numeric-literals": "error", 230 | "prefer-object-spread": "error", 231 | "prefer-promise-reject-errors": "error", 232 | "prefer-reflect": "off", 233 | "prefer-rest-params": "error", 234 | "prefer-spread": "error", 235 | "prefer-template": "off", 236 | "quote-props": "off", 237 | "quotes": "off", 238 | "radix": "error", 239 | "require-await": "error", 240 | "require-jsdoc": "off", 241 | "require-unicode-regexp": "off", 242 | "rest-spread-spacing": "error", 243 | "semi": "off", 244 | "semi-spacing": "off", 245 | "semi-style": [ 246 | "error", 247 | "last" 248 | ], 249 | "sort-imports": "error", 250 | "sort-keys": "off", 251 | "sort-vars": "off", 252 | "space-before-blocks": "off", 253 | "space-before-function-paren": "off", 254 | "space-in-parens": [ 255 | "error", 256 | "never" 257 | ], 258 | "space-infix-ops": "off", 259 | "space-unary-ops": "error", 260 | "spaced-comment": "off", 261 | "strict": "error", 262 | "switch-colon-spacing": "error", 263 | "symbol-description": "error", 264 | "template-curly-spacing": "error", 265 | "template-tag-spacing": "error", 266 | "unicode-bom": [ 267 | "error", 268 | "never" 269 | ], 270 | "valid-jsdoc": "off", 271 | "vars-on-top": "off", 272 | "wrap-iife": "error", 273 | "wrap-regex": "error", 274 | "yield-star-spacing": "error", 275 | "yoda": "off" 276 | } 277 | } 278 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | build/ 4 | addon/chrome/locale/*/zutilo/README.html 5 | *.sw* 6 | *~ 7 | \#*# 8 | -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "disallowKeywords": ["with"], 3 | "disallowKeywordsOnNewLine": ["else"], 4 | "disallowMixedSpacesAndTabs": true, 5 | "disallowMultipleVarDecl": "exceptUndefined", 6 | "disallowNewlineBeforeBlockStatements": true, 7 | "disallowQuotedKeysInObjects": true, 8 | "disallowSpaceAfterObjectKeys": true, 9 | "disallowSpaceAfterPrefixUnaryOperators": true, 10 | "disallowSpacesInFunction": { 11 | "beforeOpeningRoundBrace": true 12 | }, 13 | "disallowSpacesInsideParentheses": true, 14 | "disallowTrailingWhitespace": true, 15 | "maximumLineLength": 80, 16 | "requireCamelCaseOrUpperCaseIdentifiers": true, 17 | "requireCapitalizedConstructors": true, 18 | "requireCurlyBraces": [ 19 | "if", 20 | "else", 21 | "for", 22 | "while", 23 | "do", 24 | "try", 25 | "catch" 26 | ], 27 | "requireSpaceAfterKeywords": [ 28 | "if", 29 | "else", 30 | "for", 31 | "while", 32 | "do", 33 | "switch", 34 | "case", 35 | "return", 36 | "try", 37 | "catch", 38 | "typeof" 39 | ], 40 | "requireSpaceAfterLineComment": true, 41 | "requireSpaceAfterBinaryOperators": true, 42 | "requireSpaceBeforeBinaryOperators": true, 43 | "requireSpaceBeforeBlockStatements": true, 44 | "requireSpaceBeforeObjectValues": true, 45 | "requireSpacesInFunction": { 46 | "beforeOpeningCurlyBrace": true 47 | }, 48 | "disallowTrailingComma": true, 49 | "validateIndentation": 4, 50 | "validateLineBreaks": "LF", 51 | "validateQuoteMarks": "'" 52 | } 53 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "asi": true, 3 | "globalstrict": true, 4 | "moz": true 5 | } 6 | -------------------------------------------------------------------------------- /.tern-project: -------------------------------------------------------------------------------- 1 | { 2 | "libs": [ 3 | "browser", 4 | "ecma6" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.tx/config: -------------------------------------------------------------------------------- 1 | [main] 2 | host = https://www.transifex.com 3 | lang_map = zh: zh-CN 4 | 5 | [zutilo.zutilodtd] 6 | file_filter = addon/chrome/locale//zutilo/zutilo.dtd 7 | source_file = addon/chrome/locale/en-US/zutilo/zutilo.dtd 8 | source_lang = en 9 | type = DTD 10 | 11 | [zutilo.zutiloproperties] 12 | file_filter = addon/chrome/locale//zutilo/zutilo.properties 13 | source_file = addon/chrome/locale/en-US/zutilo/zutilo.properties 14 | source_lang = en 15 | type = MOZILLAPROPERTIES 16 | 17 | [zutilo.readme] 18 | file_filter = i18n//readme/README.md 19 | source_file = i18n/en-US/readme/README.md 20 | source_lang = en 21 | type = TXT 22 | 23 | [zutilo.license] 24 | file_filter = i18n//readme/LICENSE.md 25 | source_file = i18n/en-US/readme/LICENSE.md 26 | source_lang = en 27 | type = TXT 28 | 29 | [zutilo.changelog] 30 | file_filter = i18n//readme/CHANGELOG.md 31 | source_file = i18n/en-US/readme/CHANGELOG.md 32 | source_lang = en 33 | type = TXT 34 | 35 | [zutilo.authors] 36 | file_filter = i18n//readme/AUTHORS.md 37 | source_file = i18n/en-US/readme/AUTHORS.md 38 | source_lang = en 39 | type = TXT 40 | 41 | [zutilo.bugs] 42 | file_filter = i18n//readme/docs/BUGS.md 43 | source_file = i18n/en-US/readme/docs/BUGS.md 44 | source_lang = en 45 | type = TXT 46 | 47 | [zutilo.commands] 48 | file_filter = i18n//readme/docs/COMMANDS.md 49 | source_file = i18n/en-US/readme/docs/COMMANDS.md 50 | source_lang = en 51 | type = TXT 52 | 53 | [zutilo.developers] 54 | file_filter = i18n//readme/docs/DEVELOPERS.md 55 | source_file = i18n/en-US/readme/docs/DEVELOPERS.md 56 | source_lang = en 57 | type = TXT 58 | 59 | [zutilo.usage] 60 | file_filter = i18n//readme/docs/USAGE.md 61 | source_file = i18n/en-US/readme/docs/USAGE.md 62 | source_lang = en 63 | type = TXT 64 | 65 | -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | Zutilo is modeled on the Firefox extension format suggested in the [XUL School tutorial](https://developer.mozilla.org/en-US/docs/XUL_School). 2 | Additionally, examples were taken from the [Mozilla Developer Network](https://developer.mozilla.org/) documentation and the Zotero source code. 3 | It's shortcut features were modeled on those implemented by [Keyconfig extension](http://forums.mozillazine.org/viewtopic.php?t=72994). 4 | Patches submitted by bjohas, bwiernik, and gracile-fr via GitHub. 5 | Translation support was provided by Armin Stroß-Radschinski, Goofy, gracile-fr, Urko, and Wang H. K. 6 | 7 | If you want an attribution added or modified, please contact the author. 8 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | * In version 4.0.1: 2 | 3 | + Fixes for Zotero 7.1 4 | 5 | * In version 4.0.0: 6 | 7 | + Fixes for Zotero 7.0 8 | + New copy item IDs function 9 | 10 | * In version 3.10.0: 11 | 12 | + Fixes for Zotero 5.0.97-beta and upcoming Zotero 6 13 | 14 | * In version 3.9.0: 15 | 16 | + Fix Open Style Editor shortcut 17 | + Add Open Run JavaScript window shortcut 18 | + Add mdnotes shortcuts 19 | + Update French translations 20 | 21 | * In version 3.8.1: 22 | 23 | + Update French translations 24 | + Fix ZotFile Quick Extract shortcut 25 | + Fix show file shortcut 26 | 27 | * In version 3.8.0: 28 | 29 | + Add find available PDFs shortcut 30 | 31 | * In version 3.7.0: 32 | 33 | + Add ZotFile Quick Extract shortcut 34 | 35 | * In version 3.6.1: 36 | 37 | + Update French locale 38 | 39 | * In version 3.6.0: 40 | 41 | + Add "Paste item type" function for batch item type changes 42 | + Update French locale 43 | + Documentation updates 44 | 45 | * In version 3.5.0: 46 | 47 | + Add "Open Zotero URI" function 48 | + Allow arbitrary number of alt quick copy functions 49 | + Fix "Retrieve metadata for PDF" shortcut 50 | + Update French locale 51 | 52 | * In version 3.4.0: 53 | 54 | + Added shortcut for pushing reference to TeXstudio with Better BibTeX 55 | + Add "Advanced search" shortcut 56 | + Add "Locate item" shortcut 57 | + Add "Show Locate menu" shortcut 58 | + Add tag selector shortcuts: 59 | - Toggle displaying automatic tags 60 | - Toggle displaying all tags 61 | - Deselect all tags 62 | - Focus search box 63 | 64 | * In version 3.3.3: 65 | 66 | + Filter attachments by mode before trying to modify paths 67 | 68 | * In version 3.3.2: 69 | 70 | + Fix mishandling of attachments with paths that did not match the old path pattern in the modify attachments function. 71 | 72 | * In version 3.3.1: 73 | 74 | + Fix add tag shortcut for Zotero 5.0.78 75 | 76 | * In version 3.3.0: 77 | 78 | + Added shortcut for ZotFile's move and rename attachment 79 | 80 | * In version 3.2.1: 81 | 82 | + Compatibility updates for Zotero 5.0.75 83 | 84 | * In version 3.2.0: 85 | 86 | + Drop support for Zotero as a Firefox addon and for Zotero 4.x 87 | + Update item select link to newer format used by recent version of Zotero 88 | + Add functions to copy select links and web links to collections 89 | + Add copy/paste item field functions 90 | 91 | * In version 3.1.0: 92 | 93 | + Update Chinese translation 94 | + Add "Link to File..." shortcut 95 | + Add "Show file" shortcut 96 | + Add "Attach new file" shortcut for ZotFile 97 | 98 | * In version 3.0.3: 99 | 100 | + Fix French locale 101 | 102 | * In version 3.0.2: 103 | 104 | + Add shortcuts for BetterBibTeX 105 | 106 | * In version 3.0.1: 107 | 108 | + Update base URL used for copying Zotero web links 109 | 110 | * In version 3.0.0: 111 | 112 | + Zutilo is now distributed on from [its GitHub releases page](https://github.com/willsalmanj/zutilo/releases). Starting with version 3.0, new releases will not be uploaded to addons.mozilla.org and will use the GitHub page to check for updates. 113 | + New function to modify linked URL attachments 114 | + New shortcut for adding items by identifier 115 | + Minor bug fixes 116 | - Don't change clipboard when no valid items copied 117 | - Add Zutilo preferences to Tools menu on all platforms 118 | 119 | * In version 2.0.3: 120 | 121 | + Improved French locale (thanks to gracile-fr) 122 | + Add preferences menu item to the global menu in Zotero 5.0 (thanks to gracile-fr) 123 | 124 | * In version 2.0.2: 125 | 126 | + Allow some functions (like copy tags) to work on attachments and notes as well as regular items. 127 | 128 | * In version 2.0.1: 129 | 130 | + Fix bug that made Zutilo not work at all in Zotero Standalone 131 | 132 | * In version 2.0.0: 133 | 134 | 1. New function: copy attachment paths to clipboard 135 | 2. Many compatibility fixes for Zotero 5.0 136 | 137 | * In version 1.4.0: 138 | 139 | 1. Shortcuts for attaching stored files and URI links 140 | 2. Sort shortcuts by category 141 | 3. Hide most item menu functions by default 142 | 143 | * In version 1.3.0: 144 | 145 | - New features 146 | 147 | 1. New shortcuts/menu items: 148 | - Copy Zotero select link 149 | - Copy Zotero URI 150 | 2. New shortcuts: 151 | - Focus collections, items pane, and various item pane tabs 152 | - Attachments: recognize PDF, create parent item, and rename from parent 153 | - Toggle visiblity of collections and item pane 154 | 3. New remove tags function 155 | 4. Create book item from book section item and vice versa 156 | 5. Move notes/attachments from one item to another 157 | 158 | - Bugfixes 159 | 160 | 1. Fix bug in relating items 161 | 2. Fix item saving toolbar menu items and keyboard shortcuts 162 | 3. Minor fix for handling different attachment types correctly. 163 | 4. Preferences window bug fix 164 | 5. Update the Save to Zotero menupopup items to work with the new Zotero / Save to Zotero combo button. 165 | 6. Allow the duplicate item shortcut to work in Zotero Standalone. 166 | 167 | * In version 1.2.5: 168 | 169 | 1. keyboard shortcuts were added to Zutilo and a QuickCopy menu item was added. 170 | 2. A bug that prevented Zutilo from loading into Zotero's Firefox tab was fixed. 171 | 3. A partial zh-CN locale was added. 172 | 173 | * In version 1.2.4, fr, es, and de locales were added (please report any translation errors (along with better translations)!). 174 | 175 | * In version 1.2.3, functions were added to attach pages and links in Firefox to the currently selected Zotero item and to save the current page to Zotero with attachments if the default setting is to save without attachments (or to save without attachments if the default setting is to save with them). 176 | 177 | * As of version 1.2.1, Zutilo can be installed and uninstalled without restarting Firefox. 178 | 179 | * As of version 1.1.17, changes made with modifyAttachments should always persist after restarting Firefox. 180 | 181 | * As of version 1.1.16, modifyAttachments can now replace elements of the path other than the beginning. 182 | 183 | * As of version 1.1.15, modifyAttachments should actually work with Windows paths. 184 | 185 | * As of version 1.1.11, the main JavaScript object that Zutilo creates to add functionality to Zotero has been renamed from "Zotero.Zutilo" to "ZutiloChrome.zoteroOverlay". 186 | Any keyboard shortcuts calling methods of this object need to switch names in order to keep working. 187 | 188 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | BLDDIR = build 2 | 3 | LOCALES := $(shell ls i18n) 4 | 5 | INTERNAL_READMES := $(patsubst %, addon/chrome/locale/%/zutilo/README.html, $(LOCALES)) 6 | 7 | # Necessary because zip copies leading directories if run from above targets 8 | ABS_BLDDIR := $(shell realpath $(BLDDIR)) 9 | 10 | all: xpi 11 | 12 | 0x0: $(BLDDIR)/zutilo.xpi 13 | curl -F'file=@$(BLDDIR)/zutilo.xpi' https://0x0.st 14 | 15 | xpi: $(BLDDIR)/zutilo.xpi 16 | 17 | $(BLDDIR)/zutilo.xpi: $(INTERNAL_READMES) 18 | @mkdir -p $(dir $@) 19 | cd addon; zip -FSr $(ABS_BLDDIR)/zutilo.xpi * -x \*.swp 20 | 21 | addon/chrome/locale/%/zutilo/README.html: 22 | @mkdir -p $(BLDDIR)/internal_readme/$* 23 | scripts/substitute_relative_links i18n/$*/readme/README.md $(BLDDIR)/internal_readme/$*/README.md 24 | pandoc -f markdown_strict -t html \ 25 | $(BLDDIR)/internal_readme/$*/README.md > \ 26 | addon/chrome/locale/$*/zutilo/README.html 27 | 28 | clean: 29 | rm -f $(BLDDIR)/zutilo.xpi 30 | rm -f $(INTERNAL_READMES) 31 | rm -f $(AMO_READMES) 32 | rm -rf $(BLDDIR)/internal_readme/* 33 | 34 | .PHONY: all clean xpi 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Zutilo 2 | Zutilo is a plugin for [Zotero](http://www.zotero.org/). 3 | Zutilo adds several functions not available in base Zotero through extra menu items and keyboard shortcuts. 4 | Here are some of Zutilo's features: 5 | 6 | * Copy, paste, and remove sets of tags 7 | * Select and right-click to relate several items 8 | * Copy items to the clipboard in several formats 9 | * Keyboard shortcuts for editing items and focusing and hiding different elements of the Zotero user interface 10 | 11 | Zutilo strives to enable whatever Zotero workflow is desired and otherwise to get out of the way. 12 | All of Zutilo's graphical elements can be disabled individually, so that unwanted features do not clutter the user interface. 13 | 14 | > [!NOTE] 15 | > Zutilo is largely maintained by one person (@wshanks) who does not have much time for Zutilo any more. 16 | > @wshanks still uses Zotero but not as heavily and so has less need for the power user features of Zutilo. 17 | > Additional help adapting to new releases of Zotero and fixing other bugs is very welcome. 18 | > Without additional contributors, Zutilo may not be able to keep compatibility with future releases of Zotero. 19 | > As of Zotero version 7.0, some features of Zutilo, mainly keyboard shortcuts, no longer function. 20 | > There was also a long gap between the release of Zotero 7 and a release of Zutilo that could be installed with it. 21 | 22 | ## Installation 23 | 24 | Download the Zutilo `zutilo.xpi` file from [Zutilo's GitHub releases page](https://github.com/wshanks/Zutilo/releases). 25 | Then go to Tools->Add-ons in Zotero Standalone. 26 | Click on the gear button in the upper right area of the Add-ons Manager window that appears and choose "Install Add-on From File." 27 | Then select the downloaded `zutilo.xpi` file. 28 | 29 | **NOTE for Firefox users:** Firefox treats `.xpi` files as Firefox add-ons and tries to install them. 30 | Rather than clicking on the `.xpi` file, you can try right-clicking and choosing to save the link as a file. 31 | In some cases (particularly on Linux), Firefox does not allow right-clicking and saving the `.xpi` link either. 32 | In that case, you must download it either with a different browser or with a command-line tool like `curl` or `wget`. 33 | 34 | ## Getting started 35 | 36 | Zutilo can be customized via its preferences window, which can reached via the Zotero Addons Manager or the Tools menu. 37 | 38 | ### Zotero item menu 39 | 40 | By default, Zutilo adds a set of menu items to a submenu (named `Zutilo`) of the menu that appears when an item is right-clicked in Zotero. 41 | Which items appear can be set in Zutilo's preferences window. 42 | Items can be set to appear in the Zutilo submenu or directly in the Zotero item menu. 43 | Not all available functions are visible in Zutilo submenu by default. 44 | 45 | ### Keyboard shortcuts 46 | 47 | All of the functions that can appear in the item menu can also be called by keyboard shortcuts. 48 | Zutilo also provides some additional keyboard shortcut functions that are not available from the item menu. 49 | By default, no keyboard shortcuts are defined. 50 | A shortcut key combination can be set for each function in Zutilo's preferences. 51 | If the key combination is already assigned for another function, a warning will be displayed. 52 | 53 | ## Usage notes 54 | 55 | For additional notes on usage, see [USAGE](docs/USAGE.md). 56 | 57 | ## Command reference 58 | 59 | For a detailed list of Zutilo's commands, please see the [command reference](docs/COMMANDS.md). 60 | 61 | ## Support 62 | 63 | For guidelines regarding bug reports, feature requests, and translation help, please see the [feedback page](docs/BUGS.md). 64 | 65 | ## Development 66 | 67 | For notes on working with the Zutilo code, please see the [build document](docs/DEVELOPERS.md). 68 | 69 | ## Credits 70 | 71 | For a list of acknowledgments, please see the [author page](AUTHORS.md). 72 | 73 | ## Changes 74 | 75 | For a summary changes by version number, please see the [changelog](CHANGELOG.md). 76 | 77 | ## How to Contribute 78 | 79 | 1. Star the repository on GitHub. The number of stars on GitHub is one of the most visible metrics for gauging the level of interest in project. 80 | 2. Encourage others to use the project, either directly or by writing a blog post. Besides GitHub stars, the other metric for gauging interest in the project is the total number of downloads of the xpi. 81 | 3. Submit new features or translations. However, keep in mind that new features add to the maintenance burden of the project. So get in contact before putting a lot of time into a new feature. 82 | -------------------------------------------------------------------------------- /addon/.editorconfig: -------------------------------------------------------------------------------- 1 | [*.js] 2 | indent_style = space 3 | indent_size = 4 4 | -------------------------------------------------------------------------------- /addon/bootstrap.js: -------------------------------------------------------------------------------- 1 | /* Copyright 2012 Will Shanks. 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 | 6 | "use strict"; 7 | /* global Components, Services */ 8 | /* global Zutilo, APP_SHUTDOWN */ 9 | const {classes: Cc, utils: Cu} = Components; 10 | var chromeHandle 11 | 12 | Cu.import("resource://gre/modules/Services.jsm"); 13 | 14 | // eslint-disable-next-line no-unused-vars 15 | function install(data, reason) { 16 | 17 | } 18 | 19 | // eslint-disable-next-line no-unused-vars 20 | function startup(data, reason) { 21 | let aomStartup = Cc["@mozilla.org/addons/addon-manager-startup;1"].getService(Ci.amIAddonManagerStartup) 22 | let manifestURI = Services.io.newURI(data.rootURI + "manifest.json"); 23 | chromeHandle = aomStartup.registerChrome(manifestURI, [ 24 | ["content", "zutilo", "chrome/content/zutilo/"], 25 | ["locale", "zutilo", "en-US", "chrome/locale/en-US/zutilo/"], 26 | ["locale", "zutilo", "de", "chrome/locale/de/zutilo/"], 27 | ["locale", "zutilo", "es", "chrome/locale/es/zutilo/"], 28 | ["locale", "zutilo", "fr", "chrome/locale/fr/zutilo/"], 29 | ["locale", "zutilo", "zh-CN", "chrome/locale/zh-CN/zutilo/"] 30 | ]) 31 | 32 | Cu.import("chrome://zutilo/content/zutilo.js"); 33 | Zutilo.init(data.rootURI, Zotero); 34 | } 35 | 36 | // eslint-disable-next-line no-unused-vars 37 | function shutdown(data, reason) { 38 | if (reason == APP_SHUTDOWN) { 39 | return; 40 | } 41 | 42 | var windows = Services.wm.getEnumerator('navigator:browser'); 43 | while (windows.hasMoreElements()) { 44 | var tmpWin=windows.getNext(); 45 | 46 | tmpWin.ZutiloChrome.removeXUL(); 47 | if (typeof tmpWin.ZutiloChrome.zoteroOverlay != 'undefined') { 48 | tmpWin.ZutiloChrome.zoteroOverlay.unload(); 49 | } 50 | delete tmpWin.ZutiloChrome; 51 | delete tmpWin.Zutilo; 52 | } 53 | 54 | Zutilo.cleanup(); 55 | chromeHandle.destruct() 56 | chromeHandle = null 57 | 58 | Cc["@mozilla.org/intl/stringbundle;1"]. 59 | getService(Components.interfaces.nsIStringBundleService).flushBundles(); 60 | 61 | Cu.unload("chrome://zutilo/content/zutilo.js"); 62 | } 63 | 64 | // eslint-disable-next-line no-unused-vars 65 | function uninstall(data, reason) { 66 | 67 | } 68 | -------------------------------------------------------------------------------- /addon/chrome.manifest: -------------------------------------------------------------------------------- 1 | content zutilo chrome/content/zutilo/ 2 | skin zutilo default chrome/skin/default/zutilo/ 3 | locale zutilo en-US chrome/locale/en-US/zutilo/ 4 | locale zutilo de chrome/locale/de/zutilo/ 5 | locale zutilo es chrome/locale/es/zutilo/ 6 | locale zutilo fr chrome/locale/fr/zutilo/ 7 | locale zutilo zh-CN chrome/locale/zh-CN/zutilo/ 8 | -------------------------------------------------------------------------------- /addon/chrome/content/zutilo/preferences.js: -------------------------------------------------------------------------------- 1 | /* Copyright 2012 Will Shanks. 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 | 6 | 'use strict'; 7 | /* global window, document, Components */ 8 | /* global keyconfigOnLoad, Zutilo */ 9 | Components.utils.import('chrome://zutilo/content/zutilo.js'); 10 | 11 | // eslint-disable-next-line no-unused-vars 12 | function initializePrefWindow() { 13 | // keyconfigOnLoad(); 14 | } 15 | 16 | // eslint-disable-next-line no-unused-vars 17 | function buildMenuPrefs() { 18 | for (const menuName of ['item', 'collection']) { 19 | for (const functionName of Zutilo._menuFunctions[menuName]) { 20 | addMenuRadiogroup(menuName, functionName); 21 | } 22 | } 23 | } 24 | 25 | function addMenuRadiogroup(menuName, menuFunction) { 26 | var newRow = document.createXULElement('groupbox'); 27 | 28 | var newHbox = document.createXULElement('hbox'); 29 | newHbox.setAttribute('align', 'center'); 30 | var newLabel = document.createXULElement('label'); 31 | newLabel.setAttribute( 32 | 'value', 33 | Zutilo.getString(`zutilo.preferences.${menuName}menu.${menuFunction}`) 34 | ) 35 | newHbox.appendChild(newLabel); 36 | newRow.appendChild(newHbox); 37 | 38 | var newRadiogroup = document.createXULElement('radiogroup'); 39 | newRadiogroup.setAttribute('orient', 'horizontal'); 40 | newRadiogroup.setAttribute('align', 'center'); 41 | newRadiogroup.setAttribute('preference', 42 | `extensions.zutilo.${menuName}menu.${menuFunction}`); 43 | 44 | var newRadio; 45 | for (const label of ['Zotero', 'Zutilo', 'Hide']) { 46 | newRadio = document.createXULElement('radio'); 47 | newRadio.setAttribute( 48 | 'label', 49 | Zutilo.getString(`zutilo.preferences.${menuName}menu.${label}`) 50 | ) 51 | newRadio.setAttribute('value', label); 52 | newRadiogroup.appendChild(newRadio); 53 | } 54 | 55 | newRow.appendChild(newRadiogroup); 56 | 57 | var menuRows = document.getElementById(`zutilo-prefpane-${menuName}-rows`); 58 | menuRows.appendChild(newRow); 59 | } 60 | 61 | // eslint-disable-next-line no-unused-vars 62 | function showReadme() { 63 | window.openDialog('chrome://zutilo/content/readme.xul', 64 | 'zutilo-readme-window', 'chrome'); 65 | } 66 | -------------------------------------------------------------------------------- /addon/chrome/content/zutilo/preferences.xhtml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 28 | 29 | 33 | 34 | 38 | 39 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 51 |