rollup-plugin-font-subsetter
Version:
A Rollup plugin that subsets fonts at bundle time based on page contents.
73 lines (72 loc) • 3.28 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fontSubsetter = fontSubsetter;
const subset_font_1 = __importDefault(require("subset-font"));
const IsAssetInfo = (info) => {
return info.type === 'asset';
};
const extractCharacterSet = (info) => {
if (IsAssetInfo(info)) {
if (typeof (info.source) === 'string') {
return new Set(info.source);
}
else {
return new Set();
}
}
return new Set(info.code);
};
const defaultPluginOptions = {
verbose: false,
};
function generateBundle(options, bundle, pluginOptions) {
return __awaiter(this, void 0, void 0, function* () {
// list files
const fontFiles = Object.keys(bundle).filter((fileName) => {
return fileName.match(/\.woff2?$/);
});
const sourceFiles = Object.keys(bundle).filter((fileName) => {
return fileName.match(/\.(js|css|htm|html)$/);
});
if (pluginOptions === null || pluginOptions === void 0 ? void 0 : pluginOptions.verbose) {
console.log("subsetting font");
console.log("subset target:", fontFiles);
console.log("subset based on:", sourceFiles);
}
// compute glyph set
const glyphSet = sourceFiles.map((fileName) => extractCharacterSet(bundle[fileName])).reduce((acc, set) => new Set([...acc, ...set]), new Set());
const glyphSetString = Array.from(glyphSet).join('');
if (pluginOptions === null || pluginOptions === void 0 ? void 0 : pluginOptions.verbose) {
console.log("glyph set size:", glyphSet.size);
}
// subset fonts
for (const fileName of fontFiles) {
const font = bundle[fileName];
if (IsAssetInfo(font) && typeof (font.source) !== 'string') {
// Determine target format from filename
const targetFormat = fileName.endsWith('.woff2') ? 'woff2' : 'woff';
const subset = yield (0, subset_font_1.default)(Buffer.from(font.source), glyphSetString, { targetFormat });
font.source = new Uint8Array(subset);
}
}
});
}
function fontSubsetter(options) {
const pluginOptions = Object.assign(Object.assign({}, defaultPluginOptions), options);
return {
name: "font-subsetter",
generateBundle: (options, bundle) => generateBundle(options, bundle, pluginOptions)
};
}