UNPKG

sparkle-design-cli

Version:

Sparkle Design CSS Generator - デザインシステムCSSを設定ファイルから生成するツール

202 lines (171 loc) 6.61 kB
/** * フォント管理機能 * sparkle-design.css からフォントimportを抽出し、globals.css に移動する */ import fs from 'fs'; import path from 'path'; import { REGEX, COMMENTS, IMPORTS, MESSAGES } from './constants.js'; /** * sparkle-design.css からフォントの@import文を抽出する * @param {string} cssContent CSS内容 * @returns {Array<string>} フォントimport文の配列 */ export function extractFontImports(cssContent) { const matches = cssContent.match(REGEX.FONT_IMPORT); return matches || []; } /** * sparkle-design.css からフォントの@import文を削除する * @param {string} cssContent CSS内容 * @returns {string} フォントimportを削除したCSS */ export function removeFontImportsFromCSS(cssContent) { return cssContent.replace(REGEX.FONT_IMPORT_WITH_COMMENT, ''); } /** * フォントimportブロックを生成する * @param {Array<string>} fontImports フォントimport文の配列 * @returns {string} フォントimportブロック */ function createFontImportBlock(fontImports) { return [COMMENTS.FONT_IMPORT, ...fontImports, ''].join('\n'); } /** * sparkle-design.css importブロックを生成する * @returns {string} sparkle-design.css importブロック */ function createSparkleImportBlock() { return ['', COMMENTS.SPARKLE_IMPORT, IMPORTS.SPARKLE_DESIGN, ''].join('\n'); } /** * globals.css の既存のimportを削除する * @param {string} globalsContent globals.cssの内容 * @returns {string} 既存importを削除したglobals.css */ function removeExistingImports(globalsContent) { let cleaned = globalsContent; // 既存のフォントimportを削除 cleaned = cleaned.replace(REGEX.EXISTING_FONT_IMPORT_BLOCK, ''); // 既存のsparkle-design.css importを削除 cleaned = cleaned.replace(REGEX.SPARKLE_IMPORT, ''); return cleaned; } /** * Tailwind import の位置を見つける * @param {string} globalsContent globals.cssの内容 * @returns {{match: string, index: number, afterIndex: number} | null} Tailwind importの情報 */ function findTailwindImport(globalsContent) { const tailwindMatch = globalsContent.match(REGEX.TAILWIND_IMPORT); if (!tailwindMatch) { return null; } const tailwindIndex = globalsContent.indexOf(tailwindMatch[0]); const afterTailwindIndex = tailwindIndex + tailwindMatch[0].length; return { match: tailwindMatch[0], index: tailwindIndex, afterIndex: afterTailwindIndex, }; } /** * globals.css を再構築する * @param {string} globalsContent 元のglobals.cssの内容 * @param {string} fontImportBlock フォントimportブロック * @param {string} sparkleImportBlock sparkle-design.css importブロック * @param {Object} tailwindInfo Tailwind importの情報 * @returns {string} 再構築されたglobals.css */ function reconstructGlobalsCss(globalsContent, fontImportBlock, sparkleImportBlock, tailwindInfo) { const beforeTailwind = globalsContent.substring(0, tailwindInfo.index); const afterTailwind = globalsContent.substring(tailwindInfo.afterIndex); // フォントimport + Tailwind + sparkle-design.css + 残りのコンテンツ return ( fontImportBlock + beforeTailwind + tailwindInfo.match + sparkleImportBlock + afterTailwind.trimStart() ); } /** * globals.css を構造化して管理する * - フォントimportを先頭に配置 * - Tailwind importを確保 * - sparkle-design.css importをTailwindの後に配置 * @param {Array<string>} fontImports フォントimport文の配列 * @param {string} globalsPath globals.cssのパス * @returns {boolean} globals.css の更新に成功した場合は true */ export function updateGlobalsWithFonts(fontImports, globalsPath) { if (fontImports.length === 0) { return false; } try { // 1. globals.css を読み込む let globalsContent = fs.readFileSync(globalsPath, 'utf8'); // 2. 既存のimportを削除 globalsContent = removeExistingImports(globalsContent); // 3. Tailwind import の位置を見つける const tailwindInfo = findTailwindImport(globalsContent); if (!tailwindInfo) { console.warn(MESSAGES.TAILWIND_NOT_FOUND); return false; } // 4. importブロックを生成 const fontImportBlock = createFontImportBlock(fontImports); const sparkleImportBlock = createSparkleImportBlock(); // 5. globals.css を再構築 const reconstructedContent = reconstructGlobalsCss( globalsContent, fontImportBlock, sparkleImportBlock, tailwindInfo ); // 6. 更新したglobals.cssを書き込む fs.writeFileSync(globalsPath, reconstructedContent, 'utf8'); console.log(MESSAGES.GLOBALS_UPDATED(globalsPath)); return true; } catch (error) { console.error(MESSAGES.GLOBALS_UPDATE_FAILED(error.message)); // globals.cssの更新は必須ではないので、エラーでも処理を続行 return false; } } /** * フォント管理の自動処理を実行する * sparkle-design.css からフォントimportを抽出し、globals.css に移動する * @param {string} sparkleDesignPath sparkle-design.cssのパス */ export function manageFontImports(sparkleDesignPath) { try { // 1. globals.cssのパスを推定(sparkle-design.cssと同じディレクトリ) const globalsPath = path.join(path.dirname(sparkleDesignPath), 'globals.css'); // 2. globals.cssが存在しない場合はスキップ if (!fs.existsSync(globalsPath)) { console.log(MESSAGES.GLOBALS_NOT_FOUND); return; } // 3. sparkle-design.css からフォントimportを抽出 const sparkleContent = fs.readFileSync(sparkleDesignPath, 'utf8'); const fontImports = extractFontImports(sparkleContent); if (fontImports.length === 0) { console.log(MESSAGES.NO_FONT_IMPORTS); return; } console.log(MESSAGES.FONT_DETECTED(fontImports.length)); // 4. globals.css にフォントimportを追加 const globalsUpdated = updateGlobalsWithFonts(fontImports, globalsPath); if (!globalsUpdated) { console.log(MESSAGES.FONT_REMOVE_SKIPPED); return; } // 5. sparkle-design.css からフォントimportを削除 const cleanedSparkleContent = removeFontImportsFromCSS(sparkleContent); fs.writeFileSync(sparkleDesignPath, cleanedSparkleContent, 'utf8'); console.log(MESSAGES.FONT_REMOVED); } catch (error) { console.error(MESSAGES.FONT_MANAGEMENT_ERROR(error.message)); // フォント管理は必須ではないので、エラーでも処理を続行 } }