|
|
@@ -35,6 +35,7 @@ this.fontsAltMinifier = this.fontsAltMinifier || (() => {
|
|
|
const REGEXP_FONT_SRC = /(.*?)\s*,?$/;
|
|
|
const EMPTY_URL_SOURCE = "url(\"data:base64,\")";
|
|
|
const LOCAL_SOURCE = "local(";
|
|
|
+ const MEDIA_ALL = "all";
|
|
|
const FONT_WEIGHTS = {
|
|
|
normal: "400",
|
|
|
bold: "700"
|
|
|
@@ -53,27 +54,80 @@ this.fontsAltMinifier = this.fontsAltMinifier || (() => {
|
|
|
|
|
|
return {
|
|
|
process: (doc, stylesheets) => {
|
|
|
- const fontsDetails = new Map();
|
|
|
+ const fontsDetails = {
|
|
|
+ fonts: new Map(),
|
|
|
+ medias: new Map(),
|
|
|
+ supports: new Map()
|
|
|
+ };
|
|
|
const stats = { rules: { processed: 0, discarded: 0 }, fonts: { processed: 0, discarded: 0 } };
|
|
|
+ let sheetIndex = 0;
|
|
|
stylesheets.forEach(stylesheetInfo => {
|
|
|
const cssRules = stylesheetInfo.stylesheet.children;
|
|
|
stats.rules.processed += cssRules.getSize();
|
|
|
stats.rules.discarded += cssRules.getSize();
|
|
|
- getFontsDetails(doc, cssRules, fontsDetails);
|
|
|
+ if (stylesheetInfo.mediaText && stylesheetInfo.mediaText != MEDIA_ALL) {
|
|
|
+ const mediaFontsDetails = createFontsDetailsInfo();
|
|
|
+ mediaFontsDetails.medias.set("media-" + sheetIndex + "-" + stylesheetInfo.mediaText, mediaFontsDetails);
|
|
|
+ getFontsDetails(doc, cssRules, sheetIndex, mediaFontsDetails);
|
|
|
+ } else {
|
|
|
+ getFontsDetails(doc, cssRules, sheetIndex, fontsDetails);
|
|
|
+ }
|
|
|
+ sheetIndex++;
|
|
|
});
|
|
|
processFontDetails(fontsDetails);
|
|
|
+ sheetIndex = 0;
|
|
|
stylesheets.forEach(stylesheetInfo => {
|
|
|
const cssRules = stylesheetInfo.stylesheet.children;
|
|
|
- processFontFaceRules(cssRules, fontsDetails, "all", stats);
|
|
|
+ if (stylesheetInfo.mediaText && stylesheetInfo.mediaText != MEDIA_ALL) {
|
|
|
+ processFontFaceRules(cssRules, sheetIndex, fontsDetails.medias.get("media-" + sheetIndex + "-" + stylesheetInfo.mediaText), stats);
|
|
|
+ } else {
|
|
|
+ processFontFaceRules(cssRules, sheetIndex, fontsDetails, stats);
|
|
|
+ }
|
|
|
stats.rules.discarded -= cssRules.getSize();
|
|
|
+ sheetIndex++;
|
|
|
});
|
|
|
return stats;
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+ function getFontsDetails(doc, cssRules, sheetIndex, mediaFontsDetails) {
|
|
|
+ let mediaIndex = 0, supportsIndex = 0;
|
|
|
+ cssRules.forEach(cssRule => {
|
|
|
+ if (cssRule.type == "Atrule" && cssRule.name == "media" && cssRule.block && cssRule.block.children && cssRule.prelude) {
|
|
|
+ const mediaText = cssTree.generate(cssRule.prelude);
|
|
|
+ const fontsDetails = createFontsDetailsInfo();
|
|
|
+ mediaFontsDetails.medias.set("media-" + sheetIndex + "-" + mediaIndex + "-" + mediaText, fontsDetails);
|
|
|
+ mediaIndex++;
|
|
|
+ getFontsDetails(doc, cssRule.block.children, sheetIndex, fontsDetails);
|
|
|
+ } if (cssRule.type == "Atrule" && cssRule.name == "supports" && cssRule.block && cssRule.block.children && cssRule.prelude) {
|
|
|
+ const supportsText = cssTree.generate(cssRule.prelude);
|
|
|
+ const fontsDetails = createFontsDetailsInfo();
|
|
|
+ mediaFontsDetails.supports.set("supports-" + sheetIndex + "-" + supportsIndex + "-" + supportsText, fontsDetails);
|
|
|
+ supportsIndex++;
|
|
|
+ getFontsDetails(doc, cssRule.block.children, sheetIndex, fontsDetails);
|
|
|
+ } else {
|
|
|
+ if (cssRule.type == "Atrule" && cssRule.name == "font-face") {
|
|
|
+ const fontKey = getFontKey(cssRule);
|
|
|
+ let fontInfo = mediaFontsDetails.fonts.get(fontKey);
|
|
|
+ if (!fontInfo) {
|
|
|
+ fontInfo = [];
|
|
|
+ mediaFontsDetails.fonts.set(fontKey, fontInfo);
|
|
|
+ }
|
|
|
+ const src = getPropertyValue(cssRule, "src");
|
|
|
+ if (src) {
|
|
|
+ const fontSources = src.match(REGEXP_URL_FUNCTION);
|
|
|
+ if (fontSources) {
|
|
|
+ fontSources.forEach(source => fontInfo.unshift(source));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
function processFontDetails(fontsDetails) {
|
|
|
- fontsDetails.forEach((fontInfo, fontKey) => {
|
|
|
- fontsDetails.set(fontKey, fontInfo.map(fontSource => {
|
|
|
+ fontsDetails.fonts.forEach((fontInfo, fontKey) => {
|
|
|
+ fontsDetails.fonts.set(fontKey, fontInfo.map(fontSource => {
|
|
|
const fontFormatMatch = fontSource.match(REGEXP_FONT_FORMAT_VALUE);
|
|
|
let fontFormat;
|
|
|
const urlMatch = fontSource.match(REGEXP_URL_SIMPLE_QUOTES_FN) ||
|
|
|
@@ -103,19 +157,26 @@ this.fontsAltMinifier = this.fontsAltMinifier || (() => {
|
|
|
return { src: fontSource.match(REGEXP_FONT_SRC)[1], fontUrl, format: fontFormat };
|
|
|
}));
|
|
|
});
|
|
|
+ fontsDetails.medias.forEach(mediaFontsDetails => processFontDetails(mediaFontsDetails));
|
|
|
}
|
|
|
|
|
|
- function processFontFaceRules(cssRules, fontsDetails, media, stats) {
|
|
|
+ function processFontFaceRules(cssRules, sheetIndex, fontsDetails, stats) {
|
|
|
const removedRules = [];
|
|
|
+ let mediaIndex = 0, supportsIndex = 0;
|
|
|
for (let cssRule = cssRules.head; cssRule; cssRule = cssRule.next) {
|
|
|
const ruleData = cssRule.data;
|
|
|
- if (ruleData.type == "Atrule" && ruleData.name == "media" && ruleData.block && ruleData.prelude && ruleData.prelude.children) {
|
|
|
+ if (ruleData.type == "Atrule" && ruleData.name == "media" && ruleData.block && ruleData.block.children && ruleData.prelude) {
|
|
|
const mediaText = cssTree.generate(ruleData.prelude);
|
|
|
- processFontFaceRules(ruleData.block.children, fontsDetails, mediaText, stats);
|
|
|
- } else if (ruleData.type == "Atrule" && ruleData.name == "font-face" && (media.includes("all") || media.includes("screen"))) {
|
|
|
- const fontInfo = fontsDetails.get(getFontKey(ruleData));
|
|
|
+ processFontFaceRules(ruleData.block.children, sheetIndex, fontsDetails.medias.get("media-" + sheetIndex + "-" + mediaIndex + "-" + mediaText), stats);
|
|
|
+ mediaIndex++;
|
|
|
+ } else if (ruleData.type == "Atrule" && ruleData.name == "supports" && ruleData.block && ruleData.block.children && ruleData.prelude) {
|
|
|
+ const supportsText = cssTree.generate(ruleData.prelude);
|
|
|
+ processFontFaceRules(ruleData.block.children, sheetIndex, fontsDetails.supports.get("supports-" + sheetIndex + "-" + supportsIndex + "-" + supportsText), stats);
|
|
|
+ supportsIndex++;
|
|
|
+ } else if (ruleData.type == "Atrule" && ruleData.name == "font-face") {
|
|
|
+ const fontInfo = fontsDetails.fonts.get(getFontKey(ruleData));
|
|
|
if (fontInfo) {
|
|
|
- fontsDetails.delete(getFontKey(ruleData));
|
|
|
+ fontsDetails.fonts.delete(getFontKey(ruleData));
|
|
|
processFontFaceRule(ruleData, fontInfo, stats);
|
|
|
} else {
|
|
|
removedRules.push(cssRule);
|
|
|
@@ -171,30 +232,6 @@ this.fontsAltMinifier = this.fontsAltMinifier || (() => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- function getFontsDetails(doc, cssRules, fontsDetails) {
|
|
|
- cssRules.forEach(cssRule => {
|
|
|
- if (cssRule.type == "Atrule" && cssRule.name == "media" && cssRule.block) {
|
|
|
- getFontsDetails(doc, cssRule.block.children, fontsDetails);
|
|
|
- } else {
|
|
|
- if (cssRule.type == "Atrule" && cssRule.name == "font-face") {
|
|
|
- const fontKey = getFontKey(cssRule);
|
|
|
- let fontInfo = fontsDetails.get(fontKey);
|
|
|
- if (!fontInfo) {
|
|
|
- fontInfo = [];
|
|
|
- fontsDetails.set(fontKey, fontInfo);
|
|
|
- }
|
|
|
- const src = getPropertyValue(cssRule, "src");
|
|
|
- if (src) {
|
|
|
- const fontSources = src.match(REGEXP_URL_FUNCTION);
|
|
|
- if (fontSources) {
|
|
|
- fontSources.forEach(source => fontInfo.unshift(source));
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
function getFontKey(cssRule) {
|
|
|
return JSON.stringify([
|
|
|
getFontFamily(getPropertyValue(cssRule, "font-family")),
|
|
|
@@ -226,4 +263,12 @@ this.fontsAltMinifier = this.fontsAltMinifier || (() => {
|
|
|
return FONT_STRETCHES[stretch] || stretch;
|
|
|
}
|
|
|
|
|
|
+ function createFontsDetailsInfo() {
|
|
|
+ return {
|
|
|
+ fonts: new Map(),
|
|
|
+ medias: new Map(),
|
|
|
+ supports: new Map()
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
})();
|