您需要先安装一个扩展,例如 篡改猴、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('清除成功') })