TAIXU PROJECT TEMPLATE GUIDE / SCHEMA 1

把一套工程,
变成可分享的起点。

一个 ZIP 就能携带工程骨架、动态字段、统一方形预览图,以及需要用户明确授权的构造脚本。这里记录的是当前模板导入器、表单渲染器和物化引擎的真实约束。

01 / 从工程到模板

  1. 建立模板目录并放入工程骨架。
  2. template.json 中声明类型、分类、预览图和变量。
  3. 把需要替换的值写成 {{variableName}}
  4. 可选:在 template-hooks/ 携带前置或后置脚本。
  5. 将目录压缩为 ZIP,在“工坊 → 模板管理”导入。
  6. 验证后直接导出 ZIP,与其他用户分享。

最快的开始方式是在模板管理页导出一个内置模板。修改 template.jsonid,并移除系统保留的 builtin. 前缀后再导入。

02 / 模板包目录结构

模板使用普通 ZIP。ZIP 根目录可以直接放置清单,也可以只包含一个模板文件夹。

my-android-template/
├── template.json
├── preview.png                   # 可选,固定 270×270
├── template-hooks/             # 可选
│   ├── before-create.sh
│   └── after-create.sh
└── app/
    ├── build.gradle.kts
    └── src/main/java/TAIXU_PACKAGE_PATH/
        └── MainActivity.kt.template
  • 最多 5000 个 ZIP 条目。
  • 单文件最大 16 MiB。
  • 总解压体积最大 128 MiB。
  • 绝对路径、Windows 盘符和包含 .. 的越界路径会被拒绝。

03 / 编写 template.json

{
  "schemaVersion": 1,
  "id": "example.android-basic",
  "name": "Basic Android",
  "version": "1.0.0",
  "description": "A reusable Android starter",
  "projectType": "ANDROID",
  "category": {
    "id": "starter",
    "name": "Starter",
    "sortOrder": 0
  },
  "previewImage": "preview.png",
  "variables": []
}
字段当前约束
schemaVersion当前固定为 1
id小写字母和数字,可用点、下划线、短横线分隔;builtin. 为保留前缀。
projectTypeANDROIDFLUTTERGENERAL
category模板选择页的分组;sortOrder 越小越靠前。
previewImage可选的单张 1:1、270×270 预览图。
variables声明动态表单和所有模板变量。
hooks可选的前置、后置构造脚本。
validation模板自带的生成结果校验规则。

清单采用严格解析,未知字段不会被忽略。机器可读的 JSON Schema 可从项目仓库直接获取。

04 / 让清单渲染动态 UI

"variables": [
  {
    "name": "packageName",
    "label": "Package name",
    "prompt": true,
    "inputType": "TEXT",
    "placeholder": "com.example.app",
    "validationRegex": "^[a-zA-Z_][\\w]*(\\.[a-zA-Z_][\\w]*)+$"
  },
  {
    "name": "uiStyle",
    "label": "UI style",
    "prompt": true,
    "inputType": "SELECT",
    "defaultValue": "compose",
    "options": [
      { "value": "compose", "label": "Jetpack Compose" },
      { "value": "views", "label": "Android Views" }
    ]
  }
]

prompt: true 会在创建工程的最后一步自动渲染控件。支持 TEXTMULTILINENUMBERBOOLEANSELECTSECRET

  • 变量名必须匹配 ^[A-Za-z][A-Za-z0-9_]*$,且不能重复。
  • 隐藏必填变量必须提供默认值,系统派生变量除外。
  • SELECT 必须有不重复的选项;可选字段允许留空。
  • 项目名称与创建路径由工坊统一填写,不应伪装成动态字段。

系统提供 projectNameappNameprojectPath;如果模板把 appName 设为动态字段,则优先使用用户输入。只有模板声明 packageNamepackagePath 时,才会启用 Java 包名规则。

模板可将 projectName 声明为 prompt: false 的固定变量,并用 validationRegex 约束统一项目名称输入框。校验失败时工坊显示该变量的 description 并禁止创建,不会静默改写用户输入。

05 / 替换文件内容和路径

文本内容与相对路径都能使用变量:

modules/{{moduleName}}/config.json.template

{
  "name": "{{projectName}}",
  "mode": "{{buildMode}}"
}

