1
0

update claude

This commit is contained in:
2025-06-06 03:53:38 +09:00
parent 9ef3e18510
commit 81d36c3096
10 changed files with 1799 additions and 0 deletions

View File

@ -0,0 +1,98 @@
# AI Moji Font Generator Makefile
.PHONY: help setup build clean font css package install test
# デフォルトターゲット
help:
@echo "AI Moji Font Generator"
@echo "======================"
@echo ""
@echo "使用可能なコマンド:"
@echo " make setup - 初期セットアップを実行"
@echo " make build - 全体ビルドを実行"
@echo " make clean - 出力ディレクトリをクリア"
@echo " make font - フォントファイルのみ生成"
@echo " make css - CSS/SCSSファイルのみ生成"
@echo " make package - パッケージングのみ実行"
@echo " make install - 生成されたパッケージをローカルにインストール"
@echo " make test - テストビルドを実行"
@echo " make publish - npmに公開"
@echo ""
# 初期セットアップ
setup:
@echo "🚀 セットアップ開始..."
chmod +x setup.sh
./setup.sh
# 全体ビルド
build:
@echo "🔨 フルビルド開始..."
python3 build.py
# クリーンアップ
clean:
@echo "🗑️ クリーンアップ..."
python3 build.py --clean
# フォントのみ生成
font:
@echo "🔤 フォント生成..."
python3 build.py --font-only
# CSSのみ生成
css:
@echo "🎨 CSS生成..."
python3 build.py --css-only
# パッケージングのみ
package:
@echo "📦 パッケージング..."
python3 build.py --package-only
# ローカルインストール
install: build
@echo "📦 ローカルインストール..."
cd ../../dist && npm pack
@echo "✅ パッケージファイルが生成されました"
@echo " npm install ../../dist/aimoji-*.tgz でインストールできます"
# テストビルド
test:
@echo "🧪 テストビルド..."
$(MAKE) clean
python3 build.py --font-only
@echo "✅ テスト完了"
# npm公開
publish: build
@echo "🚀 npm公開準備..."
cd ../../dist && npm publish --dry-run
@echo ""
@echo "本当に公開する場合:"
@echo " cd ../../dist && npm publish"
# 開発用 - ファイル監視
watch:
@echo "👀 ファイル監視モード(要 entr インストール)"
find ../../svg -name "*.svg" | entr -r make build
# 統計情報表示
stats:
@echo "📊 プロジェクト統計"
@echo "=================="
@echo "SVGファイル数:"
@find ../../svg -name "*.svg" | wc -l
@echo ""
@echo "生成されたフォントファイル:"
@find ../../dist/fonts -name "*" 2>/dev/null | wc -l || echo "0"
@echo ""
@echo "出力ディレクトリサイズ:"
@du -sh ../../dist 2>/dev/null || echo "なし"
# 依存関係チェック
check-deps:
@echo "🔍 依存関係チェック..."
@python3 -c "import fontforge; print('✅ FontForge OK')" || echo "❌ FontForge が見つかりません"
@python3 -c "import fontTools; print('✅ FontTools OK')" || echo "❌ FontTools が見つかりません"
@command -v python3 >/dev/null 2>&1 && echo "✅ Python3 OK" || echo "❌ Python3 が見つかりません"

View File

