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.csscontent/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,实现色值类名的快捷管理。

相关推荐
gnip43 分钟前
链式调用和延迟执行
前端·javascript
SoaringHeart1 小时前
Flutter组件封装:页面点击事件拦截
前端·flutter
杨天天.1 小时前
小程序原生实现音频播放器,下一首上一首切换,拖动进度条等功能
前端·javascript·小程序·音视频
Dragon Wu1 小时前
React state在setInterval里未获取最新值的问题
前端·javascript·react.js·前端框架
Jinuss1 小时前
Vue3源码reactivity响应式篇之watch实现
前端·vue3
YU大宗师1 小时前
React面试题
前端·javascript·react.js
木兮xg1 小时前
react基础篇
前端·react.js·前端框架
ssshooter2 小时前
你知道怎么用 pnpm 临时给某个库打补丁吗?
前端·面试·npm
未来之窗软件服务2 小时前
浏览器开发CEFSharp (十七)网页自定义下载—仙盟创梦IDE
chrome·浏览器开发·cefsharp·仙盟创梦ide·东方仙盟
IT利刃出鞘2 小时前
HTML--最简的二级菜单页面
前端·html