├── github1s
├── src
│ ├── icons
│ │ ├── icon128.png
│ │ ├── icon16.png
│ │ ├── icon160.png
│ │ ├── icon38.png
│ │ └── icon48.png
│ ├── options
│ │ ├── options.js
│ │ ├── options.html
│ │ ├── options.css
│ │ └── pages.js
│ ├── manifest.json
│ ├── background
│ │ └── background.js
│ ├── js
│ │ ├── common.js
│ │ └── utils.js
│ └── content
│ │ └── content.js
├── extension.202105090813.zip
├── extension.202105261113.zip
├── extension.202108241012.zip
├── webpack.dev.js
├── .babelrc
├── webpack.options.js
├── webpack.prod.js
├── package.json
├── webpack.common.js
├── webpack.config.js
└── webpack.config.bak.js
├── LICENSE
├── .gitignore
├── README.md
└── images
└── buymeacoffee.svg
/github1s/src/icons/icon128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fhefh2015/GitHub1s_chrome_extension/HEAD/github1s/src/icons/icon128.png
--------------------------------------------------------------------------------
/github1s/src/icons/icon16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fhefh2015/GitHub1s_chrome_extension/HEAD/github1s/src/icons/icon16.png
--------------------------------------------------------------------------------
/github1s/src/icons/icon160.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fhefh2015/GitHub1s_chrome_extension/HEAD/github1s/src/icons/icon160.png
--------------------------------------------------------------------------------
/github1s/src/icons/icon38.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fhefh2015/GitHub1s_chrome_extension/HEAD/github1s/src/icons/icon38.png
--------------------------------------------------------------------------------
/github1s/src/icons/icon48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fhefh2015/GitHub1s_chrome_extension/HEAD/github1s/src/icons/icon48.png
--------------------------------------------------------------------------------
/github1s/extension.202105090813.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fhefh2015/GitHub1s_chrome_extension/HEAD/github1s/extension.202105090813.zip
--------------------------------------------------------------------------------
/github1s/extension.202105261113.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fhefh2015/GitHub1s_chrome_extension/HEAD/github1s/extension.202105261113.zip
--------------------------------------------------------------------------------
/github1s/extension.202108241012.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fhefh2015/GitHub1s_chrome_extension/HEAD/github1s/extension.202108241012.zip
--------------------------------------------------------------------------------
/github1s/src/options/options.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import Pages from './pages';
4 |
5 |
6 | ReactDOM.render(
7 | ,
8 | document.getElementById('options')
9 | );
--------------------------------------------------------------------------------
/github1s/webpack.dev.js:
--------------------------------------------------------------------------------
1 | const { merge } = require('webpack-merge');
2 | const config = require('./webpack.config.js');
3 | const ExtensionReloader = require("webpack-extension-reloader");
4 |
5 | module.exports = merge(config, {
6 | plugins: [
7 | new ExtensionReloader()
8 | ],
9 | devtool: "source-map",
10 | });
--------------------------------------------------------------------------------
/github1s/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "@babel/preset-env",
4 | "@babel/preset-react"
5 | ],
6 | "plugins": [
7 | [
8 | "import",{
9 | "libraryName":"antd",
10 | "libraryDirectory":"es",
11 | "style":"css"
12 | }],
13 | "@babel/plugin-transform-runtime",
14 | "@babel/plugin-proposal-class-properties"
15 | ]
16 | }
--------------------------------------------------------------------------------
/github1s/src/options/options.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | GitHub1s Config
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/github1s/src/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "update_url": "https://clients2.google.com/service/update2/crx",
3 | "manifest_version": 2,
4 | "homepage_url": "https://github.com/conwnet/github1s",
5 | "name": "GitHub1s",
6 | "description": "One second to read GitHub code with VS Code",
7 | "version": "0.3.8",
8 | "icons": {
9 | "16": "icons/icon16.png",
10 | "48": "icons/icon48.png",
11 | "128": "icons/icon128.png"
12 | },
13 | "browser_action": {},
14 | "options_ui": {
15 | "page": "options.html",
16 | "open_in_tab": true
17 | },
18 | "background": {
19 | "scripts": [
20 | "js/background.js"
21 | ],
22 | "persistent": true
23 | },
24 | "content_scripts": [
25 | {
26 | "matches": [
27 | "*://github.com/*"
28 | ],
29 | "js": [
30 | "js/content.js"
31 | ],
32 | "run_at": "document_end"
33 | }
34 | ],
35 | "permissions": [
36 | "storage",
37 | "contextMenus",
38 | "activeTab"
39 | ]
40 | }
--------------------------------------------------------------------------------
/github1s/src/options/options.css:
--------------------------------------------------------------------------------
1 | body {
2 | background-color: #f0f2f5 !important;
3 | }
4 |
5 | .container {
6 | padding-bottom: 60px;
7 | }
8 |
9 | .logo {
10 | width: 72px;
11 | height: 72px;
12 | background: url(../icons/icon160.png) no-repeat center center;
13 | background-size: 100% 100%;
14 | margin: 0 auto;
15 | margin-top: 40px;
16 | }
17 |
18 | .text {
19 | padding: 10px 0;
20 | font-size: 32px;
21 | color: #000;
22 | text-align: center;
23 | }
24 |
25 | .mt20 {
26 | margin-top: 20px;
27 | }
28 |
29 | .mb10 {
30 | margin-bottom: 10px;
31 | }
32 |
33 | .prview_btn {
34 | position: relative;
35 | display: inline-block;
36 | padding: 5px 16px;
37 | font-size: 14px;
38 | font-weight: 500;
39 | line-height: 20px;
40 | white-space: nowrap;
41 | vertical-align: middle;
42 | cursor: pointer;
43 | -webkit-user-select: none;
44 | -moz-user-select: none;
45 | -ms-user-select: none;
46 | user-select: none;
47 | border: 1px solid transparent;
48 | border-radius: 6px;
49 | -webkit-appearance: none;
50 | -moz-appearance: none;
51 | appearance: none;
52 | }
53 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 fhefh2015
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/github1s/webpack.options.js:
--------------------------------------------------------------------------------
1 | const { merge } = require('webpack-merge');
2 | const common = require('./webpack.common.js');
3 | const { resolve } = require('path');
4 |
5 | const HtmlWebpackPlugin = require('html-webpack-plugin');
6 | const { CleanWebpackPlugin } = require('clean-webpack-plugin');
7 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
8 | const TerserPlugin = require('terser-webpack-plugin');
9 | const CopyWebpackPlugin = require("copy-webpack-plugin");
10 | const isDev = "development" == process.env.NODE_ENV ? true : false;
11 |
12 | module.exports = merge(common, {
13 | plugins: [
14 | new MiniCssExtractPlugin({
15 | filename: 'css/[name].[contenthash:7].css',
16 | }),
17 | new HtmlWebpackPlugin({
18 | template: './src/options/options.html',
19 | filename: 'options.html',
20 | favicon: './src/icons/icon160.png',
21 | inject: 'body',
22 | chunks: ['options'],
23 | minify: {
24 | collapseWhitespace: true,
25 | removeComments: true,
26 | }
27 | }),
28 | new CopyWebpackPlugin({
29 | patterns: [
30 | { from: resolve(__dirname, 'src/icons'), to: resolve(__dirname, 'build/icons') },
31 | { from: resolve(__dirname, 'src/manifest.json'), to: resolve(__dirname, 'build') },
32 | ],
33 | }),
34 | new CleanWebpackPlugin(),
35 | ],
36 | mode: isDev ? 'development' : 'production',
37 | target: 'web',
38 | devtool: isDev ? "eval-source-map" : "source-map",
39 | devServer: {
40 | contentBase: resolve(__dirname, 'dist'),
41 | compress: true,
42 | open: false,
43 | hot: true,
44 | port: 9999,
45 | }
46 | });
--------------------------------------------------------------------------------
/github1s/webpack.prod.js:
--------------------------------------------------------------------------------
1 | const { merge } = require('webpack-merge');
2 | const common = require('./webpack.common.js');
3 | const { resolve } = require('path');
4 |
5 | const HtmlWebpackPlugin = require('html-webpack-plugin');
6 | const { CleanWebpackPlugin } = require('clean-webpack-plugin');
7 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
8 | const TerserPlugin = require('terser-webpack-plugin');
9 | const CopyWebpackPlugin = require("copy-webpack-plugin");
10 |
11 | module.exports = merge(common, {
12 | plugins: [
13 | new MiniCssExtractPlugin({
14 | filename: 'css/[name].[contenthash:7].css',
15 | }),
16 | new TerserPlugin({
17 | exclude: /node_modules/,
18 | terserOptions: {
19 | warnings: false,
20 | compress: {
21 | drop_console: true,
22 | drop_debugger: true,
23 | pure_funcs: ['console.log'] // 移除console
24 | }
25 | }
26 | }),
27 | new HtmlWebpackPlugin({
28 | template: './src/options/options.html',
29 | filename: 'options.html',
30 | favicon: './src/icons/icon160.png',
31 | inject: 'body',
32 | chunks: ['options'],
33 | minify: {
34 | collapseWhitespace: true,
35 | removeComments: true,
36 | }
37 | }),
38 | new CopyWebpackPlugin({
39 | patterns: [
40 | { from: resolve(__dirname, 'src/icons'), to: resolve(__dirname, 'build/icons') },
41 | { from: resolve(__dirname, 'src/manifest.json'), to: resolve(__dirname, 'build') },
42 | ],
43 | }),
44 | new CleanWebpackPlugin(),
45 | ],
46 | mode: 'production',
47 | // devtool: "source-map",
48 | });
--------------------------------------------------------------------------------
/github1s/src/background/background.js:
--------------------------------------------------------------------------------
1 | import { getQueryTab, getItem, getHref, setItemByKey } from '../js/utils';
2 |
3 | // chrome.browserAction.onClicked.addListener(async () => {
4 |
5 | // const tabs = await getQueryTab();
6 | // const form = await getItem("form");
7 | // const url = tabs[0]["url"];
8 |
9 | // const href = await getHref(form, url);
10 | // createTab(href);
11 | // });
12 |
13 | chrome.extension.onRequest.addListener((request) => {
14 |
15 | const { href, action } = request;
16 |
17 | console.log("chrome runtime: ", request);
18 |
19 | if (action == 'createContextMenuItem') {
20 |
21 | const { button_title, href } = request;
22 |
23 | setItemByKey("right_menu_create", 1);
24 |
25 | chrome.contextMenus.create({
26 | title: `Open with ${button_title}`,
27 | type: 'normal',
28 | contexts: ['page'],
29 | onclick: function (data) {
30 |
31 | const pageUrl = data['pageUrl'];
32 | createTab(href);
33 |
34 | },
35 | documentUrlPatterns: ['https://*.github.com/*/*']
36 | });
37 | }
38 |
39 | if (action == 'keyboard') {
40 | createTab(href);
41 | }
42 | });
43 |
44 | // chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
45 | // const { status } = changeInfo;
46 |
47 | // if (status == "complete") {
48 | // chrome.tabs.sendMessage(tabId, "url-update");
49 | // }
50 |
51 | // });
52 |
53 |
54 | async function createTab(href) {
55 |
56 | const tabs = await getQueryTab();
57 |
58 | if (tabs) {
59 | const index = tabs[0]['index'];
60 | chrome.tabs.create({
61 | index: index + 1,
62 | url: href
63 | });
64 | } else {
65 | chrome.tabs.create({
66 | url: href
67 | });
68 | }
69 | }
--------------------------------------------------------------------------------
/github1s/src/js/common.js:
--------------------------------------------------------------------------------
1 | export const validateMessages = {
2 | required: "${name} is a required field",
3 | };
4 |
5 | export const checkBoxItems = [
6 | {
7 | name: "new_tab",
8 | desc: "Open with new tab",
9 | note: "",
10 | },
11 | {
12 | name: "right_menu",
13 | desc: "Open with Right-click menu",
14 | note: "This feature requires a browser restart",
15 | },
16 | {
17 | name: "is_private",
18 | desc: "Allow use it in private repositories",
19 | note: "Please make sure your project is a private repository, otherwise the settings will not take effect"
20 | },
21 | {
22 | name: "use_keyboard",
23 | desc: "Allow use it with keyboard_shortcuts",
24 | note: "Keyboard shortcuts disabled by default"
25 | },
26 | ];
27 |
28 | export const selectBoxItems = [
29 | {
30 | name: "CodeSandbox",
31 | url: "https://codesandbox.io/s/github/",
32 | index: 0,
33 | },
34 | {
35 | name: "Github1s",
36 | url: "https://github1s.com/",
37 | index: 1,
38 | },
39 | {
40 | name: "Gitpod",
41 | url: "https://gitpod.io/#https://github.com/",
42 | index: 2,
43 | },
44 | {
45 | name: "Repl.it",
46 | url: "https://repl.it/github/",
47 | index: 3,
48 | },
49 | {
50 | name: "Vscode",
51 | url: "vscode://vscode.git/clone?url=https://github.com/",
52 | index: 4,
53 | },
54 | {
55 | name: "Stackblitz",
56 | // url: "https://githubblitz.com/",
57 | url: "https://stackblitz.com/github/",
58 | index: 5,
59 | },
60 | {
61 | name: "GitHub.Dev",
62 | url: "https://github.dev/",
63 | index: 6,
64 | }
65 | ];
66 |
67 | export const defaultSetting = {
68 | "input_url": "https://github1s.com",
69 | "button_title": "Github1s",
70 | "button_title_color": "#ffffff",
71 | "button_background_color": "#2ea44f",
72 | "check_box": {
73 | "new_tab": 1,
74 | "right_menu": 0,
75 | "is_private": 0,
76 | "use_keyboard": 0,
77 | },
78 | "web_service": 1,
79 | "keyboard_shortcuts": "alt+shift+g",
80 | };
--------------------------------------------------------------------------------
/github1s/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "github1s",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "dev": "webpack --config webpack.dev.js --mode=development --watch",
8 | "dev:options": "cross-env NODE_ENV=production webpack-dev-server --config webpack.options.js",
9 | "build": "webpack --config webpack.config.js --mode=production",
10 | "zip": "zip -r extension.$(date +%Y%m%d%H%M).zip dist/"
11 | },
12 | "author": "",
13 | "license": "ISC",
14 | "dependencies": {
15 | "antd": "^3.26.20",
16 | "hotkeys-js": "^3.8.2",
17 | "react": "^16.14.0",
18 | "react-dom": "^16.14.0"
19 | },
20 | "devDependencies": {
21 | "@babel/core": "^7.12.16",
22 | "@babel/plugin-proposal-class-properties": "^7.12.13",
23 | "@babel/plugin-syntax-jsx": "^7.12.13",
24 | "@babel/plugin-transform-runtime": "^7.12.15",
25 | "@babel/preset-env": "^7.12.16",
26 | "@babel/preset-react": "^7.12.13",
27 | "@webpack-cli/serve": "^1.3.0",
28 | "babel-core": "^6.26.3",
29 | "babel-loader": "^8.2.2",
30 | "babel-plugin-import": "^1.13.3",
31 | "clean-webpack-plugin": "^3.0.0",
32 | "copy-webpack-plugin": "^6.0.3",
33 | "core-js": "^2.6.12",
34 | "cross-env": "^7.0.3",
35 | "css-loader": "^5.0.2",
36 | "cssnano": "^4.1.10",
37 | "eslint": "^7.20.0",
38 | "eslint-config-airbnb-base": "^14.2.1",
39 | "eslint-loader": "^4.0.2",
40 | "eslint-plugin-import": "^2.22.1",
41 | "file-loader": "^6.2.0",
42 | "html-loader": "^1.3.2",
43 | "html-webpack-plugin": "4.5.2",
44 | "less-loader": "^8.0.0",
45 | "mini-css-extract-plugin": "^0.9.0",
46 | "postcss": "^8.2.6",
47 | "postcss-loader": "^4.2.0",
48 | "postcss-preset-env": "^6.7.0",
49 | "style-loader": "^2.0.0",
50 | "terser-webpack-plugin": "^5.1.1",
51 | "url-loader": "^4.1.1",
52 | "webpack": "^4.43.0",
53 | "webpack-cli": "^3.3.12",
54 | "webpack-dev-server": "3.11.2",
55 | "webpack-extension-reloader": "^1.1.4",
56 | "webpack-merge": "^5.7.3"
57 | }
58 | }
--------------------------------------------------------------------------------
/github1s/src/js/utils.js:
--------------------------------------------------------------------------------
1 | /**
2 | * r:react state data
3 | * c:chrome store data
4 | */
5 | import { checkBoxItems, defaultSetting, selectBoxItems } from './common';
6 |
7 | export function r2c(r) {
8 | let items = r["check_box"];
9 |
10 | if (typeof items === "undefined") {
11 | throw Error("check_box undefined");
12 | }
13 |
14 | let temp = {};
15 |
16 | if (typeof items !== 'undefined') {
17 |
18 | for (let m = 0; m < checkBoxItems.length; m++) {
19 | temp[checkBoxItems[m]["name"]] = 0;
20 | }
21 |
22 | for (let n = 0; n < items.length; n++) {
23 | temp[items[n]] = 1;
24 | }
25 | }
26 |
27 | return Object.assign({}, r, {
28 | "check_box": temp
29 | });
30 | }
31 |
32 | export function c2r(c) {
33 | let items = c["check_box"];
34 | if (typeof items === "undefined") {
35 | throw Error("check_box undefined");
36 | }
37 |
38 | let temp = [];
39 |
40 | if (typeof items !== 'undefined') {
41 | for (let i in items) {
42 | if (items[i] == 1) {
43 | temp.push(i);
44 | }
45 | }
46 | }
47 |
48 | return Object.assign({}, c, {
49 | "check_box": temp
50 | });
51 | }
52 |
53 | export function setItemByKey(key, value) {
54 | let obj = {};
55 | obj[key] = value;
56 | chrome.storage.sync.set(obj);
57 | chrome.storage.local.set(obj);
58 | }
59 |
60 | export function getItem(obj) {
61 | return new Promise(function (resolve, reject) {
62 | chrome.storage.sync.get(obj, function (result) {
63 | if (result) {
64 | resolve(result[obj]);
65 | }
66 | reject(false);
67 | });
68 | });
69 | }
70 |
71 | export async function fixOldVersion() {
72 | let form = await getItem('form');
73 |
74 | if (form == undefined) {
75 | formReset();
76 | return defaultSetting;
77 | }
78 |
79 | return Object.assign({}, defaultSetting, form);
80 | }
81 |
82 | export function formReset() {
83 | setItemByKey("form", defaultSetting);
84 | setItemByKey("right_menu_create", 0);
85 | }
86 |
87 | export function getQueryTab() {
88 | return new Promise(function (resolve, reject) {
89 | chrome.tabs.query({
90 | active: true,
91 | currentWindow: true
92 | }, (tabs) => {
93 | if (tabs) {
94 | resolve(tabs);
95 | } else {
96 | reject(false);
97 | }
98 | });
99 | });
100 | }
101 |
102 | export function getHref(data, siteURL, inputURL) {
103 |
104 | const url = new URL(siteURL);
105 | const path = url.pathname.split('/').slice(1).join('/');
106 | // const [userName, repository] = url.pathname.split('/').slice(1, 3);
107 |
108 | let href;
109 | const {
110 | web_service
111 | } = data;
112 |
113 | switch (web_service) {
114 | case 1:
115 | href = `${inputURL}/${path}`;
116 | break;
117 | case 0:
118 | case 2:
119 | case 3:
120 | case 4:
121 | case 5:
122 | case 6:
123 | href = `${selectBoxItems[web_service]["url"]}${path}`;
124 | break;
125 | }
126 |
127 | return href;
128 | }
129 |
130 |
131 |
132 |
133 |
--------------------------------------------------------------------------------
/github1s/src/content/content.js:
--------------------------------------------------------------------------------
1 | import hotkeys from 'hotkeys-js';
2 | import { fixOldVersion, getHref, getItem } from '../js/utils';
3 |
4 |
5 | init();
6 |
7 | function insertGitHub1sButton(setting) {
8 | const {
9 | input_url,
10 | button_title,
11 | button_title_color,
12 | button_background_color,
13 | check_box,
14 | } = setting;
15 |
16 | const localURL = window.location.href;
17 | const href = getHref(setting, localURL, input_url);
18 |
19 | const target = (check_box["new_tab"] == 1) ? "_blank" : "_self";
20 |
21 | // const insertNode = document.querySelector('.details-overlay.d-block');
22 | const insertNode = document.querySelector(".btn.d-none.d-md-block");
23 |
24 | if (insertNode) {
25 | const layoutClass = insertNode.classList.contains('ml-2') ? 'ml-2' : 'mr-2';
26 | const btn = `
27 | ${button_title}
28 | `;
29 |
30 | // insertNode.insertAdjacentHTML('afterend', btn);
31 | insertNode.insertAdjacentHTML('beforebegin', btn);
32 | }
33 | }
34 |
35 | function ensureGitHub1sButtonExists(setting) {
36 | if (!document.getElementById('github1s_kkk')) {
37 | insertGitHub1sButton(setting);
38 | }
39 | }
40 |
41 | async function init() {
42 | let setting = await fixOldVersion();
43 | const localURL = window.location.href;
44 |
45 | const {
46 | input_url,
47 | button_title,
48 | check_box,
49 | keyboard_shortcuts
50 | } = setting;
51 |
52 | const href = getHref(setting, localURL, input_url);
53 |
54 | const privateElems = document.querySelectorAll('#js-repo-pjax-container .Label');
55 | let judge_is_private = false;
56 |
57 | judge_is_private = Array.from(privateElems).some(item => {
58 | return (item.textContent.trim().toLowerCase() == "private");
59 | });
60 |
61 | if (judge_is_private) {
62 | if (check_box["is_private"] == 0) {
63 | return;
64 | }
65 | }
66 |
67 | const mutationObserver = new MutationObserver(() => ensureGitHub1sButtonExists(setting));
68 | mutationObserver.observe(document.body, { childList: true, subtree: true });
69 |
70 | if (check_box["use_keyboard"]) {
71 | const key = keyboard_shortcuts.replace(/\s/ig, "").toLowerCase();
72 | hotkeys(key, function (event, handler) {
73 | // Prevent the default refresh event under WINDOWS system
74 | event.preventDefault();
75 | chrome.extension.sendRequest({
76 | "action": "keyboard",
77 | "href": href,
78 | "key": key,
79 | });
80 | });
81 | }
82 |
83 | if (check_box["right_menu"]) {
84 | const right_menu_create = await getItem("right_menu_create");
85 |
86 | if (right_menu_create == 1) {
87 | return;
88 | } else {
89 | chrome.extension.sendRequest({
90 | "action": "createContextMenuItem",
91 | "href": href,
92 | "button_title": button_title
93 | });
94 | }
95 | }
96 | }
97 |
98 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.toptal.com/developers/gitignore/api/node,vscode,macos
3 | # Edit at https://www.toptal.com/developers/gitignore?templates=node,vscode,macos
4 |
5 | ### macOS ###
6 | # General
7 | .DS_Store
8 | .AppleDouble
9 | .LSOverride
10 |
11 | # Icon must end with two \r
12 | Icon
13 |
14 |
15 | # Thumbnails
16 | ._*
17 |
18 | # Files that might appear in the root of a volume
19 | .DocumentRevisions-V100
20 | .fseventsd
21 | .Spotlight-V100
22 | .TemporaryItems
23 | .Trashes
24 | .VolumeIcon.icns
25 | .com.apple.timemachine.donotpresent
26 |
27 | # Directories potentially created on remote AFP share
28 | .AppleDB
29 | .AppleDesktop
30 | Network Trash Folder
31 | Temporary Items
32 | .apdisk
33 |
34 | ### Node ###
35 | # Logs
36 | logs
37 | *.log
38 | npm-debug.log*
39 | yarn-debug.log*
40 | yarn-error.log*
41 | lerna-debug.log*
42 |
43 | # Diagnostic reports (https://nodejs.org/api/report.html)
44 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
45 |
46 | # Runtime data
47 | pids
48 | *.pid
49 | *.seed
50 | *.pid.lock
51 |
52 | # Directory for instrumented libs generated by jscoverage/JSCover
53 | lib-cov
54 |
55 | # Coverage directory used by tools like istanbul
56 | coverage
57 | *.lcov
58 |
59 | # nyc test coverage
60 | .nyc_output
61 |
62 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
63 | .grunt
64 |
65 | # Bower dependency directory (https://bower.io/)
66 | bower_components
67 |
68 | # node-waf configuration
69 | .lock-wscript
70 |
71 | # Compiled binary addons (https://nodejs.org/api/addons.html)
72 | build/Release
73 |
74 | # Dependency directories
75 | node_modules/
76 | jspm_packages/
77 |
78 | # TypeScript v1 declaration files
79 | typings/
80 |
81 | # TypeScript cache
82 | *.tsbuildinfo
83 |
84 | # Optional npm cache directory
85 | .npm
86 |
87 | # Optional eslint cache
88 | .eslintcache
89 |
90 | # Optional stylelint cache
91 | .stylelintcache
92 |
93 | # Microbundle cache
94 | .rpt2_cache/
95 | .rts2_cache_cjs/
96 | .rts2_cache_es/
97 | .rts2_cache_umd/
98 |
99 | # Optional REPL history
100 | .node_repl_history
101 |
102 | # Output of 'npm pack'
103 | *.tgz
104 |
105 | # Yarn Integrity file
106 | .yarn-integrity
107 |
108 | # dotenv environment variables file
109 | .env
110 | .env.test
111 | .env*.local
112 |
113 | # parcel-bundler cache (https://parceljs.org/)
114 | .cache
115 | .parcel-cache
116 |
117 | # Next.js build output
118 | .next
119 |
120 | # Nuxt.js build / generate output
121 | .nuxt
122 | dist
123 |
124 | # Gatsby files
125 | .cache/
126 | # Comment in the public line in if your project uses Gatsby and not Next.js
127 | # https://nextjs.org/blog/next-9-1#public-directory-support
128 | # public
129 |
130 | # vuepress build output
131 | .vuepress/dist
132 |
133 | # Serverless directories
134 | .serverless/
135 |
136 | # FuseBox cache
137 | .fusebox/
138 |
139 | # DynamoDB Local files
140 | .dynamodb/
141 |
142 | # TernJS port file
143 | .tern-port
144 |
145 | # Stores VSCode versions used for testing VSCode extensions
146 | .vscode-test
147 |
148 | ### vscode ###
149 | .vscode/*
150 | !.vscode/settings.json
151 | !.vscode/tasks.json
152 | !.vscode/launch.json
153 | !.vscode/extensions.json
154 | *.code-workspace
155 |
156 | # End of https://www.toptal.com/developers/gitignore/api/node,vscode,macos
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # GitHub1s_chrome_extension
2 |
3 | # Introduction
4 |
5 | [](https://badges.toozhao.com/stats/01EYB0JV8TJM3A7E0TK240SB29 "Get your own page views count badge on badges.toozhao.com")
6 |
7 | Easier and faster to use Github1s
8 |
9 | Based on conwnet/github1s, Thanks!
10 |
11 | One second to read GitHub code with VS Code.
12 |
13 | https://github.com/conwnet/github1s
14 |
15 | ---
16 |
17 | # chrome extension
18 |
19 | https://chrome.google.com/webstore/detail/github1s/lodjfmkfbfkpdhnhkcdcoonghhghbkhe
20 |
21 | # safari extension
22 |
23 | https://github.com/code4you2021/GitHub1s-For-Safari-Extension
24 |
25 | # Buy Me A Coffee
26 |
27 | Love the project? Wanna buy me a coffee? (or a beer :D)
28 |
29 | [](https://www.buymeacoffee.com/fhefh2015)
30 |
31 | ---
32 |
33 | # Noted
34 |
35 | ```
36 | Why does my chrome extension ask for history permissions?
37 |
38 | This is the standard warning for the "tabs" permission.
39 | It allows you to query, and be notified of changes, to URLs of all tabs. This allows you to spy on the user's history in real time - even if you don't have access to the browser's own history log.
40 |
41 | Note that "tabs" permission is not required in most cases. Providing access to URLs is basically the only reason to include it. You can use most of the tabs API without it, and can get access to current tab without warning using the "activeTab" permission.
42 | ```
43 |
44 | manifest - Why does my chrome extension ask for history permissions? - Stack Overflow
45 |
46 | https://stackoverflow.com/questions/40660407/why-does-my-chrome-extension-ask-for-history-permissions
47 |
48 | I'm so sorry for that, i have changed the permission to activeTab.
49 |
50 | ---
51 |
52 | # Tampermonkey
53 |
54 | https://greasyfork.org/zh-CN/scripts/421412-%E4%B8%80%E9%94%AE%E5%BC%80%E5%90%AFgithub1s%E9%A1%B5%E9%9D%A2
55 |
56 | # Bookmarklet
57 |
58 | ```javascript
59 | javascript: window.location.href = window.location.href.replace(
60 | "github.com",
61 | "github1s.com"
62 | );
63 | ```
64 |
65 | # Preview
66 |
67 | 
68 | 
69 | 
70 | 
71 |
72 | # History
73 |
74 | v0.2.1
75 |
76 | add customization options
77 |
78 | v0.2.2
79 |
80 | add 'Open with new tab' option
81 |
82 | v0.2.3
83 |
84 | add 'Open with Right-click menu' option
85 |
86 | v0.2.4
87 |
88 | add 'Allow use of GitHub1s in private repositories' option
89 |
90 | v0.2.5
91 |
92 | add 'Switching to use Gitpod' option
93 |
94 | v0.3.0
95 |
96 | Configuration page UI modification
97 |
98 | Add the option to use keyboard shortcut keys
99 |
100 | v0.3.1
101 |
102 | Fix the problem of not being able to customize URLs
103 |
104 | v0.3.2
105 |
106 | Fix the problem that GitHub Pjax loading makes it impossible to use GitHub1s
107 |
108 | v0.3.3
109 |
110 | v0.3.4
111 |
112 | fix bugs
113 |
114 | v0.3.5
115 |
116 | Fix the button not appearing problem
117 |
118 | v0.3.6
119 |
120 | Add stackblitz.com support
121 |
122 | Use GitHub1s without logging into Github
123 |
--------------------------------------------------------------------------------
/github1s/webpack.common.js:
--------------------------------------------------------------------------------
1 | const { resolve } = require('path');
2 |
3 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
4 | const webpack = require('webpack');
5 |
6 | const isDev = "development" == process.env.NODE_ENV ? true : false;
7 |
8 | /**
9 | * loader:
10 | * 1.下载
11 | * 2.使用配置loader
12 | *
13 | * plugin:
14 | * 1.下载
15 | * 2.引入
16 | * 3.配置使用
17 | */
18 |
19 | module.exports = {
20 | // 入口
21 | entry: {
22 | options: './src/options/options.js',
23 | background: './src/background/background.js',
24 | content: './src/content/content.js',
25 | },
26 | // 输出路径配置
27 | output: {
28 | // 输出文件名
29 | filename: 'js/[name].js',
30 | // 输出文件路径
31 | path: resolve(__dirname, 'dist')
32 | },
33 | // loader配置,将非js文件翻译成js文件
34 | module: {
35 | rules: [
36 | //需要匹配的文件
37 | // js语法检查
38 | {
39 | test: /\.(js|jsx)$/,
40 | // 只检查自己写的源代码,第三方的库是不用检查的
41 | exclude: /node_modules/,
42 | use: [
43 | {
44 | /**
45 | * 解决js代码对浏览器兼容问题
46 | * @babel/preset-env 基本js兼容性处理,只能转换基本语法,不能转换Promise
47 | * @babel/polyfill 将兼容性代码完全引入,体积大
48 | * core-js 按需引用
49 | */
50 | loader: 'babel-loader',
51 |
52 | },
53 | // {
54 | // loader: 'eslint-loader',
55 | // options: {
56 | // // 自动修复eslint的错误
57 | // fix: true,
58 | // }
59 | // }
60 | ],
61 | },
62 | {
63 | //匹配css文件类型
64 | test: /\.css$/,
65 | // 使用哪个loader进行转换
66 | //调用loader顺序,从右至左,从下到上 依次执行
67 | use: [
68 | //创建
15 |
16 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
59 |
89 |
119 |
131 |
141 |
151 |
161 |
171 |
172 |
173 |
174 |
--------------------------------------------------------------------------------