@ -0,0 +1,211 @@
# AI Moji Font Generator
AI Moji文字システムから FontAwesome 風のアイコンフォントパッケージを自動生成するシステムです。
## 概要
このツールは:
- SVGファイルから自動的にWebフォントWOFF2, TTF等を生成
- FontAwesome風のCSS/SCSSファイルを自動生成
- npm パッケージとして配布可能な形式で出力
- エコシステム統合設計書の名前規則に準拠
## 名前規則
エコシステム統合設計書に基づく命名:
- **package**: `aimoji`
- **directory**: `ai/moji`
- **domain**: `ai.moji`
## システム構成
```
ai_moji_generator/
├── build.py # メインビルドスクリプト
├── font_generator.py # SVG→フォント変換
├── css_generator.py # CSS/SCSS生成
├── packager.py # npmパッケージング
├── requirements.txt # Python依存関係
├── setup.sh # セットアップスクリプト
└── README.md # このファイル
出力(../../dist/):
├── fonts/ # woff2, ttf, eot, svg
├── css/ # aimoji.css, aimoji.min.css
├── scss/ # _variables.scss, _mixins.scss
├── package.json # npm配布用
├── README.md # パッケージドキュメント
├── LICENSE # MITライセンス
└── metadata.json # ビルドメタデータ
```
## セットアップ
### 自動セットアップ
```bash
# 実行権限付与
chmod +x setup.sh
# セットアップ実行
./setup.sh
```
### 手動セットアップ
1. **依存関係インストール**
```bash
# macOS (Homebrew必須)
brew install fontforge
# Ubuntu/Debian
sudo apt-get install fontforge python3-fontforge
# Python依存関係
pip3 install -r requirements.txt
```
2. **ディレクトリ確認**
```bash
# SVGファイルが存在することを確認
ls ../../svg/*.svg
```
## 使用方法
### 基本的な使用方法
```bash
# 全体ビルド(推奨)
python3 build.py
# クリーンビルド
python3 build.py --clean
python3 build.py
```
### 部分ビルド
```bash
# フォントのみ生成
python3 build.py --font-only
# CSS/SCSSのみ生成
python3 build.py --css-only
# パッケージングのみ
python3 build.py --package-only
```
### カスタムパス指定
```bash
# カスタムSVGディレクトリ
python3 build.py --svg-dir /path/to/svg
# カスタム出力ディレクトリ
python3 build.py --output-dir /path/to/output
```
## 出力パッケージの使用方法
生成されたパッケージは npm で配布可能:
```bash
# パッケージディレクトリに移動
cd ../../dist
# npmで公開
npm publish
```
### 使用例
```html
<!-- CSS読み込み -->
<link rel="stylesheet" href="node_modules/aimoji/css/aimoji.css">
<!-- アイコン使用 -->
<i class="aimoji aimoji-ai"></i>
<i class="aimoji aimoji-game"></i>
<i class="aimoji aimoji-card"></i>
```
```scss
// SCSS使用
@import "node_modules/aimoji/scss/variables";
@import "node_modules/aimoji/scss/mixins";
.my-icon {
@include aimoji-icon($aimoji-ai);
@include aimoji-size(24px);
@include aimoji-spin();
}
```
## 技術詳細
### フォント生成
- **ツール**: FontForge + fonttools
- **フォーマット**: TTF, WOFF, WOFF2, EOT, SVG
- **Unicode範囲**: Private Use Area (U+E900~)
- **グリフサイズ**: 1024x1024 ユニット
### CSS生成
- **FontAwesome風クラス**: `.aimoji .aimoji-{name}`
- **最小化版**: gzip圧縮対応
- **SCSS変数**: 全アイコンの Unicode 値
- **Mixins**: アニメーション、サイズ、回転等
### パッケージング
- **npm準拠**: package.json自動生成
- **ドキュメント**: README.md、LICENSE自動生成
- **メタデータ**: ビルド情報含む metadata.json
## トラブルシューティング
### FontForge エラー
```bash
# macOS: Homebrewで再インストール
brew uninstall fontforge
brew install fontforge
# Linux: 依存関係インストール
sudo apt-get install python3-dev python3-fontforge
```
### Python モジュールエラー
```bash
# 仮想環境使用を推奨
python3 -m venv ~/.config/syui/ai/moji
source ~/.config/syui/ai/moji/bin/activate
pip install -r requirements.txt
```
### SVG読み込みエラー
- SVGファイルが有効な形式であることを確認
- パスデータが含まれていることを確認
- Inkscape等で最適化を実行
## ライセンス
MIT License - 詳細は生成される LICENSE ファイルを参照
## 開発者
- **作者**: syui
- **プロジェクト**: AI Moji エコシステム
- **設計**: エコシステム統合設計書に基づく
## 関連プロジェクト
- **ai.gpt**: 自律的送信AI
- **ai.card**: カードゲームシステム
- **ai.verse**: UEメタバース
- **ai.bot**: 分散SNS連携

View File

