/* eslint-env node */ const fs = require('fs'); const path = require('path'); const glob = require('glob'); const { stringify } = require('qs'); const localFontPath = path.join(__dirname, 'RobotoCondensed-Regular.ttf'); const localFontName = 'RobotoCondensed'; const scale = 2; module.exports = async function(content) { this.cacheable && this.cacheable(); const callback = this.async(); const { publicPath } = this._compiler.options.output; const ROOT_PATH = path.join(this.rootContext, 'src'); const localeName = path.basename(this.resourcePath, `.${this.resourcePath.split('.').pop()}`); const renderText2Png = (key, { text, size, color }) => new Promise((resolve, reject) => { if (!text || !size || !color) { reject(new Error('text, size and color params are required')); return; } const fileName = `${key.replace(/\./g, '_')}_${localeName}.png`; const args = { localFontPath, localFontName, text, color, font: `${size * scale}px RobotoCondensed`, // eslint-disable-line generator-star-spacing }; const renderTextRequest = `text2png-loader?${stringify(args)}!`; const emitFileRequest = `image-size-loader?name=assets${path.sep}${fileName}?[hash]!${renderTextRequest}`; this.loadModule(emitFileRequest, (err, module) => { if (err) { reject(err); return; } global.__webpack_public_path__ = publicPath; // eslint-disable-line camelcase const { src, width, height } = this.exec(module, fileName); Reflect.deleteProperty(global, '__webpack_public_path__'); const targetWidth = Math.ceil(width / scale); const targetHeight = Math.ceil(height / scale); resolve(`${text}`); }); }); const examine = (key, value) => new Promise((resolve, reject) => { const pathParts = key.split('.'); const id = pathParts.pop(); const pattern = path.join(ROOT_PATH, pathParts.join('/'), '*.intl.json'); // glob always uses linux separators glob(pattern.replace(/\\/g, '/'), (err, matches) => { if (err) { reject(err); return; } if (matches.length === 0) { this.emitWarning(`Unable to find corresponding intl file for ${key} key`); resolve(value); return; } for (const path of matches) { const json = JSON.parse(fs.readFileSync(path)); const descriptor = json[id]; if (!descriptor) { continue; } this.addDependency(path); if (typeof descriptor === 'string') { resolve(value); continue; } if (typeof descriptor !== 'object') { this.emitWarning('Unknown value type'); continue; } const { type } = descriptor; if (type !== 'text2png') { this.emitWarning(`Unsupported object key type "${type}"`); continue; } renderText2Png(key, { ...descriptor, text: value, }).then(resolve).catch(reject); return; } resolve(value); }); }); const json = JSON.parse(content); const result = JSON.stringify(await Object.keys(json).reduce(async (translationsPromise, key) => { const translations = await translationsPromise; translations[key] = await examine(key, json[key]); return translations; }, Promise.resolve({}))); callback(null, ` import { defineMessages } from 'react-intl'; export default defineMessages(${result}); `); };