Ctrl ACV工程师的提效之路——蓝湖色值和类名的自动转换(Chrome插件)

痛点问题描述

我们的业务里,有深色模式和浅色模式的皮肤,我们实现的方案是这样的:

显然,我们会避免在业务代码里写色值的css,我们会事先把所有的颜色统一放到一个公共的CSS文件里,然后每个项目都去引用这个CSS。 因此对于开发者而言,关心的东西不是色值本身,而是色值对应的类名。

所以痛点问题就在于:我们在写样式的时候,先看到蓝湖上的色值,再去根据这个色值搜索对应的类名,然后再复制这个类名,写到HTML代码中。

作为一名Ctrl ACV工程师,我需要思考如何直接快速地通过色值直接取到类名,而不用去代码里搜。

基本思路

我们可以注入一段JS代码,改写色值的点击事件,然后直接自动复制类名。

技术选型

能做到这一点的,就是Chrome插件。

其他方案思考:VSCode插件(先得确保团队用的编辑器统一,并且只能自动将色值转成CSS变量)

核心逻辑

核心逻辑:

  1. 找到色值对应的DOM结构,获取色值,并且给这个DOM新增点击事件

  2. 根据色值查找类名,要做到这一点我们需要手动把色值和类名的对应关系维护起来

  3. 执行复制操作

核心代码

json 复制代码
{
    "manifest_version": 3,
    "name": "lanhu-color2class",
    "version": "1.0.0",
    "description": "蓝湖颜色转类名",
    "icons": {
        "16": "assets/icon.png"
    },
    "action": {
        "default_title": "lanhu-color2class",
        "default_icon": "assets/icon.png",
        "default_popup": "popup.html"
    },
    "permissions": [
        "scripting"
    ],
    "host_permissions": [
        "https://lanhuapp.com/",
        "http://localhost/*",
        "http://127.0.0.1/*"
    ],
    "content_security_policy": {
        "extension_pages": "script-src 'self'; object-src 'self'"
    },
    "content_scripts": [
        {
            "css": [
                "content/style.css"
            ],
            "js": [
                "content/content.js"
            ],
            "matches": [
                "https://lanhuapp.com/*"
            ],
            "all_frames": true,
            "run_at": "document_end",
            "match_about_blank": true
        }
    ]
}

关键点在于content_scripts的配置项,会在域名为https://lanhuapp.com/的网页里注入插件内的content/style.css和content/content.js。

content/content.js就是核心的逻辑:

js 复制代码
// 色值和类名的对应关系
var colors = {
    '#333333': [{
        className: 'text-color-1',
        desc: '标题颜色'
    }],
    '#666666': [{
        className: 'text-color-2',
        desc: '副标题颜色'
    }],
    '#f8f8f8': [{
        className: 'border-color',
        desc: '边框颜色'
    }],
    '#2878ff': [{
        className: 'bg-primary',
        desc: '主题背景色',
    }, {
        className: 'color-primary',
        desc: '主题文字颜色'
    }]
}

var domStr = 
`<div id="dlg">
    <ul>
    </ul>
</div>`

// 创建 DOMParser 对象
const range = document.createRange();
const dom = range.createContextualFragment(domStr);
document.body.after(dom)

function doCopy(str) {
    function copyToClipboard(text) {
        var textarea = document.createElement("textarea"); //创建临时的textarea元素
        textarea.value = text; //设置要复制的内容为指定的值
        document.body.appendChild(textarea); //添加到页面上
        textarea.select(); //选中输入框的内容
        try {
            var successful = document.execCommand('copy'); //执行复制命令
            var msg = successful ? '成功' : '失败';
            console.log('已复制到剪贴板', msg);
        } catch (err) {
            console.error('无法复制到剪贴板', err);
        } finally {
            document.body.removeChild(textarea); //移除临时的textarea元素
        }
    }
     
    //调用函数并传递需要复制的字符串作为参数
    copyToClipboard(str);
}

// 打开、关闭弹窗
function openDialog() {
    $('#dlg').show()
}

function closeDialog() {
    $('#dlg').hide()
}

function setDialogValue(colorDetail) {
    var html = ''
    for(var i = 0; i < colorDetail.length; i++) {
        var item = colorDetail[i]
        html += `<li>
        <div>${item.desc}</div>
        <div class="my_link" data-classname="${item.className}">复制</div>
        </li>`
    }
    $('#dlg').find('ul').html(html)

}

function transformColor(color) {
    var colorDetail = colors[color]
    if(colorDetail) {
        if(colorDetail.length == 1) {
            // 色值只对应一个类名
            console.log(`${colorDetail[0].desc}已复制,类名为${colorDetail[0].className}`)
            doCopy(colorDetail[0].className)
        } else {
            // 色值对应多个类名 弹出一个弹窗,再去选择要复制的类名
            setDialogValue(colorDetail)
            openDialog()
        }
    } else {
        // do nothing
        console.log('该色值暂未收录,请检查或向UI确认')
    }
}

// 给 copy_text 新增点击事件,copy_text就是蓝湖中色值的类名;
$('body').on('click', '.copy_text', function(e) {
    var key = $(this).text().toLowerCase()
    transformColor(key)
})

// 多个对应关系存在的时候,给弹出的弹窗绑定事件
$('#dlg').on('click', '.my_link', function() {
    var copyText = $(this).attr('data-classname')
    console.log(`已复制类名为${copyText}`)
    doCopy(copyText)
    closeDialog()
})

最终效果

点击F8F8F8,直接复制了border-color:

点击#2878FF,可以选择复制bg-primary或者color-primary:

Demo

github.com/beat-the-bu...

测试方法:

第一步:下载👆🏻的代码

第二步:Chrome打开插件管理页面:chrome://extensions/

第三步:设置为开发者模式,加载已解压的扩展程序,然后选中代码目录

第四步:打开蓝湖,在蓝湖的Demo项目里找到相关颜色并点击

后续完善

  1. 如果有CDN的话,可以把色值和类名的对应关系的json数据存起来,这样如果需要更新的话,就不用重新打包插件了;

  2. 如果有条件的话,可以把色值和类名的对应关系存在数据库中,提供增删改查接口,再配合popup.html,实现色值类名的快捷管理。

相关推荐
广州智造1 小时前
Radioss复合材料使用的单元属性
前端·设计·cad·建模·cae·radioss
张宏宇1 小时前
我把微软开源的 tgrep 做成了本地版 GitHub Code Search:45,629 个文件里搜一次 10ms
前端·后端
huakoh1 小时前
MCP 调用超时后别急着重试:三步读回分清执行状态
前端
打工仔折腾 AI1 小时前
把模型切换交给平台:用蓝耘智能路由搭建商品评论分析工具
java·服务器·前端·后端·python·性能优化·ai agent 实战
不可能片场1 小时前
Electron 发布标题的冒号 击穿命令行解析
前端·electron
reeswell2 小时前
我开源了 inspect-devtools —— 让 AI 终于能"看见"你屏幕上的组件
前端·人工智能
Yuhano2 小时前
W3. 实现Agent工具调用引擎
前端·aigc·ai编程
flash俊杰2 小时前
第三节 基于 Vue 3 的领域模型架构——Schema 驱动的低代码后台实战
前端
热爱2332 小时前
dsh里使用chatgpt plus或pro会员而不是apikey,其实很简单。
前端·openai
linux_cfan2 小时前
videojs v10 源代码系列解读:32 · Reactor 模型:信号驱动的状态机
前端·javascript·音视频