如何在自定义字体CSS文件中查找可用的字重?

huangapple go评论101阅读模式
英文:

How to find the available font-weight in a custom font css file

问题

/* latin */
@font-face {
  font-family: 'Poppins';
  font-style: italic;
  font-weight: 200;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/poppins/v20/pxiDyp8kv8JHgFVrJJLmv1pVF9eOYktMqg.woff2) format('woff2');
}
/* devanagari */
@font-face {
  font-family: 'Poppins';
  font-style: italic;
  font-weight: 300;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/poppins/v20/pxiDyp8kv8JHgFVrJJLm21lVFteOYktMqlap.woff2) format('woff2');
}
/* latin */
@font-face {
  font-family: 'Poppins';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/poppins/v20/pxiGyp8kv8JHgFVrJJLucHtAOvWDSA.woff2) format('woff2');
}

Required Data: [200, 300, 400]

英文:

I am working on a custom font feature where the user can upload a .css file and use it in our editor. In order to do show I need to know the font-weight present in the file, so that I can display them in the dropdown list in the editor.

Please suggest a best way to figure out the font-weight available for the custom font. As user will be uploading the file, therefore I wont be aware of the font-weights.

User Input:

/* latin */
@font-face {
  font-family: 'Poppins';
  font-style: italic;
  font-weight: 200;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/poppins/v20/pxiDyp8kv8JHgFVrJJLmv1pVF9eOYktMqg.woff2) format('woff2');
}
/* devanagari */
@font-face {
  font-family: 'Poppins';
  font-style: italic;
  font-weight: 300;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/poppins/v20/pxiDyp8kv8JHgFVrJJLm21lVFteOYktMqlap.woff2) format('woff2');
}
/* latin */
@font-face {
  font-family: 'Poppins';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/poppins/v20/pxiGyp8kv8JHgFVrJJLucHtAOvWDSA.woff2) format('woff2');
}

Required Data: [200, 300, 400]

Looking for JS solution.

答案1

得分: 2

感谢 @herrstrietzel 提供的上述解决方案。

不再创建带有ID并禁用它的样式标签。我使用了CSSStyleSheet()。以下是我的代码。

/**
 * 这将是通过fileReader/input检索的CSS内容
 */
let cssText = `
 /* 拉丁字体 */
  @font-face {
    font-family: 'Poppins';
    font-style: italic;
    font-weight: 200;
    font-display: swap;
    src: url(https://fonts.gstatic.com/s/poppins/v20/pxiDyp8kv8JHgFVrJJLmv1pVF9eOYktMqg.woff2) format('woff2');
  }

  /* 拉丁字体 */
  @font-face {
    font-family: 'Poppins';
    font-style: italic;
    font-weight: 400;
    font-display: swap;
    src: url(https://fonts.gstatic.com/s/poppins/v20/pxiGyp8kv8JHgFVrJJLucHtAOvWDSA.woff2) format('woff2');
  }

  /* 拉丁扩展字体 */
  @font-face {
    font-family: 'Agdasima';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url(https://fonts.gstatic.com/s/agdasima/v2/PN_0Rfyxp2f1fUCgAPCGgCza3v3xzHMj54Y.woff2) format('woff2');
  }
`;

let cssSheet = new CSSStyleSheet()
cssSheet.replaceSync(cssText)

let rules = [...cssSheet.cssRules]
let fontProps = []
rules.forEach((rule) => {
  let type = rule.type

  // 类型5是@font-face
  if (type === 5) {
    let fontFamily = rule.style.getPropertyValue('font-family')
    let fontStyle = rule.style.getPropertyValue('font-style')
    let fontWeight = rule.style.getPropertyValue('font-weight')
    fontProps.push({
      fontFamily: fontFamily,
      fontWeight: fontWeight,
      fontStyle: fontStyle
    })
  }
})
console.log(fontProps)
英文:

Thanks @herrstrietzel for the above solution.

Instead of creating a style tag with an id and then disabling it. I have used CSSStyleSheet(). Below is my code.

/**
 * this would be css content
 * retrieved via fileReader/input
 */
