Skip to content

Commit

Permalink
♻️ Combine plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
retlehs committed Dec 8, 2024
1 parent 053d0f3 commit ddf413e
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 150 deletions.
123 changes: 0 additions & 123 deletions resources/scripts/build/wordpress.js

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import type { Plugin } from 'vite'
import resolveConfig from 'tailwindcss/resolveConfig'
import {
defaultRequestToExternal,
defaultRequestToHandle,
} from '@wordpress/dependency-extraction-webpack-plugin/lib/util'

// Theme JSON Types
interface ThemeJsonColor {
name: string
slug: string
Expand Down Expand Up @@ -78,33 +83,51 @@ interface ThemeJsonOptions {
title?: string
}

/**
* Converts a slug or kebab-case string into Title Case.
*
* Examples:
* - Input: "primary-color" -> Output: "Primary Color"
* - Input: "text-lg" -> Output: "Text Lg"
*/
// WordPress Plugin Helper Functions
function extractNamedImports(imports: string): string[] {
return imports
.match(/{([^}]+)}/)[1]
.split(',')
.map((s) => s.trim())
}

function handleNamedReplacement(namedImports: string[], external: string[]): string {
return namedImports
.map((imports) => {
const [name, alias = name] = imports
.split(' as ')
.map((script) => script.trim())

return `const ${alias} = ${external.join('.')}.${name};`
})
.join('\n')
}

function handleReplacements(imports: string, external: string[]): string {
if (imports.includes('{')) {
const namedImports = extractNamedImports(imports)
return handleNamedReplacement(namedImports, external)
}

if (imports.includes('* as')) {
const alias = imports.match(/\*\s+as\s+(\w+)/)[1]
return `const ${alias} = ${external.join('.')};`
}

const name = imports.trim()
return `const ${name} = ${external.join('.')};`
}

// Theme JSON Helper Functions
const toTitleCase = (slug: string): string =>
slug
.split('-')
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ')

/**
* Checks if a value is a valid CSS color.
*
* Examples:
* - Input: "#ff0000" -> true
* - Input: "rgb(255, 255, 0)" -> true
* - Input: "invalid-color" -> false
*/
const isValidColor = (value: any): boolean =>
typeof value === 'string' && (value.startsWith('#') || value.startsWith('rgb'))

/**
* Recursively processes a Tailwind color object into an array of ThemeJsonColor.
*/
const processColors = (
obj: Record<string, any>,
prefix = ''
Expand All @@ -129,7 +152,7 @@ const processColors = (
return palette
}

// Convert Tailwind values to Theme JSON structures
// Conversion Functions
const convertTailwindColorsToThemeJson = (config: any): ThemeJsonColor[] =>
processColors(resolveConfig(config).theme.colors)

Expand All @@ -139,7 +162,7 @@ const convertTailwindFontFamiliesToThemeJson = (
Object.entries(resolveConfig(config).theme.fontFamily).map(([name, value]) => ({
name: toTitleCase(name),
slug: name.toLowerCase(),
fontFamily: Array.isArray(value) ? value.join(', ') : value,
fontFamily: Array.isArray(value) ? value.join(', ') : String(value),
}))

const convertTailwindFontSizesToThemeJson = (
Expand All @@ -151,14 +174,91 @@ const convertTailwindFontSizesToThemeJson = (
size: Array.isArray(value) ? value[0] : value,
}))

// Merge default settings with user options
const mergeSettings = (
defaults: ThemeJsonSettings,
overrides: ThemeJsonSettings | undefined
): ThemeJsonSettings => ({ ...defaults, ...overrides })

// Plugin definition
export default function wordPressThemeJson(options: ThemeJsonOptions = {}): Plugin {
// Plugin Exports
export function wordpressPlugin(): Plugin {
const dependencies = new Set<string>()

return {
name: 'wordpress-plugin',
enforce: 'post',
transform(code: string, id: string) {
if (!id.endsWith('.js')) {
return
}

const imports = [
...(code.match(/^import .+ from ['"]@wordpress\/[^'"]+['"]/gm) || []),
...(code.match(/^import ['"]@wordpress\/[^'"]+['"]/gm) || []),
]

imports.forEach((statement) => {
const match =
statement.match(/^import (.+) from ['"]@wordpress\/([^'"]+)['"]/) ||
statement.match(/^import ['"]@wordpress\/([^'"]+)['"]/)

if (!match) {
return
}

const [, imports, pkg] = match

if (!pkg) {
return
}

const external = defaultRequestToExternal(`@wordpress/${pkg}`)
const handle = defaultRequestToHandle(`@wordpress/${pkg}`)

if (external && handle) {
dependencies.add(handle)

const replacement = imports
? handleReplacements(imports, external)
: `const ${pkg.replace(/-([a-z])/g, (_, letter) =>
letter.toUpperCase()
)} = ${external.join('.')};`

code = code.replace(statement, replacement)
}
})

return { code, map: null }
},
generateBundle() {
this.emitFile({
type: 'asset',
fileName: 'editor.deps.json',
source: JSON.stringify([...dependencies]),
})
},
}
}

export function wordpressRollupPlugin(): Plugin {
return {
name: 'wordpress-rollup-plugin',
options(opts: any) {
opts.external = (id: string) => id.startsWith('@wordpress/')
opts.output = opts.output || {}
opts.output.globals = (id: string) => {
if (id.startsWith('@wordpress/')) {
const packageName = id.replace('@wordpress/', '')
return `wp.${packageName.replace(/-([a-z])/g, (_, letter) =>
letter.toUpperCase()
)}`
}
}
return opts
},
}
}

export function wordPressThemeJson(options: ThemeJsonOptions = {}): Plugin {
const defaultSettings: ThemeJsonSettings = {
background: { backgroundImage: true },
color: {
Expand All @@ -182,7 +282,6 @@ export default function wordPressThemeJson(options: ThemeJsonOptions = {}): Plug

return {
name: 'wordpress-theme-json',

generateBundle() {
const themeJson: Record<string, any> = {
__generated__: '⚠️ This file is generated. Do not edit.',
Expand Down Expand Up @@ -216,7 +315,6 @@ export default function wordPressThemeJson(options: ThemeJsonOptions = {}): Plug
}
}

// Append optional fields
if (options.customTemplates) themeJson.customTemplates = options.customTemplates
if (options.patterns) themeJson.patterns = options.patterns
if (options.styles) themeJson.styles = options.styles
Expand All @@ -230,4 +328,4 @@ export default function wordPressThemeJson(options: ThemeJsonOptions = {}): Plug
})
},
}
}
}
2 changes: 1 addition & 1 deletion vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import laravel from 'laravel-vite-plugin'
import {
wordpressPlugin,
wordpressRollupPlugin,
wordPressThemeJson,
} from './resources/scripts/build/wordpress'
import wordPressThemeJson from './resources/scripts/build/theme-json'
import tailwindConfig from './tailwind.config.js'

export default defineConfig({
Expand Down

0 comments on commit ddf413e

Please sign in to comment.