Просто сопоставьте URL и формат из каждой исходной строки. Подойдет простое регулярное выражение, регулярное выражение просто совпадает с тем, что в двойных или одинарных кавычках, например, регулярное выражение соответствует URL:
/url\(.(.+?).\)/
Что означает совпадение чего-либо между url(.
и .)
. Парень сбежал, чтобы регулярное выражение не смотрело на них как на группу. .
(любой символ) для обозначения кавычек (двойных или одинарных). (.+?)
- это то, что нас интересует, URL-адрес, он использует режим non-gready ?
, чтобы он соответствовал как можно меньшему числу символов, в противном случае вы можете получить URL-адрес, подобный: https://fontserver.xyz/test.eot?#iefix") format("embedded-opentype
, который соответствует первой цитате второй (выходит за пределы URL и входит в территорию формата).
Затем, чтобы построить объект, просто 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 и регулярному выражению формата будет:
/url(\s*["'](.+?)["']\s*)/
, который обрабатывает случаи, когда есть пробелы, такие как url( "..." )
, и ищет кавычки ("
или '
), чтобы быть безопасными. То же самое можно применить к формату регулярных выражений.
EDIT:
Если в каком-либо источнике отсутствует поле, просто проверьте, действительно ли регулярные выражения формата и URL-адреса соответствуют чему-либо, прежде чем получить доступ к группе [1]
:
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;
}, {});