├── src ├── css │ ├── popup.css │ └── options.css ├── img │ ├── close.png │ ├── icon.png │ ├── open.png │ ├── icon-34.png │ └── icon-128.png ├── js │ ├── Options │ │ ├── Translation.svelte │ │ ├── Shortcuts.svelte │ │ ├── Contact.svelte │ │ ├── ShortcutInput.svelte │ │ ├── index.svelte │ │ ├── DirectorySelect.svelte │ │ ├── Miscellaneous.svelte │ │ ├── Appearance.svelte │ │ └── Behaviors.svelte │ ├── popup.js │ ├── options.js │ ├── Popup │ │ ├── URL.svelte │ │ ├── CustomStyle.svelte │ │ ├── Children.svelte │ │ ├── Node.svelte │ │ ├── index.svelte │ │ └── behaviors.js │ ├── background.js │ └── store.js ├── background.html ├── popup.html ├── options.html ├── manifest.json └── _locales │ ├── zh_CN │ └── messages.json │ ├── zh_TW │ └── messages.json │ └── en │ └── messages.json ├── .gitignore ├── utils ├── env.js ├── build.js └── webserver.js ├── README.md ├── package.json ├── LICENSE.md └── webpack.config.js /src/css/popup.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/css/options.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | secrets.*.js 4 | build.crx 5 | build.pem 6 | -------------------------------------------------------------------------------- /src/img/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ayamomiji/bookmark-tree/HEAD/src/img/close.png -------------------------------------------------------------------------------- /src/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ayamomiji/bookmark-tree/HEAD/src/img/icon.png -------------------------------------------------------------------------------- /src/img/open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ayamomiji/bookmark-tree/HEAD/src/img/open.png -------------------------------------------------------------------------------- /src/img/icon-34.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ayamomiji/bookmark-tree/HEAD/src/img/icon-34.png -------------------------------------------------------------------------------- /src/img/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ayamomiji/bookmark-tree/HEAD/src/img/icon-128.png -------------------------------------------------------------------------------- /src/js/Options/Translation.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | {chrome.i18n.getMessage(key) || `translation missing: ${key}`} 6 | -------------------------------------------------------------------------------- /src/background.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/js/popup.js: -------------------------------------------------------------------------------- 1 | import '../img/open.png' 2 | import '../img/close.png' 3 | 4 | import Popup from './Popup/index.svelte' 5 | 6 | new Popup({ 7 | target: document.body 8 | }) 9 | -------------------------------------------------------------------------------- /utils/env.js: -------------------------------------------------------------------------------- 1 | // tiny wrapper with default env vars 2 | module.exports = { 3 | NODE_ENV: (process.env.NODE_ENV || "development"), 4 | PORT: (process.env.PORT || 3000) 5 | }; 6 | -------------------------------------------------------------------------------- /src/js/options.js: -------------------------------------------------------------------------------- 1 | import '../img/open.png' 2 | import '../img/close.png' 3 | 4 | import Options from './Options/index.svelte' 5 | 6 | new Options({ 7 | target: document.body 8 | }) 9 | -------------------------------------------------------------------------------- /src/js/Options/Shortcuts.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |

