mirror of
https://github.com/anticensority/runet-censorship-bypass.git
synced 2025-10-02 09:56:40 +03:00
Replace popup with options page offering PAC configuration from a textarea (only frontend)
This commit is contained in:
parent
f90c1adb2a
commit
5cb77c4013
|
@ -32,9 +32,9 @@ export const render = ({ version, edition }) => {
|
||||||
"action": {
|
"action": {
|
||||||
"default_title":
|
"default_title":
|
||||||
`__MSG_PacUpdated__ | __MSG_Version__: ${version + localizedSuffix}`,
|
`__MSG_PacUpdated__ | __MSG_Version__: ${version + localizedSuffix}`,
|
||||||
"default_popup": "/src/pages/options/index.html"
|
|
||||||
},
|
},
|
||||||
"options_ui": {
|
"options_ui": {
|
||||||
|
"open_in_tab": true,
|
||||||
"page": "/src/pages/options/index.html"
|
"page": "/src/pages/options/index.html"
|
||||||
},
|
},
|
||||||
"commands": {
|
"commands": {
|
||||||
|
|
|
@ -1,54 +1 @@
|
||||||
import { versions, storage } from '../lib/index.mjs';
|
console.log('Data migration checks...');
|
||||||
|
|
||||||
globalThis.migrationPromise = new Promise(async (resolve) => {
|
|
||||||
console.log('Checking for migrations...');
|
|
||||||
const dflts = {
|
|
||||||
// TODO: Define defaults.
|
|
||||||
options: {},
|
|
||||||
};
|
|
||||||
const ifEmpty = await storage.isEmptyAsync();
|
|
||||||
if (ifEmpty) {
|
|
||||||
// Initialisation. First install.
|
|
||||||
await storage.setAsync({
|
|
||||||
...dflts,
|
|
||||||
version: versions.current,
|
|
||||||
});
|
|
||||||
return resolve();
|
|
||||||
}
|
|
||||||
// Migration (may be already migrated).
|
|
||||||
console.log(`Current extension version is ${versions.current}.`);
|
|
||||||
const oldVersion = await storage.getAsync('version');
|
|
||||||
const ifNoNeedToMigrate = oldVersion === versions.current;
|
|
||||||
if (ifNoNeedToMigrate) {
|
|
||||||
console.log('No need for migration.');
|
|
||||||
return resolve();
|
|
||||||
}
|
|
||||||
console.log(`Migrating to ${versions.current} from ${oldVersion || 'a very old version'}.`);
|
|
||||||
switch(true) {
|
|
||||||
case !oldVersion: {
|
|
||||||
// Update from version <= 0.0.1.
|
|
||||||
const ifSentence = await storage.getAsync('SOME_KEY');
|
|
||||||
if (ifSentence !== undefined) {
|
|
||||||
console.log('Migrating to 0.0.1.');
|
|
||||||
await storage.setAsync({
|
|
||||||
ifToEncodeUrlTerminators: ifSentence,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}; // Fallthrough.
|
|
||||||
case versions.isLeq(oldVersion, '0.0.18'): {
|
|
||||||
console.log('Migrating to >= 0.0.19.');
|
|
||||||
const oldState = await storage.getAsync();
|
|
||||||
// `oldState` looks like `{ 'ifToEncodeSentenceTerminators': true, 'ifFoobar': false }`.
|
|
||||||
const migratedOpts = dflts.options.reduce((acc, [ dfltKey, dfltValue ]) => {
|
|
||||||
const oldValue = oldState[dfltKey];
|
|
||||||
acc.push([ dfltKey, typeof(oldValue) === 'boolean' ? oldValue : dfltValue ]);
|
|
||||||
return acc;
|
|
||||||
}, []);
|
|
||||||
await storage.clearAsync();
|
|
||||||
await storage.setAsync({ ...dflts, options: migratedOpts });
|
|
||||||
}; // Fallthrough.
|
|
||||||
default:
|
|
||||||
await storage.setAsync({ version: versions.current });
|
|
||||||
}
|
|
||||||
return resolve();
|
|
||||||
});
|
|
|
@ -1,116 +1 @@
|
||||||
import { storage } from '../lib/index.mjs';
|
browser.action.onClicked.addListener(handleClick);
|
||||||
|
|
||||||
console.log('Main script starts...');
|
|
||||||
|
|
||||||
(async () => {
|
|
||||||
const theState = await storage.getAsync();
|
|
||||||
console.log('The state is:', theState);
|
|
||||||
})();
|
|
||||||
|
|
||||||
/*
|
|
||||||
const ID_TO_MENU_HANDLER = {};
|
|
||||||
|
|
||||||
const createMenuEntry = (id, type, title, handler, contexts, rest) => {
|
|
||||||
ID_TO_MENU_HANDLER[id] = handler;
|
|
||||||
console.log('Registered handler for', id);
|
|
||||||
|
|
||||||
chrome.contextMenus.create({
|
|
||||||
id,
|
|
||||||
type,
|
|
||||||
title,
|
|
||||||
contexts,
|
|
||||||
...rest,
|
|
||||||
}, () => {
|
|
||||||
if (chrome.runtime.lastError) {
|
|
||||||
// Suppress menus recreation.
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const copyUrlInstalledPromise = (async () => {
|
|
||||||
console.log('Main waits for migrations...');
|
|
||||||
await globalThis.migrationPromise;
|
|
||||||
console.log('Migration is finished.');
|
|
||||||
|
|
||||||
const options = await storage.getAsync('options');
|
|
||||||
|
|
||||||
// CheckBoxes
|
|
||||||
const capitalizeFirstLetter = (str) => str
|
|
||||||
.replace(
|
|
||||||
/^./g,
|
|
||||||
(firstLetter) => firstLetter.toUpperCase(),
|
|
||||||
);
|
|
||||||
|
|
||||||
options.forEach(([ key, value ], i) =>
|
|
||||||
createMenuEntry(key, 'checkbox',
|
|
||||||
chrome.i18n.getMessage(capitalizeFirstLetter(key)),
|
|
||||||
(info) => {
|
|
||||||
options[i] = [ key, info.checked ]; // Ordered.
|
|
||||||
storage.setAsync({ options });
|
|
||||||
},
|
|
||||||
['action'],
|
|
||||||
{
|
|
||||||
checked: value === true,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
// /CheckBoxes
|
|
||||||
|
|
||||||
createMenuEntry('copyUrlFromTheAddressBar', 'normal',
|
|
||||||
chrome.i18n.getMessage('CopyUrlFromTheAddressBar'),
|
|
||||||
({ pageUrl }) => copyUrl(pageUrl),
|
|
||||||
['page'],
|
|
||||||
);
|
|
||||||
|
|
||||||
createMenuEntry('donate', 'normal',
|
|
||||||
chrome.i18n.getMessage('Donate'),
|
|
||||||
async (info) => {
|
|
||||||
chrome.tabs.create({ url: await storage.getAsync('donateUrl') });
|
|
||||||
},
|
|
||||||
['action'],
|
|
||||||
);
|
|
||||||
|
|
||||||
createMenuEntry('copyUrl', 'normal',
|
|
||||||
chrome.i18n.getMessage('CopyUnicodeUrl'),
|
|
||||||
(info) => copyUrl(
|
|
||||||
info.linkUrl ||
|
|
||||||
info.srcUrl ||
|
|
||||||
info.frameUrl ||
|
|
||||||
info.selectionText ||
|
|
||||||
info.pageUrl // Needed?
|
|
||||||
),
|
|
||||||
['link', 'image', 'video', 'audio', 'frame', 'selection'],
|
|
||||||
);
|
|
||||||
|
|
||||||
createMenuEntry(
|
|
||||||
'copyHighlightLink', 'normal',
|
|
||||||
chrome.i18n.getMessage('CopyUnicodeLinkToHighlight'),
|
|
||||||
(info) => {
|
|
||||||
copyUrl(`${info.pageUrl.replace(/#.*\/g, '')}#:~:text=${info.selectionText}`);
|
|
||||||
},
|
|
||||||
['selection'],
|
|
||||||
);
|
|
||||||
|
|
||||||
return Promise.resolve();
|
|
||||||
|
|
||||||
})();
|
|
||||||
|
|
||||||
chrome.contextMenus.onClicked.addListener(async (info, tab) => {
|
|
||||||
const result = await copyUrlInstalledPromise;
|
|
||||||
console.log('Promise resolved to:', result);
|
|
||||||
const id = info.menuItemId;
|
|
||||||
console.log('ALL THE LISTENERS:', Object.keys(ID_TO_MENU_HANDLER));
|
|
||||||
const handler = ID_TO_MENU_HANDLER[id];
|
|
||||||
console.log(`Here is the handler for ${id} w/ 'info':`, handler, info);
|
|
||||||
if (handler) {
|
|
||||||
handler(info);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
chrome.action.onClicked.addListener(async ({ url: urlToBeCopied }) => {
|
|
||||||
console.log('Main waits for listeners to be installed...');
|
|
||||||
const copyUrl = await copyUrlInstalledPromise;
|
|
||||||
console.log('Action clicked with url:', urlToBeCopied);
|
|
||||||
//copyUrl(urlToBeCopied);
|
|
||||||
});
|
|
||||||
*/
|
|
|
@ -1,5 +1,4 @@
|
||||||
import './00-start.mjs';
|
console.log('Extension started.')
|
||||||
import './05-data-init-and-migrations.mjs';
|
chrome.action.onClicked.addListener(
|
||||||
import './10-main.mjs';
|
() => chrome.runtime.openOptionsPage(),
|
||||||
|
);
|
||||||
console.log('Background script finished loading.');
|
|
|
@ -2,41 +2,73 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<script src="./top.mjs" type="module"></script>
|
<title>PAC-конфигуратор</title>
|
||||||
|
<link rel="icon" href="/icons/default-128.png" type="image/png" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<!--script src="./top.mjs" type="module"></script-->
|
||||||
<style>
|
<style>
|
||||||
/*
|
/*
|
||||||
Josh's Custom CSS Reset
|
Josh's Custom CSS Reset
|
||||||
https://www.joshwcomeau.com/css/custom-css-reset/
|
https://www.joshwcomeau.com/css/custom-css-reset/
|
||||||
*/
|
*/
|
||||||
|
/* 1. Use a more-intuitive box-sizing model */
|
||||||
*, *::before, *::after {
|
*, *::before, *::after {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 2. Remove default margin */
|
||||||
* {
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 3. Enable keyword animations */
|
||||||
|
@media (prefers-reduced-motion: no-preference) {
|
||||||
|
html {
|
||||||
|
interpolate-size: allow-keywords;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
/* 4. Add accessible line-height */
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
|
/* 5. Improve text rendering */
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 6. Improve media defaults */
|
||||||
img, picture, video, canvas, svg {
|
img, picture, video, canvas, svg {
|
||||||
display: block;
|
display: block;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 7. Inherit fonts for form controls */
|
||||||
input, button, textarea, select {
|
input, button, textarea, select {
|
||||||
font: inherit;
|
font: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 8. Avoid text overflows */
|
||||||
p, h1, h2, h3, h4, h5, h6 {
|
p, h1, h2, h3, h4, h5, h6 {
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 9. Improve line wrapping */
|
||||||
|
p {
|
||||||
|
text-wrap: pretty;
|
||||||
|
}
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
text-wrap: balance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
10. Create a root stacking context
|
||||||
|
*/
|
||||||
#root, #__next {
|
#root, #__next {
|
||||||
isolation: isolate;
|
isolation: isolate;
|
||||||
}
|
}
|
||||||
/* Reset ends */
|
/* Reset ends */
|
||||||
|
|
||||||
|
/*
|
||||||
:root {
|
:root {
|
||||||
border-color: black;
|
|
||||||
border-radius: 0;
|
|
||||||
/*
|
|
||||||
The initial theme is light but it's quickly inverted to dark.
|
The initial theme is light but it's quickly inverted to dark.
|
||||||
Dark theme should be the first theme user sees by default.
|
Dark theme should be the first theme user sees by default.
|
||||||
TODO: Ponder more. E.g. valid color (green) must remain the
|
TODO: Ponder more. E.g. valid color (green) must remain the
|
||||||
|
@ -50,185 +82,116 @@
|
||||||
border: 0 none white;
|
border: 0 none white;
|
||||||
outline: 0 none white;*/
|
outline: 0 none white;*/
|
||||||
/*color-scheme: light;
|
/*color-scheme: light;
|
||||||
/* COLOR INVERTION */
|
/* COLOR INVERTION *
|
||||||
filter: invert(0); /* TODO: temporary disabled. */
|
filter: invert(0); TODO: temporary disabled.
|
||||||
}
|
}*/
|
||||||
:root, html, body {
|
:root, html, body {
|
||||||
/*background: url('./gsbg.png') no-repeat;*/
|
/*background: url('./gsbg.png') no-repeat;*/
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
outline: none;
|
||||||
|
border: 0;
|
||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
--ribbon-color: #0075ff; /* #4169e1;*/
|
--ribbon-color: #0075ff; /* #4169e1;*/
|
||||||
font-family: Ubuntu, Arial, sans-serif;
|
font-family: Ubuntu, Arial, sans-serif;
|
||||||
font-size: 80%;
|
font-size: 80%;
|
||||||
padding: 10px;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
nav {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
padding: 0.2em;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
margin-left: 0.1em;
|
||||||
|
padding: 1px 6px 1px 6px;
|
||||||
|
}
|
||||||
|
output#status {
|
||||||
|
flex-grow: 1;
|
||||||
|
align-content: center;
|
||||||
|
text-align: left;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
}
|
||||||
|
textarea#editor {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
align-self: stretch;
|
||||||
|
resize: none;
|
||||||
|
border: 0;
|
||||||
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
menu {
|
|
||||||
list-style: none;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
li {
|
|
||||||
margin-top: 0.2rem;
|
|
||||||
}
|
|
||||||
a, a:visited {
|
a, a:visited {
|
||||||
|
/*color: #0000ee;*/
|
||||||
|
color: crimson;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: var(--ribbon-color);
|
|
||||||
}
|
}
|
||||||
label {
|
#donate {
|
||||||
vertical-align: bottom;
|
align-self: center;
|
||||||
/*padding: 3px;*/
|
align-content: center;
|
||||||
|
margin: 0 5px 0 5px;
|
||||||
}
|
}
|
||||||
input {
|
|
||||||
vertical-align: text-bottom;
|
|
||||||
}
|
|
||||||
input[type="url"] {
|
|
||||||
border: 1px solid black;
|
|
||||||
/*border-width: 0 0 1px 0;
|
|
||||||
border-color: crimson;*/
|
|
||||||
flex-grow: 1;
|
|
||||||
/*padding: 0 3px 0 3px;*/
|
|
||||||
/*width: 100%;*/
|
|
||||||
}
|
|
||||||
input[type="radio"], label {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
#disabledRadio:checked + label {
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
#ownInputs {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
input#ownRadio ~ div:has(> input#customPacUrl):after {
|
|
||||||
border: 5px solid lime;
|
|
||||||
background-color: navy;
|
|
||||||
content: "";
|
|
||||||
}
|
|
||||||
input#ownRadio ~ div:after:not(:empty) {
|
|
||||||
border: 5px solid pink;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
.use-preferred-color-scheme {
|
.use-preferred-color-scheme {
|
||||||
/*background-color: violet;
|
background-color: #9e9eff;/* pink;*/
|
||||||
color: darkred;*/
|
color: purple;
|
||||||
/*color-scheme: light;*/
|
}
|
||||||
}/*
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
.use-preferred-color-scheme {
|
.use-preferred-color-scheme {
|
||||||
color-scheme: dark;
|
color-scheme: dark;
|
||||||
background-color: green;
|
}
|
||||||
color: #bfbfbf;
|
.use-preferred-color-scheme:has(#ifToggle:checked) {
|
||||||
|
color-scheme: light;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@media (prefers-color-scheme: light) {
|
@media (prefers-color-scheme: light) {
|
||||||
.use-preferred-color-scheme {
|
.use-preferred-color-scheme {
|
||||||
color-scheme: dark;
|
color-scheme: light;
|
||||||
background-color: pink;
|
}
|
||||||
color: purple;
|
.use-preferred-color-scheme:has(#ifToggle:checked) {
|
||||||
border: 5px solid red;
|
color-scheme: dark;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
/*
|
|
||||||
img.gsbg {
|
|
||||||
z-index: -1;
|
|
||||||
position: relative;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
input:invalid {
|
|
||||||
border: 5px solid red;
|
|
||||||
}*/
|
|
||||||
#customPacUrl:disabled {
|
|
||||||
/*background-color: grey;*/
|
|
||||||
}
|
|
||||||
#ownInputs button {
|
|
||||||
font-family: emoji, monospace;
|
|
||||||
width: 2em;
|
|
||||||
width: 2ch;
|
|
||||||
border-width: 1px 1px 1px 0px;
|
|
||||||
}
|
|
||||||
#ownInputs > input {
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
#ownInputs > div {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
#customPacUrl:disabled ~ .editPanel {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
#customPacUrl:not(:disabled) ~ .unlockPanel {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
#boxes {
|
|
||||||
padding: 1em 0;
|
|
||||||
padding: 1ch 0;
|
|
||||||
}
|
|
||||||
#boxes > div {
|
|
||||||
/* Don't break sentences on spaces. */
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="use-preferred-color-scheme">
|
<body class="use-preferred-color-scheme">
|
||||||
<!--img src="./gsbg.png" class="gsbg"-->
|
|
||||||
<header>
|
|
||||||
PAC-скрипт:
|
|
||||||
</header>
|
|
||||||
<nav>
|
<nav>
|
||||||
<form id="pacChooserForm">
|
<button id="readButton">READ</button>
|
||||||
<menu id="radios">
|
<button id="saveButton">SAVE</button>
|
||||||
<li>
|
<button id="clearButton">CLEAR</button>
|
||||||
<pac-record label="Антизапрет" value="antizapret">
|
<output id="status">Press READ button to read PAC from settings</output>
|
||||||
<pac-url>https://e.cen.rodeo:18443/proxy.pac</pac-url>
|
<div>
|
||||||
<pac-url>https://e.cen.rodeo:8443/proxy.pac</pac-url>
|
<input type="checkbox" id="ifToggle" name="ifToggle" hidden/>
|
||||||
<pac-url>https://e.cen.rodeo/proxy.pac</pac-url>
|
<button><label for="ifToggle">INVERT</label></button>
|
||||||
<pac-url>https://antizapret.prostovpn.org:18443/proxy.pac</pac-url>
|
</div>
|
||||||
<pac-url>https://antizapret.prostovpn.org:8443/proxy.pac</pac-url>
|
<div id="donate">
|
||||||
<pac-url>https://antizapret.prostovpn.org/proxy.pac</pac-url>
|
<a target="_blank" data-localize="__MSG_Donate__"
|
||||||
</pac-record>
|
href="https://github.com/anticensority/runet-censorship-bypass/wiki/Поддержать"
|
||||||
</li>
|
>Donate ❤</a>
|
||||||
<li>
|
</div>
|
||||||
<pac-record label="Антицензорити" value="anticensority">
|
|
||||||
<pac-url>https://anticensority.github.io/generated-pac-scripts/anticensority.pac</pac-url>
|
|
||||||
<pac-url>https://raw.githubusercontent.com/anticensority/generated-pac-scripts/master/anticensority.pac</pac-url>
|
|
||||||
</pac-record>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<pac-record label="Свои скрипты" value="own">
|
|
||||||
<textarea>
|
|
||||||
https://foo.bar:1221
|
|
||||||
https://example.com:1223
|
|
||||||
</textarea>
|
|
||||||
</pac-record>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<pac-record label="Отключить / Сброс" value="disabled" />
|
|
||||||
</li>
|
|
||||||
</menu>
|
|
||||||
<div id="boxes">
|
|
||||||
<div>
|
|
||||||
<input type="checkbox" name="resetBox" id="resetBox" checked>
|
|
||||||
<label for="resetBox">Отключать прокси перед скачиванием</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<input type="checkbox" name="updateBox" id="updateBox" checked>
|
|
||||||
<label for="updateBox">Обновлять каждые 12ч</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</nav>
|
</nav>
|
||||||
<footer style="text-align: center">
|
<textarea id="editor">
|
||||||
<a id="donate" target="_blank" data-localize="__MSG_Donate__"
|
# Комментарии начинаются с решётки и действуют до конца строки.
|
||||||
href="https://github.com/anticensority/runet-censorship-bypass/wiki/Поддержать"
|
# Для начала работы вам нужно добавить один или несколько
|
||||||
>Donate ❤</a>
|
# URL-ссылок на PAC-скрипты, как показано на примере ниже
|
||||||
</footer>
|
# (на example.com, только без решётки).
|
||||||
<script src="./bottom.mjs" type="module"></script>
|
#
|
||||||
|
# Желательно не добавлять ссылки из различных
|
||||||
|
# проектов, иначе при каких-либо сбоях вам будет сложно
|
||||||
|
# определить причину и выявить ту команду поддержки, в которую
|
||||||
|
# следует обратиться.
|
||||||
|
#
|
||||||
|
# Где брать ссылки на PAC-скрипты?
|
||||||
|
# Из ваших доверенных источников.
|
||||||
|
# Я их здесь не публикую, т.к. это может стать лишним
|
||||||
|
# поводом для блокировки расширения в магазинах или
|
||||||
|
# репозиториях.
|
||||||
|
|
||||||
|
# https://example.com/foo/bar/proxy.pac
|
||||||
|
</textarea>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
Loading…
Reference in New Issue
Block a user