英文:
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.styleSheets
和cssRules
属性检索所有属性。
显然,当追加新样式表时,我们不希望覆盖当前应用程序/页面样式,因此我们需要禁用新样式表/样式规则。
示例:填充<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>
工作原理
- 创建一个带有唯一ID(例如 "cssTmp")的
<style>
元素。 - 使用上传的CSS内容填充此元素:
cssTmp.textContent = cssText
。 - 通过筛选具有指定ID的所有文档样式表来选择样式表:
let stylesheetTmp = [...document.styleSheets].filter((style) => {
return style.ownerNode.id == "cssTmp";
})[0];
- 禁用此样式表:
stylesheetTmp.disabled = true;
- 循环遍历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 <style>
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: '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');
}
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's UI style
*/
let stylesheetTmp = [...document.styleSheets].filter((style) => {
return style.ownerNode.id == "cssTmp";
})[0];
// disable stylesheet
stylesheetTmp.disabled = true;
/**
* get @font-face rules
*/
let rules = [...stylesheetTmp.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);
<!-- language: lang-html -->
<style id="cssTmp"></style>
<p>Test</p>
<!-- end snippet -->
How it works
- create a
<style>
element with a unique ID e.g "cssTmp" - Populate this element with the uploaded CSS content
cssTmp.textContent = cssText
- Select the stylesheet by filtering all document stylesheets by the specified ID:
<!-- language: lang-js -->
let stylesheetTmp = [...document.styleSheets].filter((style) => {
return style.ownerNode.id == "cssTmp";
})[0];
- Disable this stylesheet:
<!-- language: lang-js -->
stylesheetTmp.disabled = true;
- Loop through cssRules
We first need to make the styles rules iterable by applying the spread operator or usingArray.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 <select>
's options with the retrieved data.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论