6 | 7 | 8 |
chrome://extensions/shortcuts
9 | -------------------------------------------------------------------------------- /src/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /utils/build.js: -------------------------------------------------------------------------------- 1 | var webpack = require("webpack"), 2 | config = require("../webpack.config"); 3 | 4 | delete config.chromeExtensionBoilerplate; 5 | 6 | webpack( 7 | config, 8 | function (err) { if (err) throw err; } 9 | ); 10 | -------------------------------------------------------------------------------- /src/options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ayaya's Bookmark Tree Options 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ayaya's bookmark tree 2 | 3 | A Google Chrome extension that provides a button to show bookmark tree and open bookmark in new tab. 4 | 5 | https://chrome.google.com/webstore/detail/dneehabidhbfdiohdhbhjbbljobchgab 6 | 7 | ## Development 8 | 9 | npm run start 10 | 11 | ## Build 12 | 13 | NODE_ENV=production npm run build 14 | 15 | ## License 16 | 17 | ayaya's bookmark tree is released under the MIT License. 18 | -------------------------------------------------------------------------------- /src/js/Popup/URL.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 14 | 15 |
16 | {#if $hoveringNode} 17 | {#if $hoveringNode.children} 18 | {$hoveringNode.children.length} item(s). 19 | {:else} 20 | {$hoveringNode.url} 21 | {/if} 22 | {/if} 23 |   24 |
25 | -------------------------------------------------------------------------------- /src/js/Options/Contact.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |

6 | 7 |

8 | 9 | 25 | -------------------------------------------------------------------------------- /src/js/Popup/CustomStyle.svelte: -------------------------------------------------------------------------------- 1 | 18 | 19 |
20 | body { 21 | font-family: {$fontFace}; 22 | font-size: {$fontSize}; 23 | width: {$width}px; 24 | height: {$height}px; 25 | } 26 | 27 | {$customStyle} 28 |
29 | -------------------------------------------------------------------------------- /src/js/Options/ShortcutInput.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 |
10 |
11 | 16 |
17 |
18 | 23 |
24 |
25 | -------------------------------------------------------------------------------- /src/js/Options/index.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 |
11 |

12 | 13 |
14 |
15 | 16 |
17 | 18 |
19 | 20 |
21 | 22 |
23 | 24 | 25 | 26 |
27 |
28 |
29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bookmark-tree", 3 | "version": "0.14.2", 4 | "description": "Provides a button to show bookmark tree and open bookmark in new tab.", 5 | "scripts": { 6 | "build": "node utils/build.js", 7 | "start": "node utils/webserver.js" 8 | }, 9 | "devDependencies": { 10 | "clean-webpack-plugin": "3.0.0", 11 | "copy-webpack-plugin": "^5.1.1", 12 | "css-loader": "^3.4.0", 13 | "file-loader": "^5.0.0", 14 | "fs-extra": "8.1.0", 15 | "html-loader": "0.5.5", 16 | "html-webpack-plugin": "3.2.0", 17 | "style-loader": "^1.1.1", 18 | "svelte": "^3.16.7", 19 | "svelte-loader": "^2.13.6", 20 | "webpack": "^4.41.4", 21 | "webpack-cli": "^3.3.10", 22 | "webpack-dev-server": "^3.10.1", 23 | "write-file-webpack-plugin": "4.5.1" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/js/Options/DirectorySelect.svelte: -------------------------------------------------------------------------------- 1 | 19 | 20 | 21 | {#if directories} 22 | 29 | {/if} 30 | -------------------------------------------------------------------------------- /src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "__MSG_bookmarkTree__", 3 | "description": "__MSG_description__", 4 | "default_locale": "en", 5 | "options_page": "options.html", 6 | "background": { 7 | "page": "background.html" 8 | }, 9 | "browser_action": { 10 | "default_popup": "popup.html", 11 | "default_icon": "icon.png" 12 | }, 13 | "icons": { 14 | "128": "icon.png" 15 | }, 16 | "manifest_version": 2, 17 | "permissions": [ 18 | "chrome://favicon/", 19 | "bookmarks" 20 | ], 21 | "commands": { 22 | "openBookmarkTreeInNewTab": { 23 | "description": "__MSG_openBookmarkTreeInNewTab__", 24 | "suggested_key": { 25 | "default": "Alt+B", 26 | "mac": "Command+B" 27 | } 28 | }, 29 | "openBookmarkTreeInNewWindow": { 30 | "description": "__MSG_openBookmarkTreeInNewWindow__", 31 | "suggested_key": { 32 | "default": "Alt+K", 33 | "mac": "Command+K" 34 | } 35 | } 36 | }, 37 | "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'" 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019-2020 ayaya zhao 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /utils/webserver.js: -------------------------------------------------------------------------------- 1 | var WebpackDevServer = require("webpack-dev-server"), 2 | webpack = require("webpack"), 3 | config = require("../webpack.config"), 4 | env = require("./env"), 5 | path = require("path"); 6 | 7 | var options = (config.chromeExtensionBoilerplate || {}); 8 | var excludeEntriesToHotReload = (options.notHotReload || []); 9 | 10 | for (var entryName in config.entry) { 11 | if (excludeEntriesToHotReload.indexOf(entryName) === -1) { 12 | config.entry[entryName] = 13 | [ 14 | ("webpack-dev-server/client?http://localhost:" + env.PORT), 15 | "webpack/hot/dev-server" 16 | ].concat(config.entry[entryName]); 17 | } 18 | } 19 | 20 | config.plugins = 21 | [new webpack.HotModuleReplacementPlugin()].concat(config.plugins || []); 22 | 23 | delete config.chromeExtensionBoilerplate; 24 | 25 | var compiler = webpack(config); 26 | 27 | var server = 28 | new WebpackDevServer(compiler, { 29 | hot: true, 30 | contentBase: path.join(__dirname, "../build"), 31 | sockPort: env.PORT, 32 | headers: { 33 | "Access-Control-Allow-Origin": "*" 34 | }, 35 | disableHostCheck: true 36 | }); 37 | 38 | server.listen(env.PORT); 39 | -------------------------------------------------------------------------------- /src/js/Popup/Children.svelte: -------------------------------------------------------------------------------- 1 | 40 | 41 | {#each sort(nodes) as child (child.id)} 42 | 43 | {/each} 44 | -------------------------------------------------------------------------------- /src/js/background.js: -------------------------------------------------------------------------------- 1 | import { readWidth, readHeight } from './store' 2 | import '../img/icon.png' 3 | 4 | chrome.extension.onRequest.addListener(function (req, sender, callback) { 5 | switch (req.type) { 6 | case 'openAllInNewWindow': 7 | openAllInNewWindow(req.directory.children) 8 | break 9 | case 'openAllInNewIncognitoWindow': 10 | openAllInNewWindow(req.directory.children, { incognito: true }) 11 | break 12 | } 13 | }) 14 | 15 | chrome.commands.onCommand.addListener(function(command) { 16 | switch (command) { 17 | case 'openBookmarkTreeInNewTab': 18 | chrome.tabs.create({ 19 | url: chrome.extension.getURL('popup.html?full') 20 | }) 21 | break 22 | case 'openBookmarkTreeInNewWindow': 23 | window.open(chrome.extension.getURL('popup.html?full'), 24 | '', 25 | `width=${readWidth()},height=${readHeight()}`) 26 | break 27 | } 28 | }) 29 | 30 | function openAllInNewWindow (children, options = {}) { 31 | // open the first bookmark in new window 32 | chrome.windows.create( 33 | { url: children.shift().url, ...options }, 34 | // and then open remaining bookmarks in the opened window 35 | window => children.forEach(child => { 36 | !child.children && chrome.tabs.create({ 37 | url: child.url, 38 | windowId: window.id, 39 | selected: false 40 | }) 41 | }) 42 | ) 43 | } 44 | -------------------------------------------------------------------------------- /src/js/Popup/Node.svelte: -------------------------------------------------------------------------------- 1 | 27 | 28 | 48 | 49 |
event.preventDefault()} on:mouseup={handleClick} 51 | on:mouseenter={setHovering} on:mouseleave={unsetHovering}> 52 |
{node.title}
53 |
{node.title}
54 |
55 | 56 | {#if node.children && $opening} 57 | 58 | {/if} 59 | -------------------------------------------------------------------------------- /src/js/Popup/index.svelte: -------------------------------------------------------------------------------- 1 | 24 | 25 | 53 | 54 | e.preventDefault()} /> 55 | 56 |
57 | {#if !$disableSearchBar} 58 | 60 | {/if} 61 | 62 |
63 | {#if result} 64 | 65 | {:else if rootNode} 66 | 67 | {:else} 68 | Loading... 69 | {/if} 70 |
71 | 72 |
73 | 74 | -------------------------------------------------------------------------------- /src/js/Options/Miscellaneous.svelte: -------------------------------------------------------------------------------- 1 | 18 | 19 |

20 | 21 |
22 | 24 | 27 |
28 | 29 |
30 | 32 | 35 |
36 | 37 |
38 | 40 | 43 |
44 | 45 |
46 | 49 | 50 |
51 | 52 |
53 | 56 | 62 |
63 | -------------------------------------------------------------------------------- /src/js/Options/Appearance.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 |

13 | 14 |

15 | 16 |
17 | 20 |
21 | 23 |
24 |
25 |
26 | 29 |
30 | 32 |
33 |
34 |
35 | 36 |

37 | 38 |
39 | 42 |
43 | 45 |
46 |
47 |
48 | 51 |
52 | 54 |
55 |
56 |
57 |
58 |
59 | 60 |

61 | 62 |