大家好!我叫戴向天。
QQ群:602504799
可设置样式scoped作用域
scss/less转换的时候暂不支持 变量 以及 函数处理
/**
* author: 戴向天
* time: 2022-03-03
* QQ: 809002582
* desc:
* 可设置样式scoped作用域
* scss to css / less to css
* scss/less转换的时候暂不支持 变量 以及 函数处理
*/
/**
* scss to css / less to css
* @param text string;
* @param scopedId? string;
*/
function toCss(text: string, scopedId?: string) {
let content = text.replace(/\/*(.+)\*\//g, '');
content = toCss.removeNotes(content) // 去掉注释
const json = toCss.toJSON(content, scopedId)
const perfectNameResult = toCss.perfectName(json)
const mergeResult = toCss.mergeJSON(perfectNameResult)
const textResult = toCss.toText(mergeResult)
return toCss.format(textResult)
}
// css 样式格式化
toCss.format = function (text: string) {
// 格式化代码
let s = text.replace(/\s*([\{\}\:\;\,])\s*/g, '$1');
s = s.replace(/;\s*;/g, ';'); // 清除连续分号
s = s.replace(/\,[\s\.\#\d]*{/g, '{');
s = s.replace(/([^\s])\{([^\s])/g, '$1 {\n\t$2');
s = s.replace(/([^\s])\}([^\n]*)/g, '$1\n}\n$2');
s = s.replace(/([^\s]);([^\s\}])/g, '$1;\n\t$2');
return s;
}
/**
* 将样式表内容转换成json数据
* @param text string;
*/
toCss.toJSON = function (text: string, scopedId?: string) {
let s = text.replace(/\s*([\{])\s*/g, '{\n') // 左大括号换行
s = s.replace(/\s*([\}])\s*/g, '\n}\n') // 右大括号换行
s = s.replace(/\s*([;])\s*/g, ';\n') // 分号换行
s = s.replace(/;\s*;/g, ';') // 清除连续分号
s = s.replace(/,\s*\n\s*/g, ',') // 逗号合并一行
const sa = s.split(/\n/).filter(row => row.trim()) // 去掉空白行
let res = sa.map((str: string) => {
// 判断是不是样式名称行
if (str.indexOf('{') > 0) {
const result = str.split('{')
// 设置作用域
if (scopedId) {
const names = result[0].split(',')
const newName = names.map(name => {
if (name.indexOf(':') >= 0) {
const ns = name.split(':')
const n = ns.shift()
return `${n}[${scopedId}]:${ns.join(':')}`
}
return `${name}[${scopedId}]`
}).join(',')
return `${newName}:{`
}
return `"${result[0]}":{`
}
// 样式属性行
if (str.indexOf(':') >= 0 && str.indexOf('{') < 0) {
const result = str.split(':')
return `"${result[0]}":"${result[1]}",`
}
// 结束符处理
if (str.trim().indexOf('}') === 0) {
return '},'
}
return str
}).join('')
res = res.substring(0, res.length - 1) // 去掉最后一个逗号
return eval('({' + res + '})') // 返回对象
}
/**
* 去掉样式注释
* @param text string;
*/
toCss.removeNotes = function (text: string) {
// 去掉多行注释
const s = text.replace(/\/\*.*\*\//g, '')
// 换成行数数组
const sa = s.split(/\n/)
// 去掉单行数组
const result = sa.reduce(function (total: string[], str: string) {
if (str.indexOf('//') >= 0) {
str = str.replace(/\/\/.*/, '')
}
total.push(str)
return total
}, []).join('\n')
return result
}
/**
* 完善名称
* @param obj json;对象
* @param parentKey string;名称前缀
* @returns
*/
toCss.perfectName = function (obj: any, parentKey: string = '') {
const keys = Object.keys(obj);
return keys.reduce((total: any, key) => {
const rightKey = key.replace(/\&/g, parentKey);
total[rightKey] = typeof obj[key] === 'object' ? toCss.perfectName(obj[key], rightKey) : obj[key];
return total;
}, {});
}
/**
* 合并成一个对象,没有曾经
* @param obj cssJSON
* @returns
*/
toCss.mergeJSON = function (obj: { [key: string]: string }) {
const res: any = {};
function getSheet(params: any, parentKey?: string) {
const objKeys = Object.keys(params).filter(key => typeof params[key] === 'object' && (parentKey || '').indexOf('@keyframes') < 0);
objKeys.forEach((key: string) => {
getSheet(params[key], key);
delete params[key];
}, {});
if (parentKey && Object.keys(params).length > 0) {
res[parentKey] = params;
}
}
getSheet(obj);
return res;
}
/**
* json转样式表
* @param obj json样式数据
*/
toCss.toText = function (obj: any) {
return Object.keys(obj).reduce((content, key) => {
const res: any = Object.keys(obj[key]).reduce((total, name) => {
let value = obj[key][name]
if (typeof obj[key][name] === 'object') {
const child: any = {}
child[name] = obj[key][name]
value = toCss.toText(child)
total += `${value}`;
} else {
total += `${name}: ${value}`;
}
return total;
}, '');
content += `
${key} {
${res}
}
`;
return content.replace(/\s\s+/g, ' ');
}, '');
}
export default toCss;