|
|
@@ -27,7 +27,7 @@ this.fontsMinifier = this.fontsMinifier || (() => {
|
|
|
const REGEXP_URL_NO_QUOTES_FN = /url\s*\(\s*(.*?)\s*\)/i;
|
|
|
|
|
|
return {
|
|
|
- process: (doc, removeUnusedCSSRules) => {
|
|
|
+ process: (doc, removeUnusedCSSRules, secondPass) => {
|
|
|
const declaredFonts = new Set();
|
|
|
const usedFonts = new Set();
|
|
|
const stats = {
|
|
|
@@ -44,7 +44,7 @@ this.fontsMinifier = this.fontsMinifier || (() => {
|
|
|
if (style.sheet) {
|
|
|
const processedRules = style.sheet.cssRules.length;
|
|
|
stats.rules.processed += processedRules;
|
|
|
- style.textContent = processRules(doc, style.sheet.cssRules, declaredFonts, usedFonts, removeUnusedCSSRules, stats);
|
|
|
+ style.textContent = processRules(doc, style.sheet.cssRules, declaredFonts, usedFonts, removeUnusedCSSRules, stats, secondPass);
|
|
|
stats.rules.discarded += processedRules - style.sheet.cssRules.length;
|
|
|
}
|
|
|
});
|
|
|
@@ -67,13 +67,13 @@ this.fontsMinifier = this.fontsMinifier || (() => {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
- function processRules(doc, rules, declaredFonts, usedFonts, removeUnusedCSSRules, stats) {
|
|
|
+ function processRules(doc, rules, declaredFonts, usedFonts, removeUnusedCSSRules, stats, secondPass) {
|
|
|
let stylesheetContent = "";
|
|
|
if (rules) {
|
|
|
Array.from(rules).forEach(rule => {
|
|
|
if (rule.type == CSSRule.MEDIA_RULE) {
|
|
|
stylesheetContent += "@media " + Array.prototype.join.call(rule.media, ",") + " {";
|
|
|
- stylesheetContent += processRules(doc, rule.cssRules, declaredFonts, usedFonts, removeUnusedCSSRules, stats);
|
|
|
+ stylesheetContent += processRules(doc, rule.cssRules, declaredFonts, usedFonts, removeUnusedCSSRules, stats, secondPass);
|
|
|
stylesheetContent += "}";
|
|
|
} else if (removeUnusedCSSRules && rule.type == CSSRule.STYLE_RULE) {
|
|
|
if (rule.style && rule.style.fontFamily) {
|
|
|
@@ -91,7 +91,11 @@ this.fontsMinifier = this.fontsMinifier || (() => {
|
|
|
if (src) {
|
|
|
const fontSources = src.match(/url\(.*?\)\s*(,|$)/g);
|
|
|
if (fontSources) {
|
|
|
- cssText = processFontFaceRule(rule, fontSources, stats);
|
|
|
+ if (secondPass || testUnicodeRange(doc, rule)) {
|
|
|
+ cssText = processFontFaceRule(rule, fontSources, stats);
|
|
|
+ } else {
|
|
|
+ cssText = "";
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -102,6 +106,41 @@ this.fontsMinifier = this.fontsMinifier || (() => {
|
|
|
return stylesheetContent;
|
|
|
}
|
|
|
|
|
|
+ function testUnicodeRange(doc, rule) {
|
|
|
+ const unicodeRange = rule.style.getPropertyValue("unicode-range");
|
|
|
+ const docContent = doc.body.outerText;
|
|
|
+ if (unicodeRange) {
|
|
|
+ const unicodeRanges = unicodeRange.split(/\s*,\s*/);
|
|
|
+ const result = unicodeRanges.filter(rangeValue => {
|
|
|
+ const range = rangeValue.split(/-/);
|
|
|
+ if (range.length == 2) {
|
|
|
+ range[0] = transformRange(range[0]);
|
|
|
+ const regExpString = "[" + range[0] + "-\\u" + range[1] + "]";
|
|
|
+ return (new RegExp(regExpString)).test(docContent);
|
|
|
+ }
|
|
|
+ if (range.length == 1) {
|
|
|
+ if (range[0].includes("?")) {
|
|
|
+ const firstRange = transformRange(range[0]);
|
|
|
+ const secondRange = firstRange;
|
|
|
+ const regExpString = "[" + firstRange.replace(/\?/g, "0") + "-" + secondRange.replace(/\?/g, "F") + "]";
|
|
|
+ return (new RegExp(regExpString)).test(docContent);
|
|
|
+
|
|
|
+ } else {
|
|
|
+ const regExpString = "[" + transformRange(range[0]) + "]";
|
|
|
+ return (new RegExp(regExpString)).test(docContent);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ });
|
|
|
+ return result.length;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ function transformRange(range) {
|
|
|
+ return range.replace(/^U\+/i, "\\u");
|
|
|
+ }
|
|
|
+
|
|
|
function processFontFaceRule(rule, fontSources, stats) {
|
|
|
fontSources = fontSources.map(fontSrc => {
|
|
|
const fontFormatMatch = fontSrc.match(/format\((.*?)\)\s*,?$/);
|