我正在研究一种工具而且卡住了。
我正在访问网站的样式表对象,只想获得“CSSFontFaceRule”。我解决了这个问题,但我返回的对象中的输出是一个巨大的字符串。我想将字符串细分为on对象。我还创造了一个小提琴:http://jsfiddle.net/9eoytc6v/1/
这是我的现状:
@font-face {font-family: "Test-Book";
src:
url("https://fontserver.xyz/test.eot?#iefix") format("embedded-opentype"),
url("https://fontserver.xyz/test.woff2") format("woff2"),
url("https://fontserver.xyz/test.woff") format("woff"),
url("https://fontserver.xyz/test.ttf") format("truetype"),
url("https://fontserver.xyz/test.svg#Test-Book") format("svg");
}
let fonts = {};
function getFontPairs(obj) {
let object = obj || {},
stylesheet = document.styleSheets,
rule = null,
length = stylesheet.length,
j;
while (0 <= --length) {
rule = stylesheet[length].rules || stylesheet[length].cssRules || [];
j = rule.length;
while (0 <= --j) {
if (rule[j].constructor.name === "CSSFontFaceRule") {
let sourcesString = rule[j].style.src;
let re = /\s*(?:,|$)\s*/;
let sources = sourcesString.split(re);
let final = [];
sources.forEach(function(element){
let reg = /[ ,]+/;
let srcArray = element.split(reg);
srcArray = srcArray.reverse();
final.push(srcArray);
});
object[rule[j].style.fontFamily] = final;
}
}
}
return object;
}
getFontPairs(fonts);
console.log(fonts);
我尝试使用数组,但我的输出有点凌乱:Current array solution
相反,我希望实现这样的目标:Expected object solution
所以我现在不擅长RegEx,我想要脱掉url("")
和format("")
as。我感谢任何帮助。也许有人可以帮助我提高代码的效率。
只需匹配每个源字符串中的url和格式。一个简单的正则表达式,正则表达式只匹配双引号或单引号内的内容,正则表达式的例子匹配url:
/url\(.(.+?).\)/
这意味着匹配url(.
和.)
之间的任何东西。 parens被逃脱,因此正则表达式不会将它们视为一组。 .
(任何字符)代表引号(双打或单打)。 (.+?)
是我们所关注的,网址,这是使用非gready模式?
,以便它匹配尽可能少的字符,否则你可能最终得到一个网址:https://fontserver.xyz/test.eot?#iefix") format("embedded-opentype
匹配从第一个引用到第二个(超出网址并进入格式区域)。
然后,要构建对象,只需将reduce
的源代码转换为:
let sourcesObj = sources.reduce((acc, source) => { // for each source
let format = source.match(/format\(.(.+?).\)/)[1], // get the format
url = source.match(/url\(.(.+?).\)/)[1]; // and the url
acc[format] = { format, url }; // add them to the sourcesObj under the key format ({ format, url } is short for { format: format, url: url })
return acc;
}, {});
完整代码:
function getFontPairs() {
let object = {},
stylesheet = document.styleSheets,
rule = null,
length = stylesheet.length,
j;
while (0 <= --length) {
rule = stylesheet[length].rules || stylesheet[length].cssRules || [];
j = rule.length;
while (0 <= --j) {
if (rule[j].constructor.name === "CSSFontFaceRule") {
let sourcesString = rule[j].style.src;
let sources = sourcesString.split(/\s*,\s*/);
let sourcesObj = sources.reduce((acc, source) => {
let format = source.match(/format\(.(.+?).\)/)[1],
url = source.match(/url\(.(.+?).\)/)[1];
acc[format] = { format, url };
return acc;
}, {});
object[rule[j].style.fontFamily] = sourcesObj;
}
}
}
return object;
}
let fonts = getFontPairs();
console.log(fonts);
注意:url和format regex的更复杂的替代方法是:
/url(\s*["'](.+?)["']\s*)/
其中处理有url( "..." )
等空格并寻找引号("
或'
)的情况是安全的。同样的事情可以应用于格式正则表达式。
编辑:
如果某个源有一个缺少的字段,那么在访问组[1]
之前,只需检查格式和url正则表达式是否确实匹配了某些内容:
let sourcesObj = sources.reduce((acc, source) => {
let format = source.match(/format\(.(.+?).\)/),
url = source.match(/url\(.(.+?).\)/);
if(format && url) { // if and only if the two regexes matched what they are intended for
acc[format[1]] = { format: format[1], url: url[1] }; // add the current source to 'sourcesObj' (notice the '[1]' is used after we've made sure that neither 'format' nor 'url' are 'null')
}
return acc;
}, {});
编辑2:
当format
缺失时,请替换为"Unknown"
:
let sourcesObj = sources.reduce((acc, source) => {
let format = source.match(/format\(.(.+?).\)/),
url = source.match(/url\(.(.+?).\)/)[1];
format = format? format[1]: "Unknown";
acc = { format, url };
return acc;
}, {});