let cssText = `
 /* latin */
  @font-face {
    font-family: 'Poppins';
    font-style: italic;
    font-weight: 200;
    font-display: swap;
    src: url(https://fonts.gstatic.com/s/poppins/v20/pxiDyp8kv8JHgFVrJJLmv1pVF9eOYktMqg.woff2) format('woff2');
  }

  /* latin */
  @font-face {
    font-family: 'Poppins';
    font-style: italic;
    font-weight: 400;
    font-display: swap;
    src: url(https://fonts.gstatic.com/s/poppins/v20/pxiGyp8kv8JHgFVrJJLucHtAOvWDSA.woff2) format('woff2');
  }

  /* latin-ext */
  @font-face {
    font-family: 'Agdasima';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url(https://fonts.gstatic.com/s/agdasima/v2/PN_0Rfyxp2f1fUCgAPCGgCza3v3xzHMj54Y.woff2) format('woff2');
  }
`;

let cssSheet = new CSSStyleSheet()
cssSheet.replaceSync(cssText)

let rules = [...cssSheet.cssRules]
let fontProps = []
rules.forEach((rule) => {
  let type = rule.type

  // type 5 is @font-face
  if (type === 5) {
    let fontFamily = rule.style.getPropertyValue("font-family")
    let fontStyle = rule.style.getPropertyValue("font-style")
    let fontWeight = rule.style.getPropertyValue("font-weight")
    fontProps.push({
      fontFamily: fontFamily,
      fontWeight: fontWeight,
      fontStyle: fontStyle
    })
  }
})
console.log(fontProps)

答案2

得分: 1

一种方法是将上传的CSS文本追加到文档样式表中,并通过document.styleSheetscssRules属性检索所有属性。

显然,当追加新样式表时,我们不希望覆盖当前应用程序/页面样式,因此我们需要禁用新样式表/样式规则

示例:填充<style>元素并禁用它

/**
 * 这将是通过fileReader/input检索的CSS内容
 */
let cssText = `
 /* 拉丁字体 */
  @font-face {
    font-family: 'Poppins';
    font-style: italic;
    font-weight: 200;
    font-display: swap;
    src: url(https://fonts.gstatic.com/s/poppins/v20/pxiDyp8kv8JHgFVrJJLmv1pVF9eOYktMqg.woff2) format('woff2');
  }

  /* 拉丁字体 */
  @font-face {
    font-family: 'Poppins';
    font-style: italic;
    font-weight: 400;
    font-display: swap;
    src: url(https://fonts.gstatic.com/s/poppins/v20/pxiGyp8kv8JHgFVrJJLucHtAOvWDSA.woff2) format('woff2');
  }

  body {
    font-family: Poppins;
    font-style: italic;
    background: red;
  }
`;

/**
 * 填充已禁用的样式元素
 */
cssTmp.textContent = cssText;

/**
 * 获取临时样式表通过ID并禁用它,以防止覆盖应用程序的UI样式
 */
let stylesheetTmp = [...document.styleSheets].filter((style) => {
  return style.ownerNode.id == "cssTmp";
})[0];

// 禁用样式表
stylesheetTmp.disabled = true;

/**
 * 获取@font-face规则
 */
let rules = [...stylesheetTmp.cssRules];
let fontProps = [];
rules.forEach((rule) => {
  let type = rule.type;

  // 类型5是@font-face
  if (type === 5) {
    let fontFamily = rule.style.getPropertyValue('font-family');
    let fontStyle = rule.style.getPropertyValue('font-style');
    let fontWeight = rule.style.getPropertyValue('font-weight');
    fontProps.push({
      fontFamily: fontFamily,
      fontWeight: fontWeight,
      fontStyle: fontStyle
    });
  }
});

console.log(fontProps);
<style id="cssTmp"></style>
<p>测试</p>

工作原理

  1. 创建一个带有唯一ID(例如 "cssTmp")的<style>元素。
  2. 使用上传的CSS内容填充此元素:cssTmp.textContent = cssText
  3. 通过筛选具有指定ID的所有文档样式表来选择样式表:
