├── .babelrc
├── .eslintignore
├── .eslintrc.js
├── .github
└── FUNDING.yml
├── .gitignore
├── .prettierrc
├── README.md
├── build
├── build-plus.sh
└── build.sh
├── config
├── utils.js
├── webpack.steward.config.js
└── webpack.stewardplus.config.js
├── docs
└── index.html
├── extension
├── _locales
│ ├── en
│ │ └── messages.json
│ └── zh_CN
│ │ └── messages.json
├── collection
│ ├── component.ts
│ ├── diary.ts
│ ├── plugin.ts
│ ├── website.ts
│ └── workflow.ts
├── common
│ ├── auth.ts
│ ├── config.ts
│ ├── events.ts
│ ├── request.ts
│ ├── steward.ts
│ ├── storage.ts
│ ├── type.ts
│ └── util.ts
├── components
│ ├── application
│ │ └── index.vue
│ ├── cmdbox
│ │ └── index.vue
│ ├── easycomplete
│ │ ├── easycompleteItem.vue
│ │ ├── index.vue
│ │ └── mockData.js
│ └── jsoneditor
│ │ └── index.vue
├── conf
│ ├── general.ts
│ ├── index.ts
│ ├── pocket_conf.ts
│ └── themes.ts
├── constant
│ ├── base.ts
│ ├── code.ts
│ ├── i18n.ts
│ ├── index.ts
│ ├── keycode.ts
│ ├── number.ts
│ ├── options.ts
│ └── storage.ts
├── css
│ └── base.css
├── enum
│ ├── bookmarkTag.ts
│ ├── index.ts
│ ├── messageType.ts
│ ├── pageAction.ts
│ └── pageCommand.ts
├── helper
│ ├── action.helper.ts
│ ├── alias.helper.ts
│ ├── component.helper.ts
│ ├── config.helper.ts
│ ├── diary.helper.ts
│ ├── editor.helper.ts
│ ├── extension.helper.ts
│ ├── i18n.helper.ts
│ ├── index.ts
│ ├── plugin.helper.ts
│ ├── result.helper.ts
│ ├── storage.helper.ts
│ ├── theme.helper.ts
│ ├── wallpaper.helper.ts
│ ├── wallpaperSource.helper.ts
│ ├── websites.helper.ts
│ └── workflow.helper.ts
├── img
│ ├── icon.png
│ ├── icon128.png
│ ├── icon16.png
│ ├── icon48.png
│ ├── jenkins
│ │ ├── aborted.png
│ │ ├── blue.png
│ │ ├── health-00to19.png
│ │ ├── health-20to39.png
│ │ ├── health-40to59.png
│ │ ├── health-60to79.png
│ │ ├── health-80plus.png
│ │ ├── nobuilt.png
│ │ └── red.png
│ └── wordcard.png
├── info
│ ├── changelog.ts
│ ├── help.ts
│ ├── i18n.ts
│ └── links.ts
├── lib
│ ├── backbone.chromestorage.ts
│ └── social-share-urls.ts
├── main
│ ├── Steward.ts
│ ├── cache.ts
│ ├── main.ts
│ ├── type.ts
│ └── wallpaper.ts
├── manifest-plus.json
├── manifest.json
├── pages
│ ├── background
│ │ ├── background.ejs
│ │ └── index.ts
│ ├── content
│ │ ├── content.ejs
│ │ ├── content.scss
│ │ ├── index.ts
│ │ └── pageService.ts
│ ├── login
│ │ ├── index.ts
│ │ └── login.ejs
│ ├── options
│ │ ├── App.vue
│ │ ├── index.js
│ │ ├── options.ejs
│ │ ├── preview.html
│ │ ├── router
│ │ │ └── index.js
│ │ └── views
│ │ │ ├── Advanced.vue
│ │ │ ├── Appearance.vue
│ │ │ ├── General.vue
│ │ │ ├── Help.vue
│ │ │ ├── Newtabcomponents.vue
│ │ │ ├── Plugins.vue
│ │ │ ├── Update.vue
│ │ │ ├── Wallpapers.vue
│ │ │ ├── Websites.vue
│ │ │ └── Workflows.vue
│ ├── popup
│ │ ├── App.vue
│ │ ├── index.js
│ │ └── popup.ejs
│ ├── steward
│ │ ├── App.vue
│ │ ├── index.js
│ │ └── steward.ejs
│ └── urlblock
│ │ ├── index.ts
│ │ └── urlblock.ejs
├── plugins
│ ├── browser
│ │ ├── bookmark.ts
│ │ ├── chrome.ts
│ │ ├── del.ts
│ │ ├── download.ts
│ │ ├── extensions.ts
│ │ ├── his.ts
│ │ ├── off.ts
│ │ ├── on.ts
│ │ ├── run.ts
│ │ ├── set.ts
│ │ ├── tab.ts
│ │ └── topsites.ts
│ ├── extension
│ │ └── wordcard.ts
│ ├── index.ts
│ ├── other
│ │ ├── calculate.ts
│ │ ├── diary.ts
│ │ ├── note.ts
│ │ ├── openurl.ts
│ │ ├── pocket.ts
│ │ ├── search.ts
│ │ ├── todo.ts
│ │ └── urlblock.ts
│ ├── steward
│ │ ├── about.ts
│ │ ├── component.ts
│ │ ├── custom.ts
│ │ ├── help.ts
│ │ ├── newtab.ts
│ │ ├── random.ts
│ │ ├── spm.ts
│ │ ├── steward.ts
│ │ ├── wallpaper.ts
│ │ ├── workflow.ts
│ │ └── wsm.ts
│ └── type.ts
├── scripts
│ ├── newtab.js
│ └── popup.js
├── scss
│ ├── main.scss
│ └── themes
│ │ ├── base.scss
│ │ ├── newtab
│ │ └── classical.scss
│ │ └── popup
│ │ └── classical.scss
├── server
│ ├── controller
│ │ └── recordsController.ts
│ └── db
│ │ └── index.ts
├── service
│ ├── bing.ts
│ ├── desktoppr.ts
│ ├── index.ts
│ ├── nasa.ts
│ ├── picsum.ts
│ ├── pixabay.ts
│ └── selection.ts
├── svg
│ ├── alias.svg
│ ├── allowbatch.svg
│ ├── app.svg
│ ├── author.svg
│ ├── baidu.svg
│ ├── bbs.svg
│ ├── bing.svg
│ ├── bookmark.svg
│ ├── btc.svg
│ ├── calc.svg
│ ├── chrome.svg
│ ├── copy.svg
│ ├── del.svg
│ ├── delete-icon.svg
│ ├── diary.svg
│ ├── download-red.svg
│ ├── download.svg
│ ├── enter-white.svg
│ ├── enter.svg
│ ├── exts
│ │ └── wordcard
│ │ │ ├── level0.svg
│ │ │ ├── level1.svg
│ │ │ ├── level2.svg
│ │ │ ├── level3.svg
│ │ │ ├── level4.svg
│ │ │ ├── level5.svg
│ │ │ └── tag.svg
│ ├── github.svg
│ ├── google.svg
│ ├── help.svg
│ ├── history.svg
│ ├── iframe.svg
│ ├── index.svg
│ ├── jenkins.svg
│ ├── loading.svg
│ ├── miniapp.svg
│ ├── new-tab.svg
│ ├── newversion.svg
│ ├── note.svg
│ ├── notshow.svg
│ ├── off.svg
│ ├── on.svg
│ ├── openurl.svg
│ ├── plus.svg
│ ├── plusone.svg
│ ├── pm25.svg
│ ├── random.svg
│ ├── refresh-red.svg
│ ├── refresh.svg
│ ├── save-red.svg
│ ├── selected-icon.svg
│ ├── set.svg
│ ├── share-icons
│ │ ├── baidu.svg
│ │ ├── blogger.svg
│ │ ├── buffer.svg
│ │ ├── delicious.svg
│ │ ├── digg.svg
│ │ ├── douban.svg
│ │ ├── evernote.svg
│ │ ├── facebook.svg
│ │ ├── flipboard.svg
│ │ ├── friendfeed.svg
│ │ ├── getpocket.svg
│ │ ├── google_plus.svg
│ │ ├── instapaper.svg
│ │ ├── line.me.svg
│ │ ├── linkedin.svg
│ │ ├── livejournal.svg
│ │ ├── myspace.svg
│ │ ├── newsvine.svg
│ │ ├── pinterest.svg
│ │ ├── qzone.svg
│ │ ├── reddit.svg
│ │ ├── renren.svg
│ │ ├── skype.svg
│ │ ├── stumbleupon.svg
│ │ ├── telegram_me.svg
│ │ ├── tumblr.svg
│ │ ├── twitter.svg
│ │ ├── viber.svg
│ │ ├── weibo.svg
│ │ ├── whatsapp.svg
│ │ ├── xing.svg
│ │ └── yahoo.svg
│ ├── sspai.svg
│ ├── stackoverflow.svg
│ ├── star-fill.svg
│ ├── star.svg
│ ├── tab.svg
│ ├── todo.svg
│ ├── topsites.svg
│ ├── urlblock.svg
│ ├── viewext.svg
│ ├── wallpaper-icon.svg
│ ├── weather.svg
│ ├── weibo-red.svg
│ ├── weibo.svg
│ ├── workflow.svg
│ ├── youdao.svg
│ └── zhihu.svg
└── utils
│ ├── api.ts
│ ├── date.ts
│ ├── index.ts
│ ├── object.ts
│ └── storage.ts
├── jsconfig.json
├── package.json
├── tsconfig.json
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [["@babel/preset-env", {
3 | "targets": {
4 | "chrome": "59"
5 | }
6 | }]]
7 | }
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | !/*.js
2 | /extension/lib/
3 | /output/
4 | /config/
5 | /extension/js/common/ga.js
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "env": {
3 | "browser": true,
4 | "es6": true,
5 | "node": true
6 | },
7 | "extends": [
8 | "eslint:recommended",
9 | "plugin:vue/essential"
10 | ],
11 | "globals": {
12 | "Atomics": "readonly",
13 | "SharedArrayBuffer": "readonly",
14 | "chrome": true,
15 | "EXT_TYPE": true
16 | },
17 | "parserOptions": {
18 | "ecmaVersion": 2018,
19 | "parser": "babel-eslint",
20 | "sourceType": "module"
21 | },
22 | "plugins": [
23 | "vue"
24 | ],
25 | "rules": {
26 | "no-inner-declarations": "off",
27 | "no-empty": "off"
28 | }
29 | };
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [solobat]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: tomasy
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | custom: https://paypal.me/tomasy/5
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Project related
2 | output
3 | .private
4 |
5 | ### node etc ###
6 |
7 | # Logs
8 | logs
9 | *.log
10 | npm-debug.log
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 |
17 | #For ionic build
18 | platforms/
19 | www/lib
20 |
21 | # Directory for instrumented libs generated by jscoverage/JSCover
22 | lib-cov
23 |
24 | # Coverage directory used by tools like istanbul
25 | coverage
26 |
27 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
28 | .grunt
29 |
30 | # Dependency directorys
31 | # Deployed apps should consider commenting these lines out:
32 | # see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git
33 | node_modules/
34 | bower_components/
35 | package-lock.json
36 |
37 |
38 | # Packages #
39 | ############
40 | # it's better to unpack these files and commit the raw source
41 | # git has its own built in compression methods
42 | *.7z
43 | *.dmg
44 | *.gz
45 | *.iso
46 | *.jar
47 | *.rar
48 | *.tar
49 | *.zip
50 |
51 |
52 |
53 | # OS generated files #
54 | ######################
55 | .DS_Store
56 | .DS_Store?
57 | ._*
58 | .Spotlight-V100
59 | .Trashes
60 | ehthumbs.db
61 | Thumbs.db
62 |
63 | # Text Editors
64 | *.vscode
65 | *.sublime
66 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": true,
3 | "singleQuote": true,
4 | "tabWidth": 2,
5 | "trailingComma": "all",
6 | "useTabs": false
7 | }
--------------------------------------------------------------------------------
/build/build-plus.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # prepare
4 | echo "准备目录......"
5 | rm -fr output
6 | mkdir -p output
7 |
8 | # build
9 | echo "编译中....."
10 | npm run build:minified:plus || { echo "编译失败,请检查后重试"; exit 1; }
11 |
12 | zip -r stewardplus.zip output/steward_plus/
13 |
14 | echo "打包完毕"
15 |
16 | mv -f stewardplus.zip ~/Desktop
17 |
18 | echo "移动到桌面"
--------------------------------------------------------------------------------
/build/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # prepare
4 | echo "准备目录......"
5 | rm -fr output
6 | mkdir -p output
7 |
8 | # build
9 | echo "编译中....."
10 | npm run build:minified || { echo "编译失败,请检查后重试"; exit 1; }
11 |
12 | zip -r steward.zip output/steward/
13 |
14 | echo "打包完毕"
15 |
16 | mv -f steward.zip ~/Desktop
17 |
18 | echo "移动到桌面"
--------------------------------------------------------------------------------
/config/utils.js:
--------------------------------------------------------------------------------
1 | const glob = require("glob")
2 | const path = require('path')
3 | const HtmlWebpackPlugin = require('html-webpack-plugin')
4 |
5 | const pages = []
6 | const entries = {}
7 |
8 | glob.sync("./extension/pages/*/index.*s").forEach(pagePath => {
9 | const chunk = pagePath.split('pages/')[1].split("/index.")[0]
10 |
11 | entries[chunk] = pagePath
12 | pages.push(new HtmlWebpackPlugin({
13 | title: `Steward - ${chunk}`,
14 | template: `./extension/pages/${chunk}/${chunk}.ejs`,
15 | filename: `${chunk}.html`,
16 | inject: true,
17 | chunksSortMode: 'auto',
18 | chunks: ['manifest', 'vendor', 'common', chunk]
19 | }))
20 | })
21 |
22 | module.exports = {
23 | pages,
24 | entries
25 | }
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Documentation
8 |
9 |
10 |
13 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/extension/collection/component.ts:
--------------------------------------------------------------------------------
1 |
2 | import Backbone from 'backbone';
3 |
4 | import ChromeStorage from '../lib/backbone.chromestorage';
5 |
6 | export const Component = Backbone.Model.extend({
7 | sync: Backbone.sync,
8 | defaults: function() {
9 | return {
10 | created: Number(new Date()),
11 | updated: Number(new Date()),
12 | };
13 | },
14 | });
15 |
16 | export const ComponentList = Backbone.Collection.extend({
17 | model: Component,
18 |
19 | chromeStorage: new ChromeStorage('components', 'local'),
20 |
21 | nextOrder: function() {
22 | if (!this.length) {
23 | return 1;
24 | }
25 | return this.last().get('created') + 1;
26 | },
27 |
28 | comparator: 'created',
29 | });
30 |
--------------------------------------------------------------------------------
/extension/collection/diary.ts:
--------------------------------------------------------------------------------
1 |
2 | import Backbone from 'backbone';
3 |
4 | import ChromeStorage from '../lib/backbone.chromestorage';
5 |
6 | export const Diary = Backbone.Model.extend({
7 | sync: Backbone.sync,
8 | defaults: function() {
9 | return {
10 | created: Number(new Date()),
11 | updated: Number(new Date()),
12 | };
13 | },
14 | });
15 |
16 | export const DiaryList = Backbone.Collection.extend({
17 | model: Diary,
18 |
19 | chromeStorage: new ChromeStorage('diarylist', 'local'),
20 |
21 | nextOrder: function() {
22 | if (!this.length) {
23 | return 1;
24 | }
25 | return this.last().get('created') + 1;
26 | },
27 |
28 | comparator: 'created',
29 | });
30 |
--------------------------------------------------------------------------------
/extension/collection/plugin.ts:
--------------------------------------------------------------------------------
1 |
2 | import Backbone from 'backbone';
3 |
4 | import ChromeStorage from '../lib/backbone.chromestorage';
5 |
6 | export const CustomPlugin = Backbone.Model.extend({
7 | sync: Backbone.sync,
8 | defaults: function() {
9 | return {
10 | created: Number(new Date()),
11 | updated: Number(new Date()),
12 | };
13 | },
14 | });
15 |
16 | export const CustomPluginList = Backbone.Collection.extend({
17 | model: CustomPlugin,
18 |
19 | chromeStorage: new ChromeStorage('custompluginlist', 'local'),
20 |
21 | nextOrder: function() {
22 | if (!this.length) {
23 | return 1;
24 | }
25 | return this.last().get('created') + 1;
26 | },
27 |
28 | comparator: 'created',
29 | });
30 |
--------------------------------------------------------------------------------
/extension/collection/website.ts:
--------------------------------------------------------------------------------
1 | import Backbone from 'backbone';
2 |
3 | import ChromeStorage from '../lib/backbone.chromestorage';
4 |
5 | export const Website = Backbone.Model.extend({
6 | sync: Backbone.sync,
7 | defaults: function() {
8 | return {
9 | created: Number(new Date()),
10 | updated: Number(new Date()),
11 | };
12 | },
13 | });
14 |
15 | export const WebsiteList = Backbone.Collection.extend({
16 | model: Website,
17 |
18 | chromeStorage: new ChromeStorage('websites', 'local'),
19 |
20 | nextOrder: function() {
21 | if (!this.length) {
22 | return 1;
23 | }
24 | return this.last().get('created') + 1;
25 | },
26 |
27 | comparator: 'created',
28 | });
29 |
--------------------------------------------------------------------------------
/extension/collection/workflow.ts:
--------------------------------------------------------------------------------
1 | import Backbone from 'backbone';
2 |
3 | import ChromeStorage from '../lib/backbone.chromestorage';
4 |
5 | export const Workflow = Backbone.Model.extend({
6 | sync: Backbone.sync,
7 | defaults: function() {
8 | return {
9 | created: Number(new Date()),
10 | updated: Number(new Date()),
11 | };
12 | },
13 | });
14 |
15 | export const WorkflowList = Backbone.Collection.extend({
16 | model: Workflow,
17 |
18 | chromeStorage: new ChromeStorage('workflows', 'sync'),
19 |
20 | nextOrder: function() {
21 | if (!this.length) {
22 | return 1;
23 | }
24 | return this.last().get('created') + 1;
25 | },
26 |
27 | comparator: 'created',
28 | });
29 |
--------------------------------------------------------------------------------
/extension/common/events.ts:
--------------------------------------------------------------------------------
1 |
2 | import $ from 'jquery';
3 |
4 | const events = {
5 | tabs: {
6 | onRemoved: function(cb) {
7 | chrome.tabs.onRemoved.addListener(function(...args) {
8 | Reflect.apply(cb, null, args);
9 | });
10 | },
11 |
12 | onCreated: function(cb) {
13 | chrome.tabs.onCreated.addListener(function(...args) {
14 | Reflect.apply(cb, null, args);
15 | });
16 | },
17 | },
18 |
19 | windows: {
20 | onCreated: function(cb) {
21 | chrome.windows.onCreated.addListener(function(...args) {
22 | Reflect.apply(cb, null, args);
23 | });
24 | },
25 | },
26 | };
27 |
28 | function trigger(obj, actionFn) {
29 | $.each(obj, function(eventType, eventList) {
30 | if (!eventList.length) {
31 | return;
32 | }
33 |
34 | const allTypeEvents = events[eventType];
35 | for (let i = 0, len = eventList.length; i < len; i = i + 1) {
36 | allTypeEvents[eventList[i]](actionFn);
37 | }
38 | });
39 | }
40 |
41 | export default {
42 | on: trigger,
43 | };
44 |
--------------------------------------------------------------------------------
/extension/common/request.ts:
--------------------------------------------------------------------------------
1 |
2 | function emptyFn() {}
3 |
4 | function send(obj, callback = (res: any) => {}) {
5 | chrome.extension.sendRequest(obj || {}, function(response) {
6 | callback(response);
7 | });
8 | }
9 |
10 | function log(msg) {
11 | send(
12 | {
13 | msg: msg,
14 | },
15 | emptyFn,
16 | );
17 | }
18 |
19 | function get(cb) {
20 | chrome.extension.onRequest.addListener(function(...args) {
21 | Reflect.apply(cb, null, args);
22 | });
23 | }
24 |
25 | export default {
26 | send,
27 | log,
28 | get,
29 | };
30 |
--------------------------------------------------------------------------------
/extension/common/steward.ts:
--------------------------------------------------------------------------------
1 |
2 | export function getSteward() {
3 | return window.__Steward__;
4 | }
5 |
6 | export function getOptionsPage() {
7 | return window.optionsPage;
8 | }
--------------------------------------------------------------------------------
/extension/common/storage.ts:
--------------------------------------------------------------------------------
1 |
2 | const h5 = {
3 | set: function(key: string, value) {
4 | localStorage[key] = value;
5 | },
6 |
7 | get: function(key: string) {
8 | return localStorage[key];
9 | },
10 | };
11 |
12 | function baseSet(type, data, cb) {
13 | chrome.storage[type].set(data, function(...args) {
14 | Reflect.apply(cb, this, args);
15 | });
16 | }
17 |
18 | function baseGet(type, key, cb) {
19 | chrome.storage[type].get(key, function(...args) {
20 | Reflect.apply(cb, this, args);
21 | });
22 | }
23 |
24 | const local = {
25 | set: function(data, cb) {
26 | baseSet('local', data, cb);
27 | },
28 |
29 | get: function(key, cb) {
30 | baseGet('sync', key, cb);
31 | },
32 | };
33 |
34 | const sync = {
35 | set: function(data, cb) {
36 | baseSet('sync', data, cb);
37 | },
38 |
39 | get: function(key, cb) {
40 | baseGet('sync', key, cb);
41 | },
42 | };
43 |
44 | export default {
45 | h5,
46 | local,
47 | sync,
48 | };
49 |
--------------------------------------------------------------------------------
/extension/components/easycomplete/easycompleteItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
![]()
4 |
5 | {{item.title}}
6 | {{ item.desc }}
7 |
8 |
![]()
9 |
10 |
11 |
--------------------------------------------------------------------------------
/extension/components/easycomplete/mockData.js:
--------------------------------------------------------------------------------
1 | import { getURL } from "helper/extension.helper";
2 |
3 | export const dataList = [{
4 | key: 'plugins',
5 | title: '测试个鬼',
6 | icon: getURL('img/icon.png'),
7 | desc: '描述个鬼',
8 | url: 'https://baidu.com'
9 | }, {
10 | key: 'plugins',
11 | title: '测试个鬼1',
12 | icon: getURL('img/icon.png'),
13 | desc: '描述个鬼',
14 | url: 'https://baidu.com'
15 | }, {
16 | key: 'plugins',
17 | title: '测试个鬼2',
18 | icon: getURL('img/icon.png'),
19 | desc: '描述个鬼',
20 | url: 'https://baidu.com'
21 | }, {
22 | key: 'plugins',
23 | title: '测试个鬼3',
24 | icon: getURL('img/icon.png'),
25 | desc: '描述个鬼',
26 | url: 'https://baidu.com'
27 | }, {
28 | key: 'plugins',
29 | title: '测试个鬼4',
30 | icon: getURL('img/icon.png'),
31 | desc: '描述个鬼',
32 | url: 'https://baidu.com'
33 | }, {
34 | key: 'plugins',
35 | title: '测试个鬼5',
36 | icon: getURL('img/icon.png'),
37 | desc: '描述个鬼',
38 | url: 'https://baidu.com'
39 | }, {
40 | key: 'plugins',
41 | title: '测试个鬼6',
42 | icon: getURL('img/icon.png'),
43 | desc: '描述个鬼',
44 | url: 'https://baidu.com'
45 | }, {
46 | key: 'plugins',
47 | title: '测试个鬼7',
48 | icon: getURL('img/icon.png'),
49 | desc: '描述个鬼',
50 | url: 'https://baidu.com'
51 | }, {
52 | key: 'plugins',
53 | title: '测试个鬼8',
54 | icon: getURL('img/icon.png'),
55 | desc: '描述个鬼',
56 | url: 'https://baidu.com'
57 | }, {
58 | key: 'plugins',
59 | title: '测试个鬼9',
60 | icon: getURL('img/icon.png'),
61 | desc: '描述个鬼',
62 | url: 'https://baidu.com'
63 | }, {
64 | key: 'plugins',
65 | title: '测试个鬼10',
66 | icon: getURL('img/icon.png'),
67 | desc: '描述个鬼',
68 | url: 'https://baidu.com'
69 | }, {
70 | key: 'plugins',
71 | title: '测试个鬼11',
72 | icon: getURL('img/icon.png'),
73 | desc: '描述个鬼',
74 | url: 'https://baidu.com'
75 | }];
76 |
--------------------------------------------------------------------------------
/extension/components/jsoneditor/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
68 |
--------------------------------------------------------------------------------
/extension/conf/general.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | cacheLastCmd: true,
3 | defaultPlugin: '',
4 | customCmd: '',
5 | autoScrollToMiddle: false,
6 | speedFirst: false,
7 | autoHideCmd: false,
8 | maxOperandsNum: 5,
9 | autoResizeBoxFontSize: false,
10 | wallpaperSources: ['bing', 'favorites'],
11 | newtabWidgets: ['wpbtns'],
12 | autoSelectByMouse: false,
13 | enableRandomWallpaper: true,
14 | storeTypedQuery: true,
15 | autoCreateWebsite: true,
16 | websiteUrls: true,
17 | componentsMirror: 'github',
18 | websiteShareUrls: true,
19 | emptyCommand: '',
20 | shortcuts: {
21 | 'open-in-content-page': { cmd: '' },
22 | pageboxShortcut_0: { cmd: 'his ' },
23 | pageboxShortcut_1: { cmd: 'tab ' },
24 | pageboxShortcut_2: { cmd: 'bm ' },
25 | pageboxShortcut_3: { cmd: 'wf ' },
26 | pageboxShortcut_4: { cmd: 'tabp ' },
27 | pageboxShortcut_5: { cmd: 'tabm ' },
28 | pageboxShortcut_6: { cmd: "'" },
29 | pageboxShortcut_7: { cmd: '`' },
30 | pageboxShortcut_8: { cmd: 'tq ' },
31 | pageboxShortcut_9: { cmd: ': ' },
32 | },
33 | };
34 |
--------------------------------------------------------------------------------
/extension/conf/index.ts:
--------------------------------------------------------------------------------
1 | import { getOptionsPage, getSteward } from 'common/steward';
2 | import { getValueByPath } from 'utils/object';
3 |
4 | export function getAppConfig(path, defaultValue) {
5 | return getValueByPath((getSteward() || getOptionsPage()).config, path, defaultValue);
6 | }
7 |
--------------------------------------------------------------------------------
/extension/conf/pocket_conf.ts:
--------------------------------------------------------------------------------
1 | import { getURL } from "helper/extension.helper";
2 |
3 | export default {
4 | consumer_key: '36254-48fd5cd99b53d0e9cfabbee0',
5 | requestUrl: 'https://getpocket.com/v3/oauth/request',
6 | authenticateUrl: 'https://getpocket.com/auth/authorize',
7 | accessTokenUrl: 'https://getpocket.com/v3/oauth/authorize',
8 | redirect_uri: getURL('login.html'),
9 | appName: 'pocket',
10 | };
11 |
--------------------------------------------------------------------------------
/extension/constant/base.ts:
--------------------------------------------------------------------------------
1 | export const PLUGIN_TYPE = {
2 | ALWAYS: 'always',
3 | REGEXP: 'regexp',
4 | KEYWORD: 'keyword',
5 | OTHER: 'other',
6 | SEARCH: 'search',
7 | };
8 |
9 | export const EMPTY_COMMAND = '_empty_';
10 |
11 | export const ITEM_TYPE = {
12 | PLUGINS: 'plugins',
13 | URL: 'url',
14 | COPY: 'copy',
15 | ACTION: 'action',
16 | APP: 'app',
17 | };
18 |
19 | export const MODE = {
20 | NEWTAB: 'newTab',
21 | POPUP: 'popup',
22 | };
23 |
24 | export const EXTENSION = {
25 | STEWARD: 'steward',
26 | STEWARDPLUS: 'stewardplus',
27 | };
28 |
29 | export const PLUGIN_STATUS = {
30 | NOTINSTALL: 0,
31 | NEWVESION: 1,
32 | INSTALLED: 2,
33 | };
34 |
35 | export const WEBSITE_STATUS = {
36 | NOTINSTALL: 0,
37 | NEWVESION: 1,
38 | INSTALLED: 2,
39 | };
40 |
41 | export const stewardTabs = [
42 | 'Steward',
43 | 'General',
44 | 'Plugins',
45 | 'Workflows',
46 | 'Websites',
47 | 'Wallpapers',
48 | 'Appearance',
49 | 'Advanced',
50 | 'Help',
51 | 'Update',
52 | ];
53 |
54 | export const stewardPlusTabs = [
55 | 'Steward',
56 | 'General',
57 | 'Plugins',
58 | 'Workflows',
59 | 'Websites',
60 | 'NewtabComponents',
61 | 'Wallpapers',
62 | 'Appearance',
63 | 'Advanced',
64 | 'Help',
65 | 'Update',
66 | ];
67 |
--------------------------------------------------------------------------------
/extension/constant/code.ts:
--------------------------------------------------------------------------------
1 | export const PLUGIN_DEFAULT = `
2 | module.exports = function (steward) {
3 | const version = 1;
4 | const author = 'solobat';
5 | const name = 'yourPlugin';
6 | const key = 'xxx';
7 | const type = 'keyword';
8 | const icon = 'http://static.oksteward.com/icon128.png';
9 | const title = 'your plugin';
10 | const subtitle = 'custom your plugin';
11 | const commands = [{
12 | key,
13 | type,
14 | title,
15 | subtitle,
16 | icon
17 | }];
18 |
19 | function onInput(query, command) {
20 | // return a promise
21 | return Promise.resolve([
22 | {
23 | icon,
24 | key: 1,
25 | title: 'result 1',
26 | desc: 'desc 1'
27 | },
28 | {
29 | icon,
30 | key: 2,
31 | title: 'result 2',
32 | desc: 'desc 2'
33 | }
34 | ]);
35 | }
36 |
37 | function onEnter(item, command, query, keyStatus, list) {
38 | steward.util.copyToClipboard(item.title, true);
39 | }
40 |
41 | return {
42 | author,
43 | version,
44 | name,
45 | category: 'other',
46 | icon,
47 | title,
48 | commands,
49 | onInput,
50 | onEnter
51 | };
52 | }
53 | `;
54 |
--------------------------------------------------------------------------------
/extension/constant/i18n.ts:
--------------------------------------------------------------------------------
1 |
2 | export const TIPS = {
3 | autoScrollToMiddle: 'autoScrollToMiddle',
4 | autoHideCmd: 'autoHideCmd',
5 | maxOperandsNum: 'maxOperandsNum',
6 | allowBatch: 'allowBatch',
7 | bm_shift: 'bm_shift',
8 | his_shift: 'his_shift',
9 | site_shift: 'site_shift',
10 | tabc_shift: 'tabc_shift',
11 | wd_shift: 'wd_shift',
12 | storeTypedQuery: 'storeTypedQuery',
13 | };
14 |
--------------------------------------------------------------------------------
/extension/constant/index.ts:
--------------------------------------------------------------------------------
1 | import * as BASE from './base';
2 | import * as CODE from './code';
3 | import * as I18N from './i18n';
4 | import KEY from './keycode';
5 | import * as NUMBER from './number';
6 | import * as OPTIONS from './options';
7 | import STORAGE from './storage';
8 |
9 | export default {
10 | BASE,
11 | KEY,
12 | NUMBER,
13 | STORAGE,
14 | OPTIONS,
15 | I18N,
16 | CODE,
17 | };
18 |
--------------------------------------------------------------------------------
/extension/constant/keycode.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | TAB: 9,
3 | ENTER: 13,
4 | SHIFT: 16,
5 | CTRL: 17,
6 | ALT: 18,
7 | LEFT: 37,
8 | UP: 38,
9 | RIGHT: 39,
10 | DOWN: 40,
11 | NUM0: 49,
12 | NUM9: 57,
13 | };
14 |
--------------------------------------------------------------------------------
/extension/constant/number.ts:
--------------------------------------------------------------------------------
1 | export const WALLPAPER_INTERVAL = 5 * 60 * 1000;
2 |
3 | export const QUOTA_BYTES_PER_ITEM = 8192;
4 |
5 | export const MAX_WORKFLOW_NUM = 20;
6 |
--------------------------------------------------------------------------------
/extension/constant/options.ts:
--------------------------------------------------------------------------------
1 | export const APPEARANCE_ITEMS = [
2 | {
3 | name: 'New Tab',
4 | },
5 | {
6 | name: 'Popup',
7 | },
8 | {
9 | name: 'Page',
10 | },
11 | ];
12 |
13 | export const DEFAULT_PLUGINS = [
14 | 'Top Sites',
15 | 'Bookmarks',
16 | 'Tabs',
17 | 'Weather',
18 | 'Other',
19 | 'Random',
20 | ].map(name => {
21 | return {
22 | label: name,
23 | value: name,
24 | };
25 | });
26 |
27 | export const WALLPAPER_SOURCES = [
28 | {
29 | label: 'Favorites',
30 | value: 'favorites',
31 | tips: 'Your favorites',
32 | },
33 | {
34 | label: 'Bing',
35 | value: 'bing',
36 | tips: 'faster, but less',
37 | },
38 | {
39 | label: 'Unsplash',
40 | value: 'picsum',
41 | tips: 'lower, but more',
42 | },
43 | {
44 | label: 'Nasa',
45 | value: 'nasa',
46 | tips: 'NASA',
47 | },
48 | {
49 | label: 'Desktoppr',
50 | value: 'desktoppr',
51 | tips: 'desktoppr.co',
52 | },
53 | {
54 | label: 'Pixabay',
55 | value: 'pixabay',
56 | tips: 'pixabay.com',
57 | },
58 | {
59 | label: 'Solid Colors',
60 | value: 'solidcolor',
61 | },
62 | {
63 | label: "Author's Selection",
64 | value: 'selection',
65 | },
66 | ];
67 |
68 | export const NEWTAB_WIDGETS = [
69 | {
70 | label: 'Clock',
71 | value: 'clock',
72 | tips: 'Clock',
73 | },
74 | {
75 | label: 'Shortcuts',
76 | value: 'shortcuts',
77 | tips: 'Shortcuts',
78 | },
79 | {
80 | label: 'Bottom Buttons',
81 | value: 'wpbtns',
82 | tips: 'Bottom Buttons',
83 | },
84 | ];
85 |
86 | export const MIRRORS = [
87 | {
88 | id: 'github',
89 | name: 'Github',
90 | baseURL:
91 | 'https://raw.githubusercontent.com/Steward-launcher/steward-newtab-components/master',
92 | },
93 | {
94 | id: 'gitee',
95 | name: 'Gitee',
96 | baseURL:
97 | 'https://gitee.com/Steward-launcher/steward-newtab-components/raw/master',
98 | },
99 | ];
100 |
--------------------------------------------------------------------------------
/extension/constant/storage.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | LAST_CMD: 'mw_last_cmd',
3 | LASTDATE: 'lastDate',
4 | WALLPAPER: 'wallpaper',
5 | WALLPAPERS: 'wallpapers',
6 | WALLPAPER_BLACKLIST: 'wallpaper_blacklist',
7 | THEMES: 'themes',
8 | TODO: 'todo',
9 | DONE: 'done',
10 | URL: 'url',
11 | CONFIG: 'config',
12 | NOTES: 'notes',
13 | TAGS: 'tags',
14 | TIMES: 'times',
15 | DIARY: 'diary',
16 | URLBLOCK_REPLACE_PAGE: 'urlblock_replace_page',
17 | };
18 |
--------------------------------------------------------------------------------
/extension/css/base.css:
--------------------------------------------------------------------------------
1 | [v-cloak] {
2 | display: none;
3 | }
--------------------------------------------------------------------------------
/extension/enum/bookmarkTag.ts:
--------------------------------------------------------------------------------
1 | export enum BookMarkTag {
2 | TODO = 'TODO:',
3 | READ = 'READ:',
4 | TRY = 'TRY:',
5 | }
6 |
--------------------------------------------------------------------------------
/extension/enum/index.ts:
--------------------------------------------------------------------------------
1 | export * from './bookmarkTag';
2 | export * from './messageType';
3 | export * from './pageAction';
4 | export * from './pageCommand';
5 |
--------------------------------------------------------------------------------
/extension/enum/messageType.ts:
--------------------------------------------------------------------------------
1 | export enum MessageType {
2 | TOGGLE_BOOKMARK = 'toggleBookmark',
3 | SHOW = 'show',
4 | INIT = 'init',
5 | NAVS = 'navs',
6 | OUTLINE = 'outline',
7 | ANCHORS = 'anchors',
8 | REPLACE_URL = 'replaceURL',
9 | IFRAMES = 'iframes',
10 | }
11 |
--------------------------------------------------------------------------------
/extension/enum/pageAction.ts:
--------------------------------------------------------------------------------
1 | export enum PageAction {
2 | CLOSE_BOX = 'closeBox',
3 | BOX_INITED = 'boxInited',
4 | COMMAND = 'command',
5 | QUERY_NAVS = 'queryNavs',
6 | GEN_OUTLINE = 'genOutline',
7 | GET_ANCHORS = 'getAnchors',
8 | GET_META = 'getMeta',
9 | GET_IFRAMES = 'getIframes',
10 | }
11 |
--------------------------------------------------------------------------------
/extension/enum/pageCommand.ts:
--------------------------------------------------------------------------------
1 | export enum PageCommand {
2 | OUTLINE = 'outline',
3 | ANCHOR = 'anchor',
4 | CLICK = 'click',
5 | HIDE = 'hide',
6 | SHOW = 'show',
7 | COPY = 'copy',
8 | PAGE_PROTECT = 'pageprotect',
9 | TOGGLE_TODO = 'toggleTodo',
10 | ENGLISH_SYNTAX_HIGHLIGHT = 'englishSyntaxHighlight',
11 | READ_MODE = 'readMode',
12 | }
13 |
--------------------------------------------------------------------------------
/extension/helper/action.helper.ts:
--------------------------------------------------------------------------------
1 | import { Action } from 'plugins/type';
2 | import { browser } from 'webextension-polyfill-ts';
3 |
4 | import { PageCommand } from '../enum';
5 |
6 | const defaultActions: Action[] = [
7 | {
8 | title: 'Copy title as a markdown link',
9 | actionType: PageCommand.COPY,
10 | extend: {
11 | template: '[{{title}}]({{url}})',
12 | },
13 | enable: true,
14 | },
15 | {
16 | title: 'Copy selection text as a markdown link',
17 | actionType: PageCommand.COPY,
18 | extend: {
19 | template: '[{{selection}}]({{url}})',
20 | },
21 | enable: false,
22 | },
23 | {
24 | title: 'Toggle TODO',
25 | desc: 'Add a bookmark and tag it with a TODO prefix / Remove bookmark',
26 | actionType: PageCommand.TOGGLE_TODO,
27 | enable: true,
28 | },
29 | {
30 | title: 'Toggle protection status',
31 | actionType: PageCommand.PAGE_PROTECT,
32 | desc: 'Not protected',
33 | extend: {
34 | protected: false,
35 | },
36 | enable: true,
37 | },
38 | ];
39 |
40 | const GLOBAL_ACTIONS_KEY = 'global_actions';
41 |
42 | export function getAllGlobalActions() {
43 | return browser.storage.local.get(GLOBAL_ACTIONS_KEY).then(resp => {
44 | if (resp[GLOBAL_ACTIONS_KEY]) {
45 | return resp[GLOBAL_ACTIONS_KEY];
46 | } else {
47 | return defaultActions;
48 | }
49 | });
50 | }
51 |
52 | export function getGlobalActions() {
53 | return getAllGlobalActions().then(resp => resp.filter(item => item.enable));
54 | }
55 |
56 | export function setGlobalActions(jsonStr) {
57 | try {
58 | const actions = JSON.parse(jsonStr);
59 |
60 | return browser.storage.local.set({
61 | [GLOBAL_ACTIONS_KEY]: actions,
62 | });
63 | } catch (error) {
64 | return Promise.reject('parse error');
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/extension/helper/alias.helper.ts:
--------------------------------------------------------------------------------
1 | import { browser } from 'webextension-polyfill-ts';
2 |
3 | import util from 'common/util';
4 | import { ResultItem, TextAliasType } from 'plugins/type';
5 |
6 | import { getURL } from './extension.helper';
7 |
8 | const icon = getURL('iconfont/alias.svg');
9 |
10 | function format(list) {
11 | return list.map(item => {
12 | return {
13 | key: 'url',
14 | url: item.value,
15 | title: `${item.desc || item.value}[${item.label}]`,
16 | desc: item.lable,
17 | icon,
18 | weight: 100,
19 | };
20 | });
21 | }
22 |
23 | let comment;
24 |
25 | function parseLine(line) {
26 | const realLine = line.trim();
27 |
28 | if (realLine.startsWith('##')) {
29 | comment = realLine.substring(2).trim();
30 |
31 | return null;
32 | } else {
33 | const parts = realLine.split(/[\s]+/).slice(0, 2);
34 | const desc = comment;
35 |
36 | comment = null;
37 |
38 | return {
39 | label: parts[0],
40 | value: parts[1],
41 | desc,
42 | };
43 | }
44 | }
45 |
46 | const STORAGE_KEY = 'text_alias';
47 |
48 | export const TextAlias: TextAliasType = {
49 | items: null,
50 |
51 | resolveItems(text) {
52 | return text
53 | .split('\n')
54 | .filter(line => line && !line.match(/^[\s\t]+$/))
55 | .map(parseLine)
56 | .filter(line => line && Boolean(line.label));
57 | },
58 |
59 | getItems() {
60 | if (this.items) {
61 | return Promise.resolve(this.items);
62 | } else {
63 | return browser.storage.sync.get(STORAGE_KEY).then(resp => {
64 | const text = resp[STORAGE_KEY];
65 |
66 | if (text) {
67 | const items = this.resolveItems(text);
68 |
69 | this.items = items;
70 |
71 | return items;
72 | } else {
73 | return [];
74 | }
75 | });
76 | }
77 | },
78 |
79 | onInput(query): Promise | ResultItem[] {
80 | return this.getItems().then(items => {
81 | if (items && items.length) {
82 | return format(util.getMatches(items, query, 'label') || []);
83 | } else {
84 | return [];
85 | }
86 | });
87 | },
88 | };
89 |
90 | export function getTextAlias() {
91 | return browser.storage.sync.get(STORAGE_KEY).then(resp => {
92 | return resp[STORAGE_KEY] || '';
93 | });
94 | }
95 |
96 | export function saveTextAlias(text) {
97 | return browser.storage.sync.set({
98 | [STORAGE_KEY]: text,
99 | });
100 | }
101 |
--------------------------------------------------------------------------------
/extension/helper/config.helper.ts:
--------------------------------------------------------------------------------
1 | import { browser } from 'webextension-polyfill-ts';
2 |
3 | export default {
4 | key: 'config',
5 |
6 | getData() {
7 | return browser.storage.sync.get('config').then(resp => {
8 | return resp.config;
9 | });
10 | },
11 |
12 | setData(config) {
13 | if (config) {
14 | return browser.storage.sync.set({
15 | config,
16 | });
17 | } else {
18 | return Promise.resolve('no config');
19 | }
20 | },
21 | };
22 |
--------------------------------------------------------------------------------
/extension/helper/editor.helper.ts:
--------------------------------------------------------------------------------
1 | export function autoFormat(editor) {
2 | setTimeout(function() {
3 | editor.getAction('editor.action.formatDocument').run();
4 | }, 300);
5 | }
6 |
--------------------------------------------------------------------------------
/extension/helper/extension.helper.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | export function getURL(path: string) {
4 | return chrome.extension.getURL(path);
5 | }
--------------------------------------------------------------------------------
/extension/helper/i18n.helper.ts:
--------------------------------------------------------------------------------
1 |
2 | export function t(key) {
3 | return chrome.i18n.getMessage(key);
4 | }
--------------------------------------------------------------------------------
/extension/helper/result.helper.ts:
--------------------------------------------------------------------------------
1 | export function createUrl({ url, title, icon, desc = '', showDesc = false }) {
2 | return {
3 | title,
4 | desc: showDesc ? desc || url : '',
5 | icon,
6 | universal: true,
7 | url,
8 | key: 'url',
9 | };
10 | }
11 |
12 | export function createCopy({ url, title, icon, desc, showDesc }) {
13 | return {
14 | title,
15 | desc: showDesc ? desc || url : '',
16 | icon,
17 | universal: true,
18 | url,
19 | key: 'copy',
20 | };
21 | }
22 |
--------------------------------------------------------------------------------
/extension/helper/storage.helper.ts:
--------------------------------------------------------------------------------
1 | import Toast from 'toastr';
2 | import { browser } from 'webextension-polyfill-ts';
3 |
4 | export default class ItemsStorage {
5 | name: string;
6 | key: string;
7 | norepeat: any;
8 | appName?: any;
9 | constructor(name, key, norepeat) {
10 | this.name = name;
11 | this.key = key;
12 | this.norepeat = norepeat;
13 | }
14 |
15 | filter(item, target) {
16 | return item !== target;
17 | }
18 |
19 | removeItem(target) {
20 | return this.getItems().then(resp => {
21 | const others = resp.filter(item => {
22 | return this.filter(item, target);
23 | });
24 |
25 | this.log('remove', target);
26 | return browser.storage.sync.set({
27 | [this.key]: others,
28 | });
29 | });
30 | }
31 |
32 | isRepeat(list, target) {
33 | return list.indexOf(target) !== -1;
34 | }
35 |
36 | addItem(item) {
37 | if (item) {
38 | return this.getItems().then((items = []) => {
39 | if (this.norepeat) {
40 | if (!this.isRepeat(items, item)) {
41 | items.push(item);
42 | } else {
43 | this.log('add', item, 'cannot add repeatedly');
44 |
45 | return Promise.reject('');
46 | }
47 | } else {
48 | items.push(item);
49 | }
50 |
51 | this.log('add', item);
52 |
53 | return browser.storage.sync.set({
54 | [this.key]: items,
55 | });
56 | });
57 | } else {
58 | return Promise.reject('no item');
59 | }
60 | }
61 |
62 | getItems() {
63 | return browser.storage.sync.get(this.key).then(results => {
64 | return results[this.key];
65 | });
66 | }
67 |
68 | log(action, item, msg?) {
69 | const resultStr = msg ? `unsuccessfully: ${msg}` : 'successfully';
70 |
71 | Toast.success(
72 | `${action} ${this.key} [${item}] ${resultStr}`,
73 | this.appName,
74 | { timeOut: 1000 },
75 | );
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/extension/helper/theme.helper.ts:
--------------------------------------------------------------------------------
1 | import { browser } from 'webextension-polyfill-ts';
2 |
3 | import CONST from 'constant';
4 |
5 | export default {
6 | key: CONST.STORAGE.THEMES,
7 |
8 | getData() {
9 | return browser.storage.sync.get(CONST.STORAGE.THEMES).then(resp => {
10 | return resp[CONST.STORAGE.THEMES];
11 | });
12 | },
13 |
14 | setData(themes) {
15 | if (themes) {
16 | return browser.storage.sync.set({
17 | [CONST.STORAGE.THEMES]: themes,
18 | });
19 | } else {
20 | return Promise.resolve('no themes');
21 | }
22 | },
23 | };
24 |
--------------------------------------------------------------------------------
/extension/img/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solobat/Steward/bf207462ea597cc9af2db18c8be57eed77175dc7/extension/img/icon.png
--------------------------------------------------------------------------------
/extension/img/icon128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solobat/Steward/bf207462ea597cc9af2db18c8be57eed77175dc7/extension/img/icon128.png
--------------------------------------------------------------------------------
/extension/img/icon16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solobat/Steward/bf207462ea597cc9af2db18c8be57eed77175dc7/extension/img/icon16.png
--------------------------------------------------------------------------------
/extension/img/icon48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solobat/Steward/bf207462ea597cc9af2db18c8be57eed77175dc7/extension/img/icon48.png
--------------------------------------------------------------------------------
/extension/img/jenkins/aborted.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solobat/Steward/bf207462ea597cc9af2db18c8be57eed77175dc7/extension/img/jenkins/aborted.png
--------------------------------------------------------------------------------
/extension/img/jenkins/blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solobat/Steward/bf207462ea597cc9af2db18c8be57eed77175dc7/extension/img/jenkins/blue.png
--------------------------------------------------------------------------------
/extension/img/jenkins/health-00to19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solobat/Steward/bf207462ea597cc9af2db18c8be57eed77175dc7/extension/img/jenkins/health-00to19.png
--------------------------------------------------------------------------------
/extension/img/jenkins/health-20to39.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solobat/Steward/bf207462ea597cc9af2db18c8be57eed77175dc7/extension/img/jenkins/health-20to39.png
--------------------------------------------------------------------------------
/extension/img/jenkins/health-40to59.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solobat/Steward/bf207462ea597cc9af2db18c8be57eed77175dc7/extension/img/jenkins/health-40to59.png
--------------------------------------------------------------------------------
/extension/img/jenkins/health-60to79.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solobat/Steward/bf207462ea597cc9af2db18c8be57eed77175dc7/extension/img/jenkins/health-60to79.png
--------------------------------------------------------------------------------
/extension/img/jenkins/health-80plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solobat/Steward/bf207462ea597cc9af2db18c8be57eed77175dc7/extension/img/jenkins/health-80plus.png
--------------------------------------------------------------------------------
/extension/img/jenkins/nobuilt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solobat/Steward/bf207462ea597cc9af2db18c8be57eed77175dc7/extension/img/jenkins/nobuilt.png
--------------------------------------------------------------------------------
/extension/img/jenkins/red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solobat/Steward/bf207462ea597cc9af2db18c8be57eed77175dc7/extension/img/jenkins/red.png
--------------------------------------------------------------------------------
/extension/img/wordcard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solobat/Steward/bf207462ea597cc9af2db18c8be57eed77175dc7/extension/img/wordcard.png
--------------------------------------------------------------------------------
/extension/info/changelog.ts:
--------------------------------------------------------------------------------
1 | const langZh = [
2 | {
3 | version: 'v4.1.1',
4 | detail: '修复: 计算结果不能复制的问题;外观: 新增各种 height 的可配置。'
5 | },
6 | {
7 | version: 'v4.1.0',
8 | detail: '整体重构;新增plugin/组件的参数支持;新增命令框空查询;支持plugin级别的使用频次排序;移除无效的plugins。'
9 | },
10 | {
11 | version: 'v4.0.6',
12 | detail: '移除一些失效的内置 chrome 页面,以及小优化',
13 | },
14 | {
15 | version: 'v4.0.5',
16 | detail: '优化及 Bug 修复',
17 | },
18 | {
19 | version: 'v4.0.4',
20 | detail: '优化及 Bug 修复',
21 | },
22 | {
23 | version: 'v4.0.3',
24 | detail: 'bugfix',
25 | },
26 | {
27 | version: 'v4.0.2',
28 | detail:
29 | '组件支持快捷键显示/隐藏;component plugin 提供 show/hide 命令启动和禁用组件',
30 | },
31 | {
32 | version: 'v4.0.1',
33 | detail: '搜索结果按使用次数排序;newtab layout 优化; 组件源切换',
34 | },
35 | {
36 | version: 'v4.0.0',
37 | detail: 'Newtab 组件化,可定制; 设置页重构',
38 | },
39 | ];
40 |
41 | const langEn = [
42 | {
43 | version: 'v4.1.1',
44 | detail: 'fix: calc result copy issue; appearance: height of box configurable',
45 | },
46 | {
47 | version: 'v4.1.0',
48 | detail: 'Refactor; Plugin/Component args supportted; Query onEmpty setting; Plugin level results sorted; Remove some invalid plugins.'
49 | },
50 | {
51 | version: 'v4.0.6',
52 | detail: 'remove some invalid chrome pages && optimization',
53 | },
54 | {
55 | version: 'v4.0.5',
56 | detail: 'optimization && bugfix',
57 | },
58 | {
59 | version: 'v4.0.4',
60 | detail: 'optimization && bugfix',
61 | },
62 | {
63 | version: 'v4.0.3',
64 | detail: 'bugfix',
65 | },
66 | {
67 | version: 'v4.0.2',
68 | detail:
69 | 'Use shortcut keys to show components; Provide show / hide command to enable and disable components',
70 | },
71 | {
72 | version: 'v4.0.1',
73 | detail:
74 | 'Sort search results by number of uses; newtab layout optimization; component source switching',
75 | },
76 | {
77 | version: 'v4.0.0',
78 | detail: 'Component Newtab page, customizable; refactor the settings page',
79 | },
80 | ];
81 |
82 | let results;
83 |
84 | if (chrome.i18n.getUILanguage().indexOf('zh') > -1) {
85 | results = langZh;
86 | } else {
87 | results = langEn;
88 | }
89 |
90 | export default results;
91 |
--------------------------------------------------------------------------------
/extension/info/help.ts:
--------------------------------------------------------------------------------
1 |
2 | const langZh = `
3 | 帮助文档
4 | 论坛
5 | Telegram
6 |
7 | QQ群: 575397892
8 |
9 |
10 |
11 | `;
12 |
13 | const langEn = `
14 | Documentation
15 |
16 |
17 | Please try to upgrade the latest version of the browser, to avoid some of the features can not be used.
18 | If you have any suggestions / problems in the process of using it, you can go here,or join the Telegram channel.
19 | `;
20 |
21 | let results;
22 |
23 | if (chrome.i18n.getUILanguage().indexOf('zh') > -1) {
24 | results = langZh;
25 | } else {
26 | results = langEn;
27 | }
28 |
29 | export const helpInfo = results;
30 |
--------------------------------------------------------------------------------
/extension/info/i18n.ts:
--------------------------------------------------------------------------------
1 | import { t } from "helper/i18n.helper";
2 |
3 | export const settings = {
4 | notion: {
5 | workflow: t('settings_notion_workflow'),
6 | website: t('settings_notion_website'),
7 | },
8 | fields: {
9 | title: t('settings_fields_title'),
10 | description: t('settings_fields_description'),
11 | content: t('settings_fields_content'),
12 | host: t('settings_fields_host'),
13 | siteicon: t('settings_fields_siteicon'),
14 | paths: t('settings_fields_paths'),
15 | navigations: t('settings_fields_navigations'),
16 | outlinescope: t('settings_fields_outlinescope'),
17 | anchors: t('settings_fields_anchors'),
18 | disable: t('settings_fields_disable'),
19 | enable: t('settings_fields_enable'),
20 | show: t('settings_fields_show'),
21 | showByDefault: t('settings_fields_showbydefault'),
22 | },
23 | tabs: {
24 | general: t('settings_tabs_general'),
25 | plugins: t('settings_tabs_plugins'),
26 | workflows: t('settings_tabs_workflows'),
27 | websites: t('settings_tabs_websites'),
28 | wallpapers: t('settings_tabs_wallpapers'),
29 | newtabcomponents: t('settings_tabs_newtabcomponents'),
30 | appearance: t('settings_tabs_appearance'),
31 | advanced: t('settings_tabs_advanced'),
32 | help: t('settings_tabs_help'),
33 | update: t('settings_tabs_update'),
34 | },
35 | blocks: {
36 | commandsplugins: t('settings_blocks_commandsplugins'),
37 | operationinteraction: t('settings_blocks_operationinteraction'),
38 | websitesconfiguration: t('settings_blocks_websitesconfiguration'),
39 | newtab: t('settings_blocks_newtab'),
40 | performance: t('settings_blocks_performance'),
41 | shortcutconfiguration: t('settings_blocks_shortcutconfiguration'),
42 | websitebaseinfo: t('settings_blocks_websitebaseinfo'),
43 | websitenav: t('settings_blocks_websitenav'),
44 | inpagenav: t('settings_blocks_inpagenav'),
45 | exportimport: t('settings_blocks_exportimport'),
46 | socialshareconfig: t('settings_blocks_socialshareconfig'),
47 | plugineditor: t('settings_blocks_plugineditor'),
48 | },
49 | actions: {
50 | save: t('settings_actions_save'),
51 | delete: t('settings_actions_delete'),
52 | newworkflow: t('settings_actions_newworkflow'),
53 | newwebsite: t('settings_actions_newwebsite'),
54 | applysave: t('settings_actions_applysave'),
55 | reset: t('settings_actions_reset'),
56 | export: t('settings_actions_export'),
57 | import: t('settings_actions_import'),
58 | downloadcrx: t('settings_actions_downloadcrx'),
59 | },
60 | };
61 |
--------------------------------------------------------------------------------
/extension/main/Steward.ts:
--------------------------------------------------------------------------------
1 | import Axios from 'axios';
2 | import md5 from 'blueimp-md5';
3 | import dayjs from 'dayjs';
4 | import $ from 'jquery';
5 | import Toast from 'toastr';
6 | import _ from 'underscore';
7 | import { browser } from 'webextension-polyfill-ts';
8 |
9 | import { StewardApp } from 'common/type';
10 | import util from 'common/util';
11 | import CONST from 'constant';
12 | import PromisifyStorage from 'utils/storage';
13 |
14 | function installGlobalSteward() {
15 | window.__Steward__ = window.stewardApp = getGlobalStewardAPI();
16 | }
17 |
18 | export function getGlobalStewardAPI() {
19 | return {
20 | chrome: window.chrome,
21 | browser,
22 | Toast,
23 | md5,
24 | axios: Axios,
25 | dayjs: dayjs,
26 | $,
27 | storage: PromisifyStorage,
28 |
29 | state: {
30 | background: false,
31 | key: '',
32 | stage: '',
33 | str: '',
34 | cmd: '',
35 | query: '',
36 | delay: 0,
37 | lastcmd: '',
38 | command: null,
39 | workflowStack: [],
40 | keyStatus: {
41 | shiftKey: false,
42 | ctrlKey: false,
43 | metaKey: false,
44 | altKey: false,
45 | },
46 | },
47 |
48 | util,
49 | constant: CONST,
50 | } as StewardApp;
51 | }
52 |
53 | const Steward = new Proxy({} as StewardApp, {
54 | get(_, path) {
55 | if (!window.__Steward__) {
56 | installGlobalSteward();
57 | }
58 |
59 | return window.__Steward__[path];
60 | },
61 | set(_, path, value) {
62 | if (!window.__Steward__) {
63 | installGlobalSteward();
64 | }
65 | window.__Steward__[path] = value;
66 |
67 | return true
68 | }
69 | });
70 |
71 | export default Steward;
72 |
--------------------------------------------------------------------------------
/extension/main/cache.ts:
--------------------------------------------------------------------------------
1 | import { StewardCache } from 'common/type'
2 |
3 | function initCache() {
4 | window.__StewardCache__ = {}
5 | }
6 |
7 | const stewardCache = new Proxy({}, {
8 | get(_, path: keyof StewardCache) {
9 | if (!window.__StewardCache__) {
10 | initCache()
11 | }
12 | return window.__StewardCache__[path]
13 | },
14 | set(_, path, value) {
15 | if (!window.__StewardCache__) {
16 | initCache()
17 | }
18 |
19 | window.__StewardCache__[path] = value;
20 |
21 | return true;
22 | }
23 | })
24 |
25 | export default stewardCache
--------------------------------------------------------------------------------
/extension/main/type.ts:
--------------------------------------------------------------------------------
1 | import { PluginCommand, StewardApp } from "common/type";
2 | import { KeyStatus } from "plugins/type";
3 |
4 | export interface AppState {
5 | background: boolean;
6 | key: string;
7 | stage: string;
8 | str: string;
9 | cmd: string;
10 | query: string;
11 | delay: number;
12 | lastcmd: string;
13 | command: PluginCommand | null;
14 | workflowStack: string[];
15 | keyStatus: Partial;
16 | searchTimer?: number;
17 | }
18 |
19 | export interface CommandResultItem {
20 | key: string;
21 | id: string;
22 | icon: string;
23 | title: string;
24 | desc: string;
25 | weight: number;
26 | }
27 |
28 | export interface StewardReadyEventDetail {
29 | app: StewardApp,
30 | }
31 |
32 | export type StewardReadyEvent = CustomEvent
33 |
34 | export type WALLPAPER_ACTION_TYPE = 'save' | 'remove'
35 | export interface WALLPAPER_ACTION {
36 | action: WALLPAPER_ACTION_TYPE;
37 | msg: string
38 | }
--------------------------------------------------------------------------------
/extension/pages/background/background.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Documentation
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/extension/pages/content/content.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | content page
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/extension/pages/content/content.scss:
--------------------------------------------------------------------------------
1 |
2 | .steward-main {
3 | position: fixed;
4 | z-index: 2222222222;
5 | top: 60px;
6 | left: 50%;
7 | width: 530px;
8 | margin-left: -255px;
9 |
10 | &.newtab {
11 | width: 100%;
12 | height: 100%;
13 | left: 0;
14 | top: 0;
15 | margin-left: 0;
16 | }
17 | }
18 |
19 | .base0E {
20 | color: #f2777a;
21 | }
--------------------------------------------------------------------------------
/extension/pages/login/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @file login for auth callback
3 | * @description auth validation callback
4 | * @author tomasy
5 | * @email solopea@gmail.com
6 | */
7 |
8 | import Auth from 'common/auth';
9 | import conf from 'conf/pocket_conf';
10 |
11 | console.log('hello login.js....');
12 |
13 | const auth = new Auth(conf);
14 |
15 | function handler(results) {
16 | const ret = results || {};
17 |
18 | return ret;
19 | }
20 |
21 | auth.getAccessToken(handler, function() {
22 | console.log('login success!....');
23 | window.close();
24 | });
25 |
--------------------------------------------------------------------------------
/extension/pages/login/login.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Login Page
7 |
8 |
9 |
10 | Hello Steward
11 |
12 |
13 |
--------------------------------------------------------------------------------
/extension/pages/options/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import ElementUI from 'element-ui';
3 | import App from './App.vue';
4 | import 'element-ui/lib/theme-default/index.css';
5 | import 'bootstrap/dist/css/bootstrap.min.css'
6 | import 'spectre.css/dist/spectre-icons.min.css'
7 | import util from 'common/util';
8 | import * as i18n from 'info/i18n';
9 | import CONST from 'constant/index';
10 | import router from '@/pages/options/router';
11 | import { t } from 'helper/i18n.helper';
12 |
13 | const manifest = chrome.runtime.getManifest();
14 | const version = manifest.version;
15 |
16 | Vue.use(ElementUI);
17 |
18 | const getConfig = util.getData('getConfig');
19 |
20 | function init() {
21 | Promise.all([getConfig()]).then(([config]) => {
22 | const tips = CONST.I18N.TIPS;
23 |
24 | config.lastVersion = config.version || version;
25 | // only used for options page
26 | window.optionsPage = {
27 | config,
28 | };
29 |
30 | const i18nTexts = getI18nTexts({ general: config.general, tips });
31 |
32 | i18nTexts.ui = i18n;
33 |
34 | render(config, i18nTexts);
35 | });
36 | }
37 |
38 | function getI18nTexts(obj, prefix) {
39 | try {
40 | if (typeof obj === 'object' && !(obj instanceof Array)) {
41 | const ret = {};
42 |
43 | for (const key in obj) {
44 | const nextPrefix = prefix ? `${prefix}_${key}` : key;
45 |
46 | ret[key] = getI18nTexts(obj[key], nextPrefix);
47 | }
48 | return ret;
49 | } else {
50 | return t(prefix);
51 | }
52 | } catch (e) {
53 | console.log(e);
54 | return {};
55 | }
56 | }
57 |
58 | function render({ general, plugins }, i18nTexts) {
59 | new Vue({
60 | el: '#app',
61 | data: {
62 | config: {
63 | general,
64 | plugins,
65 | version,
66 | },
67 | i18nTexts,
68 | },
69 | router,
70 | components: { App },
71 | template: '',
72 | });
73 | }
74 |
75 | init();
76 |
--------------------------------------------------------------------------------
/extension/pages/options/options.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Preference
7 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/extension/pages/options/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueRouter from 'vue-router'
3 | import General from '@/pages/options/views/General.vue'
4 | import Plugins from '@/pages/options/views/Plugins.vue'
5 | import Workflows from '@/pages/options/views/Workflows.vue'
6 | import Websites from '@/pages/options/views/Websites.vue'
7 | import Newtabcomponents from '@/pages/options/views/Newtabcomponents.vue'
8 | import Wallpapers from '@/pages/options/views/Wallpapers.vue'
9 | import Appearance from '@/pages/options/views/Appearance.vue'
10 | import Advanced from '@/pages/options/views/Advanced.vue'
11 | import Help from '@/pages/options/views/Help.vue'
12 | import Update from '@/pages/options/views/Update.vue'
13 |
14 | Vue.use(VueRouter)
15 |
16 | const routes = [
17 | {
18 | path: '/',
19 | name: 'General',
20 | component: General,
21 | meta: {
22 | }
23 | },
24 | {
25 | path: '/plugins',
26 | name: 'Plugins',
27 | component: Plugins,
28 | meta: {
29 | }
30 | },
31 | {
32 | path: '/workflows',
33 | name: 'Workflows',
34 | component: Workflows,
35 | meta: {
36 | }
37 | },
38 | {
39 | path: '/websites',
40 | name: 'Websites',
41 | component: Websites,
42 | meta: {
43 | }
44 | },
45 | {
46 | path: '/newtabcomponents',
47 | name: 'Newtabcomponents',
48 | component: Newtabcomponents,
49 | meta: {
50 | }
51 | },
52 | {
53 | path: '/wallpapers',
54 | name: 'Wallpapers',
55 | component: Wallpapers,
56 | meta: {
57 | }
58 | },
59 | {
60 | path: '/appearance',
61 | name: 'Appearance',
62 | component: Appearance,
63 | meta: {
64 | }
65 | },
66 | {
67 | path: '/advanced',
68 | name: 'Advanced',
69 | component: Advanced,
70 | meta: {
71 | }
72 | },
73 | {
74 | path: '/help',
75 | name: 'Help',
76 | component: Help,
77 | meta: {
78 | }
79 | },
80 | {
81 | path: '/update',
82 | name: 'Update',
83 | component: Update,
84 | meta: {
85 | }
86 | },
87 | { path: '*', redirect: '/' }
88 | ]
89 |
90 | const router = new VueRouter({
91 | mode: 'hash',
92 | routes
93 | })
94 |
95 | export default router
96 |
--------------------------------------------------------------------------------
/extension/pages/options/views/Help.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
20 |
21 |
--------------------------------------------------------------------------------
/extension/pages/options/views/Update.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{ extType }} v{{config.version}}
5 |
13 |
19 |
20 |
21 |
22 |
23 |
39 |
40 |
--------------------------------------------------------------------------------
/extension/pages/popup/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
34 |
35 |
82 |
83 |
--------------------------------------------------------------------------------
/extension/pages/popup/popup.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | popup
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/extension/pages/steward/index.js:
--------------------------------------------------------------------------------
1 | import { initConfig, globalApi, installApp } from '../../main/main';
2 | import Vue from 'vue';
3 | import ElementUI from 'element-ui';
4 | import 'element-ui/lib/theme-default/index.css';
5 | import App from './App.vue';
6 | import dayjs from 'dayjs';
7 | import axios from 'axios';
8 | import { Loading } from 'element-ui';
9 | import { registerComponents } from 'helper/component.helper';
10 |
11 | Vue.use(ElementUI);
12 | Vue.config.productionTip = false;
13 | Vue.config.devtools = true;
14 | Vue.prototype.$dayjs = dayjs;
15 | Vue.prototype.$http = axios;
16 | Vue.use(Loading.directive);
17 | Vue.prototype.$axios = axios;
18 | Vue.prototype.$notify = function notify(title, body) {
19 | Notification.requestPermission(function(status) {
20 | if (status === 'granted') {
21 | new Notification(title, { body });
22 | }
23 | });
24 | };
25 |
26 | const mode = 'newTab';
27 |
28 | initConfig(mode, false).then(config => {
29 | const appData = { mode, data: {}, config };
30 | globalApi(appData);
31 | registerComponents(Vue, config.components);
32 |
33 | const app = new Vue({
34 | el: '#app',
35 | data: {
36 | config,
37 | },
38 | components: { App },
39 | template: '',
40 | });
41 |
42 | installApp(app);
43 | });
44 |
--------------------------------------------------------------------------------
/extension/pages/steward/steward.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | New Tab
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/extension/pages/urlblock/index.ts:
--------------------------------------------------------------------------------
1 | import PluginHelper from 'helper/plugin.helper';
2 |
3 | const pluginHelper = new PluginHelper();
4 |
5 | chrome.runtime.sendMessage(
6 | {
7 | action: 'getData',
8 | },
9 | resp => {
10 | pluginHelper.init(resp.data.blockedUrls);
11 | },
12 | );
13 |
--------------------------------------------------------------------------------
/extension/pages/urlblock/urlblock.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | url block message
6 |
12 |
13 |
14 | This page has been blocked by yourself!
15 |
16 |
17 |
--------------------------------------------------------------------------------
/extension/plugins/browser/del.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @description delete extensions / apps by del command
3 | * @author tomasy
4 | * @mail solopea@gmail.com
5 | */
6 |
7 | import { StewardApp } from 'common/type';
8 | import { getURL } from 'helper/extension.helper';
9 | import { t } from 'helper/i18n.helper';
10 | import { Command, Plugin } from 'plugins/type';
11 |
12 | export default function(Steward: StewardApp): Plugin {
13 | const { chrome, util } = Steward;
14 |
15 | const version = 2;
16 | const name = 'deleteExtension';
17 | const key = 'del';
18 | const type = 'keyword';
19 | const icon = getURL('iconfont/del.svg');
20 | const title = t(`${name}_title`);
21 | const subtitle = t(`${name}_subtitle`);
22 | const commands: Command[] = [
23 | {
24 | key,
25 | type,
26 | title,
27 | subtitle,
28 | icon,
29 | editable: true,
30 | },
31 | ];
32 |
33 | function uninstall(id, cb) {
34 | Steward.chrome.management.uninstall(id, function(...args) {
35 | Reflect.apply(cb, null, args);
36 | });
37 | }
38 |
39 | // get all
40 | function getExtensions(query, enabled, callback) {
41 | chrome.management.getAll(function(extList) {
42 | const matchExts = extList.filter(function(ext) {
43 | return util.matchText(query, ext.name);
44 | });
45 |
46 | callback(matchExts);
47 | });
48 | }
49 |
50 | function dataFormat(rawList) {
51 | return rawList.map(function(item) {
52 | const url =
53 | item.icons instanceof Array
54 | ? item.icons[item.icons.length - 1].url
55 | : '';
56 | const isWarn = item.installType === 'development';
57 | return {
58 | key,
59 | id: item.id,
60 | icon: url,
61 | title: item.name,
62 | desc: item.description,
63 | isWarn: isWarn,
64 | };
65 | });
66 | }
67 |
68 | function onInput(query) {
69 | return new Promise(resolve => {
70 | getExtensions(query.toLowerCase(), false, function(matchExts) {
71 | resolve(dataFormat(matchExts));
72 | });
73 | });
74 | }
75 |
76 | function onEnter(item) {
77 | uninstall(item.id, () => {
78 | Steward.app.refresh();
79 | });
80 | }
81 | return {
82 | version,
83 | name: 'Delete Extension',
84 | category: 'browser',
85 | icon,
86 | title,
87 | commands,
88 | onInput,
89 | onEnter,
90 | canDisabled: false,
91 | };
92 | }
93 |
--------------------------------------------------------------------------------
/extension/plugins/browser/on.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @description enable extensions/apps
3 | * @author tomasy
4 | * @email solopea@gmail.com
5 | */
6 |
7 | import { StewardApp } from 'common/type';
8 | import { getURL } from 'helper/extension.helper';
9 | import { t } from 'helper/i18n.helper';
10 | import { Command, Plugin, Type } from 'plugins/type';
11 |
12 | export default function(Steward: StewardApp): Plugin {
13 | const { chrome, util } = Steward;
14 |
15 | const version = 2;
16 | const name = 'onExtension';
17 | const key = 'on';
18 | const type: Type = 'keyword';
19 | const icon = getURL('iconfont/on.svg');
20 | const title = t(`${name}_title`);
21 | const subtitle = t(`${name}_subtitle`);
22 | const commands: Command[] = [
23 | {
24 | key,
25 | type,
26 | title,
27 | subtitle,
28 | icon,
29 | editable: true,
30 | },
31 | ];
32 |
33 | function setEnabled(id, enabled) {
34 | chrome.management.setEnabled(id, enabled, function() {});
35 | }
36 |
37 | function getExtensions(query, enabled, callback) {
38 | chrome.management.getAll(function(extList) {
39 | const matchExts = extList.filter(function(ext) {
40 | return (
41 | ext.type === 'extension' &&
42 | util.matchText(query, ext.name) &&
43 | ext.enabled === enabled
44 | );
45 | });
46 |
47 | callback(matchExts);
48 | });
49 | }
50 |
51 | function dataFormat(rawList) {
52 | return rawList.map(function(item) {
53 | const url =
54 | item.icons instanceof Array
55 | ? item.icons[item.icons.length - 1].url
56 | : '';
57 | const isWarn = item.installType === 'development';
58 |
59 | return {
60 | key,
61 | id: item.id,
62 | icon: url,
63 | title: item.name,
64 | desc: item.description,
65 | isWarn,
66 | };
67 | });
68 | }
69 |
70 | function onInput(query) {
71 | return new Promise(resolve => {
72 | getExtensions(query.toLowerCase(), false, function(matchExts) {
73 | resolve(dataFormat(matchExts));
74 | });
75 | });
76 | }
77 |
78 | function onEnter(item) {
79 | if (item && item.id) {
80 | setEnabled(item.id, true);
81 | window.slogs.push(`Enable: ${item.title}`);
82 | Steward.app.refresh();
83 | }
84 | }
85 |
86 | return {
87 | version,
88 | name: 'Enable Extension',
89 | category: 'browser',
90 | icon,
91 | title,
92 | commands,
93 | onInput,
94 | onEnter,
95 | canDisabled: false,
96 | };
97 | }
98 |
--------------------------------------------------------------------------------
/extension/plugins/browser/run.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @description run app
3 | * @author tomasy
4 | * @email solopea@gmail.com
5 | */
6 |
7 | import { StewardApp } from 'common/type';
8 | import { getURL } from 'helper/extension.helper';
9 | import { t } from 'helper/i18n.helper';
10 | import { Command, Plugin } from 'plugins/type';
11 |
12 | export default function(Steward: StewardApp): Plugin {
13 | const { chrome, util } = Steward;
14 |
15 | const version = 2;
16 | const name = 'runapp';
17 | const key = 'run';
18 | const type = 'keyword';
19 | const icon = getURL('iconfont/app.svg');
20 | const title = t(`${name}_title`);
21 | const subtitle = t(`${name}_subtitle`);
22 | const commands: Command[] = [
23 | {
24 | key,
25 | type,
26 | title,
27 | subtitle,
28 | icon,
29 | editable: true,
30 | },
31 | ];
32 |
33 | function getExtensions(query, callback) {
34 | chrome.management.getAll(function(extList) {
35 | const data = extList.filter(function(ext) {
36 | return util.matchText(query, ext.name) && ext.isApp;
37 | });
38 |
39 | callback(data);
40 | });
41 | }
42 |
43 | function dataFormat(rawList) {
44 | return rawList.map(function(item) {
45 | const url = item.icons instanceof Array ? item.icons[0].url : '';
46 | const isWarn = item.installType === 'development';
47 |
48 | return {
49 | key,
50 | id: item.id,
51 | icon: url,
52 | title: item.name,
53 | desc: item.description,
54 | isWarn,
55 | };
56 | });
57 | }
58 |
59 | function onInput(query) {
60 | return new Promise(resolve => {
61 | getExtensions(query.toLowerCase(), function(data) {
62 | resolve(dataFormat(data));
63 | });
64 | });
65 | }
66 |
67 | function launch(id) {
68 | chrome.management.setEnabled(id, true, function() {
69 | chrome.management.launchApp(id, function() {});
70 | });
71 | }
72 |
73 | function onEnter(item) {
74 | const { id } = item;
75 |
76 | launch(id);
77 | Steward.app.refresh();
78 | }
79 |
80 | return {
81 | version,
82 | name: 'Run App',
83 | category: 'browser',
84 | icon,
85 | title,
86 | commands,
87 | onInput,
88 | onEnter,
89 | canDisabled: false,
90 | };
91 | }
92 |
--------------------------------------------------------------------------------
/extension/plugins/browser/set.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @description open extension's option page
3 | * @author tomasy
4 | * @mail solopea@gmail.com
5 | */
6 |
7 | import { StewardApp } from 'common/type';
8 | import { getURL } from 'helper/extension.helper';
9 | import { t } from 'helper/i18n.helper';
10 | import { Command, Plugin } from 'plugins/type';
11 |
12 | export default function(Steward: StewardApp): Plugin {
13 | const { chrome, util } = Steward;
14 |
15 | const version = 2;
16 | const name = 'setOption';
17 | const key = 'set';
18 | const type = 'keyword';
19 | const icon = getURL('iconfont/set.svg');
20 | const title = t(`${name}_title`);
21 | const subtitle = t(`${name}_subtitle`);
22 | const commands: Command[] = [
23 | {
24 | key,
25 | type,
26 | title,
27 | subtitle,
28 | icon,
29 | editable: true,
30 | },
31 | ];
32 |
33 | function openOptionPage(item, keyStatus) {
34 | const url = item.url;
35 |
36 | if (!url) {
37 | return;
38 | }
39 |
40 | util.createTab({ url: url }, keyStatus);
41 | }
42 |
43 | // get all
44 | function getExtensions(query, enabled, callback) {
45 | chrome.management.getAll(function(extList) {
46 | const matchExts = extList.filter(function(ext) {
47 | return (
48 | !ext.isApp &&
49 | ext.enabled === enabled &&
50 | util.matchText(query, ext.name)
51 | );
52 | });
53 |
54 | callback(matchExts);
55 | });
56 | }
57 |
58 | function dataFormat(rawList) {
59 | return rawList.map(function(item) {
60 | const url =
61 | item.icons instanceof Array
62 | ? item.icons[item.icons.length - 1].url
63 | : '';
64 | const isWarn = item.installType === 'development';
65 |
66 | return {
67 | key,
68 | id: item.id,
69 | icon: url,
70 | title: item.name,
71 | url: item.optionsUrl,
72 | desc: item.description,
73 | isWarn,
74 | };
75 | });
76 | }
77 | function onInput(query) {
78 | return new Promise(resolve => {
79 | getExtensions(query.toLowerCase(), true, function(matchExts) {
80 | resolve(dataFormat(matchExts));
81 | });
82 | });
83 | }
84 |
85 | function onEnter(item, command, query, keyStatus) {
86 | openOptionPage(item, keyStatus);
87 | }
88 |
89 | return {
90 | version,
91 | name: 'Set Extension',
92 | category: 'browser',
93 | icon,
94 | title,
95 | commands,
96 | onInput,
97 | onEnter,
98 | canDisabled: false,
99 | };
100 | }
101 |
--------------------------------------------------------------------------------
/extension/plugins/browser/topsites.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @description list the most visit websites
3 | * @author tomasy
4 | * @email solopea@gmail.com
5 | */
6 |
7 | import { StewardApp } from 'common/type';
8 | import { getURL } from 'helper/extension.helper';
9 | import { t } from 'helper/i18n.helper';
10 | import { Command, Plugin } from 'plugins/type';
11 |
12 | export default function(Steward: StewardApp): Plugin {
13 | const { chrome, util } = Steward;
14 |
15 | const version = 4;
16 | const name = 'topsites';
17 | const key = 'site';
18 | const type = 'keyword';
19 | const icon = getURL('iconfont/topsites.svg');
20 | const title = t(`${name}_title`);
21 | const subtitle = t(`${name}_subtitle`);
22 | const commands: Command[] = [
23 | {
24 | key,
25 | type,
26 | title,
27 | subtitle,
28 | icon,
29 | allowBatch: true,
30 | shiftKey: true,
31 | editable: true,
32 | },
33 | ];
34 |
35 | function onInput() {
36 | return new Promise(resolve => {
37 | chrome.topSites.get(sites => {
38 | const arr = [];
39 | const wrapDesc = util.wrapWithMaxNumIfNeeded('url');
40 | let i;
41 |
42 | for (i in sites) {
43 | const item = sites[i];
44 | const desc = wrapDesc(item, i);
45 | arr.push({
46 | key,
47 | id: item.url,
48 | icon: icon,
49 | url: item.url,
50 | title: item.title,
51 | desc,
52 | isWarn: false,
53 | });
54 | }
55 |
56 | resolve(arr);
57 | });
58 | });
59 | }
60 |
61 | function onEnter(item, command, query, { shiftKey }, list) {
62 | util.batchExecutionIfNeeded(shiftKey, util.tabCreateExecs, [list, item]);
63 | return Promise.resolve('');
64 | }
65 |
66 | return {
67 | version,
68 | name: 'Top Sites',
69 | category: 'browser',
70 | icon,
71 | title,
72 | commands,
73 | onInput,
74 | onEnter,
75 | canDisabled: false,
76 | };
77 | }
78 |
--------------------------------------------------------------------------------
/extension/plugins/other/calculate.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @description calculate
3 | * @author tomasy
4 | * @mail solopea@gmail.com
5 | */
6 |
7 | import mathexp from 'math-expression-evaluator';
8 |
9 | import { Command, Plugin } from 'plugins/type';
10 | import { StewardApp } from 'common/type';
11 | import { t } from 'helper/i18n.helper';
12 | import { getURL } from 'helper/extension.helper';
13 |
14 | export default function(Steward: StewardApp): Plugin {
15 | const { chrome, util } = Steward;
16 |
17 | const name = 'calculate';
18 | const version = 4;
19 | const type = 'always';
20 | const key = 'calc';
21 | const icon = getURL('iconfont/calc.svg');
22 | const title = t(`${name}_title`);
23 | const subtitle = t(`${name}_subtitle`);
24 | const commands: Command[] = [
25 | {
26 | key,
27 | type,
28 | title,
29 | subtitle,
30 | icon,
31 | editable: false,
32 | },
33 | ];
34 |
35 | function onInput(query) {
36 | let data = [];
37 | if (query.startsWith('calc ') && query) {
38 | return;
39 | }
40 | try {
41 | const result = mathexp.eval(Steward.state.str);
42 | data = [
43 | {
44 | key: 'copy',
45 | icon: icon,
46 | title: result,
47 | desc: subtitle,
48 | content: result,
49 | universal: true
50 | },
51 | ];
52 | } catch (e) {
53 | data = null;
54 | }
55 |
56 | return Promise.resolve(data);
57 | }
58 |
59 | function onEnter(item) {
60 | const text = item.title;
61 |
62 | util.copyToClipboard(text, true);
63 |
64 | return Promise.resolve(false);
65 | }
66 |
67 | return {
68 | version,
69 | name: 'Calculator',
70 | category: 'other',
71 | icon,
72 | title,
73 | commands,
74 | onInput,
75 | onEnter,
76 | canDisabled: false,
77 | };
78 | }
79 |
--------------------------------------------------------------------------------
/extension/plugins/other/openurl.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @description open url in browser
3 | * @author tomasy
4 | * @mail solopea@gmail.com
5 | */
6 |
7 | import urlRegex from 'url-regex';
8 |
9 | import { Command, Plugin } from 'plugins/type';
10 | import { StewardApp } from 'common/type';
11 | import { t } from 'helper/i18n.helper';
12 | import { getURL } from 'helper/extension.helper';
13 |
14 | export default function(Steward: StewardApp): Plugin {
15 | const { chrome, util } = Steward;
16 |
17 | const version = 3;
18 | const name = 'openurl';
19 | const key = 'open';
20 | const type = 'regexp';
21 | const icon = getURL('iconfont/openurl.svg');
22 | const title = t(`${name}_title`);
23 | const subtitle = t(`${name}_subtitle`);
24 | const regExp: RegExp = urlRegex({ exact: true, strict: false });
25 |
26 | regExp.formatter = (query: string) => query.replace(/。/g, '.')
27 |
28 | const commands: Command[] = [
29 | {
30 | key,
31 | title,
32 | type,
33 | subtitle,
34 | icon,
35 | editable: false,
36 | regExp,
37 | },
38 | ];
39 |
40 | function onInput(url) {
41 | const data = [
42 | {
43 | key: 'url',
44 | id: name,
45 | icon,
46 | title: regExp.formatter(url),
47 | desc: subtitle,
48 | url,
49 | },
50 | ];
51 |
52 | return data;
53 | }
54 |
55 | function onEnter(item, command, query, keyStatus) {
56 | const { url } = item;
57 | let theurl = url;
58 |
59 | if (!/^https?/.test(url)) {
60 | theurl = `http://${url}`;
61 | }
62 | util.createTab({ url: theurl }, keyStatus);
63 | }
64 |
65 | return {
66 | version,
67 | name: 'Open Url',
68 | category: 'other',
69 | icon,
70 | title,
71 | onInput,
72 | onEnter,
73 | commands,
74 | canDisabled: false,
75 | };
76 | }
77 |
--------------------------------------------------------------------------------
/extension/plugins/steward/about.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @description about steward
3 | * @author tomasy
4 | * @email solopea@gmail.com
5 | */
6 |
7 | import { StewardApp } from 'common/type';
8 | import { getAboutLinks, getUpLinks } from 'info/links';
9 | import { Plugin } from 'plugins/type';
10 | import { t } from 'helper/i18n.helper';
11 | import { getURL } from 'helper/extension.helper';
12 |
13 | export default function(Steward: StewardApp): Plugin {
14 | const { chrome, util } = Steward;
15 |
16 | const version = 1;
17 | const name = 'about';
18 | const keys = [
19 | { key: 'about', shiftKey: true, allowBatch: true, editable: false },
20 | { key: 'up', shiftKey: true, allowBatch: true, editable: false },
21 | ];
22 | const type = 'keyword';
23 | const icon = getURL('img/icon.png');
24 | const title = t(`${name}_title`);
25 | const commands = util.genCommands(name, icon, keys, type);
26 | const lang = chrome.i18n.getUILanguage().indexOf('zh') > -1 ? 'zh' : 'en';
27 | const aboutLinks = getAboutLinks(lang);
28 | const upLinks = getUpLinks(lang);
29 |
30 | function dataFormat(list, command?: any) {
31 | const wrapDesc = util.wrapWithMaxNumIfNeeded('desc');
32 |
33 | return list.map((item, i) => {
34 | const desc = wrapDesc(item, i);
35 | return {
36 | key: 'plugins',
37 | title: item.title,
38 | icon: item.icon || icon,
39 | desc,
40 | url: item.url,
41 | };
42 | });
43 | }
44 |
45 | function onInput(query, command) {
46 | return new Promise(resolve => {
47 | if (command.orkey === 'about') {
48 | resolve(dataFormat(aboutLinks, command));
49 | } else {
50 | resolve(dataFormat(upLinks, command));
51 | }
52 | });
53 | }
54 |
55 | function onEnter(item, command, query, { shiftKey }, list) {
56 | util.batchExecutionIfNeeded(shiftKey, util.tabCreateExecs, [list, item]);
57 | }
58 |
59 | return {
60 | version,
61 | name: 'About Steward',
62 | category: 'steward',
63 | icon,
64 | title,
65 | commands,
66 | onInput,
67 | onEnter,
68 | canDisabled: false,
69 | };
70 | }
71 |
--------------------------------------------------------------------------------
/extension/plugins/steward/component.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @description components manager
3 | * @author tomasy
4 | * @email solopea@gmail.com
5 | */
6 |
7 | import { StewardApp } from 'common/type';
8 | import { componentHelper, getComponentsConfig } from 'helper/component.helper';
9 | import { Plugin } from 'plugins/type';
10 | import { t } from 'helper/i18n.helper';
11 | import { getURL } from 'helper/extension.helper';
12 |
13 | export default function(Steward: StewardApp): Plugin {
14 | const { chrome, util } = Steward;
15 |
16 | const version = 1;
17 | const name = 'component';
18 | const keys = [{ key: 'show' }, { key: 'hide' }];
19 | const type = 'keyword';
20 | const icon = getURL('img/icon.png');
21 | const title = t(`${name}_title`);
22 | const commands = util.genCommands(name, icon, keys, type);
23 |
24 | function dataFormatter(item) {
25 | const { title, subtitle, icon: theIcon, id } = item.meta;
26 | return {
27 | key: 'component',
28 | title,
29 | desc: subtitle,
30 | icon: theIcon || icon,
31 | id,
32 | };
33 | }
34 |
35 | function onInput(key, command) {
36 | const isShow = command.orkey === 'show';
37 |
38 | return getComponentsConfig().then(list => {
39 | const items = list
40 | .filter(item => item.show === !isShow)
41 | .map(dataFormatter);
42 | const matched = key ? util.getMatches(items, key, 'title') : items;
43 |
44 | return matched;
45 | });
46 | }
47 |
48 | function onEnter(item, command) {
49 | const { orkey } = command;
50 | const isShow = orkey === 'show';
51 | const { id } = item;
52 |
53 | return componentHelper
54 | .update({
55 | id,
56 | show: isShow,
57 | })
58 | .then(() => {
59 | Steward.app.refresh();
60 | });
61 | }
62 |
63 | return {
64 | version,
65 | name: 'Components Manager',
66 | category: 'other',
67 | icon,
68 | title,
69 | commands,
70 | onInput,
71 | onEnter,
72 | canDisabled: false,
73 | };
74 | }
75 |
--------------------------------------------------------------------------------
/extension/plugins/steward/custom.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @description cusotm the newTab default command
3 | * @author tomasy
4 | * @mail solopea@gmail.com
5 | */
6 |
7 | import { Command, Plugin } from 'plugins/type';
8 | import { StewardApp } from 'common/type';
9 | import { t } from 'helper/i18n.helper';
10 | import { getURL } from 'helper/extension.helper';
11 |
12 | export default function(Steward: StewardApp): Plugin {
13 | const { chrome, Toast } = Steward;
14 |
15 | const version = 1;
16 | const name = 'custom';
17 | const key = 'custom';
18 | const type = 'keyword';
19 | const icon = getURL('img/icon.png');
20 | const title = t(`${name}_title`);
21 | const subtitle = t(`${name}_subtitle`);
22 | const commands: Command[] = [
23 | {
24 | key,
25 | type,
26 | title,
27 | subtitle,
28 | icon,
29 | editable: true,
30 | },
31 | ];
32 |
33 | function onInput() {
34 | return [
35 | {
36 | key,
37 | title,
38 | desc: subtitle,
39 | icon,
40 | },
41 | ];
42 | }
43 |
44 | function onEnter(item, command, query) {
45 | if (query) {
46 | chrome.runtime.sendMessage({
47 | action: 'saveConfig',
48 | data: {
49 | general: {
50 | cacheLastCmd: false,
51 | defaultPlugin: 'Other',
52 | customCmd: query,
53 | },
54 | },
55 | });
56 | Steward.app.applyCommand(query);
57 | Toast.success(t('save_ok'));
58 | } else {
59 | Toast.warning(t('custom_warning_notempty'));
60 | }
61 | }
62 |
63 | return {
64 | version,
65 | name: 'Custom',
66 | category: 'steward',
67 | type,
68 | icon,
69 | title,
70 | commands,
71 | onInput,
72 | onEnter,
73 | canDisabled: false,
74 | };
75 | }
76 |
--------------------------------------------------------------------------------
/extension/plugins/steward/help.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @file help command plugin script
3 | * @description help
4 | * @author rong
5 | */
6 |
7 | import _ from 'underscore';
8 |
9 | import { StewardApp } from 'common/type';
10 | import { getURL } from 'helper/extension.helper';
11 | import { t } from 'helper/i18n.helper';
12 | import stewardCache from 'main/cache';
13 | import { Command, Plugin } from 'plugins/type';
14 |
15 | export default function(Steward: StewardApp): Plugin {
16 | const { chrome, util } = Steward;
17 |
18 | const version = 3;
19 | const name = 'help';
20 | const key = 'help';
21 | const type = 'keyword';
22 | const icon = getURL('iconfont/help.svg');
23 | const title = t(`${name}_title`);
24 | const subtitle = t(`${name}_subtitle`);
25 | const commands: Command[] = [
26 | {
27 | key,
28 | type,
29 | title,
30 | subtitle,
31 | icon,
32 | shiftKey: true,
33 | editable: true,
34 | },
35 | ];
36 |
37 | // NOTE: Only get the commands when needed, main.js has been immediately obtained
38 | // and then get the object will be empty
39 | function getPlugins(query) {
40 | const allcommands = stewardCache.commands;
41 | const helpList = _.uniq(_.values(allcommands))
42 | .map(command => {
43 | return {
44 | icon: command.icon,
45 | id: command.key,
46 | name: command.name,
47 | title: `${command.key}: ${command.title}`,
48 | desc: `⇧: ${command.subtitle}`,
49 | type: command.type,
50 | category: command.plugin.category,
51 | };
52 | })
53 | .filter(item => item.type === 'keyword')
54 | .filter(function(command) {
55 | return util.matchText(query, `${command.name}${command.title}`);
56 | });
57 |
58 | return _.sortBy(helpList, 'id');
59 | }
60 |
61 | function onInput(query) {
62 | return getPlugins(query);
63 | }
64 |
65 | function onEnter(item, command, query, keyStatus) {
66 | const { shiftKey } = keyStatus;
67 |
68 | if (shiftKey) {
69 | util.createTab(
70 | { url: util.getDocumentURL(item.name, item.category) },
71 | keyStatus,
72 | );
73 | } else {
74 | return Promise.resolve(`${String(item.id.split(',')[0])} `);
75 | }
76 | }
77 |
78 | return {
79 | version,
80 | name: 'Help',
81 | category: 'steward',
82 | icon,
83 | title,
84 | commands,
85 | onInput,
86 | onEnter,
87 | canDisabled: false,
88 | };
89 | }
90 |
--------------------------------------------------------------------------------
/extension/plugins/steward/steward.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @description chrome urls
3 | * @author tomasy
4 | * @mail solopea@gmail.com
5 | */
6 |
7 | import { StewardApp } from 'common/type';
8 | import { Plugin } from 'plugins/type';
9 | import { t } from 'helper/i18n.helper';
10 | import { getURL } from 'helper/extension.helper';
11 |
12 | export default function(Steward: StewardApp): Plugin {
13 | const { chrome, util, constant } = Steward;
14 | const { stewardPlusTabs, stewardTabs } = constant.BASE
15 | const version = 1;
16 | const name = 'steward';
17 | const type = 'search';
18 | const icon = getURL('img/icon.png');
19 | const title = t(`${name}_title`);
20 | const baseUrl = getURL('options.html');
21 |
22 | let optionTabs;
23 |
24 | if (EXT_TYPE === 'stewardplus') {
25 | optionTabs = stewardPlusTabs;
26 | } else {
27 | optionTabs = stewardTabs;
28 | }
29 |
30 | optionTabs.push('Backup');
31 |
32 | function caseFormat(str) {
33 | return str[0].toUpperCase() + str.slice(1);
34 | }
35 |
36 | function onInput(text) {
37 | const filterByName = suggestions => util.getMatches(suggestions, text);
38 | const extType = caseFormat(EXT_TYPE);
39 | const mapTo = itemType => item => {
40 | const isBackup = item === 'Backup';
41 |
42 | return {
43 | icon,
44 | key: isBackup ? 'app' : itemType,
45 | title: item,
46 | url: item === extType ? baseUrl : `${baseUrl}#/${item.toLowerCase()}`,
47 | weight: 2,
48 | };
49 | };
50 |
51 | const tabs = filterByName(optionTabs).map(mapTo('url'));
52 |
53 | return Promise.resolve(tabs);
54 | }
55 |
56 | function onEnter() {}
57 |
58 | return {
59 | version,
60 | name: 'Steward',
61 | category: 'steward',
62 | type,
63 | icon,
64 | title,
65 | onInput,
66 | onEnter,
67 | canDisabled: false,
68 | };
69 | }
70 |
--------------------------------------------------------------------------------
/extension/scripts/popup.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | function initTheme(mode) {
3 | chrome.storage.sync.get('themes', function (resp) {
4 | const themes = resp.themes
5 |
6 | if (themes && themes[mode]) {
7 | let cssText = '';
8 | const theme = themes[mode];
9 |
10 | for (const prop in theme) {
11 | cssText += `${prop}: ${theme[prop]};`;
12 | }
13 |
14 | document.querySelector('html').style.cssText = cssText;
15 | }
16 | })
17 | }
18 |
19 | if (window.parent === window) {
20 | initTheme('popup');
21 | } else {
22 | initTheme('page');
23 | }
24 | })();
--------------------------------------------------------------------------------
/extension/scss/main.scss:
--------------------------------------------------------------------------------
1 | @import './themes/base.scss';
2 |
3 | #toast-container em {
4 | color: #d4237a;
5 | font-style: normal;
6 | }
7 |
8 | .cmdbox {
9 | &.exceeded {
10 | font-size: 16px;
11 | }
12 | }
--------------------------------------------------------------------------------
/extension/scss/themes/newtab/classical.scss:
--------------------------------------------------------------------------------
1 | :root {
2 | --app-background-color: rgba(0, 0, 0, .4);
3 | --newtab-background-color: #000;
4 | --app-width-size: 560px;
5 | --search-input-height: 64px;
6 | --search-input-value-text-color: #fafafa;
7 | --search-input-value-text-size: 26px;
8 | --search-results-height: 432px;
9 | --search-results-scrollbar-width: 2px;
10 | --search-results-scrollbar-color: rgba(0, 0, 0, 0.5);
11 | --selected-suggestion-background-color: rgba(0, 0, 0, 0.2);
12 | --selected-suggestion-title-text-color: #fff;
13 | --selected-suggestion-subtitle-text-color: #ccc;
14 | --highlighted-suggestion-text-color: #fabb2d;
15 | --suggestion-border-color: rgba(209, 209, 209, .1);
16 | --suggestion-height: 48px;
17 | --suggestion-title-text-color: #eee;
18 | --suggestion-title-text-size: 16px;
19 | --suggestion-title-text-weight: 300;
20 | --suggestion-subtitle-text-color: #bbb;
21 | --suggestion-subtitle-text-size: 12px;
22 | --suggestion-subtitle-text-style: "PingFangSC-Light";
23 | }
24 |
25 | body {
26 | background: var(--app-newtab-background-image);
27 | background-position: center center;
28 | background-size: cover;
29 | background-repeat: no-repeat;
30 | background-attachment: fixed;
31 | }
32 |
33 | #newtab {
34 | display: none;
35 | position: fixed;
36 | width: 100vw;
37 | min-height: 100vh;
38 | left: 0;
39 | top: 0;
40 | z-index: 100000;
41 | }
42 |
43 | .use-iframe {
44 | #newtab {
45 | display: block;
46 | }
47 | #app {
48 | display: none;
49 | }
50 | .container {
51 | display: none;
52 | }
53 | }
54 |
55 | .use-filter {
56 | .main {
57 | position: relative;
58 |
59 | &::before {
60 | position: absolute;
61 | top: 0;
62 | left: 0;
63 | width: 100%;
64 | height: 100%;
65 | z-index: 1;
66 | opacity: .2;
67 | background-color: #fff;
68 | content: '';
69 | }
70 |
71 | &::after {
72 | position: absolute;
73 | top: 0;
74 | left: 0;
75 | width: 100%;
76 | height: 100%;
77 | background-size: cover;
78 | background-position: center;
79 | background-attachment: fixed;
80 | filter: blur(5px) brightness(110%);
81 | background-image: var(--app-newtab-background-image);
82 | content: '';
83 | }
84 |
85 | .cmdbox {
86 | position: relative;
87 | z-index: 2;
88 | }
89 |
90 | #list-wrap {
91 | position: relative;
92 | z-index: 2;
93 | }
94 | }
95 | }
--------------------------------------------------------------------------------
/extension/scss/themes/popup/classical.scss:
--------------------------------------------------------------------------------
1 | :root {
2 | --app-background-color: #fff;
3 | --app-width-size: 500px;
4 | --search-input-height: 50px;
5 | --search-input-value-text-color: #000;
6 | --search-input-value-text-size: 22px;
7 | --search-results-height: 400px;
8 | --search-results-scrollbar-width: 2px;
9 | --search-results-scrollbar-color: rgba(0, 0, 0, 0.5);
10 | --selected-suggestion-background-color: rgb(209, 209, 209);
11 | --selected-suggestion-title-text-color: #000;
12 | --selected-suggestion-subtitle-text-color: #000;
13 | --highlighted-suggestion-text-color: red;
14 | --suggestion-height: 44px;
15 | --suggestion-border-color: rgba(209, 209, 209, .1);
16 | --suggestion-title-text-color: #000;
17 | --suggestion-title-text-size: 14px;
18 | --suggestion-title-text-weight: 400;
19 | --suggestion-subtitle-text-color: #000;
20 | --suggestion-subtitle-text-size: 12px;
21 | --suggestion-subtitle-text-style: 'inherit';
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/extension/server/controller/recordsController.ts:
--------------------------------------------------------------------------------
1 | import db, { IRecords } from '../db/index';
2 |
3 | export function list() {
4 | return db.records.toArray();
5 | }
6 |
7 | export function save(record: IRecords) {
8 | return db.records.put(record);
9 | }
10 |
11 | export function query(filter: { scope: string, query: string }) {
12 | const { scope, query } = filter;
13 |
14 | return db.records
15 | .where({
16 | scope,
17 | query,
18 | })
19 | .toArray();
20 | }
21 |
22 | export function addTimes(result: IRecords) {
23 | return db.records.update(result.id, { times: result.times + 1 });
24 | }
25 |
26 | export async function log(attrs: IRecords) {
27 | const { scope, query, result } = attrs;
28 | const resp = await db.records.get({
29 | scope,
30 | query,
31 | result,
32 | });
33 |
34 | if (resp) {
35 | return addTimes(resp);
36 | } else {
37 | return save({
38 | ...attrs,
39 | times: 1,
40 | });
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/extension/server/db/index.ts:
--------------------------------------------------------------------------------
1 | import Dexie from 'dexie';
2 |
3 | export class StewardDatabase extends Dexie {
4 | records: Dexie.Table;
5 |
6 | constructor() {
7 | super('steward');
8 |
9 | this.version(1).stores({
10 | records: '++id,[scope+query],result,mode,times',
11 | });
12 | }
13 | }
14 |
15 | export interface IRecords {
16 | id?: number;
17 | scope: string;
18 | query: string;
19 | result: string;
20 | mode: string;
21 | times?: number;
22 | }
23 |
24 | const db = new StewardDatabase();
25 |
26 | export default db;
27 |
--------------------------------------------------------------------------------
/extension/service/bing.ts:
--------------------------------------------------------------------------------
1 | import { WallpaperSource } from 'common/type';
2 | import * as apiUtils from 'utils/api';
3 |
4 | export const root = 'https://www.bing.com';
5 | const baseParams = {
6 | format: 'js',
7 | idx: 0,
8 | n: 1,
9 | nc: Number(new Date()),
10 | mkt: 'zh-CN',
11 | };
12 | const MAX_IDX = 16;
13 |
14 | function getRandom(to = MAX_IDX) {
15 | return Math.round(Math.random() * to);
16 | }
17 |
18 | export const today = () => {
19 | return apiUtils.fetch(apiUtils.url(root, '/HPImageArchive.aspx'), baseParams);
20 | };
21 |
22 | export const rand = () => {
23 | return apiUtils.fetch(
24 | apiUtils.url(root, '/HPImageArchive.aspx'),
25 | Object.assign({}, baseParams, {
26 | idx: getRandom(),
27 | }),
28 | );
29 | };
30 |
31 | const api = {
32 | today,
33 | rand,
34 | };
35 |
36 | export default {
37 | name: 'bing',
38 | api: method => () => api[method](),
39 | handle: result => root + result.images[0].url,
40 | weight: 1,
41 | } as WallpaperSource;
42 |
--------------------------------------------------------------------------------
/extension/service/desktoppr.ts:
--------------------------------------------------------------------------------
1 | import { WallpaperSource } from 'common/type';
2 |
3 | import * as apiUtils from '../utils/api';
4 |
5 | const BASE_URL = 'https://api.desktoppr.co/1/wallpapers';
6 |
7 | export function getRandom() {
8 | return apiUtils.fetch(`${BASE_URL}/random`);
9 | }
10 |
11 | export default {
12 | name: 'desktoppr',
13 | api: () => getRandom(),
14 | handle: result => result.response.image.url,
15 | weight: 3,
16 | } as WallpaperSource;
17 |
--------------------------------------------------------------------------------
/extension/service/index.ts:
--------------------------------------------------------------------------------
1 | export * as bing from './bing'
2 | export * as picsum from './picsum'
3 | export * as nasa from './nasa'
4 | export * as desktoppr from './desktoppr'
5 | export * as pixabay from './pixabay'
--------------------------------------------------------------------------------
/extension/service/nasa.ts:
--------------------------------------------------------------------------------
1 | import { WallpaperSource } from 'common/type';
2 |
3 | import * as apiUtils from '../utils/api';
4 |
5 | const KEY = 'kxwrn5RQGnJVYU5wwipadjsGjOSrEGbyEihSZcqY';
6 | const URL = 'https://api.nasa.gov/planetary/apod';
7 |
8 | export function getList() {
9 | return apiUtils.fetch(URL, { api_key: KEY });
10 | }
11 |
12 | export default {
13 | name: 'nasa',
14 | api: () => getList(),
15 | handle: result => result.url,
16 | weight: 0.5,
17 | } as WallpaperSource;
18 |
--------------------------------------------------------------------------------
/extension/service/picsum.ts:
--------------------------------------------------------------------------------
1 | import { WallpaperSource } from 'common/type';
2 |
3 | import * as apiUtils from '../utils/api';
4 |
5 | const STORAGE_KEY = 'picsumids';
6 |
7 | export const root = 'https://picsum.photos';
8 |
9 | export function getList() {
10 | return apiUtils.fetch(`${root}/list`);
11 | }
12 |
13 | export function refreshPicsumList() {
14 | getList().then((resp: any) => {
15 | if (resp && resp.length) {
16 | const ids = resp.map(item => item.id);
17 |
18 | try {
19 | window.localStorage.setItem(STORAGE_KEY, JSON.stringify(ids));
20 | } catch (error) {
21 | console.log(error);
22 | }
23 | }
24 | });
25 | }
26 |
27 | function getIds() {
28 | try {
29 | return JSON.parse(window.localStorage.getItem(STORAGE_KEY));
30 | } catch (error) {
31 | console.log(error);
32 |
33 | return [0];
34 | }
35 | }
36 |
37 | const IMAGE_BASE_URL = `${root}/1920/1080?image=`;
38 |
39 | export function getRandomImage() {
40 | const ids = getIds();
41 |
42 | if (ids && ids.length) {
43 | const index = Math.round(Math.random() * (ids.length - 1));
44 |
45 | return Promise.resolve(`${IMAGE_BASE_URL}${ids[index]}`);
46 | } else {
47 | return Promise.resolve(`${IMAGE_BASE_URL}0`);
48 | }
49 | }
50 |
51 | export default {
52 | name: 'picsum',
53 | api: () => getRandomImage(),
54 | handle: result => result,
55 | weight: 2,
56 | } as WallpaperSource;
57 |
--------------------------------------------------------------------------------
/extension/service/pixabay.ts:
--------------------------------------------------------------------------------
1 | import { WallpaperSource } from 'common/type';
2 |
3 | import * as apiUtils from '../utils/api';
4 |
5 | const APP_KEY = '9599926-06fed5cb1e63825bd24dd87f8';
6 | const options = {
7 | editors_choice: true,
8 | per_page: 20,
9 | page: 0,
10 | };
11 | const URL = `https://pixabay.com/api/?key=${APP_KEY}`;
12 |
13 | let page = 0;
14 |
15 | export function getPageList() {
16 | page = page + 1;
17 | options.page = page;
18 |
19 | return apiUtils.fetch(URL, options);
20 | }
21 |
22 | export default function(getRandomOne) {
23 | return {
24 | name: 'pixabay',
25 | api: () => getPageList(),
26 | handle: result => getRandomOne(result.hits).largeImageURL,
27 | weight: 3,
28 | } as WallpaperSource;
29 | }
30 |
--------------------------------------------------------------------------------
/extension/service/selection.ts:
--------------------------------------------------------------------------------
1 | import { WallpaperSource } from 'common/type';
2 |
3 | import * as apiUtils from '../utils/api';
4 |
5 | const URL = `http://static.oksteward.com/steward-wallpaper.json?t=${Number(
6 | new Date(),
7 | )}`;
8 |
9 | let cached;
10 |
11 | export function getList() {
12 | if (cached) {
13 | return Promise.resolve(cached);
14 | } else {
15 | return apiUtils.fetch(URL).then(result => {
16 | cached = result;
17 |
18 | return cached;
19 | });
20 | }
21 | }
22 |
23 | export default function(getRandomOne) {
24 | return {
25 | name: 'selection',
26 | api: () => getList(),
27 | handle: result => getRandomOne(result.list),
28 | weight: 1,
29 | } as WallpaperSource;
30 | }
31 |
--------------------------------------------------------------------------------
/extension/svg/allowbatch.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/app.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/bbs.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/bing.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/bookmark.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/btc.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/chrome.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/copy.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/del.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/delete-icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/diary.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/download-red.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/download.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/enter-white.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/enter.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/exts/wordcard/level0.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/exts/wordcard/level1.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/exts/wordcard/level2.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/exts/wordcard/level3.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/exts/wordcard/level4.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/exts/wordcard/level5.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/exts/wordcard/tag.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/github.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/google.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/help.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/history.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/iframe.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/index.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/loading.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/miniapp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/new-tab.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/newversion.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/note.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/notshow.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/off.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/on.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/plus.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/plusone.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/pm25.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/refresh-red.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/refresh.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/save-red.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/selected-icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/set.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/blogger.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/buffer.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/delicious.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/digg.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/douban.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/facebook.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/flipboard.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/friendfeed.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/getpocket.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/google_plus.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/instapaper.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/linkedin.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/livejournal.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/myspace.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/newsvine.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/pinterest.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/qzone.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/renren.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/stumbleupon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/telegram_me.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/tumblr.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/twitter.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/viber.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/whatsapp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/xing.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/share-icons/yahoo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/stackoverflow.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/star-fill.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/star.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/tab.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/todo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/topsites.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/urlblock.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/viewext.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/workflow.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/youdao.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/svg/zhihu.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/extension/utils/api.ts:
--------------------------------------------------------------------------------
1 | import $ from 'jquery';
2 |
3 | function handleParams(api, data, method) {
4 | return Promise.resolve({
5 | url: api,
6 | method,
7 | data,
8 | });
9 | }
10 |
11 | export function url(root = '', path = '/') {
12 | return root + path;
13 | }
14 |
15 | export function fetch(api, data = {}, rawMethod = 'GET') {
16 | return handleParams(api, data, rawMethod).then(options => {
17 | return new Promise((resolve, reject) => {
18 | $.ajax({
19 | url: options.url,
20 | method: options.method,
21 | data: options.data,
22 | })
23 | .done(resp => {
24 | if (typeof resp.code === 'undefined') {
25 | resolve(resp);
26 | } else if (resp.code === 200) {
27 | resolve(resp.data);
28 | } else {
29 | reject(resp);
30 | }
31 | })
32 | .fail(resp => reject(resp));
33 | });
34 | });
35 | }
36 |
--------------------------------------------------------------------------------
/extension/utils/date.ts:
--------------------------------------------------------------------------------
1 | export function format(date = new Date()) {
2 | const ret = [date.getFullYear(), date.getMonth() + 1, date.getDate()].join(
3 | '-',
4 | );
5 |
6 | return ret;
7 | }
8 |
9 | export function isNewDate(date, last) {
10 | return format(date) !== format(last);
11 | }
12 |
--------------------------------------------------------------------------------
/extension/utils/index.ts:
--------------------------------------------------------------------------------
1 |
2 | export * as api from './api'
3 | export * as date from './date'
--------------------------------------------------------------------------------
/extension/utils/storage.ts:
--------------------------------------------------------------------------------
1 | const storageFactory = storgaeArea => action => (key, defaultValue) => {
2 | return new Promise(resolve => {
3 | if (action === 'clear') {
4 | storgaeArea[action](resp => resolve(resp));
5 | } else if (action === 'get') {
6 | storgaeArea[action](key, resp => {
7 | if (resp[key]) {
8 | resolve(resp[key]);
9 | } else if (defaultValue) {
10 | resolve(defaultValue);
11 | } else {
12 | resolve(null);
13 | }
14 | });
15 | } else {
16 | storgaeArea[action](key, resp => resolve(resp));
17 | }
18 | });
19 | };
20 |
21 | const actions = ['get', 'set', 'remove', 'clear'];
22 |
23 | interface Storage {
24 | sync?: any;
25 | local?: any;
26 | }
27 | const storage: Storage = {};
28 |
29 | ['sync', 'local'].forEach(storageArea => {
30 | const factory = storageFactory(chrome.storage[storageArea]);
31 |
32 | const methods = (storage[storageArea] = {});
33 | actions.forEach(action => {
34 | methods[action] = factory(action);
35 | });
36 | });
37 |
38 | export default storage;
39 |
--------------------------------------------------------------------------------
/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | // This must be specified if "paths" is set
4 | "baseUrl": ".",
5 | // Relative to "baseUrl"
6 | "paths": {
7 | "@/*": [
8 | "./extension/*"
9 | ]
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": "./extension",
4 | "moduleResolution": "node",
5 | "outDir": "./dist/",
6 | "lib": [
7 | "es5", "es6", "dom", "dom.iterable"
8 | ],
9 | "noImplicitAny": false,
10 | "allowSyntheticDefaultImports": true,
11 | "module": "es2015",
12 | "target": "es6",
13 | "allowJs": true,
14 | "paths": {
15 | "enum/*": ["enum/*"],
16 | "constant/*": ["constant/*"],
17 | "common/*": ["common/*"],
18 | "utils/*": ["utils/*"],
19 | "service/*": ["service/*"],
20 | "conf/*": ["conf/*"],
21 | "helper/*": ["helper/*"],
22 | "collection/*": ["collection/*"],
23 | "info/*": ["info/*"],
24 | "plugins/*": ["plugins/*"],
25 | "main/*": ["main/*"]
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------