Files
Serendipity edbf78f236 feat: 初始化 Halo 暗色模式插件
- Halo Plugin 后端(Java/Gradle),含 DarkModePlugin 主类和测试
- Vue 3 + TypeScript 前端 UI,包含主题切换组件和设置页面
- 暗色模式 CSS 变量和覆盖样式(布局/编辑器/表单/滚动条等)
- 设计文档和调查文档
- Halo 插件/主题开发 Agent Skills

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-06 21:03:00 +08:00

172 lines
5.4 KiB
Markdown

# DevTools (run.halo.plugin.devtools)
A Gradle plugin for streamlined plugin development. Requires Docker.
> - [halo-gradle-plugin repo](https://github.com/halo-sigs/halo-gradle-plugin)
> - [halo-gradle-plugin releases](https://github.com/halo-sigs/halo-gradle-plugin/releases)
## Quick Commands
| Command | Purpose |
| --------------------------------- | --------------------------------------------------- |
| `./gradlew haloServer` | Start Halo in Docker with plugin loaded in dev mode |
| `./gradlew reload` | Reload plugin changes without restarting Halo |
| `./gradlew watch` | Auto-reload on file changes |
| `./gradlew build` | Build plugin JAR (includes frontend build) |
| `./gradlew generateApiClient` | Generate TypeScript API client from OpenAPI |
| `./gradlew generateRoleTemplates` | Generate role template YAML from OpenAPI |
## build.gradle Setup
```groovy
plugins {
id 'java'
id "io.freefair.lombok" version "8.13"
id "run.halo.plugin.devtools" version "0.6.0"
}
group = 'com.example.myplugin'
repositories {
mavenCentral()
}
dependencies {
implementation platform('run.halo.tools.platform:plugin:2.22.0')
compileOnly 'run.halo.app:api'
testImplementation 'run.halo.app:api'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
test {
useJUnitPlatform()
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
tasks.withType(JavaCompile).configureEach {
options.encoding = "UTF-8"
options.release = 21
}
// UI build integration (if UI is in a separate subproject)
tasks.register('processUiResources', Copy) {
from project(':ui').layout.buildDirectory.dir('dist')
into layout.buildDirectory.dir('resources/main/console')
dependsOn project(':ui').tasks.named('assemble')
shouldRunAfter tasks.named('processResources')
}
tasks.named('classes') {
dependsOn tasks.named('processUiResources')
}
halo {
version = '2.22'
superAdminUsername = 'admin'
superAdminPassword = 'admin'
port = 8090
// debug = true
// debugPort = 5005
// suspend = true
externalUrl = 'http://localhost:8090'
}
```
## halo {} Block Options
| Option | Description | Default |
| -------------------- | ------------------------------------------ | ----------------------------------------- |
| `version` | Halo Docker image version | `'2.9.1'` |
| `superAdminUsername` | Auto-created admin username | `'admin'` |
| `superAdminPassword` | Auto-created admin password | `'admin'` |
| `port` | Halo server port | `8090` |
| `externalUrl` | External access URL | `'http://localhost:8090'` |
| `debug` | Enable JDWP debug | `false` |
| `debugPort` | JDWP port | auto-assigned |
| `suspend` | Suspend on startup until debugger connects | `false` |
| `docker.url` | Docker daemon URL | `unix:///var/run/docker.sock` (Mac/Linux) |
| `docker.apiVersion` | Docker API version | `'1.42'` |
## Watch Configuration
```groovy
haloPlugin {
watchDomains {
consoleSource {
files files('ui/src/')
// exclude '**/node_modules/**'
}
}
}
```
## Generate API Client
Requires OpenAPI grouping configuration in `build.gradle`:
```groovy
haloPlugin {
openApi {
groupingRules {
extensionApis {
displayName = 'Extension API for MyPlugin'
pathsToMatch = ['/apis/my-plugin.halo.run/v1alpha1/**']
}
}
groupedApiMappings = [
'/v3/api-docs/extensionApis': 'extensionApis.json'
]
generator {
outputDir = file("${projectDir}/ui/src/api/generated")
additionalProperties = [
useES6: true,
useSingleRequestParameter: true,
withSeparateModelsAndApi: true,
apiPackage: "api",
modelPackage: "models"
]
typeMappings = [
set: "Array"
]
}
}
}
```
Usage in TypeScript:
```ts
import { axiosInstance } from "@halo-dev/api-client";
import { MyResourceV1alpha1Api } from "./api/generated";
const api = new MyResourceV1alpha1Api(undefined, "", axiosInstance);
const { data } = await api.listMyResources({});
```
## Generate Role Templates
After configuring OpenApi grouping, run:
```bash
./gradlew generateRoleTemplates
```
Generates `roleTemplates.yaml` in the `workplace/` directory. Review and customize before adding to `src/main/resources/extensions/`.
## Custom Halo Config
Place `workplace/config/application.yaml` to override Halo defaults:
```yaml
logging:
level:
run.halo.app: DEBUG
```