UNPKG

kinetic-slider

Version:

A WebGL-powered kinetic slider component using PIXI.js

1 lines 13.9 kB
{"version":3,"file":"fontUtils.cjs","sources":["../../../src/utils/fontUtils.ts"],"sourcesContent":["/**\n * Font utilities for KineticSlider\n */\nimport { Assets } from 'pixi.js';\n\n// Common system fonts that don't need to be loaded\nconst SYSTEM_FONTS = [\n // Sans-serif fonts\n 'Arial', 'Helvetica', 'Helvetica Neue', 'Verdana', 'Tahoma', 'Trebuchet MS',\n 'Segoe UI', 'Roboto', 'Open Sans', 'Liberation Sans', 'Noto Sans', 'Ubuntu',\n // Serif fonts\n 'Times', 'Times New Roman', 'Georgia', 'Palatino', 'Garamond', 'Bookman',\n 'Cambria', 'Constantia', 'Liberation Serif', 'Noto Serif',\n // Monospace fonts\n 'Courier', 'Courier New', 'Monaco', 'Consolas', 'Liberation Mono', 'Menlo',\n // Generic families\n 'sans-serif', 'serif', 'monospace', 'cursive', 'fantasy', 'system-ui'\n];\n\n// Font file extensions to check\nconst FONT_EXTENSIONS = ['.woff2', '.woff', '.ttf', '.otf'];\n\n/**\n * Extract font names from a CSS font-family string\n *\n * @param fontStack - CSS font-family value\n * @returns Array of individual font names\n */\nexport function parseFontStack(fontStack: string): string[] {\n if (!fontStack) return [];\n\n // Split by commas and clean up each font name\n return fontStack\n .split(',')\n .map(font => {\n // Remove quotes and trim whitespace\n return font\n .replace(/^[\"'\\s]+|[\"'\\s]+$/g, '') // Remove quotes and spaces at the start/end\n .trim();\n })\n .filter(Boolean); // Remove any empty entries\n}\n\n/**\n * Identify which fonts in a font stack are likely custom fonts\n *\n * @param parsedFonts - Array of font names\n * @returns Array of potential custom fonts\n */\nexport function identifyCustomFonts(parsedFonts: string[]): string[] {\n return parsedFonts.filter(font =>\n // Not in our system fonts list and not a generic family\n !SYSTEM_FONTS.some(systemFont =>\n systemFont.toLowerCase() === font.toLowerCase()\n )\n );\n}\n\n/**\n * Check if a font file exists in the fonts directory\n * This is a simplified implementation for client-side\n *\n * @param fontName - Name of the font to check\n * @param extensions - File extensions to try\n * @returns Path to the font file if found, null otherwise\n */\nexport async function findFontFile(fontName: string, extensions = FONT_EXTENSIONS): Promise<string | null> {\n // List of paths to try - check both case-sensitive and lowercase versions\n const fontPaths: string[] = [];\n for (const ext of extensions) {\n // Original case\n fontPaths.push(`/fonts/${fontName}${ext}`);\n // Lowercase version\n fontPaths.push(`/fonts/${fontName.toLowerCase()}${ext}`);\n }\n\n const additionalPaths: string[] = [];\n for (const ext of extensions) {\n // Original case\n additionalPaths.push(`/public/fonts/${fontName}${ext}`);\n // Lowercase version\n additionalPaths.push(`/public/fonts/${fontName.toLowerCase()}${ext}`);\n }\n\n // Combine paths\n const allPaths = [...fontPaths, ...additionalPaths];\n\n // Try each path\n for (const path of allPaths) {\n try {\n // Try to fetch the font file to check if it exists\n const response = await fetch(path, { method: 'HEAD' });\n if (response.ok) {\n console.log(`Found font file at: ${path}`);\n return path;\n }\n } catch (error) {\n // Ignore fetch errors and try the next path\n }\n }\n\n console.warn(`No font file found for: ${fontName}`);\n return null;\n}\n\n/**\n * Load custom fonts for use with Pixi.js\n *\n * @param fontStack - CSS font-family value\n * @returns Promise resolving to an array of successfully loaded font paths\n */\nexport async function loadCustomFonts(fontStack: string): Promise<string[]> {\n if (!fontStack) return [];\n\n // Parse font stack and identify custom fonts\n const parsedFonts = parseFontStack(fontStack);\n const customFonts = identifyCustomFonts(parsedFonts);\n\n if (!customFonts.length) {\n console.log('No custom fonts identified in font stack:', fontStack);\n return [];\n }\n\n console.log('Identified custom fonts:', customFonts);\n\n // Try to load each custom font\n const loadedFonts: string[] = [];\n\n for (const fontName of customFonts) {\n try {\n // Remove any quotes from the font name\n const cleanFontName = fontName.replace(/['\"]/g, '');\n const fontPath = await findFontFile(cleanFontName);\n\n if (fontPath) {\n // Add font to Assets and load it\n console.log(`Loading font: ${cleanFontName} from ${fontPath}`);\n\n try {\n // Register and load the font with PIXI Assets\n await Assets.load({\n src: fontPath,\n data: {\n // Add font-specific metadata if needed\n family: cleanFontName\n }\n });\n\n loadedFonts.push(fontPath);\n console.log(`Successfully loaded font: ${cleanFontName}`);\n } catch (loadError) {\n console.warn(`Failed to load font ${cleanFontName}:`, loadError);\n }\n }\n } catch (error) {\n console.warn(`Error processing font ${fontName}:`, error);\n }\n }\n\n return loadedFonts;\n}\n\n/**\n * Create @font-face CSS rules for custom fonts\n * This is needed for proper text rendering in Pixi.js\n *\n * @param fontPaths - Array of paths to font files\n * @returns CSS string with @font-face rules\n */\nexport function createFontFaceCSS(fontPaths: string[]): string {\n return fontPaths.map(path => {\n // Extract font name from path\n const fontName = path.split('/').pop()?.split('.')[0] || '';\n const fontFormat = path.split('.').pop();\n\n let format;\n switch(fontFormat) {\n case 'woff2': format = 'woff2'; break;\n case 'woff': format = 'woff'; break;\n case 'ttf': format = 'truetype'; break;\n case 'otf': format = 'opentype'; break;\n default: format = 'truetype';\n }\n\n return `\n @font-face {\n font-family: '${fontName}';\n src: url('${path}') format('${format}');\n font-weight: normal;\n font-style: normal;\n font-display: swap;\n }\n `;\n }).join('\\n');\n}\n\n/**\n * Add @font-face rules to the document head\n *\n * @param css - CSS string with @font-face rules\n */\nexport function injectFontFaceCSS(css: string): void {\n if (typeof document === 'undefined' || !css) return;\n\n // Create a style element\n const style = document.createElement('style');\n style.textContent = css;\n style.setAttribute('data-kinetic-slider-fonts', 'true');\n\n // Add it to the head\n document.head.appendChild(style);\n}\n\n/**\n * Main function to handle custom font loading for KineticSlider\n *\n * @param titleFontStack - Title font-family value\n * @param subtitleFontStack - Subtitle font-family value\n * @returns Promise resolving when fonts are loaded\n */\nexport async function setupCustomFonts(\n titleFontStack?: string,\n subtitleFontStack?: string\n): Promise<void> {\n // Skip during server-side rendering\n if (typeof window === 'undefined') return;\n\n console.log('Setting up custom fonts:', { titleFontStack, subtitleFontStack });\n\n // Track loaded fonts to avoid duplicates\n const loadedFontPaths: string[] = [];\n\n // Process title fonts\n if (titleFontStack) {\n const titleFontPaths = await loadCustomFonts(titleFontStack);\n loadedFontPaths.push(...titleFontPaths);\n }\n\n // Process subtitle fonts\n if (subtitleFontStack) {\n const subtitleFontPaths = await loadCustomFonts(subtitleFontStack);\n // Filter out duplicates\n const newPaths = subtitleFontPaths.filter(path => !loadedFontPaths.includes(path));\n loadedFontPaths.push(...newPaths);\n }\n\n // Create and inject CSS if fonts were found\n if (loadedFontPaths.length > 0) {\n const fontFaceCSS = createFontFaceCSS(loadedFontPaths);\n injectFontFaceCSS(fontFaceCSS);\n console.log('Injected font-face CSS for:', loadedFontPaths);\n\n // Allow some time for the fonts to load\n return new Promise((resolve) => {\n // Use a timeout to ensure fonts have time to load\n setTimeout(resolve, 100);\n });\n }\n\n return Promise.resolve();\n}"],"names":["Assets"],"mappings":"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"}