font handling fix
This commit is contained in:
parent
d5ecb31dad
commit
fda7bd1d12
6 changed files with 727 additions and 22 deletions
|
|
@ -32,6 +32,20 @@ define('MLF_MAX_CSS_SIZE', 512 * 1024); // 512KB max CSS response
|
|||
define('MLF_MAX_FONT_FILE_SIZE', 5 * 1024 * 1024); // 5MB max font file
|
||||
define('MLF_MAX_FONT_FACES', 20); // Max font faces per import (9 weights × 2 styles + buffer)
|
||||
|
||||
/**
|
||||
* Ensure WOFF2 MIME type is registered (fixes Safari font loading).
|
||||
*
|
||||
* @param array $mimes Existing MIME types.
|
||||
* @return array Modified MIME types.
|
||||
*/
|
||||
function mlf_add_woff2_mime_type($mimes) {
|
||||
$mimes['woff2'] = 'font/woff2';
|
||||
$mimes['woff'] = 'font/woff';
|
||||
return $mimes;
|
||||
}
|
||||
add_filter('mime_types', 'mlf_add_woff2_mime_type');
|
||||
|
||||
|
||||
/**
|
||||
* Check WordPress version on activation.
|
||||
*/
|
||||
|
|
@ -50,9 +64,46 @@ function mlf_activate() {
|
|||
if (!file_exists($font_dir['path'])) {
|
||||
wp_mkdir_p($font_dir['path']);
|
||||
}
|
||||
|
||||
// Create .htaccess for proper MIME types and CORS (Apache servers)
|
||||
$htaccess_path = trailingslashit($font_dir['path']) . '.htaccess';
|
||||
if (!file_exists($htaccess_path)) {
|
||||
$htaccess_content = "# Maple Local Fonts - Font MIME types and CORS\n";
|
||||
$htaccess_content .= "<IfModule mod_mime.c>\n";
|
||||
$htaccess_content .= " AddType font/woff2 .woff2\n";
|
||||
$htaccess_content .= " AddType font/woff .woff\n";
|
||||
$htaccess_content .= "</IfModule>\n\n";
|
||||
$htaccess_content .= "<IfModule mod_headers.c>\n";
|
||||
$htaccess_content .= " <FilesMatch \"\\.(woff2?|ttf|otf|eot)$\">\n";
|
||||
$htaccess_content .= " Header set Access-Control-Allow-Origin \"*\"\n";
|
||||
$htaccess_content .= " </FilesMatch>\n";
|
||||
$htaccess_content .= "</IfModule>\n";
|
||||
|
||||
global $wp_filesystem;
|
||||
if (empty($wp_filesystem)) {
|
||||
require_once ABSPATH . 'wp-admin/includes/file.php';
|
||||
WP_Filesystem();
|
||||
}
|
||||
|
||||
if ($wp_filesystem) {
|
||||
$wp_filesystem->put_contents($htaccess_path, $htaccess_content, FS_CHMOD_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
// Flush rewrite rules for fonts CSS endpoint
|
||||
mlf_add_rewrite_rules();
|
||||
flush_rewrite_rules();
|
||||
}
|
||||
register_activation_hook(__FILE__, 'mlf_activate');
|
||||
|
||||
/**
|
||||
* Flush rewrite rules on deactivation.
|
||||
*/
|
||||
function mlf_deactivate() {
|
||||
flush_rewrite_rules();
|
||||
}
|
||||
register_deactivation_hook(__FILE__, 'mlf_deactivate');
|
||||
|
||||
/**
|
||||
* Check WordPress version on admin init (in case WP was downgraded).
|
||||
*/
|
||||
|
|
@ -64,6 +115,44 @@ function mlf_check_version() {
|
|||
}
|
||||
add_action('admin_init', 'mlf_check_version');
|
||||
|
||||
/**
|
||||
* Ensure fonts directory htaccess exists (for MIME types and CORS).
|
||||
*/
|
||||
function mlf_ensure_htaccess() {
|
||||
$font_dir = wp_get_font_dir();
|
||||
$htaccess_path = trailingslashit($font_dir['path']) . '.htaccess';
|
||||
|
||||
// Always update htaccess to ensure latest headers
|
||||
$htaccess_content = "# Maple Local Fonts - Font MIME types and CORS\n";
|
||||
$htaccess_content .= "# Required for cross-browser font loading including iOS Safari\n\n";
|
||||
$htaccess_content .= "<IfModule mod_mime.c>\n";
|
||||
$htaccess_content .= " AddType font/woff2 .woff2\n";
|
||||
$htaccess_content .= " AddType font/woff .woff\n";
|
||||
$htaccess_content .= "</IfModule>\n\n";
|
||||
$htaccess_content .= "<IfModule mod_headers.c>\n";
|
||||
$htaccess_content .= " <FilesMatch \"\\.(woff2?|ttf|otf|eot)$\">\n";
|
||||
$htaccess_content .= " Header set Access-Control-Allow-Origin \"*\"\n";
|
||||
$htaccess_content .= " Header set Access-Control-Allow-Methods \"GET, OPTIONS\"\n";
|
||||
$htaccess_content .= " Header set Access-Control-Allow-Headers \"Origin, Content-Type\"\n";
|
||||
$htaccess_content .= " Header set Cross-Origin-Resource-Policy \"cross-origin\"\n";
|
||||
$htaccess_content .= " Header set Timing-Allow-Origin \"*\"\n";
|
||||
$htaccess_content .= " </FilesMatch>\n";
|
||||
$htaccess_content .= "</IfModule>\n";
|
||||
|
||||
if (file_exists($font_dir['path'])) {
|
||||
global $wp_filesystem;
|
||||
if (empty($wp_filesystem)) {
|
||||
require_once ABSPATH . 'wp-admin/includes/file.php';
|
||||
WP_Filesystem();
|
||||
}
|
||||
|
||||
if ($wp_filesystem) {
|
||||
$wp_filesystem->put_contents($htaccess_path, $htaccess_content, FS_CHMOD_FILE);
|
||||
}
|
||||
}
|
||||
}
|
||||
add_action('admin_init', 'mlf_ensure_htaccess');
|
||||
|
||||
/**
|
||||
* Display version notice.
|
||||
*/
|
||||
|
|
@ -133,9 +222,41 @@ add_action('plugins_loaded', 'mlf_init', 20);
|
|||
function mlf_register_rest_routes() {
|
||||
$controller = new MLF_Rest_Controller();
|
||||
$controller->register_routes();
|
||||
|
||||
// Register font server routes for cross-browser compatibility
|
||||
$font_server = new MLF_Font_Server();
|
||||
$font_server->register_routes();
|
||||
}
|
||||
add_action('rest_api_init', 'mlf_register_rest_routes');
|
||||
|
||||
/**
|
||||
* Check if we should use REST API for font serving (compatibility mode).
|
||||
*
|
||||
* @return bool True if using REST API font serving.
|
||||
*/
|
||||
function mlf_use_rest_font_serving() {
|
||||
return get_option('mlf_compatibility_mode', true); // Default to true for maximum compatibility
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL for a font file.
|
||||
*
|
||||
* Uses REST API endpoint for compatibility, or direct file URL for performance.
|
||||
*
|
||||
* @param string $filename The font filename.
|
||||
* @return string The font URL.
|
||||
*/
|
||||
function mlf_get_font_url($filename) {
|
||||
if (mlf_use_rest_font_serving()) {
|
||||
// Use REST API endpoint (guaranteed proper headers)
|
||||
return rest_url('mlf/v1/font/' . $filename);
|
||||
} else {
|
||||
// Use direct file URL (faster but depends on server config)
|
||||
$font_dir = wp_get_font_dir();
|
||||
return trailingslashit($font_dir['url']) . $filename;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the required capability for managing fonts.
|
||||
*
|
||||
|
|
@ -154,20 +275,24 @@ function mlf_get_capability() {
|
|||
/**
|
||||
* Add imported fonts to the theme.json typography settings.
|
||||
*
|
||||
* This makes fonts appear in the Site Editor typography dropdown.
|
||||
* This makes fonts appear in the Site Editor typography dropdown
|
||||
* and generates the @font-face CSS for the frontend.
|
||||
*
|
||||
* @param WP_Theme_JSON_Data $theme_json The theme.json data.
|
||||
* @return WP_Theme_JSON_Data Modified theme.json data.
|
||||
*/
|
||||
function mlf_add_fonts_to_theme_json($theme_json) {
|
||||
$registry = new MLF_Font_Registry();
|
||||
$fonts = $registry->get_imported_fonts();
|
||||
$fonts = $registry->get_imported_fonts_with_src();
|
||||
|
||||
if (empty($fonts)) {
|
||||
return $theme_json;
|
||||
}
|
||||
|
||||
// Build our font families
|
||||
$font_families = [];
|
||||
$font_dir = wp_get_font_dir();
|
||||
$font_base_url = trailingslashit($font_dir['url']);
|
||||
|
||||
foreach ($fonts as $font) {
|
||||
$font_faces = [];
|
||||
|
|
@ -175,24 +300,17 @@ function mlf_add_fonts_to_theme_json($theme_json) {
|
|||
foreach ($font['variants'] as $variant) {
|
||||
$weight = $variant['weight'];
|
||||
$style = $variant['style'];
|
||||
$filename = $variant['filename'];
|
||||
|
||||
// Build filename based on our naming convention
|
||||
$font_slug = sanitize_title($font['name']);
|
||||
if (strpos($weight, ' ') !== false) {
|
||||
// Variable font
|
||||
$filename = sprintf('%s_%s_variable.woff2', $font_slug, $style);
|
||||
} else {
|
||||
$filename = sprintf('%s_%s_%s.woff2', $font_slug, $style, $weight);
|
||||
}
|
||||
|
||||
$font_dir = wp_get_font_dir();
|
||||
$font_url = trailingslashit($font_dir['url']) . $filename;
|
||||
// Use direct file URL
|
||||
$font_url = $font_base_url . $filename;
|
||||
|
||||
$font_faces[] = [
|
||||
'fontFamily' => $font['name'],
|
||||
'fontWeight' => $weight,
|
||||
'fontStyle' => $style,
|
||||
'src' => [$font_url],
|
||||
'fontFamily' => $font['name'],
|
||||
'fontWeight' => $weight,
|
||||
'fontStyle' => $style,
|
||||
'fontDisplay' => 'swap',
|
||||
'src' => [$font_url],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -204,6 +322,7 @@ function mlf_add_fonts_to_theme_json($theme_json) {
|
|||
];
|
||||
}
|
||||
|
||||
// Use update_with to merge - WordPress handles the merging logic
|
||||
$new_data = [
|
||||
'version' => 2,
|
||||
'settings' => [
|
||||
|
|
@ -215,7 +334,172 @@ function mlf_add_fonts_to_theme_json($theme_json) {
|
|||
|
||||
return $theme_json->update_with($new_data);
|
||||
}
|
||||
add_filter('wp_theme_json_data_user', 'mlf_add_fonts_to_theme_json');
|
||||
add_filter('wp_theme_json_data_user', 'mlf_add_fonts_to_theme_json', 10);
|
||||
|
||||
/**
|
||||
* Generate @font-face CSS for imported fonts.
|
||||
*
|
||||
* @return string CSS content.
|
||||
*/
|
||||
function mlf_get_font_face_css() {
|
||||
$registry = new MLF_Font_Registry();
|
||||
$fonts = $registry->get_imported_fonts();
|
||||
|
||||
if (empty($fonts)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$css = '';
|
||||
|
||||
foreach ($fonts as $font) {
|
||||
$font_slug = sanitize_title($font['name']);
|
||||
// Escape font name for CSS (handle quotes and special chars)
|
||||
$css_font_name = addcslashes($font['name'], "'\\");
|
||||
|
||||
foreach ($font['variants'] as $variant) {
|
||||
$weight = $variant['weight'];
|
||||
$style = $variant['style'];
|
||||
|
||||
// Build filename based on our naming convention
|
||||
if (strpos($weight, ' ') !== false) {
|
||||
// Variable font
|
||||
$filename = sprintf('%s_%s_variable.woff2', $font_slug, $style);
|
||||
} else {
|
||||
$filename = sprintf('%s_%s_%s.woff2', $font_slug, $style, $weight);
|
||||
}
|
||||
|
||||
// Get font URL (uses REST API or direct based on setting)
|
||||
$font_url = mlf_get_font_url($filename);
|
||||
|
||||
// Ensure HTTPS if site uses HTTPS (important for reverse proxy setups)
|
||||
if (is_ssl() && strpos($font_url, 'http://') === 0) {
|
||||
$font_url = str_replace('http://', 'https://', $font_url);
|
||||
}
|
||||
|
||||
$css .= "@font-face {";
|
||||
$css .= "font-family: '{$css_font_name}';";
|
||||
$css .= "font-style: {$style};";
|
||||
$css .= "font-weight: {$weight};";
|
||||
$css .= "font-display: swap;";
|
||||
$css .= "src: url('" . esc_url($font_url) . "') format('woff2');";
|
||||
$css .= "}\n";
|
||||
}
|
||||
}
|
||||
|
||||
return $css;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue font face CSS on frontend.
|
||||
*
|
||||
* Uses external CSS file just like Google Fonts does.
|
||||
*/
|
||||
function mlf_enqueue_font_faces() {
|
||||
$registry = new MLF_Font_Registry();
|
||||
$fonts = $registry->get_imported_fonts();
|
||||
|
||||
if (empty($fonts)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Load CSS from custom endpoint (like Google Fonts serves CSS)
|
||||
wp_enqueue_style(
|
||||
'mlf-local-fonts',
|
||||
home_url('/mlf-fonts.css'),
|
||||
[],
|
||||
null // No version string, like Google Fonts
|
||||
);
|
||||
}
|
||||
add_action('wp_enqueue_scripts', 'mlf_enqueue_font_faces');
|
||||
|
||||
/**
|
||||
* Enqueue font face CSS in block editor.
|
||||
*/
|
||||
function mlf_enqueue_editor_font_faces() {
|
||||
$registry = new MLF_Font_Registry();
|
||||
$fonts = $registry->get_imported_fonts();
|
||||
|
||||
if (empty($fonts)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Load CSS from custom endpoint (like Google Fonts serves CSS)
|
||||
wp_enqueue_style(
|
||||
'mlf-local-fonts-editor',
|
||||
home_url('/mlf-fonts.css'),
|
||||
[],
|
||||
null
|
||||
);
|
||||
}
|
||||
add_action('enqueue_block_editor_assets', 'mlf_enqueue_editor_font_faces');
|
||||
|
||||
/**
|
||||
* Add rewrite rule for fonts CSS endpoint.
|
||||
*/
|
||||
function mlf_add_rewrite_rules() {
|
||||
add_rewrite_rule('^mlf-fonts\.css$', 'index.php?mlf_fonts_css=1', 'top');
|
||||
}
|
||||
add_action('init', 'mlf_add_rewrite_rules');
|
||||
|
||||
/**
|
||||
* Add query var for fonts CSS.
|
||||
*/
|
||||
function mlf_add_query_vars($vars) {
|
||||
$vars[] = 'mlf_fonts_css';
|
||||
return $vars;
|
||||
}
|
||||
add_filter('query_vars', 'mlf_add_query_vars');
|
||||
|
||||
/**
|
||||
* Handle fonts CSS request.
|
||||
*/
|
||||
function mlf_handle_fonts_css_request() {
|
||||
if (!get_query_var('mlf_fonts_css')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Send CSS headers
|
||||
header('Content-Type: text/css; charset=UTF-8');
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
header('Cache-Control: public, max-age=86400');
|
||||
header('X-Content-Type-Options: nosniff');
|
||||
|
||||
$registry = new MLF_Font_Registry();
|
||||
$fonts = $registry->get_imported_fonts_with_src();
|
||||
|
||||
if (empty($fonts)) {
|
||||
echo "/* No fonts installed */\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
echo "/* Maple Local Fonts */\n\n";
|
||||
|
||||
// Use direct font file URLs
|
||||
$font_dir = wp_get_font_dir();
|
||||
$font_base_url = trailingslashit($font_dir['url']);
|
||||
|
||||
foreach ($fonts as $font) {
|
||||
foreach ($font['variants'] as $variant) {
|
||||
$weight = $variant['weight'];
|
||||
$style = $variant['style'];
|
||||
|
||||
// Use the actual filename from database (stored in src)
|
||||
$filename = $variant['filename'];
|
||||
$file_url = $font_base_url . $filename;
|
||||
|
||||
echo "@font-face {\n";
|
||||
echo " font-family: '{$font['name']}';\n";
|
||||
echo " font-style: {$style};\n";
|
||||
echo " font-weight: {$weight};\n";
|
||||
echo " font-display: swap;\n";
|
||||
echo " src: url({$file_url}) format('woff2');\n";
|
||||
echo "}\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
add_action('template_redirect', 'mlf_handle_fonts_css_request');
|
||||
|
||||
/**
|
||||
* Register admin menu.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue