Upgrade to version 11.0.1 #1

Merged
steve merged 60 commits from v11.0.1 into main 2025-10-30 22:14:46 +00:00
12 changed files with 704 additions and 1461 deletions
Showing only changes of commit 723506daba - Show all commits

View File

@@ -8,33 +8,35 @@ namespace App;
use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Vite; use Illuminate\Support\Facades\Vite;
use Illuminate\Support\Str;
/** /**
* Inject the Vite assets into the head. * Inject styles into the block editor.
* *
* @return void * @return array
*/ */
add_filter('wp_head', function () { add_filter('block_editor_settings_all', function ($settings) {
echo Str::wrap(app('assets.vite')([ $style = Vite::asset('resources/css/editor.css');
'resources/css/app.css',
'resources/js/app.js', $settings['styles'][] = [
]), "\n"); 'css' => Vite::isRunningHot()
? "@import url('{$style}')"
: Vite::content('resources/css/editor.css'),
];
return $settings;
}); });
/** /**
* Inject assets into the block editor. * Inject scripts into the block editor.
* *
* @return void * @return void
*/ */
add_filter('admin_head', function () { add_filter('admin_head', function () {
$screen = get_current_screen(); if (! get_current_screen()?->is_block_editor()) {
if (! $screen?->is_block_editor()) {
return; return;
} }
$dependencies = File::json(public_path('build/editor.deps.json')) ?? []; $dependencies = json_decode(Vite::content('_editor.deps.json'));
foreach ($dependencies as $dependency) { foreach ($dependencies as $dependency) {
if (! wp_script_is($dependency)) { if (! wp_script_is($dependency)) {
@@ -42,25 +44,49 @@ add_filter('admin_head', function () {
} }
} }
echo Str::wrap(app('assets.vite')([ echo Vite::withEntryPoints([
'resources/css/editor.css',
'resources/js/editor.js', 'resources/js/editor.js',
]), "\n"); ])->toHtml();
}); });
/** /**
* Use theme.json from the build directory * Add Vite's HMR client to the block editor.
* *
* @param string $path * @return void
* @param string $file
* @return string
*/ */
add_filter('theme_file_path', function (string $path, string $file): string { add_action('enqueue_block_assets', function () {
if ($file === 'theme.json') { if (! is_admin() || ! get_current_screen()?->is_block_editor()) {
return public_path().'/build/assets/theme.json'; return;
} }
return $path; if (! Vite::isRunningHot()) {
return;
}
$script = sprintf(
<<<'JS'
window.__vite_client_url = '%s';
window.self !== window.top && document.head.appendChild(
Object.assign(document.createElement('script'), { type: 'module', src: '%s' })
);
JS,
untrailingslashit(Vite::asset('')),
Vite::asset('@vite/client')
);
wp_add_inline_script('wp-blocks', $script);
});
/**
* Use the generated theme.json file.
*
* @return string
*/
add_filter('theme_file_path', function ($path, $file) {
return $file === 'theme.json'
? public_path('build/assets/theme.json')
: $path;
}, 10, 2); }, 10, 2);
/** /**

View File

@@ -40,7 +40,7 @@
}, },
"require": { "require": {
"php": ">=8.2", "php": ">=8.2",
"roots/acorn": "v5.0.0-beta.2" "roots/acorn": "dev-main"
}, },
"require-dev": { "require-dev": {
"laravel/pint": "^1.13" "laravel/pint": "^1.13"

1874
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -16,11 +16,10 @@
"translate:mo": "wp i18n make-mo ./resources/lang ./resources/lang" "translate:mo": "wp i18n make-mo ./resources/lang ./resources/lang"
}, },
"devDependencies": { "devDependencies": {
"@tailwindcss/vite": "^4.0.0",
"@wordpress/dependency-extraction-webpack-plugin": "^6.15.0", "@wordpress/dependency-extraction-webpack-plugin": "^6.15.0",
"autoprefixer": "^10.4.20",
"laravel-vite-plugin": "^1.1.1", "laravel-vite-plugin": "^1.1.1",
"postcss": "^8.4.49", "tailwindcss": "^4.0.0",
"tailwindcss": "^3.4.17",
"vite": "^6.0.7" "vite": "^6.0.7"
} }
} }

View File

@@ -1,6 +0,0 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

View File

@@ -1,3 +1,3 @@
@tailwind base; @import "tailwindcss";
@tailwind components; @source "../views/";
@tailwind utilities; @source "../../app/";

View File

@@ -0,0 +1 @@
@import "tailwindcss";

View File

@@ -1,4 +1,3 @@
import resolveConfig from 'tailwindcss/resolveConfig'
import { import {
defaultRequestToExternal, defaultRequestToExternal,
defaultRequestToHandle, defaultRequestToHandle,
@@ -121,6 +120,7 @@ export function wordpressPlugin() {
generateBundle() { generateBundle() {
this.emitFile({ this.emitFile({
type: 'asset', type: 'asset',
name: 'editor.deps.json',
fileName: 'editor.deps.json', fileName: 'editor.deps.json',
source: JSON.stringify([...dependencies]), source: JSON.stringify([...dependencies]),
}) })
@@ -178,65 +178,126 @@ export function wordpressThemeJson({
disableTailwindFonts = false, disableTailwindFonts = false,
disableTailwindFontSizes = false, disableTailwindFontSizes = false,
}) { }) {
function flattenColors(colors, prefix = '') { let cssContent = null
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 { return {
name: 'wordpress-theme-json', name: 'wordpress-theme-json',
enforce: 'post',
transform(code, id) {
if (id.includes('app.css')) {
cssContent = code
}
return null
},
async generateBundle() { async generateBundle() {
if (!cssContent) {
return;
}
const baseThemeJson = JSON.parse( const baseThemeJson = JSON.parse(
fs.readFileSync(path.resolve('./theme.json'), 'utf8') fs.readFileSync(path.resolve('./theme.json'), 'utf8')
) )
const themeMatch = cssContent.match(/@(?:layer\s+)?theme\s*{([^}]*)}/s)
if (!themeMatch) {
return;
}
const themeContent = themeMatch[1]
if (!themeContent.trim().startsWith(':root')) {
return;
}
const rootContent = themeContent.slice(themeContent.indexOf('{') + 1, themeContent.lastIndexOf('}'))
const colorVariables = {}
const colorVarRegex = /--color-([^:]+):\s*([^;}]+)[;}]?/g
let match
while ((match = colorVarRegex.exec(rootContent)) !== null) {
const [, name, value] = match
colorVariables[name] = value.trim()
}
const colors = []
Object.entries(colorVariables).forEach(([name, value]) => {
if (name.endsWith('-*')) return
if (name.includes('-')) {
const [colorName, shade] = name.split('-')
if (shade && !isNaN(shade)) {
colors.push({
name: `${colorName}-${shade}`,
slug: `${colorName}-${shade}`.toLowerCase(),
color: value,
})
} else {
colors.push({
name: name,
slug: name.toLowerCase(),
color: value,
})
}
} else {
colors.push({
name: name,
slug: name.toLowerCase(),
color: value,
})
}
})
const fontFamilies = []
const fontVarRegex = /--font-([^:]+):\s*([^;}]+)[;}]?/g
while ((match = fontVarRegex.exec(rootContent)) !== null) {
const [, name, value] = match
if (!name.includes('-feature-settings') && !name.includes('-variation-settings')) {
fontFamilies.push({
name: name,
slug: name.toLowerCase(),
fontFamily: value.trim(),
})
}
}
const fontSizes = []
const fontSizeVarRegex = /--text-([^:]+):\s*([^;}]+)[;}]?/g
while ((match = fontSizeVarRegex.exec(rootContent)) !== null) {
const [, name, value] = match
if (!name.includes('--line-height')) {
fontSizes.push({
name: name,
slug: name.toLowerCase(),
size: value.trim(),
})
}
}
const themeJson = { const themeJson = {
__processed__: "This file was generated from the Vite build", __processed__: "This file was generated from Tailwind v4 CSS variables",
...baseThemeJson, ...baseThemeJson,
settings: { settings: {
...baseThemeJson.settings, ...baseThemeJson.settings,
...((!disableTailwindColors && resolvedConfig.theme?.colors && { ...((!disableTailwindColors && colors.length > 0) && {
color: { color: {
...baseThemeJson.settings?.color, ...baseThemeJson.settings?.color,
palette: flattenColors(resolvedConfig.theme.colors), palette: colors,
}, },
}) || {}), }),
...((!disableTailwindFonts && resolvedConfig.theme?.fontFamily && { ...((!disableTailwindFonts && fontFamilies.length > 0) && {
typography: { typography: {
...baseThemeJson.settings?.typography, ...baseThemeJson.settings?.typography,
fontFamilies: Object.entries(resolvedConfig.theme.fontFamily) fontFamilies,
.map(([name, value]) => ({
name,
slug: name,
fontFamily: Array.isArray(value) ? value.join(',') : value,
})),
}, },
}) || {}), }),
...((!disableTailwindFontSizes && resolvedConfig.theme?.fontSize && { ...((!disableTailwindFontSizes && fontSizes.length > 0) && {
typography: { typography: {
...baseThemeJson.settings?.typography, ...baseThemeJson.settings?.typography,
fontSizes: Object.entries(resolvedConfig.theme.fontSize) fontSizes,
.map(([name, value]) => ({
name,
slug: name,
size: Array.isArray(value) ? value[0] : value,
})),
}, },
}) || {}), }),
}, },
} }

View File

@@ -3,3 +3,43 @@ import domReady from '@wordpress/dom-ready';
domReady(() => { domReady(() => {
// DOM has been loaded // DOM has been loaded
}); });
if (import.meta.hot) {
import.meta.hot.on('vite:beforeUpdate', (payload) => {
const cssUpdates = payload.updates.filter(update => update.type === 'css-update');
if (cssUpdates.length > 0) {
const update = cssUpdates[0];
// Find the iframe
const editorIframe = document.querySelector('iframe[name="editor-canvas"]');
if (!editorIframe?.contentDocument) {
window.location.reload();
return;
}
// Find the existing style tag in the iframe
const styles = editorIframe.contentDocument.getElementsByTagName('style');
let editorStyle = null;
for (const style of styles) {
if (style.textContent.includes('editor.css')) {
editorStyle = style;
break;
}
}
if (!editorStyle) {
window.location.reload();
return;
}
// Update the style content with new import and cache-busting timestamp
const timestamp = Date.now();
editorStyle.textContent = `@import url('${window.__vite_client_url}${update.path}?t=${timestamp}')`;
return;
}
// For non-CSS updates, reload
window.location.reload();
});
}

View File

@@ -5,6 +5,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
@php(do_action('get_header')) @php(do_action('get_header'))
@php(wp_head()) @php(wp_head())
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head> </head>
<body @php(body_class())> <body @php(body_class())>

View File

@@ -1,12 +0,0 @@
/** @type {import('tailwindcss').Config} config */
const config = {
content: ['./app/**/*.php', './resources/**/*.{php,vue,js}'],
theme: {
extend: {
colors: {}, // Extend Tailwind's default colors
},
},
plugins: [],
};
export default config;

View File

@@ -1,15 +1,16 @@
import { defineConfig } from 'vite' import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite';
import laravel from 'laravel-vite-plugin' import laravel from 'laravel-vite-plugin'
import { import {
wordpressPlugin, wordpressPlugin,
wordpressRollupPlugin, wordpressRollupPlugin,
wordpressThemeJson, wordpressThemeJson,
} from './resources/js/build/wordpress' } from './resources/js/build/wordpress'
import tailwindConfig from './tailwind.config.js'
export default defineConfig({ export default defineConfig({
base: '/app/themes/sage/public/build/', base: '/app/themes/sage/public/build/',
plugins: [ plugins: [
tailwindcss(),
laravel({ laravel({
input: [ input: [
'resources/css/app.css', 'resources/css/app.css',
@@ -26,7 +27,6 @@ export default defineConfig({
// Generate the theme.json file in the public/build/assets directory // Generate the theme.json file in the public/build/assets directory
// based on the Tailwind config and the theme.json file from base theme folder // based on the Tailwind config and the theme.json file from base theme folder
wordpressThemeJson({ wordpressThemeJson({
tailwindConfig,
disableTailwindColors: false, disableTailwindColors: false,
disableTailwindFonts: false, disableTailwindFonts: false,
disableTailwindFontSizes: false, disableTailwindFontSizes: false,