简体   繁体   English

如何为新样式表生成 CSS 变量值

[英]How to generate CSS variable values to a new stylesheet

I'm working on a project in which a user can select colors from a color input and create their own theme dynamically using CSS variables.我正在开发一个项目,在该项目中,用户可以从颜色输入中选择颜色并使用 CSS 变量动态创建自己的主题。 I'd like the user to be able to download the entire CSS file with the values they selected.我希望用户能够使用他们选择的值下载整个 CSS 文件。

My issue : The CSS file downloaded doesn't display the actual color values, but shows the variable name.我的问题:下载的 CSS 文件不显示实际颜色值,但显示变量名称。

NOT WANTED

pre[class*="language-"] {
  background: var(--block-background);
}

instead of代替

WANTED OUTPUT

pre[class*="language-"] {
  background: #0D2831;
}

I know I can get CSS property values by doing the following.我知道我可以通过执行以下操作来获取 CSS 属性值。

const styles = getComputedStyle(document.documentElement)
const value = String(styles.getPropertyValue('--block-background')).trim()

I figured that I would create a function that loops through all my CSS variables and grabs the corresponding property values and then adds them to a new stylesheet for the user to download, but I got lost along the way.我想我会创建一个函数来循环遍历我所有的 CSS 变量并获取相应的属性值,然后将它们添加到一个新的样式表中供用户下载,但我在此过程中迷路了。 I currently have two CSS files, a main.css and a prism.css .我目前有两个 CSS 文件,一个main.css和一个prism.css The main.css file holds the page styling and all CSS variables within the root. main.css文件包含页面样式和根目录中的所有 CSS 变量。 The prism.css file contains the theme in which I want the user to be able to download. prism.css文件包含我希望用户能够下载的主题。

I'm trying to find a way to create a new stylesheet that contains everything within the prism.css file but has the actual color hex code instead of the CSS variable name as a value to the given CSS property.我试图找到一种方法来创建一个新样式表,该样式表包含prism.css文件中的所有内容,但具有实际的颜色十六进制代码而不是 CSS 变量名称作为给定 CSS 属性的值。

Index.js索引.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颜色助手.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 }

prism.css棱镜.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;
}

I have three stylesheets.我有三个样式表。

style.css holds the CSS variables in the root style.css将 CSS 变量保存在根目录中

normalize.css

prism.css contains the styles for syntax highlighting. prism.css包含语法高亮的样式。 This is the stylesheet I would like the user to download, but I would like to provide them with the actual hex values for each variable and not the variable name for the CSS property.这是我希望用户下载的样式表,但我希望为他们提供每个变量的实际十六进制值,而不是 CSS 属性的变量名称。

Stylesheet order in my HTML我的 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" />

EDIT编辑

I attempted to loop through the stylesheet and grab the CSS variable names, but some of them returned as an empty string.我试图遍历样式表并获取 CSS 变量名称,但其中一些作为空字符串返回。

This is what I did这就是我所做的

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)
} 

This was the result in the console这是控制台中的结果

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)

I then attempted to chain .replace() after the trim() but that didn't seem to work either.然后我尝试在trim() .replace()之后链接.replace() ,但这似乎也不起作用。

You can download the file as text then find and replace the variables.您可以将文件下载为文本,然后查找并替换变量。

For example:例如:

 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);

  1. You are getting empty strings from css rules that do not have var(--something) in them.您从其中没有var(--something) css 规则中获取空字符串。 Like喜欢

    @media print { pre[class*="language-"], code[class*="language-"] { text-shadow: none; } }

    which gives you the first empty string.这给你第一个空字符串。

  2. You are missing var(--operator-background) because matchAll() actually doesn't do what you expect.您缺少var(--operator-background)因为matchAll()实际上并没有按照您的预期执行。 It does它确实

    returns an iterator of all results matching a string against a regular expression返回与正则表达式匹配字符串的所有结果的迭代器

    but the regular expression you have yields only one result.但是您拥有的正则表达式只会产生一个结果。 So you need to add g flag to it所以你需要给它添加g标志

    /(?:var\\(--)[a-zA-z\\-]*(?:\\))/g

  3. mozselection ... Hmm... Not sure, but shouldn't it be -moz-selection ? mozselection ......嗯......不确定,但不应该是-moz-selection吗?

  4. The full loop for replacements can look like this:替换的完整循环如下所示:

     const updated_rules = []; for (var i = 0; i < cssRules.length; i++) { const regexp = /(?:var\\(--)[a-zA-z\\-]*(?:\\))/g; let updated_rule = cssRules[i].cssText; let cssVariables = updated_rule.matchAll(regexp); cssVariables = Array.from(cssVariables).flat(); for (const v of cssVariables) { updated_rule = updated_rule.replace(v, colors[v.slice(6, -1)]); } updated_rules.push(updated_rule); } console.log(updated_rules);

    It's an ugly code, and should be refactored, but...这是一个丑陋的代码,应该重构,但是......

  5. Why would you access css through document.styleSheets anyway?你为什么要通过document.styleSheets访问 css 呢? It's harder than just replacing strings in a css-file and for one thing, I'm not sure if you whould be able to access ::-moz-selection rule on Chrome, and in turn ::-webkit-selection on Firefox这比仅替换 css 文件中的字符串更难,一方面,我不确定您是否能够在 Chrome 上访问::-moz-selection规则,然后在 Firefox 上访问::-webkit-selection

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM