├── assets ├── 0.png ├── 1.png ├── 2.png ├── 3.png ├── 4.png ├── logo.png └── logo-large.png ├── src ├── assets │ ├── search-baidu.png │ ├── search-bing.png │ ├── search-yahoo.png │ ├── network-error.png │ ├── search-google.png │ ├── search-dogedoge.png │ └── search-duckduckgo.svg ├── stylesheet │ ├── common.sass │ └── index.sass ├── theme │ ├── black.js │ └── default.js ├── services │ ├── config.js │ ├── storage.js │ ├── i18n.js │ ├── findOne.js │ ├── fetch.js │ ├── cookie.js │ ├── colors.json │ └── languages.js ├── lang │ ├── index.js │ ├── zh.js │ └── en.js ├── vuex │ ├── types.js │ ├── index.js │ └── modules │ │ ├── search.js │ │ ├── github.js │ │ └── bookmark.js ├── index.js ├── views │ ├── components │ │ ├── dialog-bookmark-edit.vue │ │ ├── bookmark.sass │ │ ├── setting.sass │ │ ├── search.sass │ │ ├── bookmark.vue │ │ ├── setting.vue │ │ ├── searchEngines.js │ │ ├── search.vue │ │ ├── github-trending.vue │ │ └── github-trending.sass │ ├── main.sass │ └── main.vue └── components │ ├── image-uploader │ ├── index.scss │ └── index.vue │ └── image-uploader-box │ └── index.vue ├── static ├── assets │ └── icon │ │ ├── icon.png │ │ ├── icon-128.png │ │ ├── icon-16.png │ │ └── icon-48.png ├── manifest.json ├── popup.html ├── popup.js └── popup.css ├── .babelrc ├── .markdownlintrc ├── __config__ ├── getLastCommit.js ├── log.js ├── global.config.js ├── database.js └── exec.js ├── postcss.config.js ├── app ├── index.js ├── routes │ ├── admin.js │ ├── index.js │ ├── login.js │ ├── qiniu.js │ ├── metadata.js │ └── github.js ├── models │ ├── metadata.js │ ├── index.js │ └── admin.js └── app.js ├── .sequelizerc ├── index.html ├── .gitignore ├── .env.example ├── .github └── FUNDING.yml ├── __database__ └── migrations │ ├── 20180114-create.admin.js │ └── 20171217-create-metadata.js ├── .eslintrc.yml ├── poi.config.js ├── README.md ├── package.json └── LICENSE /assets/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuowenli/githuber/HEAD/assets/0.png -------------------------------------------------------------------------------- /assets/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuowenli/githuber/HEAD/assets/1.png -------------------------------------------------------------------------------- /assets/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuowenli/githuber/HEAD/assets/2.png -------------------------------------------------------------------------------- /assets/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuowenli/githuber/HEAD/assets/3.png -------------------------------------------------------------------------------- /assets/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuowenli/githuber/HEAD/assets/4.png -------------------------------------------------------------------------------- /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuowenli/githuber/HEAD/assets/logo.png -------------------------------------------------------------------------------- /assets/logo-large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuowenli/githuber/HEAD/assets/logo-large.png -------------------------------------------------------------------------------- /src/assets/search-baidu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuowenli/githuber/HEAD/src/assets/search-baidu.png -------------------------------------------------------------------------------- /src/assets/search-bing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuowenli/githuber/HEAD/src/assets/search-bing.png -------------------------------------------------------------------------------- /src/assets/search-yahoo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuowenli/githuber/HEAD/src/assets/search-yahoo.png -------------------------------------------------------------------------------- /static/assets/icon/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuowenli/githuber/HEAD/static/assets/icon/icon.png -------------------------------------------------------------------------------- /src/assets/network-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuowenli/githuber/HEAD/src/assets/network-error.png -------------------------------------------------------------------------------- /src/assets/search-google.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuowenli/githuber/HEAD/src/assets/search-google.png -------------------------------------------------------------------------------- /src/assets/search-dogedoge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuowenli/githuber/HEAD/src/assets/search-dogedoge.png -------------------------------------------------------------------------------- /static/assets/icon/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuowenli/githuber/HEAD/static/assets/icon/icon-128.png -------------------------------------------------------------------------------- /static/assets/icon/icon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuowenli/githuber/HEAD/static/assets/icon/icon-16.png -------------------------------------------------------------------------------- /static/assets/icon/icon-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuowenli/githuber/HEAD/static/assets/icon/icon-48.png -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-2"], 3 | "plugins": [ 4 | "transform-runtime" 5 | ], 6 | "comments": false 7 | } 8 | -------------------------------------------------------------------------------- /.markdownlintrc: -------------------------------------------------------------------------------- 1 | { 2 | "default": true, 3 | "MD007": { "indent": 4 }, 4 | "MD013": { "line_length": 300 }, 5 | "no-hard-tabs": true, 6 | "no-inline-html": false, 7 | "first-line-h1": false, 8 | "no-duplicate-header": false 9 | } 10 | -------------------------------------------------------------------------------- /__config__/getLastCommit.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: 卓文理 3 | * Created: 2017-09-04 07:52:14 4 | * Last Modified: 2017-09-04 09:47:47 5 | * Modified By: 卓文理 6 | */ 7 | 8 | const exec = require('./exec'); 9 | 10 | module.exports = () => exec('git log -10 --stat --no-merges --pretty=oneline'); 11 | -------------------------------------------------------------------------------- /__config__/log.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: 卓文理 3 | * Created: 2017-09-04 07:52:32 4 | * Last Modified: 2017-09-04 09:48:16 5 | * Modified By: 卓文理 6 | */ 7 | 8 | const color = require('cli-color'); 9 | 10 | module.exports = function log(text, theme = 'green') { 11 | console.log(color[theme](text)); 12 | }; 13 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 卓文理 3 | * @Email: 531840344@qq.com 4 | * @Date: 2017-04-28 17:34:06 5 | */ 6 | 7 | 'use strict'; 8 | 9 | module.exports = { 10 | plugins: [ 11 | require('autoprefixer')({ 12 | remove: false, 13 | browsers: ['iOS >= 7', 'Android >= 4.1'], 14 | }), 15 | ], 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /app/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 卓文理 3 | * @Email: 531840344@qq.com 4 | * @Date: 2017-12-14 21:01:55 5 | */ 6 | 7 | 'use strict'; 8 | 9 | const path = require('path'); 10 | const loadEnv = require('node-env-file'); 11 | 12 | loadEnv(path.resolve(__dirname, '../.env'), { raise: false }); 13 | 14 | require('babel-polyfill'); 15 | require('babel-register'); 16 | require('./app'); 17 | -------------------------------------------------------------------------------- /src/stylesheet/common.sass: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 卓文理 3 | * @Email: 531840344@qq.com 4 | * @Date: 2018-01-18 18:17:02 5 | */ 6 | 7 | @mixin ellipsis 8 | text-overflow: ellipsis; 9 | overflow: hidden; 10 | white-space: nowrap; 11 | 12 | @mixin max-text($num) 13 | display: -webkit-box; 14 | -webkit-box-orient: vertical; 15 | -webkit-line-clamp: $num; 16 | overflow: hidden; -------------------------------------------------------------------------------- /.sequelizerc: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 卓文理 3 | * @Email: 531840344@qq.com 4 | * @Date: 2017-12-17 15:09:16 5 | */ 6 | 7 | 'use strict'; 8 | 9 | const path = require('path'); 10 | 11 | module.exports = { 12 | 'config': path.resolve('./__config__/database.js'), 13 | 'migrations-path': path.resolve('./__database__/migrations'), 14 | 'seeders-path': path.resolve('./__database__/seeds'), 15 | }; 16 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
31 |
32 | ## 本地开发
33 |
34 | 用于调试 `chrome` 特性,代码编译成功后手动刷新页面方可生效
35 |
36 | 1. 安装依赖
37 |
38 | ```bash
39 | npm i
40 | ```
41 |
42 | 2. 编译代码
43 |
44 | ```bash
45 | npm run watch
46 | ```
47 |
48 | 3. 打开 Chrome 扩展程序 [chrome://extensions/](chrome://extensions/),开启开发者模式
49 | 4. 点击**加载已解压的扩展程序**,找到编译后输出的 `dist` 目录,加载代码
50 |
51 | ## 服务端部署
52 |
53 | 1. 添加配置文件
54 |
55 | ```bash
56 | # 添加 .env 填写正确的配置信息
57 | cp .env.example .env
58 | ```
59 |
60 | 2. 创建数据库(默认用MySQL)
61 |
62 | ```bash
63 | # 初始化数据表
64 | yarn db:migrate
65 | ```
66 |
67 | 3. 启动服务
68 |
69 | ```bash
70 | # 开发环境
71 | yarn nodemon
72 |
73 | # 生产环境
74 | yarn start
75 | ```
76 |
77 | ## TODO LIST
78 |
79 | - [ ] 高级设置(待定)
80 | - RSS
81 | - [ ] 数据同步
82 | - [x] 手动备份
83 | - 从云端恢复数据
84 | - 账号(登录,注册)
85 | - [ ] 最常访问(待定)
86 |
87 | ## 相关链接
88 |
89 | - [GitHub Octicons](https://octicons.github.com/)
90 |
91 | ## License
92 |
93 | Githuber © [zhuowenli](https://github.com/zhuowenli), Released under the [Mozilla Public License 2.0](./LICENSE) License.
94 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "githuber",
3 | "version": "1.7.1",
4 | "main": "index.js",
5 | "repository": "git@github.com:zhuowenli/githuber.git",
6 | "author": "卓文理 <531840344@qq.com>",
7 | "license": "Mozilla Public License Version 2.0",
8 | "scripts": {
9 | "dev": "cross-env NODE_OPTIONS=--openssl-legacy-provider poi --dev",
10 | "watch": "cross-env NODE_OPTIONS=--openssl-legacy-provider poi watch",
11 | "build": "rm -rf dist && cross-env NODE_OPTIONS=--openssl-legacy-provider NODE_ENV=production poi build",
12 | "start": "pm2 start ./app/index.js --name 'githuber-server'",
13 | "restart": "pm2 restart githuber-server",
14 | "nodemon": "nodemon --watch app ./app/index.js",
15 | "db:seed": "sequelize db:seed:all",
16 | "db:seed:undo": "sequelize db:seed:undo:all",
17 | "db:migrate": "sequelize db:migrate",
18 | "db:migrate:undo": "sequelize db:migrate:undo",
19 | "db:rollback": "sequelize db:migrate:undo:all",
20 | "create:migration": "sequelize migration:create",
21 | "create:seed": "sequelize seed:create"
22 | },
23 | "dependencies": {
24 | "axios": "^0.19.2",
25 | "babel-polyfill": "^6.26.0",
26 | "bluebird": "^3.7.2",
27 | "csshake": "^1.5.3",
28 | "element-ui": "^2.13.2",
29 | "file-saver": "^1.3.8",
30 | "iscroll": "^5.2.0",
31 | "jquery": "^3.4.0",
32 | "jsonp": "^0.2.1",
33 | "koa": "^2.4.1",
34 | "koa-bodyparser": "^4.2.0",
35 | "koa-convert": "^1.2.0",
36 | "koa-logger": "^3.1.0",
37 | "koa-mount": "^3.0.0",
38 | "koa-proxy": "^0.9.0",
39 | "koa-router": "^7.3.0",
40 | "koa-session": "^5.7.1",
41 | "koa-static": "^4.0.2",
42 | "koa-views": "^6.1.3",
43 | "koa2-cors": "^2.0.5",
44 | "moment": "^2.19.3",
45 | "node-env-file": "^0.1.8",
46 | "normalize.css": "^7.0.0",
47 | "octicons": "^7.1.0",
48 | "qiniu": "^7.1.1",
49 | "querystring": "^0.2.0",
50 | "vue": "^2.5.13",
51 | "vue-i18n": "^7.4.0",
52 | "vue-iscroll-view": "^1.0.3",
53 | "vue-waterfall": "^1.0.6",
54 | "vuedraggable": "^2.16.0",
55 | "vuex": "^3.0.1"
56 | },
57 | "devDependencies": {
58 | "autoprefixer": "^7.2.5",
59 | "babel-eslint": "^8.2.1",
60 | "babel-plugin-component": "^1.1.0",
61 | "babel-plugin-transform-runtime": "^6.23.0",
62 | "babel-preset-es2015": "^6.24.1",
63 | "babel-preset-stage-2": "^6.24.1",
64 | "babel-preset-vue": "^2.0.0",
65 | "cross-env": "^5.1.3",
66 | "eslint": "^4.15.0",
67 | "eslint-config-airbnb-base": "^12.1.0",
68 | "eslint-plugin-import": "^2.8.0",
69 | "eslint-plugin-vue": "^4.2.0",
70 | "mysql2": "^1.5.1",
71 | "nodemon": "^1.12.7",
72 | "pm2": "^2.9.1",
73 | "poi": "^9.5.5",
74 | "pug": "^2.0.0-rc.4",
75 | "sass": "^1.90.0",
76 | "sass-loader": "^7.3.1",
77 | "sequelize": "^5.8.9",
78 | "sequelize-cli": "^5.5.0"
79 | }
80 | }
--------------------------------------------------------------------------------
/src/vuex/modules/search.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: 卓文理
3 | * @Email: 531840344@qq.com
4 | * @Date: 2018-01-18 14:46:48
5 | */
6 |
7 | 'use strict';
8 |
9 | import { get, jsonp } from '../../services/fetch';
10 | import * as types from '../types';
11 |
12 | export const getters = {
13 | suggestions: state => state.suggestions,
14 | superpages: state => state.superpages,
15 | customSearchEngines: state => state.customSearchEngines,
16 | };
17 |
18 | export const actions = {
19 | /**
20 | * 获取搜索联想
21 | *
22 | * @param {any} { commit } state
23 | * @param {String} wd 关键词
24 | * @returns {Promise}
25 | */
26 | async fetchSuggestion ({ commit }, wd) {
27 | const data = await jsonp('http://suggestion.baidu.com/su', { wd }).then(res => res.s);
28 | commit(types.RECEIVE_SUGGESTIONS, data);
29 | return data;
30 | },
31 |
32 | /**
33 | * 获取网站联想
34 | *
35 | * @param {any} { commit } state
36 | * @param {any} wd 关键词
37 | * @returns {Promise}
38 | */
39 | async fetchSuperpage({ commit }, wd) {
40 | let data = await jsonp('http://nssug.baidu.com/su', { wd, prod: 'superpage' }).then(res => res.s);
41 |
42 | data = data.map(item => {
43 | const obj = {};
44 |
45 | try {
46 | const text = decodeURIComponent(item);
47 | const array = text.split('0{#S+_}');
48 | console.log(text, array);
49 | const content = JSON.parse(array[1]);
50 |
51 | obj.name = content[4];
52 | obj.url = content[1];
53 | } catch (e) {
54 | console.log(e);
55 | }
56 |
57 | return obj;
58 | }).filter(item => item.name);
59 |
60 | commit(types.RECEIVE_SUPERPAGES, data);
61 | return data;
62 | },
63 |
64 | /**
65 | * 获取自定义搜索引擎
66 | *
67 | * @param {any} { commit } state
68 | * @returns {Promise}
69 | */
70 | fetchCustomSearchEngine({ commit }) {
71 | commit(types.RECEIVE_SEARCH_ENGINES, [
72 | {
73 | name: 'GitHub',
74 | url: 'https://github.com/search?utf8=✓&q=%s'
75 | },
76 | {
77 | name: 'Stack Overflow',
78 | url: 'http://stackoverflow.com/search?q=%s'
79 | },
80 | ]);
81 | },
82 | };
83 |
84 | export const mutations = {
85 | [types.RECEIVE_SUGGESTIONS](state, data) {
86 | state.suggestions = data;
87 | },
88 | [types.RECEIVE_SUPERPAGES](state, data) {
89 | state.superpages = data;
90 | },
91 | [types.RECEIVE_SEARCH_ENGINES](state, data) {
92 | state.customSearchEngines = data;
93 | }
94 | };
95 |
96 | export default {
97 | actions,
98 | getters,
99 | mutations,
100 | namespaced: true,
101 | state: {
102 | suggestions: [],
103 | superpages: [],
104 | customSearchEngines: [],
105 | },
106 | };
107 |
--------------------------------------------------------------------------------
/src/views/components/bookmark.sass:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: 卓文理
3 | * @Email: 531840344@qq.com
4 | * @Date: 2018-01-20 21:28:46
5 | */
6 |
7 | @import '~csshake/scss/_tools.scss'
8 | @import '../../stylesheet/common.sass'
9 |
10 | .bookmark
11 | touch-action: none
12 | overflow: hidden
13 | height: 100%
14 | padding: 10px
15 | &__item
16 | position: relative
17 | width: 100%
18 | height: 60px
19 | display: flex
20 | padding: 10px 0
21 | cursor: pointer
22 | border-bottom: 1px solid var(--backgroundLighter)
23 | transition: all .3s ease
24 | user-select: none
25 | color: var(--fontColor)
26 | &:last-child
27 | border-bottom: 0
28 | .logo
29 | display: flex
30 | align-items: center
31 | justify-content: center
32 | flex-shrink: 0;
33 | width: 40px
34 | height: 40px
35 | outline: 0
36 | img
37 | display: inline-block
38 | width: 32px
39 |
40 | .text
41 | display: flex
42 | align-items: center
43 | justify-content: center
44 | flex-shrink: 0;
45 | width: 40px
46 | height: 40px
47 | background: var(--gray)
48 | border-radius: 50%
49 | color: var(--background)
50 | font-size: 20px
51 | user-select: none
52 | outline: 0
53 | line-height: 1
54 |
55 | .name
56 | flex: 1
57 | display: flex
58 | height: 40px
59 | font-size: 12px
60 | padding-left: 10px
61 | span
62 | @include max-text(2)
63 | width: 100%
64 | justify-content: center
65 | max-height: 40px
66 | line-height: 20px
67 |
68 | .el-icon-plus
69 | display: block
70 | margin: 0 auto
71 | font-size: 20px
72 | color: var(--gray)
73 | .el-icon-close
74 | position: absolute
75 | left: 0
76 | color: var(--red)
77 | width: 20px
78 | height: 20px
79 | top: 50%
80 | margin-top: -10px
81 | line-height: 20px
82 | text-align: center
83 | opacity: 0
84 | transition: all .3s ease
85 | pointer-events: none
86 | .el-icon-check
87 | display: block
88 | margin: 0 auto
89 | color: var(--green)
90 | font-size: 24px
91 | &.edit
92 | padding-left: 20px
93 | .el-icon-close
94 | pointer-events: auto
95 | opacity: 1
96 | .logo, .text
97 | @include do-shake('shake-slow', 2, 2, 1, 1s)
98 | @extend %running
99 | animation-play-state: running;
100 | display: flex
101 |
102 | .main-aside--collapse .bookmark__item .name
103 | width: 0
104 |
--------------------------------------------------------------------------------
/src/views/components/setting.sass:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: 卓文理
3 | * @Email: 531840344@qq.com
4 | * @Date: 2018-04-14 16:43:38
5 | */
6 |
7 | @import '../../stylesheet/common.sass'
8 |
9 | .setting
10 | position: fixed
11 | top: 0
12 | right: 0
13 | bottom: 0
14 | display: flex
15 | flex-direction: column
16 | width: 360px
17 | height: 100vh
18 | overflow: hidden
19 | background: var(--background)
20 | z-index: 100
21 | box-shadow: 0 0 3px 0 var(--shadowColor)
22 | transform: translateX(100%)
23 | transition: transform 0.2s ease
24 | .setting-title
25 | color: var(--fontColor)
26 | &.show
27 | transform: translate3d(0,0,0)
28 |
29 | &-title
30 | position: relative
31 | height: 44px
32 | line-height: 44px
33 | border-bottom: 1px solid var(--borderColor)
34 | padding-left: 20px
35 | font-size: 14px
36 | z-index: 102
37 | background: var(--background)
38 | box-shadow: 0 0 3px 0 var(--borderColor)
39 |
40 | &-content
41 | height: calc(100vh - 44px)
42 | padding: 20px
43 | background: var(--backgroundLighter)
44 |
45 | .scroller:after
46 | content: ''
47 | display: block
48 | height: 20px
49 |
50 | .el-card
51 | box-shadow: none
52 | margin-bottom: 20px
53 | &__header
54 | font-weight: bold
55 | &__tips
56 | padding-top: 10px
57 | font-size: 12px
58 | color: var(--gray)
59 | &__upload
60 | display: flex
61 | flex-direction: row
62 | .upload
63 | position: relative
64 | margin-left: 10px
65 | input
66 | position: absolute
67 | top: 0
68 | left: 0
69 | opacity: 0
70 | width: 100%
71 | height: 100%
72 | cursor: pointer
73 | &:hover + .el-button--success
74 | background: #85ce61;
75 | border-color: #85ce61;
76 | color: var(--background);
77 | .link
78 | display: inline-block
79 | text-decoration: none
80 | margin-right: 12px
81 | color: var(--gray)
82 | font-size: 14px
83 | .version
84 | color: var(--gray)
85 | padding-top: 10px
86 |
87 | .el-form
88 | margin-top: -5px
89 | .el-form-item
90 | margin-bottom: 0
91 | display: flex
92 | &__label
93 | float: none
94 | flex: 1
95 | text-align: left
96 | &__content
97 | display: block
98 | .el-select
99 | width: 96px
100 |
101 |
--------------------------------------------------------------------------------
/src/views/components/search.sass:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: 卓文理
3 | * @Email: 531840344@qq.com
4 | * @Date: 2018-01-19 18:16:25
5 | */
6 |
7 | @import '../../stylesheet/common.sass'
8 |
9 | .search
10 | display: block
11 | width: 100%
12 | max-width: 540px
13 | padding: 10px 20px 15px
14 | background: var(--background)
15 |
16 | .el-autocomplete
17 | display: block
18 | width: 100%
19 | .el-input
20 | &-group__append
21 | border-left: 0
22 | .el-button
23 | background: var(--background)
24 |
25 | .el-input
26 | &--prefix .el-input__inner
27 | padding-left: 46px
28 | &__prefix
29 | left: 0
30 | &-group__append
31 | position: absolute
32 | right: 1px
33 | top: 1px
34 | bottom: 1px
35 | display: block
36 | border: 0
37 | background: var(--background)
38 | width: auto
39 | padding: 0
40 | .el-button
41 | margin: 0
42 | border: 0
43 | padding-left: 16px
44 | padding-right: 16px
45 |
46 | .icon-search
47 | display: inline-block
48 | width: 46px
49 | height: 40px
50 | outline: 0
51 | cursor: pointer
52 | @each $icon in google, baidu, bing, yahoo, dogedoge
53 | &--#{$icon}
54 | background: url('../../assets/search-#{$icon}.png') center center no-repeat;
55 | background-size: 30px 30px
56 | &--duckduckgo
57 | background: url('../../assets/search-duckduckgo.svg') center center no-repeat
58 | background-size: 30px 30px
59 |
60 | .el-tabs
61 | // padding-left: 20px
62 | padding-bottom: 5px
63 | &__item
64 | text-align: center
65 | &__header
66 | margin-bottom: 0
67 | &__nav-wrap:after
68 | display: none
69 |
70 |
71 | .el-autocomplete-suggestion
72 | cursor: pointer
73 | li
74 | padding: 0
75 | &:hover
76 | background: transparent
77 |
78 | .suggestion
79 | & > div
80 | padding: 5px 20px
81 | &__search
82 | color: var(--yellow)
83 | &:hover
84 | background: var(--yellow)
85 | color: var(--background)
86 | &__url
87 | color: var(--blue)
88 | &:hover
89 | background: var(--blue)
90 | color: var(--background)
91 | &__word
92 | color: var(--green)
93 | &:hover
94 | background: var(--green)
95 | color: var(--background)
96 |
97 | .highlighted .suggestion
98 | &__search
99 | background: var(--yellow)
100 | color: var(--background)
101 | &__url
102 | background: var(--blue)
103 | color: var(--background)
104 | &__word
105 | background: var(--green)
106 | color: var(--background)
107 |
--------------------------------------------------------------------------------
/src/components/image-uploader/index.vue:
--------------------------------------------------------------------------------
1 |
2 | .image-uploader()
3 | el-upload(
4 | drag
5 | action="http://up-z0.qiniu.com/"
6 | :show-file-list="false"
7 | :data="qiniu"
8 | :before-upload="handleBeforeUpload"
9 | :on-success="handleUploadSuccess"
10 | )
11 | img(:src="url + '?imageView2/1/w/178'" v-if="url")
12 | .el-upload-dragger__interact(
13 | v-if="url"
14 | :class="{show: showInteract}"
15 | @mouseenter="showInteract = true"
16 | @mouseleave="showInteract = false"
17 | )
18 | span.btn
19 | i.el-icon-upload2
20 | span {{$t('KeepUpload')}}
21 | span.btn(@click.stop="handleUploadRemove")
22 | i.el-icon-delete
23 | span {{$t('Delete')}}
24 | .el-upload-dragger__inner(v-else)
25 | i.el-icon-upload
26 | .el-dragger__text(v-html="$t('UploadNote')")
27 |
28 |
29 |
96 |
97 |
100 |
--------------------------------------------------------------------------------
/src/assets/search-duckduckgo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/image-uploader-box/index.vue:
--------------------------------------------------------------------------------
1 |
2 | .my-image-box-uploader()
3 | el-upload(
4 | show-file-list
5 | list-type="picture-card"
6 | action="//up-z0.qiniu.com/"
7 | :data="qiniu"
8 | :file-list="images"
9 | :before-upload="handleBeforeUpload"
10 | :on-success="handleUploadSuccess"
11 | :on-preview="handleUploadPreview"
12 | :on-remove="handleUploadRemove"
13 | )
14 | i.el-icon-plus
15 |
16 | el-dialog(:visible.sync="dialogVisible" size="tiny")
17 | img(width="100%" :src="dialogImageUrl")
18 |
19 |
20 |
100 |
101 |
118 |
--------------------------------------------------------------------------------
/src/views/components/bookmark.vue:
--------------------------------------------------------------------------------
1 |
2 | iscroll-view.bookmark(
3 | :scrollerClass="{scroller: true}"
4 | :options="{mouseWheel: true}"
5 | ref="scrollView"
6 | )
7 | draggable(
8 | v-model="bookmarkLists"
9 | draggable=".bookmark__item"
10 | )
11 | .bookmark__item(
12 | v-for="(item, inx) in bookmarks"
13 | :key="inx"
14 | :class="{edit: edit}"
15 | @contextmenu="toggleEditAction"
16 | @click.exact="onLinkTapAction(item)"
17 | @click.meta="onLinkTapAction(item, true)"
18 | @click.ctrl="onLinkTapAction(item, true)"
19 | @dblclick="onEditAction(item, inx)"
20 | )
21 | .el-icon-close(@click.stop="onRemoveAction(item)")
22 |
23 | //- 折叠状态下、hover提示
24 | el-tooltip(
25 | class="item"
26 | effect="dark"
27 | placement="right"
28 | :content="item.name"
29 | :disabled="!collapseBookmark"
30 | )
31 | .logo.shake-constant(v-if="item.logo")
32 | img(:src="item.logo")
33 | .text.shake-constant(v-else) {{item.name[0]}}
34 |
35 | .name
36 | span {{item.name}}
37 |
38 | //- 新增、保存按钮
39 | .bookmark__item(@click="toggleEditAction" v-if="edit")
40 | .el-icon-check
41 | .bookmark__item(@click="onAddAction" v-else)
42 | .el-icon-plus
43 |
44 |
45 |
115 |
116 |
119 |
--------------------------------------------------------------------------------
/src/stylesheet/index.sass:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: 卓文理
3 | * @Email: 531840344@qq.com
4 | * @Date: 2018-01-17 15:49:10
5 | */
6 |
7 | @import '~normalize.css/normalize.css'
8 | @import '~octicons/index.scss'
9 |
10 | html
11 | font-family: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif
12 | height: 100vh
13 | overflow: hidden
14 | -webkit-font-smoothing: antialiased
15 |
16 | body
17 | --borderColor: #ebeef5
18 |
19 | *, *:before, *:after
20 | box-sizing: border-box
21 |
22 | .el-upload-dragger
23 | background-color: var(--background)
24 | border: 1px dashed var(--borderColor)
25 | &:hover
26 | border-color: var(--backgroundLightest)
27 |
28 | .el-card
29 | background-color: var(--background)
30 | color: var(--fontColor)
31 | border: 1px solid var(--borderColor)
32 | &__header
33 | border-bottom: 1px solid var(--borderColor)
34 |
35 | .el-dialog
36 | max-width: 600px
37 | background: var(--background)
38 | color: var(--fontColor)
39 | &__title
40 | color: var(--fontColor)
41 | &__body
42 | padding: 10px 20px
43 |
44 | .el-input__inner
45 | background-color: var(--background)
46 | background: var(--background)
47 | color: var(--fontColor)
48 | border: 1px solid var(--borderColor)
49 | &:hover
50 | border-color: var(--backgroundLightest)
51 | &:focus
52 | border-color: var(--borderColor)
53 |
54 | .el-radio-button__inner
55 | background: var(--background)
56 | border: 1px solid var(--borderColor)
57 | .el-radio-button:first-child .el-radio-button__inner
58 | border-left-color: var(--borderColor)
59 |
60 | .el-input.is-active .el-input__inner
61 | border-color: var(--borderColor)
62 |
63 | .el-select
64 | &:hover .el-input__inner,
65 | .el-input.is-focus .el-input__inner,
66 | .el-input__inner:focus
67 | border-color: var(--backgroundLightest)
68 | .el-tag
69 | background-color: var(--backgroundLighter)
70 | &__close.el-icon-close
71 | color: var(--fontColor)
72 | background-color: var(--background)
73 | &:hover
74 | background-color: var(--backgroundLightest)
75 | &--info
76 | color: var(--fontColor)
77 |
78 | .el-tabs__item
79 | color: var(--fontColor)
80 |
81 | .el-form
82 | &-item:last-child
83 | margin-bottom: 0
84 | &-item__label
85 | color: var(--fontColor)
86 |
87 | .el-autocomplete-suggestion__wrap
88 | background-color: var(--background)
89 | border: 1px solid var(--borderColor)
90 |
91 | .el-popper[x-placement^=bottom] .popper__arrow
92 | border-bottom-color: var(--background)
93 | &::after
94 | border-bottom-color: var(--background)
95 |
96 | .el-select-dropdown
97 | border: 1px solid var(--borderColor)
98 | background-color: var(--background)
99 | .popper__arrow
100 | transform: none
101 | &__item
102 | color: var(--fontColor)
103 | &__item.selected
104 | background-color: var(--backgroundLighter)
105 | &__item.hover,
106 | &__item:hover
107 | background-color: var(--backgroundLighter)
108 | color: var(--blue)
109 |
110 | .el-select-dropdown.is-multiple
111 | .el-select-dropdown__item.selected,
112 | .el-select-dropdown__item.selected.hover
113 | background-color: var(--backgroundLighter)
114 |
115 | .el-dropdown-menu
116 | background-color: var(--background)
117 | border: 1px solid var(--borderColor)
118 | &__item
119 | color: var(--fontColor)
120 | &:focus,
121 | &:not(.is-disabled):hover
122 | background-color: var(--background)
123 | border-bottom-color: var(--gray)
124 |
--------------------------------------------------------------------------------
/src/views/main.sass:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: 卓文理
3 | * @Email: 531840344@qq.com
4 | * @Date: 2018-01-19 18:03:22
5 | */
6 | @import '../stylesheet/common.sass'
7 |
8 | .main
9 | display: flex
10 | height: 100vh
11 | overflow: hidden
12 |
13 | // 左侧悬浮栏
14 | &-aside
15 | position: relative
16 | background: var(--background)
17 | box-shadow: 0 0 3px 0 var(--shadowColor)
18 | transform: translateX(-100%)
19 | transition: all 0.2s ease
20 | width: 0
21 | overflow: hidden
22 | flex-shrink: 0;
23 | &--show
24 | width: 300px
25 | transform: translate3d(0, 0, 0)
26 | & + .main-content
27 | max-width: calc(100% - 300px);
28 | &.main-aside--collapse
29 | width: 60px
30 | & + .main-content
31 | max-width: calc(100% - 60px);
32 |
33 | &-content
34 | flex: 1
35 | max-width: 100%
36 | background: var(--backgroundLighter)
37 |
38 | // 头部
39 | &__header
40 | width: 100%
41 | background: var(--background)
42 | .search-border
43 | height: 4px
44 | width: 100%
45 | background: var(--background)
46 | transition: all 0.2s ease
47 | &.google
48 | .search-border
49 | background: linear-gradient(to right, #4285f4 ((100/6) * 1%), #ea4335 ((100/6) * 1%), #ea4335 ((100/6) * 2%), #f9bc05 ((100/6) * 2%), #f9bc05 ((100/6) * 3%), #4285f4 ((100/6) * 3%), #4285f4 ((100/6) * 4%), #34a852 ((100/6) * 4%), #34a852 ((100/6) * 5%), #ea4335 ((100/6) * 5%), #ea4335 ((100/6) * 6%));
50 | .el-tabs__active-bar
51 | background: #1A73E8
52 | .el-tabs__item.is-active, .el-tabs__item:hover
53 | color: #1A73E8
54 | &.baidu
55 | .search-border, .el-tabs__active-bar
56 | background: #2d78f4
57 | .el-tabs__item.is-active, .el-tabs__item:hover
58 | color: #2d78f4
59 | &.yahoo
60 | .search-border, .el-tabs__active-bar
61 | background: #4d00ae
62 | .el-tabs__item.is-active, .el-tabs__item:hover
63 | color: #4d00ae
64 | &.dogedoge
65 | .search-border
66 | background: #ffce7f
67 | .el-tabs__active-bar
68 | background: #111
69 | .el-tabs__item.is-active, .el-tabs__item:hover
70 | color: #111
71 | &.bing
72 | .search-border, .el-tabs__active-bar
73 | background: #278483
74 | .el-tabs__item.is-active, .el-tabs__item:hover
75 | color: #278483
76 | &.duckduckgo
77 | .search-border, .el-tabs__active-bar
78 | background: #de5733
79 | .el-tabs__item.is-active, .el-tabs__item:hover
80 | color: #de5733
81 |
82 | .btn-setting
83 | position: absolute
84 | top: 10px
85 | right: 10px
86 | display: flex
87 | width: 30px
88 | height: 30px
89 | align-items: center
90 | justify-content: center
91 | border: 0
92 | background: var(--background)
93 | cursor: pointer
94 | outline: 0
95 | z-index: 101
96 | .oction-gear
97 | width: 14px
98 | height: 14px
99 | fill: var(--fontColor)
100 | .oction-x
101 | width: 12px
102 | height: 16px
103 | fill: var(--fontColor)
104 |
105 | // trending
106 | &__trending
107 | position: relative
108 | width: 100%
109 | height: calc(100vh - 109px)
110 | z-index: 10
111 |
--------------------------------------------------------------------------------
/src/vuex/modules/github.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: 卓文理
3 | * @Email: 531840344@qq.com
4 | * @Date: 2018-01-18 10:53:12
5 | */
6 |
7 | 'use strict';
8 |
9 | import Promise from 'bluebird';
10 | import { get } from '../../services/fetch';
11 | import * as types from '../types';
12 | import storage from '../../services/storage';
13 |
14 | const time = new Date();
15 | const year = new Date(time.getFullYear(), 0, 1);
16 | const toDay = time.getDate();
17 | const toWeek = Math.ceil((((new Date() - year) / 86400000) + year.getDay() + 1) / 7);
18 | const toMonth = time.getMonth() + 1;
19 |
20 | const fetchTrendingRepos = async (lang, since, type = 'repositories') => {
21 | console.log(lang);
22 | const data = await get(`https://gtrend.infly.io/${type}?language=${encodeURIComponent(lang)}&since=${since}`);
23 |
24 | if (type === 'developers' && lang === 'JavaScript' && (Math.random() * 2) > 1) {
25 | data.push({
26 | avatar: 'https://avatars3.githubusercontent.com/u/9620783?s=96&v=4',
27 | author: '卓文理',
28 | url: 'https://github.com/zhuowenli',
29 | username: 'zhuowenli',
30 | repo: {
31 | name: 'githuber',
32 | url: 'https://github.com/zhuowenli/githuber',
33 | description: ':octocat: Display Github Trending repositories on New Tab Extensions',
34 | }
35 | });
36 | }
37 |
38 | return data;
39 | };
40 |
41 | export const getters = {
42 | trendings: state => state.trendings,
43 | };
44 |
45 | export const actions = {
46 | /**
47 | * 获取GitHub Trending
48 | *
49 | * @param {any} { commit } state
50 | * @param {Object} [query={}] 请求参数
51 | * @param {String} query.since 时间维度:daily、weekly、monthly
52 | * @param {String} query.lang 语言
53 | * @param {String} query.type repositories、developers
54 | * @returns {Promise}
55 | */
56 | async fetchTrending ({ commit }, query = {}) {
57 | const data = await storage.getItem(JSON.stringify(query));
58 |
59 | if (
60 | data && data.repos.length && (
61 | (query.since === 'daily' && data.toDay === toDay) ||
62 | (query.since === 'weekly' && data.toWeek === toWeek) ||
63 | (query.since === 'monthly' && data.toMonth === toMonth)
64 | )
65 | ) {
66 | commit(types.RECEIVE_GITHUB_TRENDINGS, data.repos);
67 | return data.repos;
68 | }
69 |
70 | const { since, type } = query;
71 |
72 | let repos = [];
73 | let isAllLanguage = false;
74 |
75 | if (query.lang.length) {
76 | query.lang.map(item => {
77 | if (item === '') isAllLanguage = true;
78 | return item;
79 | });
80 | }
81 |
82 | if (!query.lang.length || isAllLanguage) {
83 | repos = await fetchTrendingRepos('', since, type);
84 | } else {
85 | await Promise.map(query.lang, async lang => {
86 | const res = await fetchTrendingRepos(lang, since, type);
87 | repos = repos.concat(res);
88 | return res;
89 | });
90 | repos = repos.sort((a, b) => (+b.added - a.added));
91 | }
92 |
93 | commit(types.RECEIVE_GITHUB_TRENDINGS, repos);
94 |
95 | storage.setItem(JSON.stringify(query), {
96 | repos,
97 | toDay,
98 | toWeek,
99 | toMonth
100 | });
101 |
102 | return repos;
103 | },
104 |
105 | };
106 |
107 | export const mutations = {
108 | [types.RECEIVE_GITHUB_TRENDINGS](state, data) {
109 | state.trendings = data;
110 | },
111 | };
112 |
113 | export default {
114 | actions,
115 | getters,
116 | mutations,
117 | namespaced: true,
118 | state: {
119 | trendings: [],
120 | },
121 | };
122 |
--------------------------------------------------------------------------------
/src/vuex/modules/bookmark.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: 卓文理
3 | * @Email: 531840344@qq.com
4 | * @Date: 2018-01-20 20:59:49
5 | */
6 |
7 | 'use strict';
8 |
9 | import * as types from '../types';
10 | import findOne from '../../services/findOne';
11 | import storage from '../../services/storage';
12 | import google from '../../assets/search-google.png';
13 |
14 | export const getters = {
15 | bookmarks: state => state.bookmarks,
16 | };
17 |
18 | export const actions = {
19 | async fetchBookmarks({ commit }) {
20 | let data = storage.getItem('GITHUBER_BOOKMARKS') || [];
21 |
22 | if (!data.length) {
23 | /* eslint-disable max-len */
24 | data = [
25 | {
26 | name: 'zhuowenli/githuber: 这是一个帮助 Githuber 每日发现优质内容的浏览器主页拓展。',
27 | logo: 'https://github.com/favicon.ico',
28 | url: 'https://github.com/zhuowenli/githuber'
29 | }, {
30 | name: 'zhuowenli - GitHub',
31 | url: 'https://github.com/zhuowenli',
32 | logo: 'http://st-qn.gittt.cn/2018/1/22/1516614358916991.png'
33 | }, {
34 | name: 'Dribbble - Show and tell for designers',
35 | url: 'https://dribbble.com/',
36 | logo: 'https://cdn.dribbble.com/assets/dribbble-ball-192-ec064e49e6f63d9a5fa911518781bee0c90688d052a038f8876ef0824f65eaf2.png'
37 | }, {
38 | name: 'Codrops - 右键点击列表进入编辑模式',
39 | url: 'https://tympanus.net/codrops/',
40 | logo: 'https://avatars3.githubusercontent.com/u/310036?s=200&v=4'
41 | }, {
42 | name: '编辑模式下双击可编辑、拖拽可排序',
43 | logo: google,
44 | url: 'https://www.google.com/'
45 | },
46 | ];
47 |
48 | storage.setItem('GITHUBER_BOOKMARKS', data);
49 | }
50 |
51 | commit(types.RECEIVE_BOOKMARKS, data);
52 | return data;
53 | },
54 | async updateBookmarks({ commit }, data) {
55 | commit(types.RECEIVE_BOOKMARKS, data);
56 | return data;
57 | },
58 | async saveBookmark({ commit }, { form: item, index }) {
59 | commit(types.SAVE_BOOKMARKS, { item, index });
60 | return item;
61 | },
62 | async removeBookmark({ commit }, item) {
63 | commit(types.DELETE_BOOKMARKS, item);
64 | },
65 | async restoreBackupBookmarks({ commit }, data) {
66 | commit(types.RESTORE_BACKUP_BOOKMARKS, data);
67 | }
68 | };
69 |
70 | export const mutations = {
71 | [types.RECEIVE_BOOKMARKS](state, data) {
72 | state.bookmarks = data;
73 | storage.setItem('GITHUBER_BOOKMARKS', state.bookmarks);
74 | },
75 | [types.RESTORE_BACKUP_BOOKMARKS](state, data) {
76 | data.map(item => {
77 | const { index } = findOne(state.bookmarks, { name: item.name });
78 | if (index === -1) {
79 | state.bookmarks.push(item);
80 | }
81 | return item;
82 | });
83 |
84 | storage.setItem('GITHUBER_BOOKMARKS', state.bookmarks);
85 | },
86 | [types.SAVE_BOOKMARKS](state, { item, index }) {
87 | if (index || index === 0) {
88 | state.bookmarks.splice(index, 1, item);
89 | } else {
90 | state.bookmarks.unshift(item);
91 | }
92 | storage.setItem('GITHUBER_BOOKMARKS', state.bookmarks);
93 | },
94 | [types.DELETE_BOOKMARKS](state, item) {
95 | const index = state.bookmarks.indexOf(item);
96 |
97 | if (index >= 0) {
98 | state.bookmarks.splice(index, 1);
99 | storage.setItem('GITHUBER_BOOKMARKS', state.bookmarks);
100 | }
101 | },
102 | };
103 |
104 | export default {
105 | actions,
106 | getters,
107 | mutations,
108 | namespaced: true,
109 | state: {
110 | bookmarks: [],
111 | },
112 | };
113 |
--------------------------------------------------------------------------------
/src/services/fetch.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: 卓文理
3 | * @Email: 531840344@qq.com
4 | * @Date: 2018-01-18 14:52:13
5 | */
6 |
7 | 'use strict';
8 |
9 | import axios from 'axios';
10 | // import cookie from './cookie';
11 |
12 | // const auths = {};
13 |
14 | /**
15 | * XMLHttpRequest 封装
16 | * @export
17 | * @param {Object} [query={}] 请求参数
18 | * @returns Promise
19 | */
20 | export function fetch(query = {}) {
21 | const params = Object.assign({}, query);
22 |
23 | if (params.method === 'get') {
24 | params.params = params.data;
25 | delete params.data;
26 | }
27 |
28 | params.headers = Object.assign(params.headers, {
29 | 'Content-Type': 'application/json',
30 | });
31 | params.validateStatus = (status) => status >= 200 && status < 500;
32 |
33 | // console.log('=========== FETCH START ===========');
34 | // console.log(params);
35 | return axios(params)
36 | .then((res) => {
37 | const { data, status } = res;
38 |
39 | if (status >= 400) {
40 | return Promise.reject(res);
41 | }
42 |
43 | // console.log(res, data);
44 | // console.log('=========== FETCH END ===========');
45 | return data;
46 | })
47 | .catch((error) => {
48 | const proxy = {};
49 |
50 | proxy.name = '接口请求异常';
51 | proxy.message = error.message;
52 |
53 | if (error.data) {
54 | return Promise.reject(error.data);
55 | }
56 |
57 | return Promise.reject(proxy);
58 | });
59 | }
60 |
61 | /**
62 | * http get 请求简单封装
63 | * @export
64 | * @param {String} url 请求的URL
65 | * @param {Object} [data={}] 请求参数
66 | * @param {Object} [data={}] 请求头
67 | * @returns Promise
68 | */
69 | export function get(url, data = {}, headers = {}) {
70 | return fetch({
71 | url,
72 | data,
73 | method: 'get',
74 | headers,
75 | });
76 | }
77 |
78 | /**
79 | * http post 请求简单封装
80 | * @export
81 | * @param {String} url 请求的URL
82 | * @param {Object} [data={}] 请求参数
83 | * @param {Object} [data={}] 请求头
84 | * @returns Promise
85 | */
86 | export function post(url, data = {}, headers = {}) {
87 | return fetch({
88 | url,
89 | data,
90 | method: 'post',
91 | headers,
92 | });
93 | }
94 |
95 | /**
96 | * http delete 请求简单封装
97 | * @export
98 | * @param {String} url 请求的URL
99 | * @param {Object} [data={}] 请求参数
100 | * @param {Object} [data={}] 请求头
101 | * @returns Promise
102 | */
103 | export function del(url, data = {}, headers = {}) {
104 | return fetch({
105 | url,
106 | data,
107 | method: 'delete',
108 | headers,
109 | });
110 | }
111 |
112 | /**
113 | * http put 请求简单封装
114 | * @export
115 | * @param {String} url 请求的URL
116 | * @param {Object} [data={}] 请求参数
117 | * @param {Object} [data={}] 请求头
118 | * @returns Promise
119 | */
120 | export function put(url, data = {}, headers = {}) {
121 | return fetch({
122 | url,
123 | data,
124 | method: 'put',
125 | headers,
126 | });
127 | }
128 |
129 | /**
130 | * http jsonp 请求简单封装
131 | *
132 | * @export
133 | * @param {String} url 请求的URL
134 | * @param {Object} [query={}] 请求参数
135 | * @returns {Promise}
136 | */
137 | export function jsonp(url, query = {}) {
138 | return fetch({
139 | url,
140 | data: {
141 | ...query,
142 | cb: 'callback',
143 | t: new Date().getTime(),
144 | },
145 | method: 'get',
146 | responseType: 'text',
147 | headers: {},
148 | }).then((res) => {
149 | try {
150 | const startIndex = res.indexOf('(');
151 | const endIndex = res.lastIndexOf(')');
152 |
153 | if (startIndex !== -1 && endIndex !== -1 && endIndex > startIndex) {
154 | const payload = res.slice(startIndex + 1, endIndex);
155 | const normalised = payload.replace(/[\r\n\t]/g, '').replace(/([,{\s])([a-zA-Z_$][0-9a-zA-Z_$]*)\s*:/g, '$1"$2":');
156 | return JSON.parse(normalised);
157 | }
158 | } catch (e) {
159 | const proxy = {};
160 | proxy.name = '接口请求异常';
161 | proxy.message = (e && e.message) || 'Invalid JSONP response';
162 | return Promise.reject(proxy);
163 | }
164 |
165 | const proxy = {};
166 | proxy.name = '接口请求异常';
167 | proxy.message = 'Invalid JSONP response';
168 | return Promise.reject(proxy);
169 | });
170 | }
171 |
172 | export default {
173 | fetch,
174 | get,
175 | put,
176 | delete: del,
177 | post,
178 | jsonp,
179 | };
180 |
--------------------------------------------------------------------------------
/src/services/cookie.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: 卓文理
3 | * @Email: 531840344@qq.com
4 | * @Date: 2018-01-18 14:54:16
5 | */
6 |
7 | 'use strict';
8 |
9 |
10 | const decode = decodeURIComponent;
11 | const encode = encodeURIComponent;
12 |
13 | // Helpers
14 | const isString = o => typeof o === 'string';
15 | const same = s => s;
16 |
17 | function parseCookieString(text, shouldDecode) {
18 | const cookies = {};
19 |
20 | if (isString(text) && text.length > 0) {
21 | const decodeValue = shouldDecode ? decode : same;
22 | const cookieParts = text.split(/;\s/g);
23 | let cookieName;
24 | let cookieValue;
25 | let cookieNameValue;
26 |
27 | for (let i = 0, len = cookieParts.length; i < len; i += 1) {
28 | // Check for normally-formatted cookie (name-value)
29 | cookieNameValue = cookieParts[i].match(/([^=]+)=/i);
30 | if (cookieNameValue instanceof Array) {
31 | try {
32 | cookieName = decode(cookieNameValue[1]);
33 | cookieValue = decodeValue(cookieParts[i]
34 | .substring(cookieNameValue[1].length + 1));
35 | } catch (ex) {
36 | // Intentionally ignore the cookie -
37 | // the encoding is wrong
38 | }
39 | } else {
40 | // Means the cookie does not have an "=", so treat it as
41 | // a boolean flag
42 | cookieName = decode(cookieParts[i]);
43 | cookieValue = '';
44 | }
45 |
46 | if (cookieName) {
47 | cookies[cookieName] = cookieValue;
48 | }
49 | }
50 | }
51 |
52 | return cookies;
53 | }
54 |
55 | function isNonEmptyString(s) {
56 | return isString(s) && s !== '';
57 | }
58 |
59 | function validateCookieName(name) {
60 | if (!isNonEmptyString(name)) {
61 | throw new TypeError('Cookie name must be a non-empty string');
62 | }
63 | }
64 |
65 | export default {
66 | /**
67 | * 获取 cookie
68 | * @param {String} cookie 名
69 | * @param {Function|Object} options Optional
70 | * @param {Boolean} options.raw 当 raw 为 true 时,cookie的值不会被URI解码
71 | * @param {Function} options.converter 该函数会在返回值之前执行。如果cookie不存在,则不使用该函数。 可以方便地传递函数而不是选项对象。
72 | * @return 如果 converter 不存在,则返回一个 string or undefined。
73 | * 如果获取的 cookie 为空,并且 converter 函数存在,则返回 converter 的返回值。
74 | */
75 | get(name, options) {
76 | validateCookieName(name);
77 |
78 | if (typeof options === 'function') {
79 | options = { converter: options };
80 | } else {
81 | options = options || {};
82 | }
83 |
84 | const cookies = parseCookieString(document.cookie, !options.raw);
85 | return (options.converter || same)(cookies[name]);
86 | },
87 |
88 | /**
89 | * 保存 cookie
90 | * @param {string} name 名称
91 | * @param {*} value 存储内容
92 | * @param {Object} options Optional
93 | * @param {Boolean} options.raw 当raw为true时,在设置之前不应该被URI编码。
94 | * @param {Number|Date} options.expires 到期时间
95 | * @param {Boolean} options.secure secure
96 | * @param {String} options.domain 域名
97 | * @return {string} 创建的cookie字符串。
98 | */
99 | set(name, value, options) {
100 | validateCookieName(name);
101 |
102 | options = options || {};
103 | const expires = options.expires;
104 | const domain = options.domain;
105 | const path = options.path;
106 |
107 | if (!options.raw) {
108 | value = encode(String(value));
109 | }
110 |
111 | let text = `${name}=${value}`;
112 |
113 | // expires
114 | let date = expires;
115 |
116 | //
117 | if (!date) {
118 | date = new Date('2021/01/01');
119 | }
120 |
121 | if (typeof date === 'number') {
122 | date = new Date();
123 | date.setDate(date.getDate() + expires);
124 | }
125 |
126 | if (date instanceof Date) {
127 | text += `; expires=${date.toUTCString()}`;
128 | }
129 |
130 | // domain
131 | if (isNonEmptyString(domain)) {
132 | text += `; domain=${domain}`;
133 | }
134 |
135 | // path
136 | if (isNonEmptyString(path)) {
137 | text += `; path=${path}`;
138 | }
139 |
140 | // secure
141 | if (options.secure) {
142 | text += '; secure';
143 | }
144 |
145 | document.cookie = text;
146 | return text;
147 | },
148 |
149 | /**
150 | * 通过将过期日期设置为过去的某个时间,删除一个cookie。
151 | * @param {string} name 名称
152 | * @param {Object} options Optional expires 时间将被该方法覆盖。
153 | * @param {String} options.path path
154 | * @param {Boolean} options.secure secure
155 | * @param {String} options.domain 域名
156 | * @return {string} The created cookie string.
157 | */
158 | remove(name, options) {
159 | options = options || {};
160 | options.expires = new Date(0);
161 | return this.set(name, '', options);
162 | }
163 | };
164 |
--------------------------------------------------------------------------------
/src/views/components/setting.vue:
--------------------------------------------------------------------------------
1 |
2 | .setting(:class="{show: config.showSetting}")
3 | .setting-title {{$t('Setting')}}
4 | iscroll-view.setting-content(
5 | :scrollerClass="{scroller: true}"
6 | :options="{mouseWheel: true}"
7 | ref="scrollView"
8 | )
9 | el-card
10 | div(slot="header") {{$t('GoalOpeningMethod')}}
11 | el-form
12 | el-form-item(:label="$t('openSearchInNewTab')")
13 | el-switch(v-model="config.openSearchInNewTab")
14 | el-form-item(:label="$t('openLinkInNewTab')")
15 | el-switch(v-model="config.openLinkInNewTab")
16 | el-form-item(:label="$t('openBookmarkInNewTab')")
17 | el-switch(v-model="config.openBookmarkInNewTab")
18 | .el-card__tips {{$t('GoalOpeningMethodNote')}}
19 |
20 | el-card
21 | div(slot="header") {{$t('View')}}
22 | el-form
23 | el-form-item(:label="$t('Language')")
24 | el-select(v-model="config.locale" size="medium")
25 | el-option(label="中文" value="zh")
26 | el-option(label="English" value="en")
27 | el-form-item(:label="$t('showBookmark')")
28 | el-switch(v-model="config.showBookmark")
29 | el-form-item(:label="$t('collapseBookmark')")
30 | el-switch(v-model="config.collapseBookmark")
31 | el-form-item(:label="$t('Theme')")
32 | el-switch(v-model="config.nightMode")
33 | el-form-item(:label="$t('importTopSites')")
34 | el-button(type="info" size="medium" round @click="onImportTopSites") {{$t('import')}}
35 |
36 | //- el-card
37 | //- div(slot="header") {{$t('Search')}}
38 | //- el-form
39 | //- el-form-item(:label="$t('showBookmark')")
40 | //- el-switch(v-model="config.showBookmark")
41 |
42 | el-card
43 | div(slot="header") {{$t('DataBackup')}}
44 | .el-card__upload
45 | el-button(type="info" size="medium" round @click="onExportAction") {{$t('DataBackup')}}
46 | .upload
47 | input(
48 | ref="file"
49 | type="file"
50 | accept=".githuber"
51 | @change="onImportAction"
52 | )
53 | el-button(type="success" size="medium" round) {{$t('RestoreBackup')}}
54 |
55 | el-card
56 | div(slot="header") {{$t('About')}}
57 | a.link(href="https://github.com/zhuowenli/" target="_blank") {{$t('AboutAuthor')}}
58 | a.link(href="https://github.com/zhuowenli/githuber/issues" target="_blank") {{$t('Feedback')}}
59 | a.link(href="https://github.com/zhuowenli/githuber" target="_blank") {{$t('SourceCode')}}
60 | .version v{{manifest.version}}
61 |
62 |
63 |
126 |
127 |
130 |
--------------------------------------------------------------------------------
/src/views/components/searchEngines.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: 卓文理
3 | * @Email: 531840344@qq.com
4 | * @Date: 2018-01-18 20:31:28
5 | */
6 |
7 | 'use strict';
8 |
9 | export default [
10 | {
11 | name: 'Baidu',
12 | value: 'baidu',
13 | engines: [
14 | {
15 | name: 'Web',
16 | value: 'Web',
17 | url: 'https://www.baidu.com/s?isource=infinity&wd='
18 | }, {
19 | name: 'Images',
20 | value: 'Images',
21 | url: 'https://image.baidu.com/search/index?tn=baiduimage&word='
22 | }, {
23 | name: 'News',
24 | value: 'News',
25 | url: 'http://news.baidu.com/ns?tn=news&ie=utf-8&word='
26 | }, {
27 | name: 'Musics',
28 | value: 'Musics',
29 | url: 'http://music.baidu.com/search?ie=utf-8&key='
30 | }, {
31 | name: 'Videos',
32 | value: 'Videos',
33 | url: 'http://video.baidu.com/v?ie=utf-8&word='
34 | }, {
35 | name: 'Maps',
36 | value: 'Maps',
37 | url: 'http://map.baidu.com/?newmap=1&ie=utf-8&s=s%26wd%3D'
38 | }
39 | ]
40 | },
41 | {
42 | name: 'Google',
43 | value: 'google',
44 | engines: [
45 | {
46 | name: 'Web',
47 | value: 'Web',
48 | url: 'https://www.google.com/search?q='
49 | }, {
50 | name: 'Images',
51 | value: 'Images',
52 | url: 'https://www.google.com/search?tbm=isch&q='
53 | }, {
54 | name: 'News',
55 | value: 'News',
56 | url: 'https://www.google.com/search?tbm=nws&q='
57 | }, {
58 | name: 'Videos',
59 | value: 'Videos',
60 | url: 'https://www.google.com/search?tbm=vid&q='
61 | }, {
62 | name: 'Maps',
63 | value: 'Maps',
64 | url: 'https://www.google.com/maps/preview?q='
65 | }
66 | ]
67 | },
68 | {
69 | name: 'Yahoo',
70 | value: 'yahoo',
71 | engines: [
72 | {
73 | name: 'Web',
74 | value: 'Web',
75 | url: 'https://search.yahoo.com/search?fr=yfp-t&fp=1&toggle=1&cop=mss&ei=UTF-8&p='
76 | }, {
77 | name: 'Images',
78 | value: 'Images',
79 | url: 'https://images.search.yahoo.com/search/images?p='
80 | }, {
81 | name: 'News',
82 | value: 'News',
83 | url: 'https://news.search.yahoo.com/search?p='
84 | }, {
85 | name: 'Videos',
86 | value: 'Videos',
87 | url: 'https://video.search.yahoo.com/search/video?p='
88 | }, {
89 | name: 'Sports',
90 | value: 'Sports',
91 | url: 'https://sports.search.yahoo.com/search?p='
92 | }
93 | ]
94 | },
95 | {
96 | name: 'Bing',
97 | value: 'bing',
98 | engines: [
99 | {
100 | name: 'Web',
101 | value: 'Web',
102 | url: 'https://www.bing.com/search?isource=infinity&iname=bing&itype=web&q='
103 | }, {
104 | name: 'Images',
105 | value: 'Images',
106 | url: 'https://www.bing.com/images/search?isource=infinity&iname=bing&q='
107 | }, {
108 | name: 'News',
109 | value: 'News',
110 | url: 'https://www.bing.com/news/search?isource=infinity&iname=bing&q='
111 | }, {
112 | name: 'Videos',
113 | value: 'Videos',
114 | url: 'https://www.bing.com/videos/search?isource=infinity&iname=bing&q='
115 | }, {
116 | name: 'Maps',
117 | value: 'Maps',
118 | url: 'http://www.bing.com/maps/default.aspx?q='
119 | }
120 | ]
121 | },
122 | {
123 | name: 'DogeDoge',
124 | value: 'dogedoge',
125 | engines: [
126 | {
127 | name: 'Web',
128 | value: 'Web',
129 | url: 'https://www.dogedoge.com/results?q='
130 | }
131 | ]
132 | },
133 | {
134 | name: 'DuckDuckGo',
135 | value: 'duckduckgo',
136 | engines: [
137 | {
138 | name: 'Web',
139 | value: 'Web',
140 | url: 'https://duckduckgo.com/?ia=web&q='
141 | }, {
142 | name: 'Images',
143 | value: 'Images',
144 | url: 'https://duckduckgo.com/?ia=images&iax=images&q='
145 | }, {
146 | name: 'News',
147 | value: 'News',
148 | url: 'https://duckduckgo.com/?ia=news&iar=news&q='
149 | }, {
150 | name: 'Videos',
151 | value: 'Videos',
152 | url: 'https://duckduckgo.com/?ia=videos&iax=videos&q='
153 | }, {
154 | name: 'Maps',
155 | value: 'Maps',
156 | url: 'https://duckduckgo.com/?iaxm=maps&ia=web&q='
157 | }
158 | ]
159 | }
160 | ];
161 |
--------------------------------------------------------------------------------
/src/services/colors.json:
--------------------------------------------------------------------------------
1 | {
2 | "Mercury": "#ff2b2b",
3 | "TypeScript": "#2b7489",
4 | "PureBasic": "#5a6986",
5 | "Objective-C++": "#6866fb",
6 | "Self": "#0579aa",
7 | "edn": "#db5855",
8 | "NewLisp": "#87AED7",
9 | "Jupyter Notebook": "#DA5B0B",
10 | "Rebol": "#358a5b",
11 | "Frege": "#00cafe",
12 | "Dart": "#00B4AB",
13 | "AspectJ": "#a957b0",
14 | "Shell": "#89e051",
15 | "Web Ontology Language": "#9cc9dd",
16 | "xBase": "#403a40",
17 | "Eiffel": "#946d57",
18 | "Nix": "#7e7eff",
19 | "RAML": "#77d9fb",
20 | "MTML": "#b7e1f4",
21 | "Racket": "#22228f",
22 | "Elixir": "#6e4a7e",
23 | "SAS": "#B34936",
24 | "Agda": "#315665",
25 | "wisp": "#7582D1",
26 | "D": "#ba595e",
27 | "Kotlin": "#F18E33",
28 | "Opal": "#f7ede0",
29 | "Crystal": "#776791",
30 | "Objective-C": "#438eff",
31 | "ColdFusion CFC": "#ed2cd6",
32 | "Oz": "#fab738",
33 | "Mirah": "#c7a938",
34 | "Objective-J": "#ff0c5a",
35 | "Gosu": "#82937f",
36 | "FreeMarker": "#0050b2",
37 | "Ruby": "#701516",
38 | "Component Pascal": "#b0ce4e",
39 | "Arc": "#aa2afe",
40 | "Brainfuck": "#2F2530",
41 | "Nit": "#009917",
42 | "APL": "#5A8164",
43 | "Go": "#375eab",
44 | "Visual Basic": "#945db7",
45 | "PHP": "#4F5D95",
46 | "Cirru": "#ccccff",
47 | "SQF": "#3F3F3F",
48 | "Glyph": "#e4cc98",
49 | "Java": "#b07219",
50 | "MAXScript": "#00a6a6",
51 | "Scala": "#DC322F",
52 | "Makefile": "#427819",
53 | "ColdFusion": "#ed2cd6",
54 | "Perl": "#0298c3",
55 | "Lua": "#000080",
56 | "Vue": "#2c3e50",
57 | "Verilog": "#b2b7f8",
58 | "Factor": "#636746",
59 | "Haxe": "#df7900",
60 | "Pure Data": "#91de79",
61 | "Forth": "#341708",
62 | "Red": "#ee0000",
63 | "Hy": "#7790B2",
64 | "Volt": "#1F1F1F",
65 | "LSL": "#3d9970",
66 | "eC": "#913960",
67 | "CoffeeScript": "#244776",
68 | "HTML": "#e44b23",
69 | "Lex": "#DBCA00",
70 | "API Blueprint": "#2ACCA8",
71 | "Swift": "#ffac45",
72 | "C": "#555555",
73 | "C++": "#555555",
74 | "AutoHotkey": "#6594b9",
75 | "Isabelle": "#FEFE00",
76 | "Metal": "#8f14e9",
77 | "Clarion": "#db901e",
78 | "JSONiq": "#40d47e",
79 | "Boo": "#d4bec1",
80 | "AutoIt": "#1C3552",
81 | "Clojure": "#db5855",
82 | "Rust": "#dea584",
83 | "Prolog": "#74283c",
84 | "SourcePawn": "#5c7611",
85 | "AMPL": "#E6EFBB",
86 | "FORTRAN": "#4d41b1",
87 | "ANTLR": "#9DC3FF",
88 | "Harbour": "#0e60e3",
89 | "Tcl": "#e4cc98",
90 | "BlitzMax": "#cd6400",
91 | "PigLatin": "#fcd7de",
92 | "Lasso": "#999999",
93 | "ECL": "#8a1267",
94 | "VHDL": "#adb2cb",
95 | "Elm": "#60B5CC",
96 | "Propeller Spin": "#7fa2a7",
97 | "X10": "#4B6BEF",
98 | "IDL": "#a3522f",
99 | "ATS": "#1ac620",
100 | "Ada": "#02f88c",
101 | "Unity3D Asset": "#ab69a1",
102 | "Nu": "#c9df40",
103 | "LFE": "#004200",
104 | "SuperCollider": "#46390b",
105 | "Oxygene": "#cdd0e3",
106 | "ASP": "#6a40fd",
107 | "Assembly": "#6E4C13",
108 | "Gnuplot": "#f0a9f0",
109 | "JFlex": "#DBCA00",
110 | "NetLinx": "#0aa0ff",
111 | "Turing": "#45f715",
112 | "Vala": "#fbe5cd",
113 | "Processing": "#0096D8",
114 | "Arduino": "#bd79d1",
115 | "FLUX": "#88ccff",
116 | "NetLogo": "#ff6375",
117 | "C Sharp": "#178600",
118 | "CSS": "#563d7c",
119 | "Emacs Lisp": "#c065db",
120 | "Stan": "#b2011d",
121 | "SaltStack": "#646464",
122 | "QML": "#44a51c",
123 | "Pike": "#005390",
124 | "LOLCODE": "#cc9900",
125 | "ooc": "#b0b77e",
126 | "Handlebars": "#01a9d6",
127 | "J": "#9EEDFF",
128 | "Mask": "#f97732",
129 | "EmberScript": "#FFF4F3",
130 | "TeX": "#3D6117",
131 | "Nemerle": "#3d3c6e",
132 | "KRL": "#28431f",
133 | "Ren'Py": "#ff7f7f",
134 | "Unified Parallel C": "#4e3617",
135 | "Golo": "#88562A",
136 | "Fancy": "#7b9db4",
137 | "OCaml": "#3be133",
138 | "Shen": "#120F14",
139 | "Pascal": "#b0ce4e",
140 | "F#": "#b845fc",
141 | "Puppet": "#302B6D",
142 | "ActionScript": "#882B0F",
143 | "Diff": "#88dddd",
144 | "Ragel in Ruby Host": "#9d5200",
145 | "Fantom": "#dbded5",
146 | "Zephir": "#118f9e",
147 | "Click": "#E4E6F3",
148 | "Smalltalk": "#596706",
149 | "DM": "#447265",
150 | "Ioke": "#078193",
151 | "PogoScript": "#d80074",
152 | "LiveScript": "#499886",
153 | "JavaScript": "#f1e05a",
154 | "VimL": "#199f4b",
155 | "PureScript": "#1D222D",
156 | "ABAP": "#E8274B",
157 | "Matlab": "#bb92ac",
158 | "Slash": "#007eff",
159 | "R": "#198ce7",
160 | "Erlang": "#B83998",
161 | "Pan": "#cc0000",
162 | "LookML": "#652B81",
163 | "Eagle": "#814C05",
164 | "Scheme": "#1e4aec",
165 | "PLSQL": "#dad8d8",
166 | "Python": "#3572A5",
167 | "Max": "#c4a79c",
168 | "Common Lisp": "#3fb68b",
169 | "Latte": "#A8FF97",
170 | "XQuery": "#5232e7",
171 | "Omgrofl": "#cabbff",
172 | "XC": "#99DA07",
173 | "Nimrod": "#37775b",
174 | "SystemVerilog": "#DAE1C2",
175 | "Chapel": "#8dc63f",
176 | "Groovy": "#e69f56",
177 | "Dylan": "#6c616e",
178 | "E": "#ccce35",
179 | "Parrot": "#f3ca0a",
180 | "Grammatical Framework": "#79aa7a",
181 | "Game Maker Language": "#8fb200",
182 | "Papyrus": "#6600cc",
183 | "NetLinx+ERB": "#747faa",
184 | "Clean": "#3F85AF",
185 | "Alloy": "#64C800",
186 | "Squirrel": "#800000",
187 | "PAWN": "#dbb284",
188 | "UnrealScript": "#a54c4d",
189 | "Standard ML": "#dc566d",
190 | "Slim": "#ff8f77",
191 | "Perl6": "#0000fb",
192 | "Julia": "#a270ba",
193 | "Haskell": "#29b544",
194 | "NCL": "#28431f",
195 | "Io": "#a9188d",
196 | "Rouge": "#cc0088",
197 | "cpp": "#f34b7d",
198 | "AGS Script": "#B9D9FF",
199 | "Dogescript": "#cca760",
200 | "nesC": "#94B0C7",
201 | "unknown": "#000000"
202 | }
--------------------------------------------------------------------------------
/src/views/components/search.vue:
--------------------------------------------------------------------------------
1 |
2 | .search
3 | el-form(@submit.prevent.native="")
4 | el-tabs(v-model="activeEngineNavName" @tab-click="onSearchNameTapAction")
5 | el-tab-pane(
6 | v-for="item in searchEngine.engines"
7 | :label="$t(item.name)"
8 | :name="item.value"
9 | :key="item.name"
10 | )
11 | el-autocomplete(
12 | clearable
13 | :fetch-suggestions="onQuerySearchAction"
14 | :placeholder="searchEngine.name"
15 | :trigger-on-focus="false"
16 | v-model="searchText"
17 | @select="onSearchAction"
18 | @keyup.enter.native.exact="onSearchAction"
19 | @keyup.enter.native.shift="onSearchAction($event, true)"
20 | )
21 | el-dropdown(
22 | slot="prefix"
23 | trigger="click"
24 | placement="top-start"
25 | @command="onEngineChangeAction"
26 | )
27 | i.icon-search(:class="`icon-search--${activeEngineName}`")
28 | el-dropdown-menu(slot="dropdown")
29 | el-dropdown-item(
30 | v-for="item in searchEngines"
31 | :key="item.valuw"
32 | :command="item"
33 | ) {{$t(item.name)}}
34 |
35 | .suggestion(slot-scope="props")
36 | .suggestion__search(v-if="props.item.search") {{props.item.name}}
37 | .suggestion__url(v-else-if="props.item.url") {{props.item.name}}
38 | .suggestion__word(v-else) {{props.item.name}}
39 |
40 | el-button(slot="append" icon="el-icon-search" @click="onSearchAction")
41 |
42 |
43 |
44 |
189 |
190 |
193 |
--------------------------------------------------------------------------------
/src/views/main.vue:
--------------------------------------------------------------------------------
1 |
2 | .main
3 | .main-aside(
4 | :class="{'main-aside--show': config.showBookmark, 'main-aside--collapse': config.collapseBookmark}"
5 | )
6 | bookmark(
7 | :collapseBookmark="config.collapseBookmark"
8 | @tap="onBookmarkTapAction"
9 | @add="onBookmarkAddAction"
10 | @edit="onBookmarkEditAction"
11 | @remove="onBookmarkRemoveAction"
12 | )
13 |
14 | .main-content
15 | .main__header(:class="config.engineName")
16 | search-box(
17 | :engineName="config.engineName"
18 | :engineNavName="config.engineNavName"
19 | @search="onSearchAction"
20 | @update="onConfigUpdateAction"
21 | )
22 | .search-border
23 | button.btn-setting(@click="onToggleSettingAction")
24 | svg.octicon.oction-x(v-html="octicons.x.path" v-if="config.showSetting")
25 | svg.octicon.oction-gear(v-html="octicons.gear.path" v-else)
26 |
27 | .main__trending
28 | github-trending(
29 | :lang="config.lang"
30 | :since="config.since"
31 | :type="config.type"
32 | :showBookmark="config.showBookmark"
33 | @tap="onLinkTapAction"
34 | @update="onConfigUpdateAction"
35 | )
36 |
37 | main-setting(v-model="config" @upload="onUploadAction" @import="onImportBookmarks")
38 | dialog-bookmark-edit(v-model="dialog")
39 |
40 |
41 |
192 |
193 |
194 |
--------------------------------------------------------------------------------
/src/views/components/github-trending.vue:
--------------------------------------------------------------------------------
1 |
2 | iscroll-view.github-trending(
3 | :scrollerClass="{scroller: true}"
4 | :options="{mouseWheel: true}"
5 | ref="scrollView"
6 | )
7 | .github-trending__title
8 | .select
9 | el-select(v-model="query.since")
10 | el-option(:label="$t('Today')" value="daily")
11 | el-option(:label="$t('ThisWeek')" value="weekly")
12 | el-option(:label="$t('ThisMonth')" value="monthly")
13 |
14 | el-select.language(
15 | multiple
16 | filterable
17 | :multiple-limit="5"
18 | v-model="query.lang"
19 | :placeholder="$t('AllLanguages')"
20 | )
21 | el-option(
22 | v-for="item in languages"
23 | :key="item.value"
24 | :value="item.value"
25 | :label="item.name"
26 | )
27 |
28 | el-radio-group(v-model="query.type" size="small")
29 | el-radio-button(label="repositories") Repositories
30 | el-radio-button(label="developers") Developers
31 |
32 | .github-trending__loading(ref="loading" v-show="loading")
33 |
34 | .github-trending__error(v-if="fetchError")
35 | img(src="../../assets/network-error.png", alt="")
36 | p.title {{$t('NetworkErrorTitle')}}
37 | p.content {{$t('NetworkErrorContent')}}
38 | el-button(round type="primary" @click="init") {{$t('Refresh')}}
39 |
40 | .github-trending__content(v-if="!loading && !fetchError")
41 | .trending(
42 | v-for="(item, inx) in trendings"
43 | :key="inx"
44 | )
45 | el-card.repositories(
46 | v-if="query.type === 'repositories'"
47 | @click.native.exact="onLinkTapAction(item.url)"
48 | @click.native.meta="onLinkTapAction(item.url, true)"
49 | @click.native.ctrl="onLinkTapAction(item.url, true)"
50 | )
51 | .repositories__title {{item.name}}
52 | .repositories__desc {{item.description}}
53 | .repositories__meta
54 | span.color(:style="{background: item.languageColor}")
55 | span.lang {{item.language}}
56 | svg.octicon.octicon-star(v-html="octicons.star.path")
57 | span.stars {{item.stars}}
58 | .added +{{item.currentPeriodStars}}
59 | svg.octicon.octicon-repo-forked(v-html="octicons['repo-forked'].path")
60 | span.forks {{item.forks}}
61 | .repositories__built
62 | | Built by
63 | img(v-for="(item, inx) in item.builtBy" :key="inx" :src="item.avatar")
64 |
65 | el-card.developers(v-if="query.type === 'developers'")
66 | .developers__author(
67 | @click.exact="onLinkTapAction(item.url)"
68 | @click.meta="onLinkTapAction(item.url, true)"
69 | @click.ctrl="onLinkTapAction(item.url, true)"
70 | )
71 | img.avatar(:src="item.avatar")
72 | .author
73 | h2 {{item.author}}
74 | p {{item.username}}
75 |
76 | .developers__content
77 | h3(v-if="item.repo")
78 | svg.octicon.octicon-repo(v-html="octicons.repo.path")
79 | span {{item.repo.name}}
80 |
81 | p(v-if="item.repo") {{item.repo.description}}
82 |
83 |
84 |
178 |
179 |
182 |
183 |
--------------------------------------------------------------------------------
/src/views/components/github-trending.sass:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: 卓文理
3 | * @Email: 531840344@qq.com
4 | * @Date: 2018-01-20 15:33:21
5 | */
6 |
7 | @import '../../stylesheet/common.sass'
8 |
9 | .github-trending
10 | touch-action: none
11 | overflow: hidden
12 | height: 100%
13 |
14 | &__title
15 | display: flex
16 | flex-direction: row
17 | align-items: center
18 | flex-wrap: wrap
19 | padding-left: 5px
20 | padding-right: 10px
21 | .el-radio-group
22 | margin-left: 5px
23 | white-space: nowrap
24 |
25 | .select
26 | flex: 1
27 | display: flex
28 | align-items: center
29 |
30 | .el-select
31 | margin: 5px
32 | &.language
33 | display: flex
34 | &__tags
35 | position: relative
36 | display: flex
37 | max-width: none !important
38 | padding: 5px 30px 5px 2px
39 | min-width: 195px
40 | transform: none
41 | top: 0
42 | & > span
43 | display: flex
44 | & > .el-select__input
45 | margin-left: 5px
46 | & + .el-input
47 | position: absolute
48 | top: 0
49 | left: 0
50 | right: 0
51 | bottom: 0
52 | .el-input__inner
53 | height: 40px !important
54 |
55 | .scroller
56 | padding: 10px
57 |
58 | .vue-waterfall-slot
59 | padding: 10px
60 |
61 | &__content
62 | display: flex
63 | flex-direction: row
64 | flex-wrap: wrap
65 |
66 | &__loading
67 | position: relative
68 | height: 100px
69 | .el-loading-mask
70 | background: transparent
71 |
72 | &__error
73 | padding: 50px 0
74 | text-align: center
75 | .title
76 | font-size: 32px
77 | font-weight: bold
78 | color: #333333
79 | margin: 0
80 | .content
81 | font-size: 16px
82 | color: #888888
83 | margin-bottom: 20px
84 | .button
85 | height: 58px
86 | line-height: 58px
87 | width: 220px
88 | font-size: 22px
89 | border: 0
90 | border-radius: 58px
91 | outline: 0
92 | font-size: 22px
93 | color: var(--background)
94 | background: #6abcfe
95 | text-align: center
96 | cursor: pointer
97 |
98 | .trending
99 | display: block
100 | box-shadow: none
101 | padding: 10px
102 | width: 100%
103 |
104 | .octicon
105 | width: 14px
106 | height: 16px
107 | text-align: center
108 | margin-right: 4px
109 | &-repo-forked
110 | width: 10px
111 |
112 | $colors: #f5222d #fa541c #ffa940 #ACD925 #52D925 #25D952 #25D9AC #25ACD9 #2552D9 #5225D9 #AC25D9 #ff5a93
113 | $length: length($colors)
114 |
115 | @each $color in $colors
116 | $i: index($colors, $color);
117 | &:nth-child(#{$length}n + #{$i}) .developers
118 | border-bottom-color: $color
119 |
120 | .repositories
121 | position: relative
122 | .el-card__body
123 | padding: 16px 20px
124 | cursor: pointer
125 |
126 | &__title
127 | color: var(--darkBlue)
128 | font-size: 20px
129 | line-height: 30px
130 | margin-bottom: 8px
131 | @include ellipsis
132 |
133 | &__desc
134 | height: 72px
135 | font-size: 14px
136 | line-height: 24px
137 | color: var(--fontColor)
138 | word-break: break-all
139 | @include max-text(3)
140 |
141 | &__meta
142 | display: flex
143 | height: 24px
144 | align-items: center
145 | flex-direction: row
146 | margin-top: 8px
147 | font-size: 12px
148 | margin-bottom: 6px
149 | span
150 | display: inline-block
151 | .color
152 | width: 12px
153 | height: 12px
154 | border-radius: 50%
155 | margin-right: 3px
156 | .lang
157 | margin-right: 16px
158 | .stars
159 | position: relative
160 | margin-right: 16px
161 | .added
162 | position: absolute
163 | top: 0
164 | left: -8px
165 | color: var(--red)
166 | opacity: 0
167 | transition: all 0.2s ease
168 |
169 | &__built
170 | display: flex
171 | height: 24px
172 | align-items: center
173 | flex-direction: row
174 | font-size: 12px
175 | img
176 | display: inline-block
177 | width: 20px
178 | height: 20px
179 | border-radius: 3px
180 | margin-left: 4px
181 |
182 | &:hover .repositories__meta
183 | .added
184 | opacity: 1
185 | transform: translateY(-15px)
186 |
187 | .developers
188 | border-bottom: 2px solid transparent
189 | .el-card__body
190 | padding: 24px 30px 20px
191 |
192 | &__author
193 | position: relative
194 | display: flex
195 | cursor: pointer
196 | .avatar
197 | width: 60px
198 | height: 60px
199 | border-radius: 30px
200 | overflow: hidden
201 |
202 | .author
203 | display: flex
204 | flex-direction: column
205 | justify-content: center
206 | flex: 1
207 | padding-left: 16px
208 | h2
209 | margin: 0
210 | color: var(--darkBlue)
211 | font-size: 20px
212 | line-height: 30px
213 | font-weight: normal
214 | white-space: nowrap
215 | p
216 | margin: 0
217 | font-size: 14px
218 | line-height: 24px
219 | color: var(--fontColor)
220 |
221 | &__content
222 | position: relative
223 | display: flex
224 | flex-direction: column
225 | padding-top: 40px
226 | height: 112px
227 | &:before
228 | content: ''
229 | position: absolute
230 | top: 20px
231 | left: 0
232 | width: 16px
233 | height: 1px
234 | background: var(--backgroundLightest)
235 |
236 | h3
237 | display: flex
238 | flex-direction: row
239 | justify-content: center
240 | margin: 0
241 | height: 20px
242 | +max-text(1)
243 | cursor: pointer
244 | font-weight: normal
245 | margin-bottom: 12px
246 | white-space: nowrap
247 | span
248 | font-size: 16px
249 | vertical-align: top
250 | .octicon
251 | margin-top: 2px
252 |
253 | p
254 | height: 40px
255 | font-size: 12px
256 | line-height: 20px
257 | +max-text(2)
258 | color: var(--fontColor)
259 | margin: 0
260 | word-break: break-word
261 |
262 |
263 | @media only screen and (min-width: 960px)
264 | .github-trending .trending
265 | width: 50%
266 | max-width: 50%
267 | .main-aside:not(.main-aside--show), .main-aside--collapse
268 | & ~ .main-content .github-trending .trending
269 | width: 33.3%
270 |
271 | @media only screen and (min-width: 1280px)
272 | .github-trending .trending
273 | width: 33.3%
274 | .main-aside:not(.main-aside--show), .main-aside--collapse
275 | & ~ .main-content .github-trending .trending
276 | width: 25%
277 |
278 | @media only screen and (min-width: 1600px)
279 | .github-trending .trending
280 | width: 25%
281 | .main-aside:not(.main-aside--show), .main-aside--collapse
282 | & ~ .main-content .github-trending .trending
283 | width: 20%
284 |
285 | @media only screen and (min-width: 1920px)
286 | .github-trending .trending
287 | width: 20%
288 | .main-aside:not(.main-aside--show), .main-aside--collapse
289 | & ~ .main-content .github-trending .trending
290 | width: 16.66%
291 |
292 | @media only screen and (min-width: 2560px)
293 | .github-trending .trending
294 | width: 16.66%
295 | .main-aside:not(.main-aside--show), .main-aside--collapse
296 | & ~ .main-content .github-trending .trending
297 | width: 14.285%
298 |
299 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Mozilla Public License Version 2.0
2 | ==================================
3 |
4 | 1. Definitions
5 | --------------
6 |
7 | 1.1. "Contributor"
8 | means each individual or legal entity that creates, contributes to
9 | the creation of, or owns Covered Software.
10 |
11 | 1.2. "Contributor Version"
12 | means the combination of the Contributions of others (if any) used
13 | by a Contributor and that particular Contributor's Contribution.
14 |
15 | 1.3. "Contribution"
16 | means Covered Software of a particular Contributor.
17 |
18 | 1.4. "Covered Software"
19 | means Source Code Form to which the initial Contributor has attached
20 | the notice in Exhibit A, the Executable Form of such Source Code
21 | Form, and Modifications of such Source Code Form, in each case
22 | including portions thereof.
23 |
24 | 1.5. "Incompatible With Secondary Licenses"
25 | means
26 |
27 | (a) that the initial Contributor has attached the notice described
28 | in Exhibit B to the Covered Software; or
29 |
30 | (b) that the Covered Software was made available under the terms of
31 | version 1.1 or earlier of the License, but not also under the
32 | terms of a Secondary License.
33 |
34 | 1.6. "Executable Form"
35 | means any form of the work other than Source Code Form.
36 |
37 | 1.7. "Larger Work"
38 | means a work that combines Covered Software with other material, in
39 | a separate file or files, that is not Covered Software.
40 |
41 | 1.8. "License"
42 | means this document.
43 |
44 | 1.9. "Licensable"
45 | means having the right to grant, to the maximum extent possible,
46 | whether at the time of the initial grant or subsequently, any and
47 | all of the rights conveyed by this License.
48 |
49 | 1.10. "Modifications"
50 | means any of the following:
51 |
52 | (a) any file in Source Code Form that results from an addition to,
53 | deletion from, or modification of the contents of Covered
54 | Software; or
55 |
56 | (b) any new file in Source Code Form that contains any Covered
57 | Software.
58 |
59 | 1.11. "Patent Claims" of a Contributor
60 | means any patent claim(s), including without limitation, method,
61 | process, and apparatus claims, in any patent Licensable by such
62 | Contributor that would be infringed, but for the grant of the
63 | License, by the making, using, selling, offering for sale, having
64 | made, import, or transfer of either its Contributions or its
65 | Contributor Version.
66 |
67 | 1.12. "Secondary License"
68 | means either the GNU General Public License, Version 2.0, the GNU
69 | Lesser General Public License, Version 2.1, the GNU Affero General
70 | Public License, Version 3.0, or any later versions of those
71 | licenses.
72 |
73 | 1.13. "Source Code Form"
74 | means the form of the work preferred for making modifications.
75 |
76 | 1.14. "You" (or "Your")
77 | means an individual or a legal entity exercising rights under this
78 | License. For legal entities, "You" includes any entity that
79 | controls, is controlled by, or is under common control with You. For
80 | purposes of this definition, "control" means (a) the power, direct
81 | or indirect, to cause the direction or management of such entity,
82 | whether by contract or otherwise, or (b) ownership of more than
83 | fifty percent (50%) of the outstanding shares or beneficial
84 | ownership of such entity.
85 |
86 | 2. License Grants and Conditions
87 | --------------------------------
88 |
89 | 2.1. Grants
90 |
91 | Each Contributor hereby grants You a world-wide, royalty-free,
92 | non-exclusive license:
93 |
94 | (a) under intellectual property rights (other than patent or trademark)
95 | Licensable by such Contributor to use, reproduce, make available,
96 | modify, display, perform, distribute, and otherwise exploit its
97 | Contributions, either on an unmodified basis, with Modifications, or
98 | as part of a Larger Work; and
99 |
100 | (b) under Patent Claims of such Contributor to make, use, sell, offer
101 | for sale, have made, import, and otherwise transfer either its
102 | Contributions or its Contributor Version.
103 |
104 | 2.2. Effective Date
105 |
106 | The licenses granted in Section 2.1 with respect to any Contribution
107 | become effective for each Contribution on the date the Contributor first
108 | distributes such Contribution.
109 |
110 | 2.3. Limitations on Grant Scope
111 |
112 | The licenses granted in this Section 2 are the only rights granted under
113 | this License. No additional rights or licenses will be implied from the
114 | distribution or licensing of Covered Software under this License.
115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a
116 | Contributor:
117 |
118 | (a) for any code that a Contributor has removed from Covered Software;
119 | or
120 |
121 | (b) for infringements caused by: (i) Your and any other third party's
122 | modifications of Covered Software, or (ii) the combination of its
123 | Contributions with other software (except as part of its Contributor
124 | Version); or
125 |
126 | (c) under Patent Claims infringed by Covered Software in the absence of
127 | its Contributions.
128 |
129 | This License does not grant any rights in the trademarks, service marks,
130 | or logos of any Contributor (except as may be necessary to comply with
131 | the notice requirements in Section 3.4).
132 |
133 | 2.4. Subsequent Licenses
134 |
135 | No Contributor makes additional grants as a result of Your choice to
136 | distribute the Covered Software under a subsequent version of this
137 | License (see Section 10.2) or under the terms of a Secondary License (if
138 | permitted under the terms of Section 3.3).
139 |
140 | 2.5. Representation
141 |
142 | Each Contributor represents that the Contributor believes its
143 | Contributions are its original creation(s) or it has sufficient rights
144 | to grant the rights to its Contributions conveyed by this License.
145 |
146 | 2.6. Fair Use
147 |
148 | This License is not intended to limit any rights You have under
149 | applicable copyright doctrines of fair use, fair dealing, or other
150 | equivalents.
151 |
152 | 2.7. Conditions
153 |
154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
155 | in Section 2.1.
156 |
157 | 3. Responsibilities
158 | -------------------
159 |
160 | 3.1. Distribution of Source Form
161 |
162 | All distribution of Covered Software in Source Code Form, including any
163 | Modifications that You create or to which You contribute, must be under
164 | the terms of this License. You must inform recipients that the Source
165 | Code Form of the Covered Software is governed by the terms of this
166 | License, and how they can obtain a copy of this License. You may not
167 | attempt to alter or restrict the recipients' rights in the Source Code
168 | Form.
169 |
170 | 3.2. Distribution of Executable Form
171 |
172 | If You distribute Covered Software in Executable Form then:
173 |
174 | (a) such Covered Software must also be made available in Source Code
175 | Form, as described in Section 3.1, and You must inform recipients of
176 | the Executable Form how they can obtain a copy of such Source Code
177 | Form by reasonable means in a timely manner, at a charge no more
178 | than the cost of distribution to the recipient; and
179 |
180 | (b) You may distribute such Executable Form under the terms of this
181 | License, or sublicense it under different terms, provided that the
182 | license for the Executable Form does not attempt to limit or alter
183 | the recipients' rights in the Source Code Form under this License.
184 |
185 | 3.3. Distribution of a Larger Work
186 |
187 | You may create and distribute a Larger Work under terms of Your choice,
188 | provided that You also comply with the requirements of this License for
189 | the Covered Software. If the Larger Work is a combination of Covered
190 | Software with a work governed by one or more Secondary Licenses, and the
191 | Covered Software is not Incompatible With Secondary Licenses, this
192 | License permits You to additionally distribute such Covered Software
193 | under the terms of such Secondary License(s), so that the recipient of
194 | the Larger Work may, at their option, further distribute the Covered
195 | Software under the terms of either this License or such Secondary
196 | License(s).
197 |
198 | 3.4. Notices
199 |
200 | You may not remove or alter the substance of any license notices
201 | (including copyright notices, patent notices, disclaimers of warranty,
202 | or limitations of liability) contained within the Source Code Form of
203 | the Covered Software, except that You may alter any license notices to
204 | the extent required to remedy known factual inaccuracies.
205 |
206 | 3.5. Application of Additional Terms
207 |
208 | You may choose to offer, and to charge a fee for, warranty, support,
209 | indemnity or liability obligations to one or more recipients of Covered
210 | Software. However, You may do so only on Your own behalf, and not on
211 | behalf of any Contributor. You must make it absolutely clear that any
212 | such warranty, support, indemnity, or liability obligation is offered by
213 | You alone, and You hereby agree to indemnify every Contributor for any
214 | liability incurred by such Contributor as a result of warranty, support,
215 | indemnity or liability terms You offer. You may include additional
216 | disclaimers of warranty and limitations of liability specific to any
217 | jurisdiction.
218 |
219 | 4. Inability to Comply Due to Statute or Regulation
220 | ---------------------------------------------------
221 |
222 | If it is impossible for You to comply with any of the terms of this
223 | License with respect to some or all of the Covered Software due to
224 | statute, judicial order, or regulation then You must: (a) comply with
225 | the terms of this License to the maximum extent possible; and (b)
226 | describe the limitations and the code they affect. Such description must
227 | be placed in a text file included with all distributions of the Covered
228 | Software under this License. Except to the extent prohibited by statute
229 | or regulation, such description must be sufficiently detailed for a
230 | recipient of ordinary skill to be able to understand it.
231 |
232 | 5. Termination
233 | --------------
234 |
235 | 5.1. The rights granted under this License will terminate automatically
236 | if You fail to comply with any of its terms. However, if You become
237 | compliant, then the rights granted under this License from a particular
238 | Contributor are reinstated (a) provisionally, unless and until such
239 | Contributor explicitly and finally terminates Your grants, and (b) on an
240 | ongoing basis, if such Contributor fails to notify You of the
241 | non-compliance by some reasonable means prior to 60 days after You have
242 | come back into compliance. Moreover, Your grants from a particular
243 | Contributor are reinstated on an ongoing basis if such Contributor
244 | notifies You of the non-compliance by some reasonable means, this is the
245 | first time You have received notice of non-compliance with this License
246 | from such Contributor, and You become compliant prior to 30 days after
247 | Your receipt of the notice.
248 |
249 | 5.2. If You initiate litigation against any entity by asserting a patent
250 | infringement claim (excluding declaratory judgment actions,
251 | counter-claims, and cross-claims) alleging that a Contributor Version
252 | directly or indirectly infringes any patent, then the rights granted to
253 | You by any and all Contributors for the Covered Software under Section
254 | 2.1 of this License shall terminate.
255 |
256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all
257 | end user license agreements (excluding distributors and resellers) which
258 | have been validly granted by You or Your distributors under this License
259 | prior to termination shall survive termination.
260 |
261 | ************************************************************************
262 | * *
263 | * 6. Disclaimer of Warranty *
264 | * ------------------------- *
265 | * *
266 | * Covered Software is provided under this License on an "as is" *
267 | * basis, without warranty of any kind, either expressed, implied, or *
268 | * statutory, including, without limitation, warranties that the *
269 | * Covered Software is free of defects, merchantable, fit for a *
270 | * particular purpose or non-infringing. The entire risk as to the *
271 | * quality and performance of the Covered Software is with You. *
272 | * Should any Covered Software prove defective in any respect, You *
273 | * (not any Contributor) assume the cost of any necessary servicing, *
274 | * repair, or correction. This disclaimer of warranty constitutes an *
275 | * essential part of this License. No use of any Covered Software is *
276 | * authorized under this License except under this disclaimer. *
277 | * *
278 | ************************************************************************
279 |
280 | ************************************************************************
281 | * *
282 | * 7. Limitation of Liability *
283 | * -------------------------- *
284 | * *
285 | * Under no circumstances and under no legal theory, whether tort *
286 | * (including negligence), contract, or otherwise, shall any *
287 | * Contributor, or anyone who distributes Covered Software as *
288 | * permitted above, be liable to You for any direct, indirect, *
289 | * special, incidental, or consequential damages of any character *
290 | * including, without limitation, damages for lost profits, loss of *
291 | * goodwill, work stoppage, computer failure or malfunction, or any *
292 | * and all other commercial damages or losses, even if such party *
293 | * shall have been informed of the possibility of such damages. This *
294 | * limitation of liability shall not apply to liability for death or *
295 | * personal injury resulting from such party's negligence to the *
296 | * extent applicable law prohibits such limitation. Some *
297 | * jurisdictions do not allow the exclusion or limitation of *
298 | * incidental or consequential damages, so this exclusion and *
299 | * limitation may not apply to You. *
300 | * *
301 | ************************************************************************
302 |
303 | 8. Litigation
304 | -------------
305 |
306 | Any litigation relating to this License may be brought only in the
307 | courts of a jurisdiction where the defendant maintains its principal
308 | place of business and such litigation shall be governed by laws of that
309 | jurisdiction, without reference to its conflict-of-law provisions.
310 | Nothing in this Section shall prevent a party's ability to bring
311 | cross-claims or counter-claims.
312 |
313 | 9. Miscellaneous
314 | ----------------
315 |
316 | This License represents the complete agreement concerning the subject
317 | matter hereof. If any provision of this License is held to be
318 | unenforceable, such provision shall be reformed only to the extent
319 | necessary to make it enforceable. Any law or regulation which provides
320 | that the language of a contract shall be construed against the drafter
321 | shall not be used to construe this License against a Contributor.
322 |
323 | 10. Versions of the License
324 | ---------------------------
325 |
326 | 10.1. New Versions
327 |
328 | Mozilla Foundation is the license steward. Except as provided in Section
329 | 10.3, no one other than the license steward has the right to modify or
330 | publish new versions of this License. Each version will be given a
331 | distinguishing version number.
332 |
333 | 10.2. Effect of New Versions
334 |
335 | You may distribute the Covered Software under the terms of the version
336 | of the License under which You originally received the Covered Software,
337 | or under the terms of any subsequent version published by the license
338 | steward.
339 |
340 | 10.3. Modified Versions
341 |
342 | If you create software not governed by this License, and you want to
343 | create a new license for such software, you may create and use a
344 | modified version of this License if you rename the license and remove
345 | any references to the name of the license steward (except to note that
346 | such modified license differs from this License).
347 |
348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary
349 | Licenses
350 |
351 | If You choose to distribute Source Code Form that is Incompatible With
352 | Secondary Licenses under the terms of this version of the License, the
353 | notice described in Exhibit B of this License must be attached.
354 |
355 | Exhibit A - Source Code Form License Notice
356 | -------------------------------------------
357 |
358 | This Source Code Form is subject to the terms of the Mozilla Public
359 | License, v. 2.0. If a copy of the MPL was not distributed with this
360 | file, You can obtain one at http://mozilla.org/MPL/2.0/.
361 |
362 | If it is not possible or desirable to put the notice in a particular
363 | file, then You may include the notice in a location (such as a LICENSE
364 | file in a relevant directory) where a recipient would be likely to look
365 | for such a notice.
366 |
367 | You may add additional accurate notices of copyright ownership.
368 |
369 | Exhibit B - "Incompatible With Secondary Licenses" Notice
370 | ---------------------------------------------------------
371 |
372 | This Source Code Form is "Incompatible With Secondary Licenses", as
373 | defined by the Mozilla Public License, v. 2.0.
374 |
--------------------------------------------------------------------------------
/src/services/languages.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: 卓文理
3 | * @Email: 531840344@qq.com
4 | * @Date: 2018-01-20 18:33:18
5 | */
6 |
7 | 'use strict';
8 |
9 | const languages = [
10 | {
11 | name: 'Mercury',
12 | value: 'Mercury',
13 | color: '#ff2b2b',
14 | },
15 | {
16 | name: 'PureBasic',
17 | value: 'PureBasic',
18 | color: '#5a6986',
19 | },
20 | {
21 | name: 'Objective C++',
22 | value: 'Objective-C++',
23 | color: '#6866fb',
24 | },
25 | {
26 | name: 'Self',
27 | value: 'Self',
28 | color: '#0579aa',
29 | },
30 | {
31 | name: 'edn',
32 | value: 'edn',
33 | color: '#db5855',
34 | },
35 | {
36 | name: 'NewLisp',
37 | value: 'NewLisp',
38 | color: '#87AED7',
39 | },
40 | {
41 | name: 'Jupyter Notebook',
42 | value: 'Jupyter Notebook',
43 | color: '#DA5B0B',
44 | },
45 | {
46 | name: 'Rebol',
47 | value: 'Rebol',
48 | color: '#358a5b',
49 | },
50 | {
51 | name: 'Frege',
52 | value: 'Frege',
53 | color: '#00cafe',
54 | },
55 | {
56 | name: 'Dart',
57 | value: 'Dart',
58 | color: '#00B4AB',
59 | },
60 | {
61 | name: 'AspectJ',
62 | value: 'AspectJ',
63 | color: '#a957b0',
64 | },
65 | {
66 | name: 'Shell',
67 | value: 'Shell',
68 | color: '#89e051',
69 | },
70 | {
71 | name: 'Web Ontology Language',
72 | value: 'Web Ontology Language',
73 | color: '#9cc9dd',
74 | },
75 | {
76 | name: 'xBase',
77 | value: 'xBase',
78 | color: '#403a40',
79 | },
80 | {
81 | name: 'Eiffel',
82 | value: 'Eiffel',
83 | color: '#946d57',
84 | },
85 | {
86 | name: 'Nix',
87 | value: 'Nix',
88 | color: '#7e7eff',
89 | },
90 | {
91 | name: 'RAML',
92 | value: 'RAML',
93 | color: '#77d9fb',
94 | },
95 | {
96 | name: 'MTML',
97 | value: 'MTML',
98 | color: '#b7e1f4',
99 | },
100 | {
101 | name: 'Racket',
102 | value: 'Racket',
103 | color: '#22228f',
104 | },
105 | {
106 | name: 'Elixir',
107 | value: 'Elixir',
108 | color: '#6e4a7e',
109 | },
110 | {
111 | name: 'SAS',
112 | value: 'SAS',
113 | color: '#B34936',
114 | },
115 | {
116 | name: 'Agda',
117 | value: 'Agda',
118 | color: '#315665',
119 | },
120 | {
121 | name: 'wisp',
122 | value: 'wisp',
123 | color: '#7582D1',
124 | },
125 | {
126 | name: 'D',
127 | value: 'D',
128 | color: '#ba595e',
129 | },
130 | {
131 | name: 'Kotlin',
132 | value: 'Kotlin',
133 | color: '#F18E33',
134 | },
135 | {
136 | name: 'Opal',
137 | value: 'Opal',
138 | color: '#f7ede0',
139 | },
140 | {
141 | name: 'Crystal',
142 | value: 'Crystal',
143 | color: '#776791',
144 | },
145 | {
146 | name: 'Objective C',
147 | value: 'Objective-C',
148 | color: '#438eff',
149 | },
150 | {
151 | name: 'Oz',
152 | value: 'Oz',
153 | color: '#fab738',
154 | },
155 | {
156 | name: 'Mirah',
157 | value: 'Mirah',
158 | color: '#c7a938',
159 | },
160 | {
161 | name: 'Objective J',
162 | value: 'Objective-J',
163 | color: '#ff0c5a',
164 | },
165 | {
166 | name: 'Gosu',
167 | value: 'Gosu',
168 | color: '#82937f',
169 | },
170 | {
171 | name: 'FreeMarker',
172 | value: 'FreeMarker',
173 | color: '#0050b2',
174 | },
175 | {
176 | name: 'Component Pascal',
177 | value: 'Component Pascal',
178 | color: '#b0ce4e',
179 | },
180 | {
181 | name: 'Arc',
182 | value: 'Arc',
183 | color: '#aa2afe',
184 | },
185 | {
186 | name: 'Brainfuck',
187 | value: 'Brainfuck',
188 | color: '#2F2530',
189 | },
190 | {
191 | name: 'Nit',
192 | value: 'Nit',
193 | color: '#009917',
194 | },
195 | {
196 | name: 'APL',
197 | value: 'APL',
198 | color: '#5A8164',
199 | },
200 | {
201 | name: 'Go',
202 | value: 'Go',
203 | color: '#375eab',
204 | },
205 | {
206 | name: 'Visual Basic',
207 | value: 'Visual Basic',
208 | color: '#945db7',
209 | },
210 | {
211 | name: 'PHP',
212 | value: 'PHP',
213 | color: '#4F5D95',
214 | },
215 | {
216 | name: 'Cirru',
217 | value: 'Cirru',
218 | color: '#ccccff',
219 | },
220 | {
221 | name: 'SQF',
222 | value: 'SQF',
223 | color: '#3F3F3F',
224 | },
225 | {
226 | name: 'Glyph',
227 | value: 'Glyph',
228 | color: '#e4cc98',
229 | },
230 | {
231 | name: 'Java',
232 | value: 'Java',
233 | color: '#b07219',
234 | },
235 | {
236 | name: 'MAXScript',
237 | value: 'MAXScript',
238 | color: '#00a6a6',
239 | },
240 | {
241 | name: 'Scala',
242 | value: 'Scala',
243 | color: '#DC322F',
244 | },
245 | {
246 | name: 'Makefile',
247 | value: 'Makefile',
248 | color: '#427819',
249 | },
250 | {
251 | name: 'ColdFusion',
252 | value: 'ColdFusion',
253 | color: '#ed2cd6',
254 | },
255 | {
256 | name: 'Perl',
257 | value: 'Perl',
258 | color: '#0298c3',
259 | },
260 | {
261 | name: 'Lua',
262 | value: 'Lua',
263 | color: '#000080',
264 | },
265 | {
266 | name: 'Vue',
267 | value: 'Vue',
268 | color: '#2c3e50',
269 | },
270 | {
271 | name: 'Verilog',
272 | value: 'Verilog',
273 | color: '#b2b7f8',
274 | },
275 | {
276 | name: 'Factor',
277 | value: 'Factor',
278 | color: '#636746',
279 | },
280 | {
281 | name: 'Haxe',
282 | value: 'Haxe',
283 | color: '#df7900',
284 | },
285 | {
286 | name: 'Pure Data',
287 | value: 'Pure Data',
288 | color: '#91de79',
289 | },
290 | {
291 | name: 'Forth',
292 | value: 'Forth',
293 | color: '#341708',
294 | },
295 | {
296 | name: 'Red',
297 | value: 'Red',
298 | color: '#ee0000',
299 | },
300 | {
301 | name: 'Hy',
302 | value: 'Hy',
303 | color: '#7790B2',
304 | },
305 | {
306 | name: 'Volt',
307 | value: 'Volt',
308 | color: '#1F1F1F',
309 | },
310 | {
311 | name: 'LSL',
312 | value: 'LSL',
313 | color: '#3d9970',
314 | },
315 | {
316 | name: 'eC',
317 | value: 'eC',
318 | color: '#913960',
319 | },
320 | {
321 | name: 'CoffeeScript',
322 | value: 'CoffeeScript',
323 | color: '#244776',
324 | },
325 | {
326 | name: 'Lex',
327 | value: 'Lex',
328 | color: '#DBCA00',
329 | },
330 | {
331 | name: 'API Blueprint',
332 | value: 'API Blueprint',
333 | color: '#2ACCA8',
334 | },
335 | {
336 | name: 'Swift',
337 | value: 'Swift',
338 | color: '#ffac45',
339 | },
340 | {
341 | name: 'C',
342 | value: 'C',
343 | color: '#555555',
344 | },
345 | {
346 | name: 'AutoHotkey',
347 | value: 'AutoHotkey',
348 | color: '#6594b9',
349 | },
350 | {
351 | name: 'Isabelle',
352 | value: 'Isabelle',
353 | color: '#FEFE00',
354 | },
355 | {
356 | name: 'Metal',
357 | value: 'Metal',
358 | color: '#8f14e9',
359 | },
360 | {
361 | name: 'Clarion',
362 | value: 'Clarion',
363 | color: '#db901e',
364 | },
365 | {
366 | name: 'JSONiq',
367 | value: 'JSONiq',
368 | color: '#40d47e',
369 | },
370 | {
371 | name: 'Boo',
372 | value: 'Boo',
373 | color: '#d4bec1',
374 | },
375 | {
376 | name: 'AutoIt',
377 | value: 'AutoIt',
378 | color: '#1C3552',
379 | },
380 | {
381 | name: 'Clojure',
382 | value: 'Clojure',
383 | color: '#db5855',
384 | },
385 | {
386 | name: 'Rust',
387 | value: 'Rust',
388 | color: '#dea584',
389 | },
390 | {
391 | name: 'Prolog',
392 | value: 'Prolog',
393 | color: '#74283c',
394 | },
395 | {
396 | name: 'SourcePawn',
397 | value: 'SourcePawn',
398 | color: '#5c7611',
399 | },
400 | {
401 | name: 'AMPL',
402 | value: 'AMPL',
403 | color: '#E6EFBB',
404 | },
405 | {
406 | name: 'FORTRAN',
407 | value: 'FORTRAN',
408 | color: '#4d41b1',
409 | },
410 | {
411 | name: 'ANTLR',
412 | value: 'ANTLR',
413 | color: '#9DC3FF',
414 | },
415 | {
416 | name: 'Harbour',
417 | value: 'Harbour',
418 | color: '#0e60e3',
419 | },
420 | {
421 | name: 'Tcl',
422 | value: 'Tcl',
423 | color: '#e4cc98',
424 | },
425 | {
426 | name: 'BlitzMax',
427 | value: 'BlitzMax',
428 | color: '#cd6400',
429 | },
430 | {
431 | name: 'PigLatin',
432 | value: 'PigLatin',
433 | color: '#fcd7de',
434 | },
435 | {
436 | name: 'Lasso',
437 | value: 'Lasso',
438 | color: '#999999',
439 | },
440 | {
441 | name: 'ECL',
442 | value: 'ECL',
443 | color: '#8a1267',
444 | },
445 | {
446 | name: 'VHDL',
447 | value: 'VHDL',
448 | color: '#adb2cb',
449 | },
450 | {
451 | name: 'Elm',
452 | value: 'Elm',
453 | color: '#60B5CC',
454 | },
455 | {
456 | name: 'Propeller Spin',
457 | value: 'Propeller Spin',
458 | color: '#7fa2a7',
459 | },
460 | {
461 | name: 'X10',
462 | value: 'X10',
463 | color: '#4B6BEF',
464 | },
465 | {
466 | name: 'IDL',
467 | value: 'IDL',
468 | color: '#a3522f',
469 | },
470 | {
471 | name: 'ATS',
472 | value: 'ATS',
473 | color: '#1ac620',
474 | },
475 | {
476 | name: 'Ada',
477 | value: 'Ada',
478 | color: '#02f88c',
479 | },
480 | {
481 | name: 'Nu',
482 | value: 'Nu',
483 | color: '#c9df40',
484 | },
485 | {
486 | name: 'LFE',
487 | value: 'LFE',
488 | color: '#004200',
489 | },
490 | {
491 | name: 'SuperCollider',
492 | value: 'SuperCollider',
493 | color: '#46390b',
494 | },
495 | {
496 | name: 'Oxygene',
497 | value: 'Oxygene',
498 | color: '#cdd0e3',
499 | },
500 | {
501 | name: 'ASP',
502 | value: 'ASP',
503 | color: '#6a40fd',
504 | },
505 | {
506 | name: 'Assembly',
507 | value: 'Assembly',
508 | color: '#6E4C13',
509 | },
510 | {
511 | name: 'Gnuplot',
512 | value: 'Gnuplot',
513 | color: '#f0a9f0',
514 | },
515 | {
516 | name: 'JFlex',
517 | value: 'JFlex',
518 | color: '#DBCA00',
519 | },
520 | {
521 | name: 'NetLinx',
522 | value: 'NetLinx',
523 | color: '#0aa0ff',
524 | },
525 | {
526 | name: 'Turing',
527 | value: 'Turing',
528 | color: '#45f715',
529 | },
530 | {
531 | name: 'Vala',
532 | value: 'Vala',
533 | color: '#fbe5cd',
534 | },
535 | {
536 | name: 'Processing',
537 | value: 'Processing',
538 | color: '#0096D8',
539 | },
540 | {
541 | name: 'Arduino',
542 | value: 'Arduino',
543 | color: '#bd79d1',
544 | },
545 | {
546 | name: 'FLUX',
547 | value: 'FLUX',
548 | color: '#88ccff',
549 | },
550 | {
551 | name: 'NetLogo',
552 | value: 'NetLogo',
553 | color: '#ff6375',
554 | },
555 | {
556 | name: 'C#',
557 | value: 'C#',
558 | color: '#178600',
559 | },
560 | {
561 | name: 'Emacs Lisp',
562 | value: 'Emacs Lisp',
563 | color: '#c065db',
564 | },
565 | {
566 | name: 'Stan',
567 | value: 'Stan',
568 | color: '#b2011d',
569 | },
570 | {
571 | name: 'SaltStack',
572 | value: 'SaltStack',
573 | color: '#646464',
574 | },
575 | {
576 | name: 'QML',
577 | value: 'QML',
578 | color: '#44a51c',
579 | },
580 | {
581 | name: 'Pike',
582 | value: 'Pike',
583 | color: '#005390',
584 | },
585 | {
586 | name: 'LOLCODE',
587 | value: 'LOLCODE',
588 | color: '#cc9900',
589 | },
590 | {
591 | name: 'ooc',
592 | value: 'ooc',
593 | color: '#b0b77e',
594 | },
595 | {
596 | name: 'Handlebars',
597 | value: 'Handlebars',
598 | color: '#01a9d6',
599 | },
600 | {
601 | name: 'J',
602 | value: 'J',
603 | color: '#9EEDFF',
604 | },
605 | {
606 | name: 'Mask',
607 | value: 'Mask',
608 | color: '#f97732',
609 | },
610 | {
611 | name: 'EmberScript',
612 | value: 'EmberScript',
613 | color: '#FFF4F3',
614 | },
615 | {
616 | name: 'TeX',
617 | value: 'TeX',
618 | color: '#3D6117',
619 | },
620 | {
621 | name: 'Nemerle',
622 | value: 'Nemerle',
623 | color: '#3d3c6e',
624 | },
625 | {
626 | name: 'KRL',
627 | value: 'KRL',
628 | color: '#28431f',
629 | },
630 | {
631 | name: 'Ren\'Py',
632 | value: 'Ren\'Py',
633 | color: '#ff7f7f',
634 | },
635 | {
636 | name: 'Unified Parallel C',
637 | value: 'Unified Parallel C',
638 | color: '#4e3617',
639 | },
640 | {
641 | name: 'Golo',
642 | value: 'Golo',
643 | color: '#88562A',
644 | },
645 | {
646 | name: 'Fancy',
647 | value: 'Fancy',
648 | color: '#7b9db4',
649 | },
650 | {
651 | name: 'OCaml',
652 | value: 'OCaml',
653 | color: '#3be133',
654 | },
655 | {
656 | name: 'Shen',
657 | value: 'Shen',
658 | color: '#120F14',
659 | },
660 | {
661 | name: 'Pascal',
662 | value: 'Pascal',
663 | color: '#b0ce4e',
664 | },
665 | {
666 | name: 'F#',
667 | value: 'F#',
668 | color: '#b845fc',
669 | },
670 | {
671 | name: 'Puppet',
672 | value: 'Puppet',
673 | color: '#302B6D',
674 | },
675 | {
676 | name: 'ActionScript',
677 | value: 'ActionScript',
678 | color: '#882B0F',
679 | },
680 | {
681 | name: 'Diff',
682 | value: 'Diff',
683 | color: '#88dddd',
684 | },
685 | {
686 | name: 'Ragel in Ruby Host',
687 | value: 'Ragel in Ruby Host',
688 | color: '#9d5200',
689 | },
690 | {
691 | name: 'Fantom',
692 | value: 'Fantom',
693 | color: '#dbded5',
694 | },
695 | {
696 | name: 'Zephir',
697 | value: 'Zephir',
698 | color: '#118f9e',
699 | },
700 | {
701 | name: 'Click',
702 | value: 'Click',
703 | color: '#E4E6F3',
704 | },
705 | {
706 | name: 'Smalltalk',
707 | value: 'Smalltalk',
708 | color: '#596706',
709 | },
710 | {
711 | name: 'DM',
712 | value: 'DM',
713 | color: '#447265',
714 | },
715 | {
716 | name: 'Ioke',
717 | value: 'Ioke',
718 | color: '#078193',
719 | },
720 | {
721 | name: 'PogoScript',
722 | value: 'PogoScript',
723 | color: '#d80074',
724 | },
725 | {
726 | name: 'LiveScript',
727 | value: 'LiveScript',
728 | color: '#499886',
729 | },
730 | {
731 | name: 'VimL',
732 | value: 'VimL',
733 | color: '#199f4b',
734 | },
735 | {
736 | name: 'PureScript',
737 | value: 'PureScript',
738 | color: '#1D222D',
739 | },
740 | {
741 | name: 'ABAP',
742 | value: 'ABAP',
743 | color: '#E8274B',
744 | },
745 | {
746 | name: 'Matlab',
747 | value: 'Matlab',
748 | color: '#bb92ac',
749 | },
750 | {
751 | name: 'Slash',
752 | value: 'Slash',
753 | color: '#007eff',
754 | },
755 | {
756 | name: 'R',
757 | value: 'R',
758 | color: '#198ce7',
759 | },
760 | {
761 | name: 'Erlang',
762 | value: 'Erlang',
763 | color: '#B83998',
764 | },
765 | {
766 | name: 'Pan',
767 | value: 'Pan',
768 | color: '#cc0000',
769 | },
770 | {
771 | name: 'LookML',
772 | value: 'LookML',
773 | color: '#652B81',
774 | },
775 | {
776 | name: 'Eagle',
777 | value: 'Eagle',
778 | color: '#814C05',
779 | },
780 | {
781 | name: 'Scheme',
782 | value: 'Scheme',
783 | color: '#1e4aec',
784 | },
785 | {
786 | name: 'PLSQL',
787 | value: 'PLSQL',
788 | color: '#dad8d8',
789 | },
790 | {
791 | name: 'Max',
792 | value: 'Max',
793 | color: '#c4a79c',
794 | },
795 | {
796 | name: 'Common Lisp',
797 | value: 'Common Lisp',
798 | color: '#3fb68b',
799 | },
800 | {
801 | name: 'Latte',
802 | value: 'Latte',
803 | color: '#A8FF97',
804 | },
805 | {
806 | name: 'XQuery',
807 | value: 'XQuery',
808 | color: '#5232e7',
809 | },
810 | {
811 | name: 'Omgrofl',
812 | value: 'Omgrofl',
813 | color: '#cabbff',
814 | },
815 | {
816 | name: 'XC',
817 | value: 'XC',
818 | color: '#99DA07',
819 | },
820 | {
821 | name: 'Nimrod',
822 | value: 'Nimrod',
823 | color: '#37775b',
824 | },
825 | {
826 | name: 'SystemVerilog',
827 | value: 'SystemVerilog',
828 | color: '#DAE1C2',
829 | },
830 | {
831 | name: 'Chapel',
832 | value: 'Chapel',
833 | color: '#8dc63f',
834 | },
835 | {
836 | name: 'Groovy',
837 | value: 'Groovy',
838 | color: '#e69f56',
839 | },
840 | {
841 | name: 'Dylan',
842 | value: 'Dylan',
843 | color: '#6c616e',
844 | },
845 | {
846 | name: 'E',
847 | value: 'E',
848 | color: '#ccce35',
849 | },
850 | {
851 | name: 'Parrot',
852 | value: 'Parrot',
853 | color: '#f3ca0a',
854 | },
855 | {
856 | name: 'Grammatical Framework',
857 | value: 'Grammatical Framework',
858 | color: '#79aa7a',
859 | },
860 | {
861 | name: 'Game Maker Language',
862 | value: 'Game Maker Language',
863 | color: '#8fb200',
864 | },
865 | {
866 | name: 'Papyrus',
867 | value: 'Papyrus',
868 | color: '#6600cc',
869 | },
870 | {
871 | name: 'Clean',
872 | value: 'Clean',
873 | color: '#3F85AF',
874 | },
875 | {
876 | name: 'Alloy',
877 | value: 'Alloy',
878 | color: '#64C800',
879 | },
880 | {
881 | name: 'Squirrel',
882 | value: 'Squirrel',
883 | color: '#800000',
884 | },
885 | {
886 | name: 'PAWN',
887 | value: 'PAWN',
888 | color: '#dbb284',
889 | },
890 | {
891 | name: 'UnrealScript',
892 | value: 'UnrealScript',
893 | color: '#a54c4d',
894 | },
895 | {
896 | name: 'Standard ML',
897 | value: 'Standard ML',
898 | color: '#dc566d',
899 | },
900 | {
901 | name: 'Slim',
902 | value: 'Slim',
903 | color: '#ff8f77',
904 | },
905 | {
906 | name: 'Perl6',
907 | value: 'Perl6',
908 | color: '#0000fb',
909 | },
910 | {
911 | name: 'Julia',
912 | value: 'Julia',
913 | color: '#a270ba',
914 | },
915 | {
916 | name: 'Haskell',
917 | value: 'Haskell',
918 | color: '#29b544',
919 | },
920 | {
921 | name: 'NCL',
922 | value: 'NCL',
923 | color: '#28431f',
924 | },
925 | {
926 | name: 'Io',
927 | value: 'Io',
928 | color: '#a9188d',
929 | },
930 | {
931 | name: 'Rouge',
932 | value: 'Rouge',
933 | color: '#cc0088',
934 | },
935 | {
936 | name: 'cpp',
937 | value: 'cpp',
938 | color: '#f34b7d',
939 | },
940 | {
941 | name: 'AGS Script',
942 | value: 'AGS Script',
943 | color: '#B9D9FF',
944 | },
945 | {
946 | name: 'Dogescript',
947 | value: 'Dogescript',
948 | color: '#cca760',
949 | },
950 | {
951 | name: 'nesC',
952 | value: 'nesC',
953 | color: '#94B0C7',
954 | },
955 | {
956 | name: 'unknown',
957 | value: 'unknown',
958 | color: '#aaa',
959 | },
960 | ].sort((a, b) => {
961 | const nameA = a.name.toUpperCase();
962 | const nameB = b.name.toUpperCase();
963 |
964 | if (nameA < nameB) {
965 | return 1;
966 | }
967 | if (nameA > nameB) {
968 | return 1;
969 | }
970 |
971 | return 0;
972 | });
973 |
974 | export default [
975 | {
976 | name: 'C++',
977 | value: 'C++',
978 | color: '#555555',
979 | },
980 | {
981 | name: 'CSS',
982 | value: 'CSS',
983 | color: '#563d7c',
984 | },
985 | {
986 | name: 'HTML',
987 | value: 'HTML',
988 | color: '#e44b23',
989 | },
990 | {
991 | name: 'JavaScript',
992 | value: 'JavaScript',
993 | color: '#f1e05a',
994 | },
995 | {
996 | name: 'Python',
997 | value: 'Python',
998 | color: '#3572A5',
999 | },
1000 | {
1001 | name: 'Ruby',
1002 | value: 'Ruby',
1003 | color: '#701516',
1004 | },
1005 | {
1006 | name: 'TypeScript',
1007 | value: 'TypeScript',
1008 | color: '#2b7489',
1009 | }
1010 | ].concat(languages);
1011 |
--------------------------------------------------------------------------------