生成时会替换变量并移除末尾的 .template。任意需要替换的文本都建议使用该后缀;Java、Kotlin、Dart、JSON、YAML、TOML、Shell、Python、JavaScript、C/C++ 等常见文本格式也会自动识别。

包目录使用 TAIXU_PACKAGE_PATH,创建时会替换为包名对应的目录层级。不要使用以下划线开头的占位目录,否则可能被 Android AAPT 忽略。变量生成的路径会再次规范化,越界路径会被拒绝。若文件中残留未声明的 {{unknownVariable}},创建会直接失败。

06 / 统一方形预览图

模板只声明一张预览图,不再区分手机、平板或横竖屏。比例固定为 1:1,尺寸必须为 270×270 px;支持 PNG、JPEG、WebP 和 GIF,单图不超过 4 MiB。

把 Logo、标题和关键内容留在中央安全区,并避开四周约 8%,保证不同尺寸的模板卡片都能清晰展示。

07 / 携带可审查的构造脚本

"hooks": {
  "beforeCreate": "template-hooks/before-create.sh",
  "afterCreate": "template-hooks/after-create.sh"
}

脚本不会在导入、查看或导出时执行。创建工程时,太墟会显示脚本内容,只有用户明确勾选授权后才执行。

  • 脚本必须位于 template-hooks/,单个最大 1 MiB。
  • 在 Linux 沙箱的新工程目录中运行,单阶段最长 60 秒。
  • beforeCreate 在复制模板文件前执行,afterCreate 在物化后执行。
  • 工程路径为 TAIXU_PROJECT_DIR
  • 变量以 TAIXU_VAR_<大写变量名> 传入。
  • 非零退出会终止创建,并把错误输出返回界面。
#!/bin/sh
set -eu
mkdir -p generated
printf '%s\n' "$TAIXU_VAR_PROJECTNAME" > generated/project-name.txt

08 / 模板自带结果校验

"validation": {
  "requiredFiles": ["app/src/main/java/TAIXU_PACKAGE_PATH/MainHook.kt"],
  "forbiddenFiles": ["app/src/main/java/TAIXU_PACKAGE_PATH/LegacyHook.kt"],
  "contentRules": [
    {
      "path": "app/src/main/assets/xposed_init",
      "equals": "{{packageName}}.MainHook"
    }
  ]
}

requiredFiles 声明必需文件,forbiddenFiles 声明禁止产物,contentRules 支持 equalscontainsexcludes。路径与内容均可使用模板变量。

校验在 afterCreate 完成后执行,规则属于模板本身,与内置 ID 无关;模板改名、导出和重新导入后行为保持一致。

09 / 打包、导入与分享

Windows PowerShell

Compress-Archive `
  -Path .\my-android-template\* `
  -DestinationPath .\my-android-template.zip -Force

Linux / macOS

cd my-android-template
zip -r ../my-android-template.zip .

在 Android 应用中打开“工坊 → 更多 → 模板管理 → 导入 ZIP”。导入成功后,模板会自动进入对应项目类型和分类;不需要修改应用代码或注册表。

模板管理页还可以导出模板。用户模板可删除,内置模板受到保护。

10 / 一个完整的无包名模板

GENERAL 模板不依赖 Android 包名:

{
  "schemaVersion": 1,
  "id": "example.shell-project",
  "name": "Shell Project",
  "version": "1.0.0",
  "projectType": "GENERAL",
  "category": { "id": "script", "name": "Scripts", "sortOrder": 0 },
  "variables": [
    {
      "name": "greeting",
      "label": "Greeting",
      "prompt": true,
      "inputType": "TEXT",
      "defaultValue": "Hello"
    }
  ]
}

README.md.template 中写入 # {{projectName}}\n{{greeting}} 即可。工程名称与路径仍由所有模板共用的创建页面提供。

11 / 发布前检查

  • 清单可通过 v1 JSON Schema,且没有未知字段。
  • ID 未使用 builtin.,变量名与分类 ID 合法且不重复。
  • 项目名称和路径没有被声明成动态字段。
  • 所有文本占位符均已声明,路径变量不会产生越界。
  • 单张预览图符合 1:1、270×270、格式和体积限制。
  • 脚本位于指定目录,不包含密钥,并能在 60 秒内结束。
  • 在全新目录中完成导入、表单填写、创建、导出和重新导入。
  • GENERAL 模板已确认不会被错误要求填写 Java 包名。