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

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

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

问题

  1. /* latin */
  2. @font-face {
  3. font-family: 'Poppins';
  4. font-style: italic;
  5. font-weight: 200;
  6. font-display: swap;
  7. src: url(https://fonts.gstatic.com/s/poppins/v20/pxiDyp8kv8JHgFVrJJLmv1pVF9eOYktMqg.woff2) format('woff2');
  8. }
  9. /* devanagari */
  10. @font-face {
  11. font-family: 'Poppins';
  12. font-style: italic;
  13. font-weight: 300;
  14. font-display: swap;
  15. src: url(https://fonts.gstatic.com/s/poppins/v20/pxiDyp8kv8JHgFVrJJLm21lVFteOYktMqlap.woff2) format('woff2');
  16. }
  17. /* latin */
  18. @font-face {
  19. font-family: 'Poppins';
  20. font-style: italic;
  21. font-weight: 400;
  22. font-display: swap;
  23. src: url(https://fonts.gstatic.com/s/poppins/v20/pxiGyp8kv8JHgFVrJJLucHtAOvWDSA.woff2) format('woff2');
  24. }

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:

  1. /* latin */
  2. @font-face {
  3. font-family: 'Poppins';
  4. font-style: italic;
  5. font-weight: 200;
  6. font-display: swap;
  7. src: url(https://fonts.gstatic.com/s/poppins/v20/pxiDyp8kv8JHgFVrJJLmv1pVF9eOYktMqg.woff2) format('woff2');
  8. }
  9. /* devanagari */
  10. @font-face {
  11. font-family: 'Poppins';
  12. font-style: italic;
  13. font-weight: 300;
  14. font-display: swap;
  15. src: url(https://fonts.gstatic.com/s/poppins/v20/pxiDyp8kv8JHgFVrJJLm21lVFteOYktMqlap.woff2) format('woff2');
  16. }
  17. /* latin */
  18. @font-face {
  19. font-family: 'Poppins';
  20. font-style: italic;
  21. font-weight: 400;
  22. font-display: swap;
  23. src: url(https://fonts.gstatic.com/s/poppins/v20/pxiGyp8kv8JHgFVrJJLucHtAOvWDSA.woff2) format('woff2');
  24. }

Required Data: [200, 300, 400]

Looking for JS solution.

答案1

得分: 2

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

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

  1. /**
  2. * 这将是通过fileReader/input检索的CSS内容
  3. */
  4. let cssText = `
  5. /* 拉丁字体 */
  6. @font-face {
  7. font-family: 'Poppins';
  8. font-style: italic;
  9. font-weight: 200;
  10. font-display: swap;
  11. src: url(https://fonts.gstatic.com/s/poppins/v20/pxiDyp8kv8JHgFVrJJLmv1pVF9eOYktMqg.woff2) format('woff2');
  12. }
  13. /* 拉丁字体 */
  14. @font-face {
  15. font-family: 'Poppins';
  16. font-style: italic;
  17. font-weight: 400;
  18. font-display: swap;
  19. src: url(https://fonts.gstatic.com/s/poppins/v20/pxiGyp8kv8JHgFVrJJLucHtAOvWDSA.woff2) format('woff2');
  20. }
  21. /* 拉丁扩展字体 */
  22. @font-face {
  23. font-family: 'Agdasima';
  24. font-style: normal;
  25. font-weight: 700;
  26. font-display: swap;
  27. src: url(https://fonts.gstatic.com/s/agdasima/v2/PN_0Rfyxp2f1fUCgAPCGgCza3v3xzHMj54Y.woff2) format('woff2');
  28. }
  29. `;
  30. let cssSheet = new CSSStyleSheet()
  31. cssSheet.replaceSync(cssText)
  32. let rules = [...cssSheet.cssRules]
  33. let fontProps = []
  34. rules.forEach((rule) => {
  35. let type = rule.type
  36. // 类型5是@font-face
  37. if (type === 5) {
  38. let fontFamily = rule.style.getPropertyValue('font-family')
  39. let fontStyle = rule.style.getPropertyValue('font-style')
  40. let fontWeight = rule.style.getPropertyValue('font-weight')
  41. fontProps.push({
  42. fontFamily: fontFamily,
  43. fontWeight: fontWeight,
  44. fontStyle: fontStyle
  45. })
  46. }
  47. })
  48. 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.

  1. /**
  2. * this would be css content
  3. * retrieved via fileReader/input
  4. */
  5. let cssText = `
  6. /* latin */
  7. @font-face {
  8. font-family: 'Poppins';
  9. font-style: italic;
  10. font-weight: 200;
  11. font-display: swap;
  12. src: url(https://fonts.gstatic.com/s/poppins/v20/pxiDyp8kv8JHgFVrJJLmv1pVF9eOYktMqg.woff2) format('woff2');
  13. }
  14. /* latin */
  15. @font-face {
  16. font-family: 'Poppins';
  17. font-style: italic;
  18. font-weight: 400;
  19. font-display: swap;
  20. src: url(https://fonts.gstatic.com/s/poppins/v20/pxiGyp8kv8JHgFVrJJLucHtAOvWDSA.woff2) format('woff2');
  21. }
  22. /* latin-ext */
  23. @font-face {
  24. font-family: 'Agdasima';
  25. font-style: normal;
  26. font-weight: 700;
  27. font-display: swap;
  28. src: url(https://fonts.gstatic.com/s/agdasima/v2/PN_0Rfyxp2f1fUCgAPCGgCza3v3xzHMj54Y.woff2) format('woff2');
  29. }
  30. `;
  31. let cssSheet = new CSSStyleSheet()
  32. cssSheet.replaceSync(cssText)
  33. let rules = [...cssSheet.cssRules]
  34. let fontProps = []
  35. rules.forEach((rule) => {
  36. let type = rule.type
  37. // type 5 is @font-face
  38. if (type === 5) {
  39. let fontFamily = rule.style.getPropertyValue("font-family")
  40. let fontStyle = rule.style.getPropertyValue("font-style")
  41. let fontWeight = rule.style.getPropertyValue("font-weight")
  42. fontProps.push({
  43. fontFamily: fontFamily,
  44. fontWeight: fontWeight,
  45. fontStyle: fontStyle
  46. })
  47. }
  48. })
  49. console.log(fontProps)

答案2

得分: 1

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

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

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

  1. /**
  2. * 这将是通过fileReader/input检索的CSS内容
  3. */
  4. let cssText = `
  5. /* 拉丁字体 */
  6. @font-face {
  7. font-family: 'Poppins';
  8. font-style: italic;
  9. font-weight: 200;
  10. font-display: swap;
  11. src: url(https://fonts.gstatic.com/s/poppins/v20/pxiDyp8kv8JHgFVrJJLmv1pVF9eOYktMqg.woff2) format('woff2');
  12. }
  13. /* 拉丁字体 */
  14. @font-face {
  15. font-family: 'Poppins';
  16. font-style: italic;
  17. font-weight: 400;
  18. font-display: swap;
  19. src: url(https://fonts.gstatic.com/s/poppins/v20/pxiGyp8kv8JHgFVrJJLucHtAOvWDSA.woff2) format('woff2');
  20. }
  21. body {
  22. font-family: Poppins;
  23. font-style: italic;
  24. background: red;
  25. }
  26. `;
  27. /**
  28. * 填充已禁用的样式元素
  29. */
  30. cssTmp.textContent = cssText;
  31. /**
  32. * 获取临时样式表通过ID并禁用它,以防止覆盖应用程序的UI样式
  33. */
  34. let stylesheetTmp = [...document.styleSheets].filter((style) => {
  35. return style.ownerNode.id == "cssTmp";
  36. })[0];
  37. // 禁用样式表
  38. stylesheetTmp.disabled = true;
  39. /**
  40. * 获取@font-face规则
  41. */
  42. let rules = [...stylesheetTmp.cssRules];
  43. let fontProps = [];
  44. rules.forEach((rule) => {
  45. let type = rule.type;
  46. // 类型5是@font-face
  47. if (type === 5) {
  48. let fontFamily = rule.style.getPropertyValue('font-family');
  49. let fontStyle = rule.style.getPropertyValue('font-style');
  50. let fontWeight = rule.style.getPropertyValue('font-weight');
  51. fontProps.push({
  52. fontFamily: fontFamily,
  53. fontWeight: fontWeight,
  54. fontStyle: fontStyle
  55. });
  56. }
  57. });
  58. console.log(fontProps);
  1. <style id="cssTmp"></style>
  2. <p>测试</p>

工作原理

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

  1. /**
  2. * this would be css content
  3. * retrieved via fileReader/input
  4. */
  5. let cssText = `
  6. /* latin */
  7. @font-face {
  8. font-family: &#39;Poppins&#39;;
  9. font-style: italic;
  10. font-weight: 200;
  11. font-display: swap;
  12. src: url(https://fonts.gstatic.com/s/poppins/v20/pxiDyp8kv8JHgFVrJJLmv1pVF9eOYktMqg.woff2) format(&#39;woff2&#39;);
  13. }
  14. /* latin */
  15. @font-face {
  16. font-family: &#39;Poppins&#39;;
  17. font-style: italic;
  18. font-weight: 400;
  19. font-display: swap;
  20. src: url(https://fonts.gstatic.com/s/poppins/v20/pxiGyp8kv8JHgFVrJJLucHtAOvWDSA.woff2) format(&#39;woff2&#39;);
  21. }
  22. body {
  23. font-family: Poppins;
  24. font-style: italic;
  25. background: red;
  26. }
  27. `;
  28. /**
  29. * populate disabled
  30. * style element with
  31. * new css rules for parsing
  32. */
  33. cssTmp.textContent = cssText;
  34. /**
  35. * get temporary stylesheet by id
  36. * and disable it
  37. * to prevent overriding the app&#39;s UI style
  38. */
  39. let stylesheetTmp = [...document.styleSheets].filter((style) =&gt; {
  40. return style.ownerNode.id == &quot;cssTmp&quot;;
  41. })[0];
  42. // disable stylesheet
  43. stylesheetTmp.disabled = true;
  44. /**
  45. * get @font-face rules
  46. */
  47. let rules = [...stylesheetTmp.cssRules];
  48. let fontProps = [];
  49. rules.forEach((rule) =&gt; {
  50. let type = rule.type;
  51. // type 5 is @font-face
  52. if (type === 5) {
  53. let fontFamily = rule.style.getPropertyValue(&quot;font-family&quot;);
  54. let fontStyle = rule.style.getPropertyValue(&quot;font-style&quot;);
  55. let fontWeight = rule.style.getPropertyValue(&quot;font-weight&quot;);
  56. fontProps.push({
  57. fontFamily: fontFamily,
  58. fontWeight: fontWeight,
  59. fontStyle: fontStyle
  60. });
  61. }
  62. });
  63. console.log(fontProps);

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

  1. &lt;style id=&quot;cssTmp&quot;&gt;&lt;/style&gt;
  2. &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 -->

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

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

  1. 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 -->

  1. 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:

确定