javascript - 如何为新样式表生成 CSS 变量值
问题描述
我正在开发一个项目,用户可以从颜色输入中选择颜色并使用 CSS 变量动态创建自己的主题。我希望用户能够使用他们选择的值下载整个 CSS 文件。
我的问题:下载的 CSS 文件不显示实际颜色值,但显示变量名称。
NOT WANTED
pre[class*="language-"] {
background: var(--block-background);
}
代替
WANTED OUTPUT
pre[class*="language-"] {
background: #0D2831;
}
我知道我可以通过执行以下操作来获取 CSS 属性值。
const styles = getComputedStyle(document.documentElement)
const value = String(styles.getPropertyValue('--block-background')).trim()
我想我会创建一个函数,循环遍历我的所有 CSS 变量并获取相应的属性值,然后将它们添加到新样式表中供用户下载,但我在此过程中迷路了。我目前有两个 CSS 文件,一个main.css
和一个prism.css
. 该main.css
文件在根目录中保存页面样式和所有 CSS 变量。该prism.css
文件包含我希望用户能够下载的主题。
我正在尝试找到一种方法来创建一个新样式表,该样式表包含prism.css
文件中的所有内容,但具有实际的颜色十六进制代码而不是 CSS 变量名称作为给定 CSS 属性的值。
索引.js
import { colors } from './colorHelper'
const inputs = [].slice.call(document.querySelectorAll('input[type="color"]'));
const handleThemeUpdate = (colors) => {
const root = document.querySelector(':root');
const keys = Object.keys(colors);
keys.forEach(key => {
root.style.setProperty(key, colors[key]);
});
}
inputs.forEach((input) => {
input.addEventListener('change', (e) => {
e.preventDefault()
const cssPropName = `--${e.target.id}`;
document.styleSheets[2].cssRules[3].style.setProperty(cssPropName, e.target.value)
handleThemeUpdate({
[cssPropName]: e.target.value
});
console.log(`${cssPropName} is now ${e.target.value}`)
});
});
const cssRules = document.styleSheets[2].cssRules;
for (var i = 0; i < cssRules.length; i++) {
// Finds css variable names
const regexp = /(?:var\(--)[a-zA-z\-]*(?:\))/
let cssVariables = cssRules[i].cssText.matchAll(regexp)
cssVariables = Array.from(cssVariables).join()
console.log(cssVariables)
}
colorHelper.js
const colorSelect = {
'Line Highlights': {
'highlight-background': '#F7EBC6',
'highlight-accent': '#F7D87C'
},
'Inline Code': {
'inline-code-color': '#DB4C69',
'inline-code-background': '#F9F2F4'
},
'Code Blocks': {
'block-background': '#0D2831',
'base-color': '#5C6E74',
'selected-color': '#b3d4fc'
},
'Tokens': {
'comment-color': '#93A1A1',
'punctuation-color': '#999999',
'property-color': '#990055',
'selector-color': '#669900',
'operator-color': '#a67f59',
'operator-background': '#FFFFFF',
'variable-color': '#ee9900',
'function-color': '#DD4A68',
'keyword-color': '#0077aa'
}
}
const colorNames = []
const colors = {}
Object.keys(colorSelect).map(key => {
const group = colorSelect[key]
Object.keys(group).map(color => {
colorNames.push(color)
colors[color] = group[color]
})
})
export { colorSelect, colorNames, colors }
棱镜.css
pre[class*="language-"],
code[class*="language-"] {
color: var(--base-color);
font-size: 13px;
text-shadow: none;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
direction: ltr;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::selection,
code[class*="language-"]::selection,
pre[class*="language-"]::mozselection,
code[class*="language-"]::mozselection {
text-shadow: none;
background: var(--selected-color);
}
@media print {
pre[class*="language-"],
code[class*="language-"] {
text-shadow: none;
}
}
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
background: var(--block-background);
}
:not(pre) > code[class*="language-"] {
padding: .1em .3em;
border-radius: .3em;
color: var(--inline-code-color);
background: var(--inline-code-background);
}
/* Tokens */
.namespace {
opacity: .7;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: var(--comment-color);
}
.token.punctuation {
color: var(--punctuation-color);
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: var(--property-color);
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: var(--selector-color);
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: var(--operator-color);
background: var(--operator-background);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: var(--keyword-color);
}
.token.function {
color: var(--function-color);
}
.token.regex,
.token.important,
.token.variable {
color: var(--variable-color);
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
/* Line highlighting */
pre[data-line] {
position: relative;
}
pre[class*="language-"] > code[class*="language-"] {
position: relative;
z-index: 1;
}
.line-highlight {
position: absolute;
left: 0;
right: 0;
padding: inherit 0;
margin-top: 1em;
background: var(--highlight-background);
box-shadow: inset 5px 0 0 var(--highlight-accent);
z-index: 0;
pointer-events: none;
line-height: inherit;
white-space: pre;
}
我有三个样式表。
style.css
将 CSS 变量保存在根目录中
normalize.css
prism.css
包含语法高亮的样式。这是我希望用户下载的样式表,但我想为他们提供每个变量的实际十六进制值,而不是 CSS 属性的变量名称。
我的 HTML 中的样式表顺序
<link rel="stylesheet" type="text/css" href="./style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.css"
integrity="sha256-WAgYcAck1C1/zEl5sBl5cfyhxtLgKGdpI3oKyJffVRI=" crossorigin="anonymous" />
<link href="./themes/prism.css" rel="stylesheet" />
编辑
我试图遍历样式表并获取 CSS 变量名称,但其中一些返回为空字符串。
这就是我所做的
const cssRules = document.styleSheets[2].cssRules;
for (var i = 0; i < cssRules.length; i++) {
const regexp = /(?:var\(--)[a-zA-z\-]*(?:\))/
let cssVariables = cssRules[i].cssText.matchAll(regexp)
cssVariables = Array.from(cssVariables)
console.log(cssVariables)
}
这是控制台中的结果
var(--base-color)
var(--selected-color)
<empty string>
var(--block-background)
var(--inline-code-color)
<empty string>
var(--comment-color)
var(--punctuation-color)
var(--property-color)
var(--selector-color)
var(--operator-color)
var(--keyword-color)
var(--function-color)
var(--variable-color)
<empty string>
var(--highlight-background)
然后我试图在.replace()
之后进行链接,trim()
但这似乎也不起作用。
解决方案
您可以将文件下载为文本,然后查找并替换变量。
例如:
var s = `pre[class*="language-"] {
background: var(--block-background);
}`
const variables = {"block-background":"#0D2831"};
Object.keys(variables).forEach(key => {
s = s.replace("var(--"+key+")", variables[key]);
});
console.log(s);
推荐阅读
- sql - PostgreSQL:限制行中没有重复的单元格
- android - 使用默认应用程序打开文件(强制执行权限)
- firebase - 在第三个服务器中使用 Firebase 身份验证 cookie
- javascript - 将反应门户呈现到另一个组件 DOM 中是否安全?
- c# - C# MVC 默认模型绑定器不会绑定到 DateTime,但会绑定到字符串
- vue.js - 在组件中点击时未发出事件
- vba - 如何最有效地计算或然值?
- angular - 如果没有点击事件,动态复选框不会很好地更新
- c# - 通过 Polly 重试策略确定最终重试的完成
- docker - 如何在 Docker 中监听端口