'],
7 | all_frames: true,
8 | match_about_blank: true,
9 | run_at: "document_end",
10 | };
11 |
12 | const script = document.createElement("script");
13 | script.src = importer;
14 | script.type = "module";
15 | document.body.appendChild(script);
16 | document.body.removeChild(script);
17 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "console-importer",
3 | "displayName": "Console Importer",
4 | "version": "2.1.0",
5 | "private": true,
6 | "description": "Import JavaScript and CSS resources from console, with one command",
7 | "homepage": "https://github.com/pd4d10/console-importer",
8 | "scripts": {
9 | "build": "plasmo build",
10 | "dev": "plasmo dev",
11 | "icon": "rm app/images/icon.png; svg2png app/images/icon.svg -o app/images/icon.png",
12 | "package": "plasmo package",
13 | "test": "vitest --dom"
14 | },
15 | "devDependencies": {
16 | "happy-dom": "^8.1.1",
17 | "plasmo": "^0.60.2",
18 | "rescript": "^10.1.0",
19 | "rescript-webapi": "^0.7.0",
20 | "tiza": "^2.2.1",
21 | "vitest": "^0.26.2"
22 | },
23 | "packageManager": "pnpm@7.19.0"
24 | }
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Rongjian Zhang
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 |
--------------------------------------------------------------------------------
/assets/test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
47 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Console Importer
2 |
3 | [](https://chrome.google.com/webstore/detail/console-importer/hgajpakhafplebkdljleajgbpdmplhie)
4 | [](https://chrome.google.com/webstore/detail/console-importer/hgajpakhafplebkdljleajgbpdmplhie)
5 | [](https://chrome.google.com/webstore/detail/console-importer/hgajpakhafplebkdljleajgbpdmplhie)
6 |
7 |
8 |
9 | ## Installation
10 |
11 | Install it from Chrome Web Store:
12 |
13 | https://chrome.google.com/webstore/detail/console-importer/hgajpakhafplebkdljleajgbpdmplhie
14 |
15 | ## Usage
16 |
17 | Open Chrome devtools console, a function named `$i` could be used to import JavaScript and CSS resources.
18 |
19 | ```js
20 | $i('jquery')
21 | ```
22 |
23 | Import specific version:
24 |
25 | ```js
26 | $i('jquery@2')
27 | ```
28 |
29 | Also, you can import a valid script URL:
30 |
31 | ```js
32 | $i('https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js')
33 | ```
34 |
35 | CSS is supported, too:
36 |
37 | ```js
38 | $i('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css')
39 | ```
40 |
41 | ### Import ES Module
42 |
43 | ES module has been widely supported in modern browsers. `$i.esm` method can be useful in this case:
44 |
45 | ```js
46 | d3 = await $i.esm('d3')
47 | ```
48 |
49 | or specify a version:
50 |
51 | ```js
52 | d3 = await $i.esm('d3@7')
53 | ```
54 |
55 | The advantage of this approach is that no global variables are added to the window, which allows better control over the scope of side effects. For more details, see https://esm.run.
56 |
57 | ## Trouble shooting
58 |
59 | ### Q: `$i` doesn't work as expected
60 |
61 | Some websites like Google Inbox already have `$i` used as a global variable. This extension doesn't overwrite it.
62 |
63 | You can use `console.$i` on these websites.
64 |
65 | ### Q: `$i` fail to import resources
66 |
67 | On some websites like GitHub, `$i` will fail to import resources. Console errors may be like follows:
68 |
69 | ```sh
70 | # js errors example
71 | Refused to connect to 'https://api.cdnjs.com/libraries?search=jquery' because it violates the following Content Security Policy directive:
72 |
73 | # css errors example
74 | Refused to load the stylesheet 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css' because it violates the following Content Security Policy directive:
75 | ```
76 |
77 | It is because of strict Content Security Policy of these websites. For more information, see [Content Security Policy (CSP) wiki](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP)
78 |
79 | ## How does it work?
80 |
81 | - If it is like a JavaScript lib name, like `jquery`, try to load it from cdnjs
82 | - If it has version number, like `jquery@2`, try to load it from unpkg
83 | - If it is a valid URL(CSS or JS), load it directly
84 |
85 | For advanced use, there are also two functions `$i.unpkg` and `$i.cdnjs` which could be used to import resources from specific CDN.
86 |
87 | ## License
88 |
89 | MIT
90 |
--------------------------------------------------------------------------------
/src/importer.ts:
--------------------------------------------------------------------------------
1 | import tiza from "tiza";
2 |
3 | const PREFIX_TEXT = "[$i]: ";
4 | const prefix = tiza.color("blue").text;
5 | const strong = tiza.color("blue").bold().text;
6 | const error = tiza.color("red").text;
7 | const log: typeof tiza.log = (...args) =>
8 | tiza.log(prefix(PREFIX_TEXT), ...args);
9 | const logError: typeof tiza.log = (...args) =>
10 | tiza.log(error(PREFIX_TEXT), ...args);
11 |
12 | let lastGlobalVariableSet: Set | null = null;
13 |
14 | function createBeforeLoad(name: string) {
15 | return () => {
16 | lastGlobalVariableSet = new Set(Object.keys(window));
17 | log(strong(name), " is loading, please be patient...");
18 | };
19 | }
20 |
21 | function createOnLoad(name: string, url?: string) {
22 | return () => {
23 | const urlText = url ? `(${url})` : "";
24 | log(strong(name), `${urlText} is loaded.`);
25 |
26 | const currentGlobalVariables = Object.keys(window);
27 | const newGlobalVariables = currentGlobalVariables.filter(
28 | (key) => !lastGlobalVariableSet?.has(key)
29 | );
30 | if (newGlobalVariables.length > 0) {
31 | log(
32 | "The new global variables are as follows: ",
33 | strong(newGlobalVariables.join(",")),
34 | " . Maybe you can use them."
35 | );
36 | } else {
37 | // maybe css request or script loaded already
38 | }
39 | // Update global variable list
40 | lastGlobalVariableSet = new Set(currentGlobalVariables);
41 | };
42 | }
43 |
44 | function createOnError(name: string, url?: string) {
45 | return () => {
46 | const urlText = url ? `(${strong(url)})` : "";
47 | logError(
48 | "Fail to load ",
49 | strong(name),
50 | ", is this URL",
51 | urlText,
52 | " correct?"
53 | );
54 | };
55 | }
56 |
57 | // Try to remove referrer for security
58 | // https://imququ.com/post/referrer-policy.html
59 | // https://www.w3.org/TR/referrer-policy/
60 | function addNoReferrerMeta() {
61 | const originMeta = document.querySelector(
62 | "meta[name=referrer]"
63 | );
64 |
65 | if (originMeta) {
66 | // If there is already a referrer policy meta tag, save origin content
67 | // and then change it, call `remove` to restore it
68 | const content = originMeta.content;
69 | originMeta.content = "no-referrer";
70 | return function remove() {
71 | originMeta.content = content;
72 | };
73 | } else {
74 | // Else, create a new one, call `remove` to delete it
75 | const meta = document.createElement("meta");
76 | meta.name = "referrer";
77 | meta.content = "no-referrer";
78 | document.head.appendChild(meta);
79 | return function remove() {
80 | // Removing meta tag directly not work, should set it to default first
81 | meta.content = "no-referrer-when-downgrade";
82 | document.head.removeChild(meta);
83 | };
84 | }
85 | }
86 |
87 | // Insert script tag
88 | function injectScript(
89 | url: string,
90 | onload: ReturnType,
91 | onerror: ReturnType
92 | ) {
93 | const remove = addNoReferrerMeta();
94 | const script = document.createElement("script");
95 | script.src = url;
96 | script.onload = onload;
97 | script.onerror = onerror;
98 | document.body.appendChild(script);
99 | remove();
100 | document.body.removeChild(script);
101 | }
102 |
103 | // Insert link tag
104 | function injectStyle(
105 | url: string,
106 | onload: ReturnType,
107 | onerror: ReturnType
108 | ) {
109 | const remove = addNoReferrerMeta();
110 | const link = document.createElement("link");
111 | link.href = url;
112 | link.rel = "stylesheet";
113 | // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link#Stylesheet_load_events
114 | link.onload = onload;
115 | link.onerror = onerror;
116 | document.head.appendChild(link);
117 | remove();
118 | // Should not remove tag, unlike