let stylesheetTmp = [...document.styleSheets].filter((style) => {
  return style.ownerNode.id == "cssTmp";
})[0];
  1. 禁用此样式表:
stylesheetTmp.disabled = true;
  1. 循环遍历cssRules,首先需要使用spread运算符或使用Array.from()方法使样式规则可迭代:
let rules = [...stylesheetTmp.cssRules];

@font-face规则可以通过其类型(类型为"5")进行过滤。只需添加console.log(rule)以检查规则对象中包含的所有数据。

很可能,您可能需要更多的属性值,包括字体样式(常规/斜体) - 我们可以在预先定义的对象数组中收集这些数据。

现在,您可以使用检索到的数据填充<select>的选项。

英文:

One way to go would be to append your uploaded css text to the document stylesheets and retrieve all properties via document.styleSheets and cssRules properties.

Obviously, when appending a new stylesheet – we don't want to override the current app/page styles – so we need to disable the new stylesheet/style rules.

Example: populate &lt;style&gt; element and disable it

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

/**
* this would be css content
* retrieved via fileReader/input
*/
let cssText = `
/* latin */
@font-face {
font-family: &#39;Poppins&#39;;
font-style: italic;
font-weight: 200;
font-display: swap;
src: url(https://fonts.gstatic.com/s/poppins/v20/pxiDyp8kv8JHgFVrJJLmv1pVF9eOYktMqg.woff2) format(&#39;woff2&#39;);
}
/* latin */
@font-face {
font-family: &#39;Poppins&#39;;
font-style: italic;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/poppins/v20/pxiGyp8kv8JHgFVrJJLucHtAOvWDSA.woff2) format(&#39;woff2&#39;);
}
body {
font-family: Poppins;
font-style: italic;
background: red;
}
`;
/**
* populate disabled
* style element with
* new css rules for parsing
*/
cssTmp.textContent = cssText;
/**
* get temporary stylesheet by id
* and disable it
* to prevent overriding the app&#39;s UI style
*/
let stylesheetTmp = [...document.styleSheets].filter((style) =&gt; {
return style.ownerNode.id == &quot;cssTmp&quot;;
})[0];
// disable stylesheet
stylesheetTmp.disabled = true;
/**
* get @font-face rules
*/
let rules = [...stylesheetTmp.cssRules];
let fontProps = [];
rules.forEach((rule) =&gt; {
let type = rule.type;
// type 5 is @font-face
if (type === 5) {
let fontFamily = rule.style.getPropertyValue(&quot;font-family&quot;);
let fontStyle = rule.style.getPropertyValue(&quot;font-style&quot;);
let fontWeight = rule.style.getPropertyValue(&quot;font-weight&quot;);
fontProps.push({
fontFamily: fontFamily,
fontWeight: fontWeight,
fontStyle: fontStyle
});
}
});
console.log(fontProps);

<!-- language: lang-html -->

&lt;style id=&quot;cssTmp&quot;&gt;&lt;/style&gt;
&lt;p&gt;Test&lt;/p&gt;

<!-- end snippet -->

How it works

  1. create a &lt;style&gt; element with a unique ID e.g "cssTmp"
  2. Populate this element with the uploaded CSS content
    cssTmp.textContent = cssText
  3. Select the stylesheet by filtering all document stylesheets by the specified ID:

<!-- language: lang-js -->

let stylesheetTmp = [...document.styleSheets].filter((style) =&gt; {
return style.ownerNode.id == &quot;cssTmp&quot;;
})[0];
  1. Disable this stylesheet:

<!-- language: lang-js -->

stylesheetTmp.disabled = true;
  1. Loop through cssRules
    We first need to make the styles rules iterable by applying the spread operator or using Array.from() method.

<!-- language: lang-js -->

let rules = [...stylesheetTmp.cssRules];  

@font-face rules can be filtered by their type – which is "5". Just add a console.log(rule) to inspect all data contained in the rule object.

Quite likely, you might need more property values including font styles (regular/italic) – we can collect this data in a previously defined array of objects.

Now you could populate a &lt;select&gt;'s options with the retrieved data.

huangapple
  • 本文由 发表于 2023年6月22日 15:23:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76529468.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定