refactor(assets): migrate JavaScript to TypeScript service architecture (#766)

* refactor: add TypeScript support and refactor utility functions

* docs: add CLAUDE.md for Claude Code guidance

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* refactor(assets): replace factory-function pattern with service classes and DI container

Introduce typed service container, event bus, and service interfaces to replace
the shared FixItContext factory-function pattern. Each module is now a standalone
class implementing a typed interface, with explicit constructor-injected
dependencies. The window.fixit backward-compatibility facade is built via a
publicAPI() helper that extracts class methods.

Also removes unnecessary setTimeout/afterPaint deferred execution wrappers
from init sequences, and improves module header comments.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* refactor: replace private properties with class fields in modules

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* refactor(assets): rewrite link page script in TypeScript

Rename pages/link.js to link.ts with proper type annotations and update
the Hugo template reference accordingly.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs: rewrite CLAUDE.md and copilot-instructions.md in English

Update both files to reflect the new service-class architecture with
DI container, typed event bus, and ES6 # private fields.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix: update event handling to use CustomEvent for better type safety

* refactor: enhance theme switching by adding isChanged flag to event details

* refactor(assets): refactor Mermaid module structure and event wiring

* refactor(assets): align lib integrations with TypedEventBus and add module overviews

* chore(assets): remove vite-specific import ignore comments

* refactor(assets): remove deprecated forEach utility and use native forEach

Replace custom forEach wrapper with native .forEach() on NodeList, HTMLCollection (via querySelectorAll), and arrays. The utility was already marked @deprecated and all 30+ call sites use synchronous handlers, making the wrapper unnecessary. Also replace getElementsByClassName/getElementsByTagName with querySelectorAll for consistency.

- Delete utils/array.ts (no longer needed)
- Remove forEach export from utils/index.ts
- Refactor 11 module files to use native .forEach()
- Switch getElementsByClassName to querySelectorAll in theme.ts and charts.ts

* refactor(assets): split ChartsModule into independent lib files

Move ECharts, Mapbox GL, and TypeIt integrations from the ServiceContainer-managed ChartsModule into three standalone lib files (echarts.ts, mapbox.ts, typeit.ts). Each lib:
- Instantiates its own TypedEventBus
- Reads config from window.config.*
- Self-initializes on DOMContentLoaded
- Handles decrypt/re-init events independently
- Uses implicit idempotency via DOM element queries

Key improvements:
- Reduces ServiceContainer complexity
- Makes chart libs independently loadable
- Fixes partial decryption handling in echarts (only re-inits decrypted portion)
- Maintains consistency with aplayer/file-tree lib pattern

* refactor(assets): extract third-party libraries to standalone lib files

Extract twemoji, pangu, cookieconsent, watermark, lightgallery, and json-viewer
from modules into separate lib files for better separation of concerns. Each lib
is loaded conditionally via assets.html and handles its own initialization and
event lifecycle independently.

Additionally, unify fixit event handling by replacing document.addEventListener
calls with TypedEventBus.on() in EncryptionModule and MiscModule for consistent
event architecture.

Remove unused MiscService dependency from ContentModule.

* refactor(assets): unify js.Build pipeline and defaults

- extract shared helper partial function/js-build.html for js.Build + minify

- make plugin script renderer and Mermaid use the same js.Build logic

- default Build.minify to hugo.IsProduction when unset

- default Build.sourceMap to cond hugo.IsDevelopment "linked" "none"

- remove duplicated sourceMap branching in layout templates

- update js targetPath naming to .js (no explicit .min.js suffix)

* refactor(assets): extract comment systems to independent lib files

Extract comment system initialization logic from CommentModule into 7 independent
lib files (artalk, gitalk, valine, waline, utterances, twikoo, giscus). Each lib:
- Conditionally loads based on window.config.comment configuration
- Handles backend-specific initialization via DOMContentLoaded
- Manages its own theme synchronization and event listeners
- Is loaded conditionally in assets.html only when enabled

Simplify CommentModule to handle only:
- Comment section UI display and visibility toggle
- Shared lightGallery initialization utility (used by Artalk and Twikoo)
- Comment expiration handling

This reduces module complexity and enables per-backend lazy loading.

* refactor(assets): unify js.Build pipeline and consolidate PWA config

Enhance js-build.html to accept Build as bool/dict, auto-derive
targetPath from resource name (.ts → .js), and skip js.Build when
Build is false/omit. Simplify assets.html by removing explicit
targetPath dicts for all .ts lib builds. Consolidate enablePWA and
serviceWorkerURL into a PWA config object.

* refactor(assets): decouple toc from content module and add JSDoc headers

- Remove TocService dependency from ContentModule, toc now self-manages
- Rename initContent() → setup(), init() → setup() for toc
- Make initFootnotes private (#initFootnotes)
- Add multi-line JSDoc headers with Responsibilities to all modules,
  main.ts, pages/link.ts, and head/color-scheme.ts

* refactor(assets): split types.ts into types/ directory module

* refactor(assets): simplify JS module architecture and expose typed window.fixit API

- Remove DI container (core/container.ts), use direct constructor calls
- Export shared eventBus singleton from core/event-bus.ts, remove 16 redundant instances
- Merge thin modules: SvgModule/CommentModule/LinkGuardModule into ContentModule/MiscModule
- Trim service interfaces to externally-used methods only
- Replace publicAPI() reflection with minimal typed window.fixit facade
- Expose public APIs: setThemeMode, eventBus, initContent, mask overlay, scroll state
- Extract setThemeMode from initSwitchTheme closure as public method
- Rename fixit:reset to fixit:re-encrypt, remove dead events
- Replace custom.js.example with custom.ts.example
- Update CLAUDE.md and copilot-instructions.md

* style(i18n): use semantic names for comment dividers instead of file paths

Replace file-path-based comment dividers (e.g. partials/base/header.html)
with semantic names (e.g. Header) across all 16 i18n files for consistency.

* chore(workflow): update cron schedule for library updates

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Cell
2026-05-28 12:43:42 +08:00
committed by GitHub
parent f76b6a1f1c
commit 14a965f9c1
106 changed files with 5810 additions and 4500 deletions
+57 -270
View File
@@ -1,307 +1,94 @@
# FixIt 编码标准和指导原则
# FixIt Coding Standards and Guidelines
本文档定义了 FixIt 主题项目的编码标准、最佳实践和开发指导原则。所有贡献者和 AI 助手在参与项目开发时都应遵循这些规范。
This document defines the detailed coding standards for the FixIt theme project. For project overview, architecture, and development commands, see [CLAUDE.md](../../CLAUDE.md).
## 项目概述
## SCSS Coding Standards
FixIt 是一个面向 Hugo 静态网站生成器的现代化、响应式主题。项目基于以下技术栈:
### Naming
- **Hugo**: 静态网站生成器(≥ 0.158.0)
- **SCSS**: CSS 预处理器,用于样式开发
- **JavaScript**: ES6+ 标准,用于前端交互功能
- **Go Templates**: Hugo 模板引擎
- **Node.js**: 开发环境和构建工具
- **pnpm**: 包管理器
- **CSS classes**: BEM or semantic naming (`header-desktop`, `menu-item`, `post-tag`)
- **SCSS variables**: hyphen-separated, semantic (`$global-font-family`, `$code-background-color`)
- **CSS custom properties**: prefixed with `fi-` / `--fi-`
## 目录结构约定
### Guidelines
```
FixIt/
├── apps/ # 最小化站点
│ ├── demo/ # 演示站点
│ └── test/ # 测试站点
├── archetypes/ # 内容模板
├── assets/ # 主题资源文件
│ ├── css/ # SCSS 样式文件
│ ├── js/ # JavaScript 文件
│ ├── images/ # 图像资源
│ └── lib/ # 第三方库
├── i18n/ # 国际化翻译文件
├── layouts/ # Hugo 模板文件
│ ├── _markup/ # Hugo 渲染钩子
│ ├── _partials/ # 可复用模板组件
│ └── _shortcodes/ # 自定义短代码
├── packages/ # 主题相关包
├── static/ # 静态文件
├── hugo.toml # 主题默认配置
└── package.json # npm 脚本和依赖
```
- Use 2-space indentation
- Use CSS variables for theme switching support
- Prefer relative units (rem, em, %) over absolute units
- Use SCSS variables for colors — no hardcoded values
- Keep selector nesting shallow
## SCSS/CSS 编码规范
## TypeScript Coding Standards
### 文件组织结构
### Architecture
1. **主入口文件**: `assets/scss/main.scss`
2. **变量文件**: `assets/scss/_variables.scss` - 全局变量定义
3. **覆写文件**: `assets/scss/_override.scss` - 用户自定义覆写
Service-class architecture with direct constructor calls:
### 命名约定
- **`TypedEventBus`** (`core/event-bus.ts`) — Module-level singleton (`eventBus`) wrapping DOM `CustomEvents` with typed event map.
- **Service interfaces** (`core/tokens.ts`) — Typed contracts for each module (`CoreService`, `ThemeService`, `CodeService`, etc.).
- **Module classes** (`modules/*.ts`) — Each module implements its service interface. Dependencies are constructor-injected.
1. **CSS 类名**: 使用 BEM 方法论或语义化命名
### Module Pattern
```scss
.header-desktop {}
.menu-item {}
.single-title {}
.post-tag {}
```
```typescript
export class ExampleModule implements ExampleService {
#privateState: any // ES6 # private fields, not _ prefix
2. **SCSS 变量**: 使用连字符分隔,语义化命名
constructor(private readonly core: CoreService) {}
```scss
$global-font-family: system-ui, sans-serif;
$code-background-color: #f4f6f8;
$header-height: 3.5rem;
```
3. **CSS 自定义属性**: 使用前缀约定
```scss
$prefix: fi-;
$rootPrefix: --fi-;
```
### 样式组织原则
1. **主题切换支持**: 使用 CSS 变量实现主题切换
```scss
.element {
color: fi-var(global-font-color);
}
```
2. **Mixin 使用**: 提高代码复用性
```scss
@include border-radius;
```
### 代码质量要求
1. **缩进**: 使用 2 个空格
2. **注释**: 为复杂逻辑添加注释
3. **颜色**: 使用变量而非硬编码颜色值
4. **单位**: 优先使用相对单位(rem、em、%)
## JavaScript 编码规范
### 代码风格
1. **ES6+ 标准**: 使用现代 JavaScript 语法
2. **模块化**: 使用 ES6 模块系统
### 文件组织
1. **主题核心**: `assets/js/theme.js` - 主题核心逻辑
2. **工具函数**: `assets/js/utils/` - 通用工具函数
3. **特定功能**: 按功能划分独立模块
### 编码实例
```javascript
// 使用 ES6 类
export default class Util {
static copyText(text) {
// ...
}
}
// 主题类组织
class FixIt {
constructor() {
this.config = window.config
this.scrollTop = Util.getScrollTop()
}
init() {
this.initTheme()
this.initComponents()
}
publicMethod(): void { /* ... */ }
#privateHelper(): void { /* ... */ }
}
```
### 最佳实践
### Key Rules
1. **错误处理**: 使用 try-catch 处理异常
2. **异步操作**: 优先使用 async/await
3. **事件处理**: 合理使用事件委托
4. **性能优化**: 避免不必要的 DOM 操作
- Use ES6 `#` private fields — not TypeScript `private` with `_` prefix
- Keep modules focused: one module per file, one service interface per module
- Import the shared `eventBus` singleton from `core/event-bus` for cross-module communication
- Constructor injection for dependencies — no global state access
- `window.fixit` exposes a typed public API (`FixItPublicAPI`) for user custom scripts
## Hugo 模板规范
### Utilities
### 模板组织
- Pure functions only in `utils/` — no side effects, no DOM state
- Re-export everything through `utils/index.ts`
1. **布局模板**: `layouts/` 目录下的主要模板
2. **局部模板**: `layouts/_partials/` 下的可复用组件
3. **短代码**: `layouts/_shortcodes/` 下的内容短代码
## Hugo Template Standards
### 编码约定
### Conventions
1. **变量命名**: 使用驼峰命名法
- **Variable naming**: camelCase (`$footerConfig`, `$fingerprint`)
- **Comments**: Hugo syntax `{{- /* comment */ -}}`
- **Translation**: Use `T` function for i18n (`{{ T "header.switchTheme" }}`)
- **Whitespace**: Use `{{- -}}` trim markers to control whitespace output
```go-html-template
{{- $footerConfig := .Site.Params.footer -}}
{{- $fingerprint := .Site.Store.Get "fingerprint" -}}
```
### Guidelines
2. **注释规范**: 使用 Hugo 注释语法
- Use `partialCached` for expensive partials that don't change per page
- Use `.Site.Store` for shared computed values (e.g. fingerprint)
- Check `hugo.IsProduction` before adding analytics or minification
```go-html-template
{{- /* 这是模板注释 */ -}}
{{- /*
多行注释
可以跨越多行
*/ -}}
```
## Git Workflow
3. **条件判断**: 清晰的条件结构
### Commit Convention
```go-html-template
{{- if ne $config.enable false -}}
<!-- 内容 -->
{{- end -}}
```
4. **循环遍历**: 合理使用 range
```go-html-template
{{- range $index, $value := .Pages -}}
<!-- 处理逻辑 -->
{{- end -}}
```
### 国际化处理
1. **翻译函数**: 使用 `T` 函数
```go-html-template
{{ T "header.switchTheme" }}
```
2. **多语言支持**: 考虑多语言环境
```go-html-template
{{- if hugo.IsMultilingual -}}
<!-- 多语言逻辑 -->
{{- end -}}
```
## 开发工作流程
### 环境设置
1. **前置要求**:
- Node.js (≥ 20.0.0)
- Hugo Extended (≥ 0.158.0)
- pnpm (包管理器)
2. **开发命令**:
```bash
pnpm dev:demo # 启动 demo 站点开发服务器
pnpm dev:test # 启动 test 站点开发服务器
pnpm dev:docs # 启动文档开发服务器(需有 fixit-docs 作为同级目录)
pnpm build:demo # 构建 demo 站点
pnpm build:test # 构建 test 站点
pnpm build # 一键构建所有站点
pnpm preview # 预览构建后的站点(需先构建)
```
### 代码质量
1. **代码审查**: 提交前进行自我审查
2. **测试验证**: 在多个环境中测试功能
3. **文档更新**: 必要时更新相关文档
4. **向后兼容**: 确保更改不破坏现有功能
### Git 提交规范
遵循 [Conventional Commits](https://www.conventionalcommits.org/) 规范:
Follows [Conventional Commits](https://www.conventionalcommits.org/):
```
feat: 新增功能
fix: 修复 bug
docs: 文档更新
style: 代码格式调整
refactor: 代码重构
test: 测试相关
chore: 构建过程或工具相关
<type>(<scope>): <subject>
```
## 性能优化指导
Types: `feat`, `fix`, `refactor`, `chore`, `docs`, `perf`, `style`, `test`, `ci`, `build`
### CSS 性能
Scopes: `workflow`, `archetypes`, `assets`, `i18n`, `layouts`, `config`, or specific directories.
1. **选择器优化**: 避免过深的嵌套
2. **媒体查询**: 合理组织响应式断点
3. **动画优化**: 使用 transform 和 opacity
4. **资源压缩**: 生产环境启用压缩
### Pre-commit Hooks
### JavaScript 性能
Pre-commit runs: versioning (dev mode), typecheck, lint-staged (eslint --fix on staged files).
1. **延迟加载**: 非关键脚本使用 defer
2. **事件优化**: 合理使用防抖和节流
3. **内存管理**: 及时清理事件监听器
4. **模块化**: 按需加载功能模块
## Browser Compatibility
### Hugo 模板性能
1. **缓存策略**: 合理使用 Hugo 缓存机制
2. **资源处理**: 优化图片和静态资源
3. **构建优化**: 减少不必要的模板处理
## 可访问性要求
1. **语义化 HTML**: 使用正确的 HTML 标签
2. **ARIA 属性**: 为复杂组件添加 ARIA 支持
3. **键盘导航**: 确保键盘可访问性
4. **颜色对比**: 满足 WCAG 对比度要求
5. **屏幕阅读器**: 提供适当的文本替代
## 浏览器兼容性
1. **目标浏览器**: 支持现代浏览器
2. **渐进增强**: 基础功能向下兼容
3. **特性检测**: 使用特性检测而非浏览器检测
4. **Polyfill**: 必要时提供 polyfill 支持
## 安全考虑
1. **XSS 防护**: 正确处理用户输入
2. **CSRF 保护**: 表单提交安全
3. **内容安全**: 合理设置 CSP 策略
4. **依赖安全**: 定期更新依赖包
## 文档要求
1. **代码注释**: 复杂逻辑必须注释
2. **API 文档**: 公共方法需要文档
3. **使用示例**: 提供清晰的使用示例
4. **更新日志**: 重要更改记录在 CHANGELOG
## 第三方库管理
1. **依赖选择**: 优先选择轻量、维护活跃的库
2. **版本管理**: 及时更新安全补丁
3. **许可证**: 确保许可证兼容性
4. **定制化**: 必要时进行本地化修改
## 贡献指导
1. **讨论优先**: 重大更改前先讨论
2. **小步迭代**: 避免大规模重构
3. **测试覆盖**: 新功能需要充分测试
4. **文档同步**: 功能和文档同时更新
遵循这些编码标准将有助于维护代码质量,提高开发效率,并确保项目的长期可维护性。
- Target modern browsers
- Use progressive enhancement for advanced features
- Prefer feature detection over browser detection