react-native-svg-app-icon
Version:
App icon generator for React Native projects
149 lines (121 loc) • 5.43 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.inputImageSize = exports.inputContentSize = void 0;
exports.mapInput = mapInput;
exports.readIcon = readIcon;
var fse = _interopRequireWildcard(require("fs-extra"));
var _path = _interopRequireDefault(require("path"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
const defaultBackgroundPath = _path.default.join(__dirname, "..", "assets", "default-icon-background.svg");
const inputImageSize = 108;
exports.inputImageSize = inputImageSize;
const inputContentSize = 72;
exports.inputContentSize = inputContentSize;
async function readIcon(config) {
if (config.backgroundPath) {
console.debug("Reading background file", config.backgroundPath);
}
if (config.foregroundPath) {
console.debug("Reading file", config.foregroundPath);
}
const fullConfig = getConfig(config);
return {
lastModified: await getLastModifiedTime(fullConfig),
read: lazyLoadProvider(fullConfig)
};
}
function getConfig(config) {
return {
backgroundPath: config.backgroundPath || defaultBackgroundPath,
foregroundPath: config.foregroundPath || "./icon.svg"
};
}
async function getLastModifiedTime(config) {
const fileModifiedTimes = await Promise.all([fse.stat(config.backgroundPath).then(stat => stat.mtimeMs), fse.stat(config.foregroundPath).then(stat => stat.mtimeMs)]);
return Math.max(...fileModifiedTimes);
}
function lazyLoadProvider(config) {
let lazyLoadedData = undefined;
return function () {
if (lazyLoadedData === undefined) {
lazyLoadedData = loadData(config);
}
return lazyLoadedData;
};
}
async function loadData(config) {
const sharpImport = await Promise.resolve().then(() => _interopRequireWildcard(require("sharp")));
const warmedSharpInstance = await warmupSharp(sharpImport.default);
const [backgroundImageData, foregroundImageData] = await Promise.all([readImage(warmedSharpInstance, config.backgroundPath), readImage(warmedSharpInstance, config.foregroundPath)]);
const validBackgroundImage = validateBackgroundImage(backgroundImageData);
return {
sharp: warmedSharpInstance,
backgroundImageData: validBackgroundImage,
foregroundImageData: foregroundImageData
};
} // First run might cause a xmllib error, run safe warmup
// See https://github.com/lovell/sharp/issues/1593
async function warmupSharp(sharp) {
try {
await sharp(Buffer.from(`<svg xmlns="http://www.w3.org/2000/svg"><rect width="1" height="1" /></svg>`, "utf-8")).metadata();
} catch {// Error only occurs once, so now safe to use sharp
}
return sharp;
}
async function readImage(sharp, filePath) {
const fileData = await fse.readFile(filePath);
const sharpInstance = sharp(fileData);
const [metadata, stats] = await Promise.all([sharpInstance.metadata(), sharpInstance.stats()]);
const validMetadata = validateMetadata(metadata);
return {
data: fileData,
metadata: validMetadata,
stats: stats
};
}
function validateMetadata(metadata) {
if (metadata.format !== "svg") {
throw new Error(`Unsupported image format ${metadata.format || "undefined"}.` + `Only SVG images are supported.`);
}
if (!metadata.density || !metadata.width || !metadata.height) {
throw new Error("Unsupported image, missing size and density");
}
if (metadata.width !== metadata.height) {
throw new Error("Input image not square");
} // TODO: Support different sized images
if (metadata.width !== inputImageSize || metadata.height !== inputImageSize) {
throw new Error("Input image size not 108x108");
}
return { ...metadata,
format: metadata.format,
width: metadata.width,
height: metadata.height,
density: metadata.density
};
}
function validateBackgroundImage(imageData) {
if (imageData.stats.isOpaque) {
return { ...imageData,
stats: { ...imageData.stats,
isOpaque: imageData.stats.isOpaque
}
};
} else {
throw new Error("Background image needs to be opaque");
}
}
function mapInput(fileInput, mapFunction) {
return { ...fileInput,
read: async () => {
const data = await fileInput.read();
return {
sharp: data.sharp,
...mapFunction(data)
};
}
};
}
;