Files
bedrock/resources/js/build/wordpress.js
2025-01-14 08:10:27 -05:00

155 lines
5.0 KiB
JavaScript

import resolveConfig from 'tailwindcss/resolveConfig'
import { defaultRequestToExternal, defaultRequestToHandle } from '@wordpress/dependency-extraction-webpack-plugin/lib/util'
import fs from 'fs'
import path from 'path'
/**
* WordPress dependency extraction for Vite.
*
* This plugin configures Vite to exclude WordPress packages from your bundle
* and instead load them from the `window.wp` global. It also generates a
* dependency file that is read by Sage's setup.php to enqueue required
* WordPress scripts.
*
* @returns {import('vite').Plugin}
*/
const externalMap = new Map()
export function extractWordPressDependencies() {
return {
name: 'wordpress-dependencies',
config() {
return {
build: {
rollupOptions: {
external(id) {
const result = defaultRequestToExternal(id)
if (result) {
externalMap.set(id, result)
return true
}
return false
},
output: {
globals(id) {
const global = externalMap.get(id)
return Array.isArray(global) ? global.join('.') : global
}
}
}
}
}
},
generateBundle(options, bundle) {
const deps = Object.values(bundle)
.filter(chunk => chunk.type === 'chunk' && chunk.isEntry)
.flatMap(chunk => chunk.imports)
.map(defaultRequestToHandle)
.filter(Boolean)
if (deps.length) {
this.emitFile({
type: 'asset',
fileName: 'editor.deps.json',
source: JSON.stringify(deps, null, 2)
})
}
}
}
}
/**
* Generates a WordPress theme.json file by combining:
* - Base theme.json settings
* - Tailwind configuration (colors, fonts, font sizes)
*
* The generated theme.json is emitted to public/build/assets/theme.json
* and provides WordPress with theme settings that match your Tailwind configuration.
*
* @param {Object} options Plugin options
* @param {Object} options.tailwindConfig - The resolved Tailwind configuration object
* @param {boolean} [options.disableTailwindColors=false] - Disable including Tailwind colors in theme.json
* @param {boolean} [options.disableTailwindFonts=false] - Disable including Tailwind fonts in theme.json
* @param {boolean} [options.disableTailwindFontSizes=false] - Disable including Tailwind font sizes in theme.json
* @returns {import('vite').Plugin} Vite plugin
*/
export function processThemeJson({
tailwindConfig,
disableTailwindColors = false,
disableTailwindFonts = false,
disableTailwindFontSizes = false,
}) {
function flattenColors(colors, prefix = '') {
return Object.entries(colors).reduce((acc, [name, value]) => {
const formattedName = name.charAt(0).toUpperCase() + name.slice(1)
if (typeof value === 'string') {
acc.push({
name: prefix ? `${prefix.charAt(0).toUpperCase() + prefix.slice(1)}-${formattedName}` : formattedName,
slug: prefix ? `${prefix}-${name}`.toLowerCase() : name.toLowerCase(),
color: value,
})
} else if (typeof value === 'object') {
acc.push(...flattenColors(value, name))
}
return acc
}, [])
}
const resolvedConfig = resolveConfig(tailwindConfig)
return {
name: 'wordpress-theme-json',
async generateBundle() {
const baseThemeJson = JSON.parse(
fs.readFileSync(path.resolve('./theme.json'), 'utf8')
)
const themeJson = {
__processed__: "This file was generated from the Vite build",
...baseThemeJson,
settings: {
...baseThemeJson.settings,
...((!disableTailwindColors && resolvedConfig.theme?.colors && {
color: {
...baseThemeJson.settings?.color,
palette: flattenColors(resolvedConfig.theme.colors),
},
}) || {}),
...((!disableTailwindFonts && resolvedConfig.theme?.fontFamily && {
typography: {
...baseThemeJson.settings?.typography,
fontFamilies: Object.entries(resolvedConfig.theme.fontFamily)
.map(([name, value]) => ({
name,
slug: name,
fontFamily: Array.isArray(value) ? value.join(',') : value,
})),
},
}) || {}),
...((!disableTailwindFontSizes && resolvedConfig.theme?.fontSize && {
typography: {
...baseThemeJson.settings?.typography,
fontSizes: Object.entries(resolvedConfig.theme.fontSize)
.map(([name, value]) => ({
name,
slug: name,
size: Array.isArray(value) ? value[0] : value,
})),
},
}) || {}),
},
}
delete themeJson.__preprocessed__
this.emitFile({
type: 'asset',
fileName: 'assets/theme.json',
source: JSON.stringify(themeJson, null, 2)
})
},
}
}