theme-json-generator
Version:
Generate WordPress theme.json from your tailwind.config with Webpack.
1 lines • 14.5 kB
Source Map (JSON)
{"version":3,"file":"index.esm.mjs","sources":["../src/webpack-plugin/index.js","../src/functions/transform.js","../src/index.js"],"sourcesContent":["const path = require('path');\nconst fs = require('fs');\n\nconst defaults = {\n path: path.resolve('./'),\n from: 'theme.config.js',\n to: 'theme.json',\n schema: 'https://schemas.wp.org/trunk/theme.json',\n version: 2,\n};\n\n/**\n * Webpack plugin class to create file from source.\n *\n * @see https://webpack.js.org/contribute/writing-a-plugin/\n */\nclass ThemeJsonPlugin {\n constructor(options) {\n this.name = 'theme-json-generator';\n this.options = options;\n }\n apply(compiler) {\n compiler.hooks.done.tap('ThemeJsonPlugin', () => {\n const logger = compiler.getInfrastructureLogger(this.name);\n generateThemeJson(this.options, logger);\n });\n }\n}\n\n/**\n * Generate JSON from source file.\n *\n * @param {object|Array} options Array or object of config entries.\n * @param {object} webpackLogger Optional webpack logger.\n */\nfunction generateThemeJson(options, webpackLogger = false) {\n // Determine if the options are an array or object.\n options = !Array.isArray(options) ? [options] : options;\n\n if (!options.length) {\n // Exit if no options are passed.\n if (webpackLogger) {\n webpackLogger.error(\n 'Missing parameters required to generate JSON file.'\n );\n }\n return;\n }\n\n // Loop each item in array.\n for (let i = 0; i < options.length; i++) {\n createJSON(options[i], webpackLogger);\n }\n}\n\n/**\n * Create the JSON file.\n *\n * @param {object} options Config parameters required to create JSON file.\n * @param {object} webpackLogger Optional webpack logger.\n */\nfunction createJSON(options, webpackLogger = false) {\n const params = {...defaults, ...options};\n\n // Exit if required param is missing or path is referencing an outside directory.\n const validPaths = validatePaths(params, webpackLogger);\n if (!validPaths) {\n return;\n }\n\n // Validate the file paths.\n const paths = generatePaths(params);\n\n // Comfirm file exists.\n if (fileExists(paths?.from) && paths?.to) {\n const data = requireUncached(paths.from); // Load config file.\n const out = path.resolve(paths.to); // Path to output file.\n\n // Create theme.json object.\n const json = {\n $schema: params.schema,\n version: params.version,\n ...data,\n };\n\n // Write to file.\n fs.writeFile(out, JSON.stringify(json, null, 3), function (err) {\n if (err) {\n if (webpackLogger) {\n webpackLogger.error(err);\n } else {\n console.warn(err);\n }\n return;\n }\n if (webpackLogger) {\n webpackLogger.info(\n path.basename(params.to) + ' created successfully!'\n );\n }\n });\n } else {\n if (webpackLogger) {\n webpackLogger.error(\n 'Unable to locate source file. Use the `from` option to specify the relative path to the config file and the `to` option to speicify the output file.'\n );\n }\n }\n}\n\nexport {ThemeJsonPlugin, generateThemeJson};\n\n/**\n * Check if a file exists.\n *\n * @param {string} filepath The file path to check.\n * @return {boolean}\n */\nfunction fileExists(filepath) {\n return fs.existsSync(filepath);\n}\n\n/**\n * Uncache a NodeJS require module.\n *\n * @param {string} module The module path to uncache.\n */\nfunction requireUncached(module) {\n delete require.cache[require.resolve(module)];\n return require(module);\n}\n\n/**\n * Vaildate the from and to params do not contain `./`.\n *\n * @param {object} options Webpack config options.\n * @return {object} Modified file and out params.\n */\nfunction generatePaths(params) {\n let {from, to, path} = params;\n\n // Validate the `from` path.\n from = from.replace(/\\/\\//g, '/'); // Remove `//`, from string.\n from = from.charAt(0) === '.' ? from.substring(1) : from; // Remove leading `.` from string.\n from = from.startsWith('/') ? from.substring(1) : from; // Remove leading `/` from string.\n\n // Validate the `to` path.\n to = to.replace(/\\/\\//g, '/'); // Remove // from string.\n to = to.charAt(0) === '.' ? to.substring(1) : to; // Remove leading `.` from string.\n to = to.startsWith('/') ? to.substring(1) : to; //\n\n return {\n from: `${path}/${from}`,\n to: `${path}/${to}`,\n };\n}\n\n/**\n * Validate paths to file and out parameters do not try to back out of the current .\n *\n * @param {object} options Webpack config options.\n * @param {object} webpackLogger Optional webpack logger.\n * @return {boolean} True if paths are valid.\n */\nfunction validatePaths(params, webpackLogger = false) {\n const {path, from, to} = params;\n\n // Exit if any required parameter is empty or missing.\n if (!path || !from || !to) {\n const missing =\n 'Missing parameters required to generate theme.json file.';\n if (webpackLogger) {\n webpackLogger.error(missing);\n } else {\n console.warn(missing);\n }\n return false;\n }\n\n // Exit if any path is outside current directory.\n if (from.includes('../') || to.includes('../')) {\n const msg =\n 'The path, from and to options cannot reference a directory outside of the current base working directory.';\n if (webpackLogger) {\n webpackLogger.error(msg);\n } else {\n console.warn(msg);\n }\n return false;\n }\n\n return true;\n}\n","/**\n * Transform Tailwind config data into readable theme.json data.\n *\n * @param {string} type The data type to return.\n * @param {any} data Tailwind data.\n * @param {Array} customValues Array of custom values to return.\n * @return {Array|Object} The data as an array or object.\n */\nfunction transform(type, data, customValues = []) {\n switch (type) {\n case 'palette':\n case 'spacingSizes':\n case 'fontSizes':\n return data\n ? formatArray(flattenObject(data), customValues, type)\n : false;\n\n case 'fontSizes':\n return data\n ? formatArray(flattenObject(data), customValues, type)\n : false;\n\n default:\n return data ? formatValues(flattenObject(data), customValues) : false;\n }\n}\n\nexport {transform};\n\n/**\n * Format tailwind data for theme.json.\n * e.g.\n * colors: {\n * \"red\": \"#ff0000\",\n * \"black\": \"#000000\",\n * }\n *\n * @param {object} data The data as an object from tailwind.\n * @param {Array} customValues Array of custom values to return.\n * @return {object} The data as an object.\n */\nfunction formatValues(data, customValues = []) {\n const values = {};\n for (const [key, value] of Object.entries(data)) {\n if (customValues.length) {\n // Custom values and key found.\n if (customValues.includes(key)) {\n values[key] = value.toString();\n }\n } else {\n values[key] = value.toString();\n }\n }\n return values;\n}\n\n/**\n * Format tailwnd data to be displayed as an array of options in theme.json.\n * Supported: Pallette, fontSizes, spacingSizes.\n *\n * e.g.\n * {\n * \"name\": \"black\",\n * \"slug\": \"black\",\n * \"color\": \"#000000\"\n * }\n *\n * @param {object} data The data as an object from tailwind.\n * @param {Array} customValues Array of custom values to return.\n * @param {string} type The data type to return.\n * @return {Array} The data as an array of objects.\n */\nfunction formatArray(data, customValues = [], type = 'pallette') {\n const values = [];\n\n // Convert the type to the correct option.\n let option = 'color';\n if (type === 'fontSizes' || type === 'spacingSizes') {\n option = 'size';\n }\n\n for (const [key, value] of Object.entries(data)) {\n values.push({\n name: titleCase(key),\n slug: key,\n [option]: value,\n });\n }\n\n if (!customValues.length) {\n return values; // Return all values.\n }\n\n // Filter values to only return instructed values.\n return values.filter((key) => {\n return customValues.includes(key.slug);\n });\n}\n\n/**\n * Flatten JS object from tailwind.\n *\n * @param {object} obj The object to flatten.\n * @param {object} parent The parent object.\n * @param {object} res The result of the flattened object.\n * @return {object} The flattened object.\n */\nfunction flattenObject(obj, parent, res = {}) {\n for (let key in obj) {\n let propName = parent ? parent + '-' + key : key;\n if (typeof obj[key] === 'object' && !Array.isArray(obj[key])) {\n // Only flatten if object is not an array.\n flattenObject(obj[key], propName, res);\n } else {\n res[propName] = obj[key];\n }\n }\n return res;\n}\n\n/**\n * Convert to titlecase.\n *\n * @param {string} str The string to convert.\n * @return {string} The converted string.\n */\nfunction titleCase(str) {\n if (!str) {\n return '';\n }\n\n // Don't format these words.\n const exceptions = ['of', 'the', 'and'];\n\n // Replace dashes and underscores with spaces.\n str = str.replace(/-/g, ' ').replace(/_/g, ' ');\n\n return str\n .toLowerCase()\n .split(' ')\n .map((word, i) => {\n return exceptions.includes(word) && i != 0\n ? word\n : word.charAt(0).toUpperCase().concat(word.substr(1));\n })\n .join(' ');\n}\n","import {ThemeJsonPlugin, generateThemeJson} from './webpack-plugin';\nimport {transform} from './functions/transform';\n\nmodule.exports = {ThemeJsonPlugin, generateThemeJson, transform};\n"],"names":["path","require","fs","defaults","resolve","from","to","schema","version","generateThemeJson","options","webpackLogger","Array","isArray","length","i","createJSON","error","params","_extends","validPaths","missing","console","warn","includes","msg","validatePaths","paths","replace","charAt","substring","startsWith","generatePaths","existsSync","data","module","cache","requireUncached","out","json","$schema","writeFile","JSON","stringify","err","info","basename","flattenObject","obj","parent","res","key","propName","titleCase","str","exceptions","toLowerCase","split","map","word","toUpperCase","concat","substr","join","exports","ThemeJsonPlugin","this","name","prototype","apply","compiler","_this","hooks","done","tap","logger","getInfrastructureLogger","transform","type","customValues","values","option","_i2","_Object$entries2","Object","entries","_values$push","_Object$entries2$_i","value","push","slug","filter","formatArray","_i","_Object$entries","_Object$entries$_i","toString","formatValues"],"mappings":"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"}