@ -0,0 +1,215 @@
#!/usr/bin/env python3
"""
AI Moji Build System
FontAwesome風のアイコンフォントパッケージを自動生成
使用方法:
python build.py # 全体ビルド
python build.py --font-only # フォントのみ生成
python build.py --css-only # CSSのみ生成
python build.py --package-only # パッケージングのみ
python build.py --clean # distディレクトリクリア
"""
import argparse
import shutil
import sys
from pathlib import Path
from datetime import datetime
# 同じディレクトリの他のモジュールをインポート
from font_generator import AIMojiFontGenerator
from css_generator import AIMojiCSSGenerator
from packager import AIMojiPackager
class AIMojiBuildSystem:
def __init__(self, svg_dir: str = "../../svg", output_dir: str = "../../dist"):
self.svg_dir = Path(svg_dir)
self.output_dir = Path(output_dir)
# 各コンポーネントの初期化
self.font_generator = AIMojiFontGenerator(svg_dir, output_dir)
self.css_generator = AIMojiCSSGenerator(output_dir)
self.packager = AIMojiPackager(output_dir)
def clean_dist(self):
"""distディレクトリをクリア"""
if self.output_dir.exists():
print(f"🗑️ {self.output_dir} をクリア中...")
shutil.rmtree(self.output_dir)
print("✅ クリア完了")
else:
print("📁 distディレクトリが存在しません")
def validate_prerequisites(self) -> bool:
"""前提条件チェック"""
errors = []
# SVGディレクトリ存在チェック
if not self.svg_dir.exists():
errors.append(f"SVGディレクトリが存在しません: {self.svg_dir}")
# SVGファイル存在チェック
svg_files = list(self.svg_dir.glob("*.svg"))
if not svg_files:
errors.append(f"SVGファイルが見つかりません: {self.svg_dir}")
# Python依存関係チェック
try:
import fontforge
except ImportError:
errors.append("FontForgeがインストールされていません (pip install fontforge)")
if errors:
print("❌ 前提条件エラー:")
for error in errors:
print(f" - {error}")
return False
print("✅ 前提条件チェック: 問題なし")
print(f"📂 SVGファイル数: {len(svg_files)}")
return True
def build_font(self) -> bool:
"""フォント生成"""
try:
print("\n🔤 === フォント生成フェーズ ===")
result = self.font_generator.generate()
return result["success"]
except Exception as e:
print(f"❌ フォント生成エラー: {e}")
return False
def build_css(self) -> bool:
"""CSS/SCSS生成"""
try:
print("\n🎨 === CSS/SCSS生成フェーズ ===")
self.css_generator.generate_all()
return True
except Exception as e:
print(f"❌ CSS生成エラー: {e}")
return False
def build_package(self) -> bool:
"""パッケージング"""
try:
print("\n📦 === パッケージングフェーズ ===")
result = self.packager.package_all()
return result["is_valid"]
except Exception as e:
print(f"❌ パッケージングエラー: {e}")
return False
def build_all(self) -> bool:
"""全体ビルド"""
print("🚀 AI Moji アイコンフォント パッケージ生成開始")
print(f"⏰ 開始時刻: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print("=" * 60)
# 前提条件チェック
if not self.validate_prerequisites():
return False
# フォント生成
if not self.build_font():
return False
# CSS生成
if not self.build_css():
return False
# パッケージング
if not self.build_package():
return False
print("\n" + "=" * 60)
print("🎉 AI Moji アイコンフォントパッケージ生成完了!")
print(f"⏰ 完了時刻: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print(f"📁 出力ディレクトリ: {self.output_dir.absolute()}")
print("\n📋 ファイル構成:")
self.show_output_structure()
print("\n🚀 npm パッケージとして公開準備完了!")
print(" cd dist && npm publish")
return True
def show_output_structure(self):
"""出力ディレクトリ構造表示"""
if not self.output_dir.exists():
print(" (出力ディレクトリが存在しません)")
return
def print_tree(path: Path, prefix: str = ""):
items = sorted(path.iterdir(), key=lambda x: (x.is_file(), x.name))
for i, item in enumerate(items):
is_last = i == len(items) - 1
current_prefix = "└── " if is_last else "├── "
print(f" {prefix}{current_prefix}{item.name}")
if item.is_dir() and item.name in ["fonts", "css", "scss"]:
extension = " " if is_last else ""
print_tree(item, prefix + extension)
print_tree(self.output_dir)
def main():
"""メイン実行関数"""
parser = argparse.ArgumentParser(
description="AI Moji FontAwesome風アイコンフォントパッケージ生成システム",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
使用例:
python build.py # 全体ビルド
python build.py --font-only # フォントのみ生成
python build.py --css-only # CSSのみ生成
python build.py --package-only # パッケージングのみ
python build.py --clean # distディレクトリクリア
"""
)
parser.add_argument("--font-only", action="store_true",
help="フォントファイルのみ生成")
parser.add_argument("--css-only", action="store_true",
help="CSS/SCSSファイルのみ生成")
parser.add_argument("--package-only", action="store_true",
help="パッケージングのみ実行")
parser.add_argument("--clean", action="store_true",
help="distディレクトリをクリア")
parser.add_argument("--svg-dir", default="../../svg",
help="SVGファイルディレクトリ (デフォルト: ../../svg)")
parser.add_argument("--output-dir", default="../../dist",
help="出力ディレクトリ (デフォルト: ../../dist)")
args = parser.parse_args()
# ビルドシステム初期化
build_system = AIMojiBuildSystem(args.svg_dir, args.output_dir)
try:
# クリーンアップ
if args.clean:
build_system.clean_dist()
return 0
# 個別ビルド
if args.font_only:
success = build_system.build_font()
elif args.css_only:
success = build_system.build_css()
elif args.package_only:
success = build_system.build_package()
else:
# 全体ビルド
success = build_system.build_all()
return 0 if success else 1
except KeyboardInterrupt:
print("\n⚠️ ビルドが中断されました")
return 1
except Exception as e:
print(f"\n❌ 予期しないエラーが発生しました: {e}")
return 1
if __name__ == "__main__":
exit(main())

View File

@ -0,0 +1,256 @@
#!/usr/bin/env python3
"""
AI Moji CSS Generator
フォントメタデータからCSS/SCSSファイルを自動生成
"""
import json
from pathlib import Path
from typing import Dict, List
from datetime import datetime
class AIMojiCSSGenerator:
def __init__(self, output_dir: str = "../../dist"):
self.output_dir = Path(output_dir)
self.css_dir = self.output_dir / "css"
self.scss_dir = self.output_dir / "scss"
self.metadata_file = self.output_dir / "metadata.json"
# ディレクトリ作成
self.css_dir.mkdir(parents=True, exist_ok=True)
self.scss_dir.mkdir(parents=True, exist_ok=True)
def load_metadata(self) -> Dict:
"""メタデータファイルを読み込み"""
if not self.metadata_file.exists():
raise FileNotFoundError(f"メタデータファイルが見つかりません: {self.metadata_file}")
with open(self.metadata_file, 'r', encoding='utf-8') as f:
return json.load(f)
def generate_css_template(self, metadata: Dict) -> str:
"""FontAwesome風CSSテンプレート生成"""
font_family = metadata["font_family"]
css_prefix = metadata["css_prefix"]
css_content = f"""/*!
* AI Moji Icons v{metadata["version"]}
* Generated on {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
* {metadata["total_icons"]} icons in the set
*/
@font-face {{
font-family: '{font_family}';
src: url('../fonts/{font_family}.eot');
src: url('../fonts/{font_family}.eot?#iefix') format('embedded-opentype'),
url('../fonts/{font_family}.woff2') format('woff2'),
url('../fonts/{font_family}.woff') format('woff'),
url('../fonts/{font_family}.ttf') format('truetype'),
url('../fonts/{font_family}.svg#{font_family}') format('svg');
font-weight: normal;
font-style: normal;
font-display: block;
}}
.{css_prefix} {{
/* use !important to prevent issues with browser extensions that change fonts */
font-family: '{font_family}' !important;
speak: never;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}}
/* Individual Icon Classes */
"""
# 各アイコンのCSSクラス生成
for icon in metadata["icons"]:
css_content += f'.{icon["css_class"]}::before {{\n'
css_content += f' content: "\\{icon["unicode"][2:]}";\n'
css_content += '}\n\n'
return css_content
def generate_scss_variables(self, metadata: Dict) -> str:
"""SCSS変数ファイル生成"""
scss_content = f"""//
// AI Moji Icons Variables
// Generated on {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
//
// Font Configuration
$aimoji-font-family: '{metadata["font_family"]}' !default;
$aimoji-font-path: '../fonts' !default;
$aimoji-css-prefix: '{metadata["css_prefix"]}' !default;
$aimoji-version: '{metadata["version"]}' !default;
// Unicode Variables
"""
# 各アイコンのUnicode変数
for icon in metadata["icons"]:
var_name = icon["name"].replace("-", "_").replace(".", "_")
scss_content += f'$aimoji-{var_name}: "\\{icon["unicode"][2:]}";\n'
scss_content += "\n// Icon Map for iteration\n"
scss_content += "$aimoji-icons: (\n"
for i, icon in enumerate(metadata["icons"]):
var_name = icon["name"].replace("-", "_").replace(".", "_")
comma = "," if i < len(metadata["icons"]) - 1 else ""
scss_content += f' "{icon["name"]}": $aimoji-{var_name}{comma}\n'
scss_content += ");\n"
return scss_content
def generate_scss_mixins(self) -> str:
"""SCSS mixinファイル生成"""
return """//
// AI Moji Icons Mixins
//
// Base icon mixin
@mixin aimoji-base() {
font-family: $aimoji-font-family;
speak: never;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
// Icon content mixin
@mixin aimoji-icon($unicode) {
@include aimoji-base();
&::before {
content: $unicode;
}
}
// Size mixins
@mixin aimoji-size($size) {
font-size: $size;
line-height: 1;
}
// Rotation mixins
@mixin aimoji-rotate($degrees) {
transform: rotate(#{$degrees}deg);
}
@mixin aimoji-flip-horizontal() {
transform: scaleX(-1);
}
@mixin aimoji-flip-vertical() {
transform: scaleY(-1);
}
// Animation mixins
@mixin aimoji-spin() {
animation: aimoji-spin 2s infinite linear;
}
@keyframes aimoji-spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(359deg); }
}
@mixin aimoji-pulse() {
animation: aimoji-pulse 1s infinite;
}
@keyframes aimoji-pulse {
0% { transform: scale(1); }
50% { transform: scale(1.1); }
100% { transform: scale(1); }
}
"""
def minify_css(self, css_content: str) -> str:
"""CSS最小化簡易版"""
import re
# コメント削除
css_content = re.sub(r'/\*.*?\*/', '', css_content, flags=re.DOTALL)
# 余分な空白削除
css_content = re.sub(r'\s+', ' ', css_content)
# セミコロン前後の空白削除
css_content = re.sub(r'\s*;\s*', ';', css_content)
# ブレース前後の空白削除
css_content = re.sub(r'\s*{\s*', '{', css_content)
css_content = re.sub(r'\s*}\s*', '}', css_content)
return css_content.strip()
def generate_all(self) -> Dict:
"""全CSSファイル生成"""
print("📝 CSS/SCSSファイル生成開始...")
# メタデータ読み込み
metadata = self.load_metadata()
# CSS生成
css_content = self.generate_css_template(metadata)
css_file = self.css_dir / "aimoji.css"
with open(css_file, 'w', encoding='utf-8') as f:
f.write(css_content)
print(f"✅ CSS生成完了: {css_file}")
# CSS最小化版生成
css_min_content = self.minify_css(css_content)
css_min_file = self.css_dir / "aimoji.min.css"
with open(css_min_file, 'w', encoding='utf-8') as f:
f.write(css_min_content)
print(f"✅ CSS最小化版生成完了: {css_min_file}")
# SCSS変数生成
scss_vars = self.generate_scss_variables(metadata)
scss_vars_file = self.scss_dir / "_variables.scss"
with open(scss_vars_file, 'w', encoding='utf-8') as f:
f.write(scss_vars)
print(f"✅ SCSS変数生成完了: {scss_vars_file}")
# SCSS mixins生成
scss_mixins = self.generate_scss_mixins()
scss_mixins_file = self.scss_dir / "_mixins.scss"
with open(scss_mixins_file, 'w', encoding='utf-8') as f:
f.write(scss_mixins)
print(f"✅ SCSS mixins生成完了: {scss_mixins_file}")
return {
"css_file": str(css_file),
"css_min_file": str(css_min_file),
"scss_vars_file": str(scss_vars_file),
"scss_mixins_file": str(scss_mixins_file),
"total_icons": metadata["total_icons"]
}
def main():
"""メイン実行関数"""
try:
generator = AIMojiCSSGenerator()
result = generator.generate_all()
print("\n🎨 CSS/SCSS生成完了!")
print(f"📊 総アイコン数: {result['total_icons']}")
except Exception as e:
print(f"❌ エラーが発生しました: {e}")
return 1
return 0
if __name__ == "__main__":
exit(main())

View File

@ -0,0 +1,140 @@
#!/usr/bin/env python3
"""
AI Moji Font Generator
SVGファイルからWebフォントを自動生成するツール
"""
import os
import json
import subprocess
from pathlib import Path
from typing import Dict, List, Optional
import fontforge
import configparser
class AIMojiFontGenerator:
def __init__(self, svg_dir: str = "../../svg", output_dir: str = "../../dist"):
self.svg_dir = Path(svg_dir)
self.output_dir = Path(output_dir)
self.fonts_dir = self.output_dir / "fonts"
self.metadata_file = self.output_dir / "metadata.json"
# ディレクトリ作成
self.fonts_dir.mkdir(parents=True, exist_ok=True)
# Unicode範囲設定 (Private Use Area)
self.unicode_start = 0xE900
def scan_svg_files(self) -> List[Dict[str, str]]:
"""SVGファイルをスキャンしてメタデータを生成"""
svg_files = []
unicode_point = self.unicode_start
for svg_file in sorted(self.svg_dir.glob("*.svg")):
name = svg_file.stem
svg_files.append({
"name": name,
"file": str(svg_file),
"unicode": hex(unicode_point),
"unicode_decimal": unicode_point,
"css_class": f"aimoji-{name}"
})
unicode_point += 1
return svg_files
def create_font(self, svg_metadata: List[Dict], font_name: str = "aimoji") -> str:
"""SVGからフォントファイルを生成"""
# FontForgeでフォント作成
font = fontforge.font()
font.fontname = font_name
font.familyname = "AI Moji"
font.fullname = "AI Moji Icons"
font.version = "1.0.0"
font.encoding = "UnicodeFull"
# 各SVGをフォントに追加
for icon in svg_metadata:
glyph = font.createChar(icon["unicode_decimal"])
glyph.importOutlines(icon["file"])
# グリフのサイズ調整
glyph.transform(fontforge.identity.scale(1024/glyph.boundingBox()[2]))
glyph.width = 1024
# フォントファイル生成
font_base = self.fonts_dir / font_name
# 複数フォーマットで出力
font.generate(f"{font_base}.ttf")
font.generate(f"{font_base}.woff")
font.generate(f"{font_base}.woff2")
font.generate(f"{font_base}.eot")
font.generate(f"{font_base}.svg")
font.close()
return str(font_base)
def save_metadata(self, svg_metadata: List[Dict], font_path: str):
"""メタデータをJSONファイルに保存"""
metadata = {
"name": "AI Moji",
"version": "1.0.0",
"font_family": "aimoji",
"font_path": font_path,
"total_icons": len(svg_metadata),
"icons": svg_metadata,
"css_prefix": "aimoji",
"build_info": {
"generator": "AI Moji Font Generator",
"unicode_range": f"{hex(self.unicode_start)}-{hex(self.unicode_start + len(svg_metadata) - 1)}"
}
}
with open(self.metadata_file, 'w', encoding='utf-8') as f:
json.dump(metadata, f, indent=2, ensure_ascii=False)
print(f"✅ メタデータを保存: {self.metadata_file}")
def generate(self) -> Dict:
"""フォント生成のメイン処理"""
print("🚀 AI Moji フォント生成開始...")
# SVGファイルスキャン
print("📂 SVGファイルをスキャン中...")
svg_metadata = self.scan_svg_files()
print(f"📁 {len(svg_metadata)} 個のSVGファイルを発見")
# フォント生成
print("🔤 フォントファイル生成中...")
font_path = self.create_font(svg_metadata)
print(f"✅ フォント生成完了: {font_path}")
# メタデータ保存
self.save_metadata(svg_metadata, font_path)
return {
"success": True,
"font_path": font_path,
"metadata": svg_metadata,
"total_icons": len(svg_metadata)
}
def main():
"""メイン実行関数"""
try:
generator = AIMojiFontGenerator()
result = generator.generate()
print("\n🎉 AI Moji フォント生成完了!")
print(f"📊 総アイコン数: {result['total_icons']}")
print(f"📁 出力ディレクトリ: {generator.fonts_dir}")
except Exception as e:
print(f"❌ エラーが発生しました: {e}")
return 1
return 0
if __name__ == "__main__":
exit(main())

View File

@ -0,0 +1,320 @@
#!/usr/bin/env python3
"""
AI Moji Packager
生成されたフォント・CSSファイルをnpmパッケージとして配布準備
"""
import json
import shutil
from pathlib import Path
from typing import Dict
from datetime import datetime
class AIMojiPackager:
def __init__(self, output_dir: str = "../../dist"):
self.output_dir = Path(output_dir)
self.metadata_file = self.output_dir / "metadata.json"
def load_metadata(self) -> Dict:
"""メタデータファイルを読み込み"""
if not self.metadata_file.exists():
raise FileNotFoundError(f"メタデータファイルが見つかりません: {self.metadata_file}")
with open(self.metadata_file, 'r', encoding='utf-8') as f:
return json.load(f)
def generate_package_json(self, metadata: Dict) -> str:
"""package.json生成"""
package_data = {
"name": "aimoji",
"version": metadata["version"],
"description": "AI Moji文字システム - アイコンフォントパッケージ",
"main": "css/aimoji.css",
"style": "css/aimoji.css",
"sass": "scss/_variables.scss",
"keywords": [
"icons",
"font",
"css",
"ai-moji",
"webfont",
"katakamuna",
"japanese"
],
"homepage": "https://github.com/syui/ai",
"repository": {
"type": "git",
"url": "https://github.com/syui/ai.git"
},
"bugs": {
"url": "https://github.com/syui/ai/issues"
},
"author": "syui",
"license": "MIT",
"files": [
"fonts/*",
"css/*",
"scss/*",
"README.md",
"metadata.json"
],
"engines": {
"node": ">=12"
},
"scripts": {
"build": "echo 'AI Moji Icons are pre-built'",
"test": "echo 'No tests specified'"
},
"devDependencies": {},
"dependencies": {}
}
package_file = self.output_dir / "package.json"
with open(package_file, 'w', encoding='utf-8') as f:
json.dump(package_data, f, indent=2, ensure_ascii=False)
return str(package_file)
def generate_readme(self, metadata: Dict) -> str:
"""README.md生成"""
readme_content = f"""# AI Moji Icons
AI Moji文字システムのアイコンフォントパッケージです。
アルファベット、カタカムナ、数字の組み合わせによる独自の文字システムをWebフォントとして提供します。
## インストール
```bash
npm install aimoji
```
## 使用方法
### CSS
```html
<link rel="stylesheet" href="node_modules/aimoji/css/aimoji.css">
```
### HTML
```html
<i class="aimoji aimoji-ai"></i>
<i class="aimoji aimoji-game"></i>
<i class="aimoji aimoji-card"></i>
```
### SCSS
```scss
@import "node_modules/aimoji/scss/variables";
@import "node_modules/aimoji/scss/mixins";
.my-icon {{
@include aimoji-icon($aimoji-ai);
@include aimoji-size(24px);
}}
```
## アイコン一覧
総アイコン数: **{metadata["total_icons"]}**
| アイコン名 | CSS クラス | Unicode |
|-----------|-----------|---------|
"""
# アイコン一覧テーブル生成
for icon in metadata["icons"]:
readme_content += f"| {icon['name']} | `.{icon['css_class']}` | `{icon['unicode']}` |\n"
readme_content += f"""
## SCSS Mixins
### 基本的な使用方法
```scss
// アイコンの基本スタイル
.icon {{
@include aimoji-base();
}}
// 特定のアイコンを表示
.ai-icon {{
@include aimoji-icon($aimoji-ai);
}}
// サイズ指定
.large-icon {{
@include aimoji-size(32px);
}}
```
### アニメーション
```scss
// 回転アニメーション
.spinning-icon {{
@include aimoji-spin();
}}
// パルスアニメーション
.pulsing-icon {{
@include aimoji-pulse();
}}
// 手動回転
.rotated-icon {{
@include aimoji-rotate(45);
}}
// 反転
.flipped-icon {{
@include aimoji-flip-horizontal();
}}
```
## ビルド情報
- **バージョン**: {metadata["version"]}
- **フォントファミリー**: {metadata["font_family"]}
- **Unicode範囲**: {metadata["build_info"]["unicode_range"]}
- **生成日時**: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
- **ジェネレーター**: {metadata["build_info"]["generator"]}
## ライセンス
MIT License
## 開発者
- **作者**: syui
- **リポジトリ**: https://github.com/syui/ai
- **プロジェクト**: AI Moji文字システム
## 哲学
AI Mojiは「存在子理論」に基づく文字システムです。
現実の個人の唯一性をデジタル世界で担保し、現実とゲームの循環的影響を実現します。
詳細は[エコシステム統合設計書](https://github.com/syui/ai/blob/main/CLAUDE.md)をご覧ください。
"""
readme_file = self.output_dir / "README.md"
with open(readme_file, 'w', encoding='utf-8') as f:
f.write(readme_content)
return str(readme_file)
def generate_license(self) -> str:
"""LICENSE生成"""
license_content = f"""MIT License
Copyright (c) {datetime.now().year} syui
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
license_file = self.output_dir / "LICENSE"
with open(license_file, 'w', encoding='utf-8') as f:
f.write(license_content)
return str(license_file)
def validate_package(self) -> bool:
"""パッケージの完全性チェック"""
required_files = [
"package.json",
"README.md",
"LICENSE",
"metadata.json",
"css/aimoji.css",
"css/aimoji.min.css",
"scss/_variables.scss",
"scss/_mixins.scss",
"fonts"
]
missing_files = []
for file_path in required_files:
full_path = self.output_dir / file_path
if not full_path.exists():
missing_files.append(file_path)
if missing_files:
print(f"⚠️ 以下のファイルが不足しています: {', '.join(missing_files)}")
return False
print("✅ パッケージの完全性チェック: 問題なし")
return True
def package_all(self) -> Dict:
"""全パッケージファイル生成"""
print("📦 パッケージング開始...")
# メタデータ読み込み
metadata = self.load_metadata()
# package.json生成
package_file = self.generate_package_json(metadata)
print(f"✅ package.json生成完了: {package_file}")
# README.md生成
readme_file = self.generate_readme(metadata)
print(f"✅ README.md生成完了: {readme_file}")
# LICENSE生成
license_file = self.generate_license()
print(f"✅ LICENSE生成完了: {license_file}")
# パッケージ検証
is_valid = self.validate_package()
return {
"package_file": package_file,
"readme_file": readme_file,
"license_file": license_file,
"is_valid": is_valid,
"output_dir": str(self.output_dir)
}
def main():
"""メイン実行関数"""
try:
packager = AIMojiPackager()
result = packager.package_all()
print("\n📦 パッケージング完了!")
print(f"📁 出力ディレクトリ: {result['output_dir']}")
if result["is_valid"]:
print("🚀 npmパッケージとして公開準備完了!")
print(" npm publish コマンドで公開できます")
else:
print("⚠️ パッケージに問題があります")
except Exception as e:
print(f"❌ エラーが発生しました: {e}")
return 1
return 0
if __name__ == "__main__":
exit(main())

View File

@ -0,0 +1,8 @@
# AI Moji Font Generator Dependencies
# フォント生成用
fontforge>=20230101
fonttools>=4.38.0
# その他ユーティリティ
pathlib2>=2.3.7; python_version < "3.4"

View File

@ -0,0 +1,97 @@
#!/bin/bash
# AI Moji Font Generator Setup Script
set -e
echo "🚀 AI Moji Font Generator セットアップ開始"
echo "======================================"
# Python バージョンチェック
echo "🐍 Python バージョンチェック..."
python3 --version || {
echo "❌ Python 3 が見つかりません"
echo " Python 3.6 以上をインストールしてください"
exit 1
}
# pip が利用可能かチェック
echo "📦 pip チェック..."
python3 -m pip --version || {
echo "❌ pip が見つかりません"
echo " pip をインストールしてください"
exit 1
}
# FontForge インストール (macOS)
if [[ "$OSTYPE" == "darwin"* ]]; then
echo "🍎 macOS環境を検出"
if ! command -v fontforge &> /dev/null; then
echo "🔧 FontForge をインストール中..."
if command -v brew &> /dev/null; then
brew install fontforge
else
echo "❌ Homebrew が見つかりません"
echo " Homebrewをインストールしてから再実行してください:"
echo " /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""
exit 1
fi
else
echo "✅ FontForge インストール済み"
fi
fi
# FontForge インストール (Ubuntu/Debian)
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
echo "🐧 Linux環境を検出"
if ! command -v fontforge &> /dev/null; then
echo "🔧 FontForge をインストール中..."
sudo apt-get update
sudo apt-get install -y fontforge python3-fontforge
else
echo "✅ FontForge インストール済み"
fi
fi
# Python依存関係インストール
echo "📚 Python 依存関係をインストール中..."
python3 -m pip install -r requirements.txt
# ディレクトリ構造確認
echo "📁 ディレクトリ構造確認..."
SVG_DIR="../../svg"
if [ ! -d "$SVG_DIR" ]; then
echo "⚠️ SVGディレクトリが見つかりません: $SVG_DIR"
echo " ai.mojiプロジェクトのルートディレクトリで実行していることを確認してください"
fi
SVG_COUNT=$(find "$SVG_DIR" -name "*.svg" 2>/dev/null | wc -l || echo "0")
echo " SVGファイル数: $SVG_COUNT"
# 実行権限設定
echo "🔐 実行権限設定..."
chmod +x build.py
# テストビルド
echo "🧪 テストビルド実行..."
python3 build.py --clean
if python3 build.py --font-only; then
echo "✅ テストビルド成功!"
else
echo "❌ テストビルドに失敗しました"
exit 1
fi
echo ""
echo "🎉 セットアップ完了!"
echo "======================================"
echo ""
echo "📋 使用方法:"
echo " python3 build.py # 全体ビルド"
echo " python3 build.py --font-only # フォントのみ"
echo " python3 build.py --css-only # CSSのみ"
echo " python3 build.py --package-only # パッケージングのみ"
echo " python3 build.py --clean # クリーンアップ"
echo ""
echo "📁 出力ディレクトリ: ../../dist"
echo ""
echo "🚀 準備完了! FontAwesome風aimojiパッケージを生成できます"