全局CSS导入
// ==UserScript==
// @name 全局CSS导入
// @name:en Global CSS Import
// @description 全局CSS导入!
// @version 1.0.2
// @author Yiero
// @namespace https://github.com/AliubYiero/TamperMonkeyScripts
// @require https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/highlight.min.js
// @resource highlight https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/default.min.css
// @grant GM_addStyle
// @grant GM_registerMenuCommand
// @grant GM_getResourceText
// @grant GM_addElement
// @match https://*/*
// @run-at document-body
// @license GPL-3
// ==/UserScript==
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
const cssImportStyle = `/* \u5BB9\u5668 */
.css-dialog-container {
width: 50vw;
height: 50vh;
border: none;
background-color: transparent;
overflow: hidden;
display: none;
}
.css-dialog-container[open] {
display: block;
}
.css-dialog {
width: 100%;
height: 100%;
border: 1px solid #333;
background-color: #f7d6bb;
color: #413747;
box-shadow: #ffffff 0 0 10px;
border-radius: 10px;
overflow: auto;
font-size: 16px;
box-sizing: border-box;
scrollbar-width: thin;
padding: 24px;
display: flex;
flex-flow: column;
gap: 24px;
align-items: center;
flex-basis: 100%;
}
/* \u5934\u90E8 */
.dialog-header-container {
display: flex;
flex-flow: column;
align-items: center;
gap: 4px;
}
.dialog-header-title {
font-size: 26px;
}
.dialog-header-title, .dialog-tip {
margin: 0;
padding: 0;
}
.dialog-tip {
color: grey;
font-size: 12px;
}
/* \u7F16\u8F91\u6846 */
.dialog-edit-container {
flex: 1;
width: 100%;
min-width: 150px;
min-height: 150px;
box-sizing: border-box;
scrollbar-width: thin;
overflow: hidden;
}
.hightlight-code-container {
height: 100%;
padding: 0;
margin: 0;
box-sizing: border-box;
}
.hightlight-code {
font-size: 14px;
padding: 10px;
box-sizing: border-box;
display: block;
width: 100%;
height: 100%;
}
pre, pre.hightlight-code-container {
border: none;
background-color: transparent;
}
.hightlight-code.hightlight-code {
background-color: #f7d6bb;
color: #413747;
border: 1px solid #333;
border-radius: 5px;
outline: none;
}
/* \u5FEB\u6377\u6DFB\u52A0\u8F93\u5165\u6846 */
.dialog-quick-add-container {
width: 100%;
border-radius: 5px;
border: #333 1px solid;
font-size: 16px;
box-sizing: border-box;
}
.hightlight-code.hightlight-code:focus-visible,
.dialog-quick-add-container:has(.dialog-quick-add-input:focus-visible ) {
border: #9b5f00 1px solid;
}
.dialog-quick-add-label {
display: flex;
gap: 8px;
}
.dialog-quick-add-prefix {
padding: 5px 10px;
border-right: 1px solid #333;
background-color: #f3cbaa;
border-radius: 5px 0 0 5px;
}
.dialog-quick-add-input {
flex: 1;
padding: 4px 10px;
outline: none;
background-color: #f7d6bb;
color: #413747;
border-radius: 5px;
border: none;
outline: none;
}
button.dialog-quick-add-submit-button {
border-radius: 0 5px 5px 0;
}
/* \u5E95\u90E8 */
.dialog-footer-container {
display: flex;
justify-content: center;
gap: 8px;
}
.dialog-button {
padding: 5px 10px;
border-radius: 5px;
border: none;
transition: color, background-color, border 0.2s ease-in;
}
.dialog-cancel-button {
background-color: rgba(244, 244, 245, 0.75);
color: #909399;
border: #d3d4d6 1px solid;
}
.dialog-cancel-button:hover {
background-color: #909399;
color: #ffffff;
border: #909399 1px solid;
}
.dialog-save-button, .dialog-quick-add-submit-button {
background-color: rgba(236, 245, 255, 0.75);
color: #409eff;
border: #b3d8ff 1px solid;
}
.dialog-save-button:hover, .dialog-quick-add-submit-button:hover {
background-color: #409eff;
color: #ffffff;
border: #409eff 1px solid;
}
`;
const cssImportHtmlContent = `<!doctype html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<meta content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
name="viewport">
<title>Css Import</title>
<link href="./cssImportStyle.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/highlight.min.js"><\/script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/default.min.css" rel="stylesheet">
<script defer>
window.onload = () => {
document.querySelector( 'dialog' )?.showModal();
hljs.highlightAll();
};
<\/script>
</head>
<body>
<dialog class="css-dialog-container">
<main class="css-dialog">
<header class="dialog-header-container">
<h2 class="dialog-header-title">\u5F53\u524D\u9875\u9762CSS</h2>
<!-- <p class="dialog-tip">(Shift + Enter \u6362\u884C)</p> -->
</header>
<section class="dialog-edit-container">
<pre class="hightlight-code-container"><code class="hightlight-code language-css" contenteditable></code></pre>
</section>
<section class="dialog-quick-add-container">
<label class="dialog-quick-add-label" for="dialog-quick-add-input">
<span class="dialog-quick-add-prefix">\u5FEB\u901F\u9690\u85CF\u5143\u7D20</span>
<input class="dialog-quick-add-input" id="dialog-quick-add-input" placeholder="\u8BF7\u8F93\u5165 CSS Selector" type="text">
<button class="dialog-quick-add-submit-button dialog-button">\u786E\u8BA4</button>
</label>
</section>
<footer class="dialog-footer-container">
<button class="dialog-cancel-button dialog-button">\u53D6\u6D88</button>
<button class="dialog-save-button dialog-button">\u4FDD\u5B58</button>
</footer>
</main>
</dialog>
</body>
</html>
`;
const uiCreator = (htmlContent, cssContent) => {
GM_addStyle(cssContent);
const domParser = new DOMParser();
const uiDoc = domParser.parseFromString(htmlContent, "text/html");
const documentFragment = new DocumentFragment();
const filterScriptNodeList = Array.from(uiDoc.body.children).filter((node) => node.nodeName !== "SCRIPT");
documentFragment.append(...filterScriptNodeList);
window.document.body.append(documentFragment);
return filterScriptNodeList;
};
const cssImportDefaultEvent = (dialog) => {
const stopPropagationEventList = ["keydown", "scroll", "input", "change"];
stopPropagationEventList.forEach((eventName) => {
dialog.addEventListener(eventName, (event) => {
event.stopPropagation();
});
});
GM_addStyle(GM_getResourceText("highlight"));
const codeContainer = dialog.querySelector(".hightlight-code");
if (!codeContainer) {
return;
}
hljs.highlightBlock(codeContainer);
};
class LocalStorage {
constructor(key, defaultValue) {
__publicField(this, "key");
this.key = key;
if (defaultValue && !this.get()) {
this.set(defaultValue);
}
}
/**
* 设置 / 更新键
*
* @param value - The new value to be set.
* @returns void
*/
set(value) {
localStorage.setItem(this.key, value.trim());
}
/**
* 获取值。
*
* @returns The value stored in GM_getValue or the defaultValue if the key is not found.
*/
get() {
return localStorage.getItem(this.key);
}
}
const ExtraCSSConfigStorage = new LocalStorage("ExtraCSSConfig", "");
class CssToPage {
static load() {
if (this.styleNode) {
this.styleNode.remove();
}
this.styleNode = GM_addStyle(ExtraCSSConfigStorage.get());
}
}
__publicField(CssToPage, "styleNode");
const highlightCode = (codeContainer) => {
codeContainer.textContent = codeContainer.textContent;
hljs.highlightBlock(codeContainer);
};
const cssImportCallback = (dialog) => {
var _a, _b;
const codeContainer = dialog.querySelector(".hightlight-code");
if (!codeContainer) {
return;
}
codeContainer.addEventListener("blur", () => {
highlightCode(codeContainer);
});
const handleCancel = () => {
dialog.close();
};
const handleSave = () => {
ExtraCSSConfigStorage.set(codeContainer.textContent || "");
CssToPage.load();
dialog.close();
};
(_a = dialog.querySelector(".dialog-cancel-button")) == null ? void 0 : _a.addEventListener("click", handleCancel);
(_b = dialog.querySelector(".dialog-save-button")) == null ? void 0 : _b.addEventListener("click", handleSave);
const quickAddInput = dialog.querySelector(".dialog-quick-add-input");
const submitButton = dialog.querySelector(".dialog-quick-add-submit-button");
if (!(quickAddInput && submitButton)) {
return;
}
const handleQuickAdd = (input) => {
const textContent = input.value.trim();
input.value = "";
const appendData = `${codeContainer.textContent && "\n"}${textContent} {display: none !important;}`;
codeContainer.insertAdjacentText("beforeend", appendData);
highlightCode(codeContainer);
};
quickAddInput.addEventListener("keydown", (e) => {
if (e.key === "Enter") {
handleQuickAdd(quickAddInput);
}
});
submitButton.addEventListener("click", () => handleQuickAdd(quickAddInput));
};
const cssImportOpenButton = (dialog) => {
GM_registerMenuCommand("\u4FEE\u6539CSS", () => {
const codeContainer = dialog.querySelector(".hightlight-code");
if (!codeContainer) {
return;
}
codeContainer.textContent = ExtraCSSConfigStorage.get();
highlightCode(codeContainer);
dialog.showModal();
});
};
const cssImportCreator = () => {
const docFrag = uiCreator(cssImportHtmlContent, cssImportStyle);
const dialog = docFrag.find((node) => node.classList.contains("css-dialog-container"));
if (!dialog) {
return;
}
cssImportDefaultEvent(dialog);
cssImportCallback(dialog);
cssImportOpenButton(dialog);
};
(() => {
cssImportCreator();
CssToPage.load();
})();