蓝湖导出 unocss-preset-weapp

用于将蓝湖的样式转换成 unocss-preset-weapp 适用的样式!

// ==UserScript==
// @name         蓝湖导出 unocss-preset-weapp
// @namespace    http://tampermonkey.net/
// @version      2024-03-27
// @description  用于将蓝湖的样式转换成 unocss-preset-weapp 适用的样式!
// @author       haiyulu
// @match        https://lanhuapp.com/**
// @icon         https://www.google.com/s2/favicons?sz=64&domain=lanhuapp.com
// @grant        none
// @license MIT

// ==/UserScript==


const propertyAtomCssMap = {
    width: 'w',
    height: 'h',
    background: 'bg',
    'border-radius': 'rounded',
    color: 'color',
    'line-height': 'font-leading',
    'font-size': 'text',
    'font-weight': 'fw',
    'text-align': 'text',
    /** border-custom-1-fff */
    'border': 'border',
    /** shadow-[0px_4px_4px_0px_rgba(237,_0,_0,_1)] */
    'box-shadow': 'shadow'
}

function rgbaToHex(rgba) {
    const parts = rgba.substring(rgba.indexOf("(")).split(","),
        r = parseInt(parts[0].substring(1)),
        g = parseInt(parts[1]),
        b = parseInt(parts[2]),
        a = parseFloat(parts[3].substring(0, parts[3].length - 1));

    const hex = `[#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}]/${a * 100}`;
    return hex;
}

function copyToClipboard(text) {
    navigator.clipboard.writeText(text)
        .then(() => {
            console.log('文本已成功复制到剪贴板');
        })
        .catch(err => {
            console.error('复制文本到剪贴板失败: ', err);
        });
}

// linear-gradient(90deg,#FF184B 0%,#FF4300 100%)
const degMap = {
    '0': 'gradient-to-b',
    '90': 'gradient-to-r',
    '180': 'gradient-to-t',
    '270': 'gradient-to-l',
}
const linearGradientRegexp = /^linear-gradient\((\d+)deg,(#[0-9A-Fa-f]{6}|#[0-9A-Fa-f]{3})\s\d+%,(#[0-9A-Fa-f]{6}|#[0-9A-Fa-f]{3})\s\d+%\)$/
function handleBgLinearGradient(text) {
    return text.replace(linearGradientRegexp, (match, p1, p2, p3) => {
        return `${degMap[p1]} from-${p2} to-${p3}`
    })
}


function showToast(text) {
    var toast = document.getElementById('unocssTips');
    toast.innerHTML = text;
    toast.style.visibility = 'visible';
    setTimeout(function () {
        toast.style.visibility = 'hidden';
    }, 2000);
}

(function () {
    'use strict';
    window.onload = () => {
        var popup = document.createElement('div');
        popup.innerHTML = 'Hello World';
        popup.style.position = 'fixed';
        popup.style.top = '10%';
        popup.style.left = '50%';
        popup.style.transform = 'translate(-50%, -50%)';
        popup.style.background = '#fff';
        popup.style.color = 'red';
        popup.style.padding = '20px';
        popup.style.border = '1px solid #ccc';
        popup.style.zIndex = '9999';
        popup.style.visibility = 'hidden';
        popup.id = 'unocssTips'

        // 添加弹窗到页面
        document.body.appendChild(popup);
    }

    addEventListener('mousedown', function (event) {

        if (event.target.closest('.layer_box')) {
            var button = document.createElement("button");
            button.innerHTML = "获取unocss样式";
            button.style.backgroundColor = "#2878ff";
            button.style.width = "256px";
            button.style.height = "40px";
            button.style.borderRadius = "100px";
            button.style.color = "#fff";
            button.style.margin = "0 auto";
            button.style.zIndex = '99999'
            button.style.display = 'flex';
            button.style.alignItems = 'center';
            button.style.justifyContent = 'center';
            button.id = 'copy-unocss'

            button.addEventListener("click", function () {
                // 在这里添加按钮点击后的操作
                const father = [...document.getElementsByClassName(" language-css")[1].childNodes].filter(item => {
                    if (item.innerHTML) {
                        return item.innerHTML !== ';' && item.innerHTML !== ':'
                    }
                    if (item.nodeName === "#text") {
                        return !item.textContent.includes("\n")
                    }
                    return true
                })
                // const propertyList = father.filter(item => item.innerHTML)
                // const valueList = father.filter(item => item.nodeName === "#text")
                let prevKey = ''
                /** {
                    "width": "174rpx",
                    "height": "64rpx",
                    "background": "rgba(255,255,255,0.6)",
                    "border-radius": "50rpx",
                    "border": "1rpx solid rgba(151,151,151,0.2)"
                } */
                const beforeHandleResultObj = father.reduce((prev, curv) => {
                    if (curv.className === 'token property') {
                        prevKey = curv.innerHTML
                        return {
                            ...prev,
                            [prevKey]: ''
                        }
                    }
                    if (curv.className === 'token function') {
                        return {
                            ...prev,
                            [prevKey]: `${prev[prevKey]}${['border', 'linear-gradient', 'box-shadow'].includes(prevKey) ? ' ' : ''}${curv.innerHTML}`
                        }
                    }
                    if (curv.className === 'token punctuation') {
                        const result = {
                            ...prev,
                            [prevKey]: `${prev[prevKey]}${curv.innerHTML}`
                        }
                        if (curv.innerHTML === ')') prevKey = ''
                        return result
                    }

                    if (curv.nodeName === "#text") {
                        return {
                            ...prev,
                            [prevKey]: `${prev[prevKey]}${curv.data.trim()}`
                        }
                    }   
                    return prev
                }, {})
                const valueHandleMap = {
                    /** value = '1px solid #fff' */ 
                    'border': (value) => {
                        const handleValue = (value) => value.map((item, index) => {
                            if(index === 0) return item
                            return item.includes('rgba') ? `border-${rgbaToHex(item)}` : `border-${item}`
                        }).join(' ')
                        return typeof value === 'string' ? handleValue(value.split(' ')) : handleValue(value)
                    } ,
                    /** value = "0rpx -1rpx 10rpx 0rpx rgba(0,0,0,0.2)" */
                    'box-shadow': (value) => `[${value.replaceAll(' ', '_')}]`,
                    'background': (value) => value.includes('linear-gradient') ? handleBgLinearGradient(value) : value
                }
                  const targetList = Object.keys(beforeHandleResultObj).map((label) => {
                      if(['font-family', 'font-style', ','].includes(label)) return null
                      let value = beforeHandleResultObj[label]
                      if(['background', 'color'].includes(label) && value.includes('rgba')) {
                          value = rgbaToHex(value)
                      }
                      if(valueHandleMap[label]) {
                          value = valueHandleMap[label](value)
                      }
                      if(propertyAtomCssMap[label]) {
                          label = propertyAtomCssMap[label]
                      }
                      return { label, value }
                  }).filter(item => item)

                const result = targetList.map(item => `${item.label}-${item.value.replace('#', 'hex-')}`).join(' ')
                console.warn(targetList, result)
                copyToClipboard(result);
                showToast(`复制成功, 结果为:${result}`)
            });
            setTimeout(() => {
                if(document.getElementById('copy-unocss')) return;
                document.getElementsByClassName("annotation_item code_detail")[0].appendChild(button)
            }, 1000)
        }
    });


})();