细分字符串并返回对象

时间:2018-11-06 20:39:30

标签: javascript css arrays regex javascript-objects

我正在使用工具并卡住。

我正在访问网站的样式表对象,只想获取“ 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("")。 感谢您的帮助。也许有人可以帮忙提供更高效率的代码版本。

1 个答案:

答案 0 :(得分:0)

只需匹配每个源字符串的url和格式。一个简单的正则表达式就可以了,正则表达式只匹配双引号或单引号中的内容,正则表达式的示例可以匹配网址:

/url\(.(.+?).\)/

这意味着匹配url(..)之间的任何内容。括号被转义,因此正则表达式不会将它们视为一个组。 .(任何字符)代表引号(双精度或单精度)。 (.+?)是我们所感兴趣的URL,它使用的是非预备模式?,因此它将匹配尽可能少的字符,否则您可能会得到如下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( "..." )之类的空格的情况,并寻找引号("')以确保安全。同样的东西也可以应用于正则表达式。


编辑:

如果某些源缺少字段,则只需在访问组[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;
}, {});