您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
2024/12/29 14:44:23
当前为
- // ==UserScript==
- // @name css-replace
- // @namespace css
- // @match https://codesign.qq.com/app/design/*
- // @version 1.1
- // @author Gorvey
- // @description 2024/12/29 14:44:23
- // @run-at document-idle
- // @grant GM_registerMenuCommand
- // @grant GM_setValue
- // @grant GM_deleteValue
- // @grant GM_getValue
- // @grant GM_addStyle
- // @license MIT
- // ==/UserScript==
- //--------------------设置------------------- S//
- //#region
- GM_addStyle(
- `
- .base-node{
- display: none;
- }
- .node-item[data-label="字体"],
- .node-item[data-label="段落对齐"],
- .node-item[data-label="垂直对齐"],
- .node-item[data-label="字号"],
- .node-item[data-label="字重"],
- .node-item[data-label="行高"],
- .node-item[data-label="颜色"],
- .node-item[data-label="宽度"]
- {
- display: none !important;
- }
- // .node-box{
- // display: none !important;
- // }
- .node-box:last-child{
- display: block !important;
- }
- .node-item {
- margin-bottom: 2px !important;
- }
- .node-box {
- margin-bottom: 0px !important;
- }
- `
- );
- GM_addStyle(
- `
- .tailwind-line-wrapper{
- display: flex;
- align-items: center;
- justify-content: space-between;
- }
- `
- )
- //#endregion
- document.addEventListener('click', (e) => {
- if(e.target.classList.contains('icon-v2-copy')){
- return
- }
- const wrapper = document.querySelector(".css-node__codes");
- if (!wrapper) return;
- onCssChange()
- })
- const copyToClipboard = (text) => {
- const textarea = document.createElement("textarea");
- textarea.value = text;
- document.body.appendChild(textarea);
- textarea.select();
- document.execCommand("copy");
- document.body.removeChild(textarea);
- };
- const processCssVariables = (value) => {
- const cssVarMap = GM_getValue('css-variable-map', '')
- if (!cssVarMap) return value
- // 格式化 CSS 变量映射字符串
- const formatVarMap = cssVarMap
- .replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '')
- .replace(/(:root|:root\[.*?\])\s*{/g, '')
- .replace(/}/g, '')
- .split(';')
- .filter(line => line.trim())
- .map(line => {
- const [key, val] = line.split(':').map(s => s.trim())
- return [key, val]
- })
- .filter(([key, val]) => key && val)
- // 查找匹配的变量
- const matchedVar = formatVarMap.find(([_, val]) => {
- const cleanVal = val.replace(/\s*!important\s*$/, '').trim()
- return cleanVal.toLowerCase() === value
- })
- return matchedVar ? `var(${matchedVar[0]})` : value
- }
- const cssToTailwind = (css) => {
- const cssMap = css.map(item => {
- const [name, value] = item.split(':').map(s => s.trim())
- const processedValue = processCssVariables(value)
- return [name, processedValue]
- })
- const rules = [
- // ['width', 'w-[#]'],
- // ['height', 'h-[#]'],
- ['font-size', 'text-[#]'],
- // ['font-style', '#'],
- ['font-weight', (value) =>{
- const maps={
- '300': 'font-light',
- '400': 'font-normal',
- '500': 'font-medium',
- '600': 'font-semibold',
- '700': 'font-bold',
- '800': 'font-extrabold',
- }
- return maps[value]
- }],
- ['color', 'text-[#]'],
- ['line-height', 'leading-[#]'],
- ['border-radius', 'rounded-[#]'],
- ['border', (value) => {
- const [width, style, color] = value.split(' ')
- return `border-[${width}] border-${style} border-[${color}]`
- }],
- ['letter-spacing', 'tracking-[#]'],
- ['opacity', (value) => `opacity-${Math.round(parseFloat(value) * 100)}`],
- // ['text-decoration', '#'],
- // ['text-align', 'text-#'],
- ['background', 'bg-[#]'],
- // ['padding', 'p-[#]'],
- // ['margin', 'm-[#]'],
- // ['display', '#'],
- // ['position', '#'],
- // ['top', 'top-[#]'],
- // ['left', 'left-[#]'],
- // ['right', 'right-[#]'],
- // ['bottom', 'bottom-[#]'],
- ]
- // 转换 CSS 属性到 Tailwind
- const result = cssMap.map(([prop, value]) => {
- const rule = rules.find(([cssName]) => cssName === prop)
- if(value === '') return null
- if (!rule) return null
- const [, template] = rule
- if (typeof template === 'function') {
- return template(value)
- }
- return template.replace('#', value)
- }).filter(item => {
- if(!item) return false
- // 清理默认值
- let defaultValues = ['font-normal', 'text-[14px]', 'tracking-[0]']
- if(defaultValues.includes(item)) return false
- return true
- })
- return result.join(' ')
- }
- const genCopyButton = (css) => {
- const button = document.createElement('div')
- button.innerHTML='<i style="font-size: 24px;" class="com-icon iconfont-v2 icon-v2-copy"></i>'
- button.classList.add('tailwind-copy-button')
- button.style.cursor = 'pointer'
- button.style.color = '#000'
- button.style.marginLeft = '8px'
- button.addEventListener('click', () => {
- copyToClipboard(css)
- // 获取对应的代码块元素
- const codeBlock = button.previousElementSibling
- // 添加复制成功的边框样式
- codeBlock.style.borderColor = '#22c55e'
- // 3秒后恢复原样
- setTimeout(() => {
- codeBlock.style.borderColor = 'var(--td-brand-color)'
- }, 3000)
- })
- return button
- }
- const textToHtmlCodeElement = (text) => {
- const node = document.createElement('div')
- node.classList.add('tailwind-code-block')
- node.innerText = text
- node.style.width = '100%'
- node.style.marginTop = '8px'
- node.style.padding = '8px 12px'
- node.style.whiteSpace = 'pre-wrap'
- node.style.wordBreak = 'break-all'
- node.style.minHeight = '32px'
- node.style.maxHeight = '190px'
- node.style.overflow = 'auto'
- node.style.borderRadius = '4px'
- node.style.cursor = 'text'
- node.style.backgroundColor = 'rgba(0, 0, 0, .04)'
- node.style.position = 'relative'
- node.style.border = '3px solid var(--td-brand-color)'
- return node
- }
- const onCssChange = async () => {
- await new Promise((resolve) => setTimeout(resolve, 20));
- try {
- const wrapper = document.querySelector(".css-node__codes");
- if (!wrapper) return;
- const cssNode = wrapper.querySelectorAll(".css-node__code--item")[0];
- const content = cssNode.innerText;
- const hasMultipleClasses = content.includes('{');
- let tailwind = [];
- if (hasMultipleClasses) {
- // 处理多个类声明
- const classBlocks = content.split('}').filter(block => block.trim());
- const results = classBlocks.map(block => {
- const styles = block
- .replace(/.*{/, '') // 移除类名和{
- .split(';\n')
- .filter(item => item.trim())
- .map(item => item.trim().replace(';', ''));
- return cssToTailwind(styles);
- });
- tailwind = results;
- } else {
- // 处理单个声明
- const styles = content
- .split(';\n')
- .filter(item => item.trim())
- .map(item => item.trim().replace(';', ''));
- tailwind =[cssToTailwind(styles)]
- }
- let prevNodes = document.querySelectorAll('.tailwind-line-wrapper')
- prevNodes.forEach(node => {
- node.remove()
- })
- tailwind.map(item =>{
- const node= textToHtmlCodeElement(item)
- const copyButton = genCopyButton(item)
- const lineWrapper = document.createElement('div')
- lineWrapper.classList.add('tailwind-line-wrapper')
- lineWrapper.appendChild(node)
- lineWrapper.appendChild(copyButton)
- wrapper.insertBefore(lineWrapper,cssNode)
- })
- } catch (error) {
- console.error(error);
- }
- };
- GM_registerMenuCommand('添加css变量映射', () => {
- const css = prompt('请输入css变量映射')
- if(!css) return
- GM_setValue('css-variable-map', css)
- alert('添加成功')
- })
- GM_registerMenuCommand('清除css变量映射', () => {
- GM_deleteValue('css-variable-map')
- alert('清除成功')
- })