com.elestrago.unity.package-tools 2.2.3 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CAHNGELOG.md +22 -0
- package/Documentation~/api.md +230 -198
- package/Documentation~/manual.md +19 -19
- package/Documentation~/samples.md +44 -10
- package/Editor/Tools/FileTools.cs +11 -5
- package/README.md +39 -172
- package/Samples~/ClaudeSkills/unity-package-docs/SKILL.md +50 -8
- package/Samples~/ClaudeSkills/unity-package-docs/assets/api-chunk.md.template +10 -4
- package/Samples~/ClaudeSkills/unity-package-docs/assets/api.md.template +13 -4
- package/Samples~/ClaudeSkills/unity-package-docs/scripts/scan_package.py +50 -2
- package/Samples~/ClaudeSkills/unity-package-release/SKILL.md +373 -0
- package/Samples~/ClaudeSkills/unity-package-release/scripts/discover_package.py +366 -0
- package/package.json +4 -4
- package/Samples~/ClaudeSkills/unity-package-docs/unity-package-docs/SKILL.md +0 -309
- package/Samples~/ClaudeSkills/unity-package-docs/unity-package-docs/assets/README.md.template +0 -42
- package/Samples~/ClaudeSkills/unity-package-docs/unity-package-docs/assets/api-chunk.md.template +0 -41
- package/Samples~/ClaudeSkills/unity-package-docs/unity-package-docs/assets/api-index.md.template +0 -26
- package/Samples~/ClaudeSkills/unity-package-docs/unity-package-docs/assets/api.md.template +0 -43
- package/Samples~/ClaudeSkills/unity-package-docs/unity-package-docs/assets/manual.md.template +0 -57
- package/Samples~/ClaudeSkills/unity-package-docs/unity-package-docs/assets/samples.md.template +0 -56
- package/Samples~/ClaudeSkills/unity-package-docs/unity-package-docs/scripts/scan_package.py +0 -504
package/Documentation~/manual.md
CHANGED
|
@@ -42,18 +42,18 @@ PackageTool
|
|
|
42
42
|
|
|
43
43
|
## Entry Points
|
|
44
44
|
|
|
45
|
-
- `[MenuItem("Tools/PackageTools/PrepareDll")]`
|
|
46
|
-
- `[MenuItem("Tools/PackageTools/Init Package")]`
|
|
47
|
-
- `[CreateAssetMenu(menuName = "JCMG/PackageTools/PackageManifestConfig")]`
|
|
48
|
-
- `CIUtils.Generate` at `Assets/Package/PackageTool/Editor/CIUtils.cs:65` — batch-mode entry point invoked via `unity -batchmode -executeMethod PackageTool.CIUtils.Generate <key>=<value>`. Reads keys parsed by [`CommandLineTools.GetKVPCommandLineArguments`](api.md#commandlinetools); see
|
|
49
|
-
- `CIUtils.PrepareDll` at `Assets/Package/PackageTool/Editor/CIUtils.cs:197` — exits the Editor when run under CI (`CI` env var set); fixes DLL plugin platform flags first. Also available as `Tools/PackageTools/PrepareDll` for interactive use.
|
|
50
|
-
- `PackageInitializeWindow.Open` at `Assets/Package/PackageTool/Editor/Utils/PackageInitialize/PackageInitializeWindow.cs:7` — opens the scaffolder via `Tools/PackageTools/Init Package`.
|
|
45
|
+
- `[MenuItem("Tools/PackageTools/PrepareDll")]` -> [`CIUtils.PrepareDll`](api.md#ciutils) at `Assets/Package/PackageTool/Editor/CIUtils.cs:197`. Maps to the **Tools/PackageTools/PrepareDll** entry in the Unity menu bar.
|
|
46
|
+
- `[MenuItem("Tools/PackageTools/Init Package")]` -> [`PackageInitializeWindow.Open`](api.md#packageinitializewindow) (declared inline in `Assets/Package/PackageTool/Editor/MenuItems.cs`); opens the scaffolder window.
|
|
47
|
+
- `[CreateAssetMenu(menuName = "JCMG/PackageTools/PackageManifestConfig")]` -> [`PackageManifestConfig`](api.md#packagemanifestconfig) at `Assets/Package/PackageTool/Editor/PackageManifestConfig.cs:37`. Available under **Assets > Create > JCMG/PackageTools/PackageManifestConfig**.
|
|
48
|
+
- [`CIUtils.Generate`](api.md#ciutils) at `Assets/Package/PackageTool/Editor/CIUtils.cs:65` — batch-mode entry point invoked via `unity -batchmode -executeMethod PackageTool.CIUtils.Generate <key>=<value>`. Reads keys parsed by [`CommandLineTools.GetKVPCommandLineArguments`](api.md#commandlinetools); see **CI command-line keys** below for the supported keys.
|
|
49
|
+
- [`CIUtils.PrepareDll`](api.md#ciutils) at `Assets/Package/PackageTool/Editor/CIUtils.cs:197` — exits the Editor when run under CI (`CI` env var set); fixes DLL plugin platform flags first. Also available as `Tools/PackageTools/PrepareDll` for interactive use.
|
|
50
|
+
- [`PackageInitializeWindow.Open`](api.md#packageinitializewindow) at `Assets/Package/PackageTool/Editor/Utils/PackageInitialize/PackageInitializeWindow.cs:7` — opens the scaffolder via `Tools/PackageTools/Init Package`.
|
|
51
51
|
|
|
52
52
|
Inspector buttons on `PackageManifestConfig` assets (drawn by `PackageManifestConfigInspector.OnInspectorGUI`):
|
|
53
53
|
|
|
54
|
-
- **Generate VersionConstants.cs**
|
|
55
|
-
- **Export Package Source**
|
|
56
|
-
- **Export as Legacy Package**
|
|
54
|
+
- **Generate VersionConstants.cs** -> [`CodeGenTools.GenerateVersionConstants`](api.md#codegentools)`(config)` at `Assets/Package/PackageTool/Editor/Tools/CodeGenTools.cs:36`.
|
|
55
|
+
- **Export Package Source** -> [`FileTools.CreateOrUpdatePackageSource`](api.md#filetools)`(config)` at `Assets/Package/PackageTool/Editor/Tools/FileTools.cs:59`.
|
|
56
|
+
- **Export as Legacy Package** -> [`UnityFileTools.CompileLegacyPackage`](api.md#unityfiletools)`(config)` at `Assets/Package/PackageTool/Editor/Tools/UnityFileTools.cs:36`.
|
|
57
57
|
|
|
58
58
|
## Data Model
|
|
59
59
|
|
|
@@ -64,20 +64,20 @@ Defined at `Assets/Package/PackageTool/Editor/PackageManifestConfig.cs:37`. Crea
|
|
|
64
64
|
- **Package json metadata:** `homepage`, `packageName`, `displayName`, `packageVersion`, `unityVersion`, `description`, `category`, `license`, `keywords` (`string[]`), `author` (`Author`), `dependencies` (`Dependency[]`).
|
|
65
65
|
- **Package content paths:** `sourcePath`, `documentationPath` (default `Documentation~`), `readmePath` (default `README.md`), `changelogPath` (default `CHANGELOG.md`), `licensePath` (default `LICENSE`), `packageIgnorePaths` (`string[]`).
|
|
66
66
|
- **Export targets:** `packageDestinationPath`, `legacyPackageDestinationPath`.
|
|
67
|
-
- **Staging:** `samples` ([`Sample[]`](api.md#
|
|
67
|
+
- **Staging:** `samples` ([`Sample[]`](api.md#sample)), `copyEntries` ([`CopyEntry[]`](api.md#packagemanifestconfigcopyentry)).
|
|
68
68
|
- **Code generation:** `versionConstantsPath`, `versionConstantsNamespace`.
|
|
69
69
|
- **Hidden:** `_id` (Guid; surfaced via `Id` property; used by `CIUtils.Generate id=<guid>` filtering).
|
|
70
70
|
|
|
71
71
|
Nested `[Serializable]` types, each with a `PropertyDrawer` in `PackageTool.Drawers`:
|
|
72
72
|
|
|
73
|
-
- [`Author`](api.md#
|
|
73
|
+
- [`Author`](api.md#author) — `name`, `email`, `url` (`string`).
|
|
74
74
|
- [`Dependency`](api.md#packagemanifestconfigdependency) — `packageName`, `packageVersion` (`string`); `IsEmpty()` is true when either is blank.
|
|
75
|
-
- [`Sample`](api.md#
|
|
76
|
-
- [`CopyEntry`](api.md#packagemanifestconfigcopyentry) — `sourcePath`, `destinationPath` (`string`); `IsEmpty()` is true when `sourcePath` is blank. See **Copy Entries staging**
|
|
75
|
+
- [`Sample`](api.md#sample) — `sourcePath`, `displayName`, `description`, `folderName` (`string`); `IsEmpty()` is true when any of `displayName`/`sourcePath`/`folderName` is blank. Resulting on-disk path is `{packageDestinationPath}/Samples~/{folderName}`.
|
|
76
|
+
- [`CopyEntry`](api.md#packagemanifestconfigcopyentry) — `sourcePath`, `destinationPath` (`string`); `IsEmpty()` is true when `sourcePath` is blank. See **Copy Entries staging** below.
|
|
77
77
|
|
|
78
78
|
### Export pipeline
|
|
79
79
|
|
|
80
|
-
`FileTools.CreateOrUpdatePackageSource(config)` at `Assets/Package/PackageTool/Editor/Tools/FileTools.cs:59` runs the steps below in order:
|
|
80
|
+
[`FileTools.CreateOrUpdatePackageSource`](api.md#filetools)`(config)` at `Assets/Package/PackageTool/Editor/Tools/FileTools.cs:59` runs the steps below in order:
|
|
81
81
|
|
|
82
82
|
1. Write `package.json` to `Assets/PackageManifest/Generated/<id>/package.json` (Unity needs a meta file to copy the meta downstream).
|
|
83
83
|
2. Wipe and recreate `packageDestinationPath` (e.g. `Release/`).
|
|
@@ -85,7 +85,7 @@ Nested `[Serializable]` types, each with a `PropertyDrawer` in `PackageTool.Draw
|
|
|
85
85
|
4. **`CopyEntriesToProject(config)`** — stage external content into the project; see below.
|
|
86
86
|
5. **`CopyDocumentationToDirectory(config)`** — copy `readmePath`, `changelogPath`, `licensePath` into `sourcePath`; rebuild `sourcePath/Documentation~/` from `documentationPath`.
|
|
87
87
|
6. **`RecursivelyCopyDirectoriesAndFiles(config, sourcePath, packageDestinationPath)`** — copy the package source tree, honoring `packageIgnorePaths`.
|
|
88
|
-
7. **`CopySamplesToDirectory(config)`** — wipe `packageDestinationPath/Samples~/` and copy each [`Sample`](api.md#
|
|
88
|
+
7. **`CopySamplesToDirectory(config)`** — wipe `packageDestinationPath/Samples~/` and copy each [`Sample`](api.md#sample)'s `sourcePath` to `Samples~/{folderName}`, skipping `.meta` files.
|
|
89
89
|
|
|
90
90
|
### Copy Entries staging
|
|
91
91
|
|
|
@@ -97,7 +97,7 @@ Nested `[Serializable]` types, each with a `PropertyDrawer` in `PackageTool.Draw
|
|
|
97
97
|
|
|
98
98
|
**Destination path resolution.**
|
|
99
99
|
|
|
100
|
-
- Blank `destinationPath`
|
|
100
|
+
- Blank `destinationPath` -> `EditorConstants.ProjectPath` (the repo root).
|
|
101
101
|
- Non-blank `destinationPath` is resolved via `Path.GetFullPath` (so relative paths are cwd-relative — Unity Editor cwd is the project root) and **created on demand** if it doesn't yet exist.
|
|
102
102
|
- A missing **source** path logs `[Package Tools] Copy entry source [...] does not exist, skipping.` and continues with the next entry.
|
|
103
103
|
|
|
@@ -116,7 +116,7 @@ IMGUI throughout — no UI Toolkit. There are no `.uxml` or `.uss` files in the
|
|
|
116
116
|
|
|
117
117
|
### CI command-line keys
|
|
118
118
|
|
|
119
|
-
`CIUtils.Generate` reads keys parsed by [`CommandLineTools.GetKVPCommandLineArguments`](api.md#commandlinetools). Keys are case-insensitive (lowercased on parse) and values are passed as `<key>=<value>` pairs after `-executeMethod PackageTool.CIUtils.Generate`:
|
|
119
|
+
[`CIUtils.Generate`](api.md#ciutils) reads keys parsed by [`CommandLineTools.GetKVPCommandLineArguments`](api.md#commandlinetools). Keys are case-insensitive (lowercased on parse) and values are passed as `<key>=<value>` pairs after `-executeMethod PackageTool.CIUtils.Generate`:
|
|
120
120
|
|
|
121
121
|
- `id=<guid>[,<guid>...]` — restrict to specific `PackageManifestConfig._id`s. Omit to process all configs found by `PackageManifestTools.GetAllConfigs`.
|
|
122
122
|
- `version=<semver>` — overrides `packageVersion` on every processed config (and marks the asset dirty).
|
|
@@ -127,11 +127,11 @@ To add a new key, edit `Assets/Package/PackageTool/Editor/CIUtils.cs` (constants
|
|
|
127
127
|
|
|
128
128
|
### VersionConstants template tokens
|
|
129
129
|
|
|
130
|
-
`CodeGenTools.GenerateVersionConstants(config)` substitutes a `${token}` set into the embedded `TEMPLATE` / `GLOBAL_TEMPLATE` strings (chain at `Assets/Package/PackageTool/Editor/Tools/CodeGenTools.cs:131`) using values from the config, `DateTime`, and [`GitTools`](api.md#gittools). Adding a new token is a two-edit change: append the template line and add a `.Replace("${token}", value)` call.
|
|
130
|
+
[`CodeGenTools.GenerateVersionConstants`](api.md#codegentools)`(config)` substitutes a `${token}` set into the embedded `TEMPLATE` / `GLOBAL_TEMPLATE` strings (chain at `Assets/Package/PackageTool/Editor/Tools/CodeGenTools.cs:131`) using values from the config, `DateTime`, and [`GitTools`](api.md#gittools). Adding a new token is a two-edit change: append the template line and add a `.Replace("${token}", value)` call.
|
|
131
131
|
|
|
132
132
|
### Init Package fields
|
|
133
133
|
|
|
134
|
-
`PackageInitializeWindow` lays down a `PackageManifestConfig.asset`, README, CHANGELOG, LICENSE, and `Documentation~/` / `Samples~/` folders from a flat set of `DrawTextField` inputs at `Assets/Package/PackageTool/Editor/Utils/PackageInitialize/PackageInitializeWindow.cs:32`. The scaffold logic and string templates live in [`PackageInitializeUtil`](api.md#packageinitializeutil) and [`PackageInitializeTemplates`](api.md#packageinitializetemplates); changes that affect generated content must thread through both.
|
|
134
|
+
[`PackageInitializeWindow`](api.md#packageinitializewindow) lays down a `PackageManifestConfig.asset`, README, CHANGELOG, LICENSE, and `Documentation~/` / `Samples~/` folders from a flat set of `DrawTextField` inputs at `Assets/Package/PackageTool/Editor/Utils/PackageInitialize/PackageInitializeWindow.cs:32`. The scaffold logic and string templates live in [`PackageInitializeUtil`](api.md#packageinitializeutil) and [`PackageInitializeTemplates`](api.md#packageinitializetemplates); changes that affect generated content must thread through both.
|
|
135
135
|
|
|
136
136
|
### Custom drawers, menu items, helpers
|
|
137
137
|
|
|
@@ -8,15 +8,25 @@ How the sample content in this repository uses the package. Each entry maps a sa
|
|
|
8
8
|
|
|
9
9
|
```
|
|
10
10
|
Assets/Example/Sample
|
|
11
|
-
├── Prefabs
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
├── Prefabs/ExamplePrefab.prefab
|
|
12
|
+
└── Scene/SampleScene.unity
|
|
13
|
+
|
|
14
|
+
Assets/Samples~/ClaudeSkills
|
|
15
|
+
├── Editor/ClaudeSkillsPostImport.cs
|
|
16
|
+
├── Editor/Playdarium.PackageTool.Samples.ClaudeSkills.Editor.asmdef
|
|
17
|
+
├── unity-package-docs/SKILL.md
|
|
18
|
+
├── unity-package-docs/assets/README.md.template
|
|
19
|
+
├── unity-package-docs/assets/api-chunk.md.template
|
|
20
|
+
├── unity-package-docs/assets/api-index.md.template
|
|
21
|
+
├── unity-package-docs/assets/api.md.template
|
|
22
|
+
├── unity-package-docs/assets/manual.md.template
|
|
23
|
+
├── unity-package-docs/assets/samples.md.template
|
|
24
|
+
└── unity-package-docs/scripts/scan_package.py
|
|
15
25
|
```
|
|
16
26
|
|
|
17
|
-
On export, `CopySamplesToDirectory` copies
|
|
27
|
+
On export, `CopySamplesToDirectory` copies each sample root to `Release/Samples~/<folderName>/`, skipping `.meta` files. The shipped samples are consumable from the Package Manager **Samples** tab on the published package.
|
|
18
28
|
|
|
19
|
-
## Sample
|
|
29
|
+
## Sample -> Package Type Mapping
|
|
20
30
|
|
|
21
31
|
### `Assets/Example/Sample/Prefabs/ExamplePrefab.prefab`
|
|
22
32
|
|
|
@@ -30,15 +40,29 @@ Kind: scene
|
|
|
30
40
|
|
|
31
41
|
This sample asset references no scripts from the package. It exists as a structural demo (the importing user sees a working Scene/Prefab in the package's Samples tab) rather than as an API exercise.
|
|
32
42
|
|
|
43
|
+
### `Assets/Samples~/ClaudeSkills/Editor/ClaudeSkillsPostImport.cs`
|
|
44
|
+
|
|
45
|
+
Kind: script
|
|
46
|
+
|
|
47
|
+
Editor-side post-import hook bundled with the **Claude Skills** sample. In a consumer project, after the user imports this package's Claude Skills sample, the script copies the staged `unity-package-docs/` skill folder out of the imported `Assets/Samples/<Package>/<Version>/ClaudeSkills/` location into the consumer project's `.claude/skills/` directory, then self-deletes (and cleans up empty ancestor folders) so subsequent imports do not duplicate work. It does not call into the package's runtime API — it is plumbing for the sample's primary content (`SKILL.md`, `scripts/scan_package.py`, and the `.md.template` files under `assets/`).
|
|
48
|
+
|
|
49
|
+
Non-script assets that ship alongside this script (not enumerated above because the scanner only emits scripts/scenes/prefabs):
|
|
50
|
+
|
|
51
|
+
- `Assets/Samples~/ClaudeSkills/unity-package-docs/SKILL.md` — the skill definition this sample exists to deliver.
|
|
52
|
+
- `Assets/Samples~/ClaudeSkills/unity-package-docs/scripts/scan_package.py` — the scanner the skill invokes.
|
|
53
|
+
- `Assets/Samples~/ClaudeSkills/unity-package-docs/assets/*.md.template` — the rendering templates.
|
|
54
|
+
|
|
33
55
|
## Reproducing the Sample
|
|
34
56
|
|
|
35
|
-
|
|
57
|
+
**Example Sample (`Assets/Example/Sample`)** — structural only, no MonoBehaviour scripts to instantiate. To reproduce from scratch:
|
|
36
58
|
|
|
37
59
|
1. Create an empty Unity scene and a primitive prefab; both can live anywhere in `Assets/`.
|
|
38
|
-
2. Create a `PackageManifestConfig` asset via **Assets > Create > JCMG/PackageTools/PackageManifestConfig** and configure `sourcePath`, `packageDestinationPath`, and a [`Sample`](api.md#
|
|
39
|
-
3. Click **Export Package Source** on the inspector — `FileTools.CreateOrUpdatePackageSource` runs the export pipeline (see `manual.md`
|
|
60
|
+
2. Create a `PackageManifestConfig` asset via **Assets > Create > JCMG/PackageTools/PackageManifestConfig** and configure `sourcePath`, `packageDestinationPath`, and a [`Sample`](api.md#sample) entry whose `sourcePath` points at the folder holding the scene and prefab.
|
|
61
|
+
3. Click **Export Package Source** on the inspector — [`FileTools.CreateOrUpdatePackageSource`](api.md#filetools) runs the export pipeline (see `manual.md` -> **Export pipeline**) and the sample folder lands under `packageDestinationPath/Samples~/{folderName}`.
|
|
40
62
|
|
|
41
|
-
|
|
63
|
+
**Claude Skills (`Assets/Samples~/ClaudeSkills`)** — pairs a Sample with a [`CopyEntry`](api.md#packagemanifestconfigcopyentry) so the skill's canonical source lives in `.claude/skills/unity-package-docs/` (where it is editable and used directly during development) and a synchronized copy is staged into `Assets/Samples~/ClaudeSkills/unity-package-docs/` before export. The Editor-side `ClaudeSkillsPostImport.cs` script bundled with the sample handles the reverse direction in consumer projects: on import it moves the skill folder out of `Assets/Samples/<Package>/<Version>/ClaudeSkills/unity-package-docs/` into the consumer's `.claude/skills/`.
|
|
64
|
+
|
|
65
|
+
Minimal equivalent in C# for either sample style:
|
|
42
66
|
|
|
43
67
|
```csharp
|
|
44
68
|
using PackageTool;
|
|
@@ -63,6 +87,15 @@ config.samples = new[]
|
|
|
63
87
|
description = "This is example for check test samples",
|
|
64
88
|
},
|
|
65
89
|
};
|
|
90
|
+
// Optional: stage external content into a Sample's sourcePath first.
|
|
91
|
+
config.copyEntries = new[]
|
|
92
|
+
{
|
|
93
|
+
new PackageManifestConfig.CopyEntry
|
|
94
|
+
{
|
|
95
|
+
sourcePath = ".claude/skills/unity-package-docs",
|
|
96
|
+
destinationPath = "Assets/Samples~/ClaudeSkills/unity-package-docs",
|
|
97
|
+
},
|
|
98
|
+
};
|
|
66
99
|
AssetDatabase.CreateAsset(config, "Assets/Example/PackageManifestConfig.asset");
|
|
67
100
|
FileTools.CreateOrUpdatePackageSource(config);
|
|
68
101
|
```
|
|
@@ -71,3 +104,4 @@ FileTools.CreateOrUpdatePackageSource(config);
|
|
|
71
104
|
|
|
72
105
|
- The `Samples~/` folder name (trailing tilde) is a Unity convention: tilde-suffixed folders are excluded from the AssetDatabase import, so packaged samples don't pollute the consuming project until the user clicks **Import** in the Package Manager.
|
|
73
106
|
- For samples that stage content from outside `Assets/` — e.g. a Claude skill folder, vendored data, or generated output — use a [`CopyEntry`](api.md#packagemanifestconfigcopyentry) with `destinationPath` pointing at the same `sourcePath` your `Sample` declares. The `CopyEntry` step runs first; `CopySamplesToDirectory` then ships the staged content into the package.
|
|
107
|
+
- The `ClaudeSkillsPostImport` editor script only runs in consumer projects after they import the **Claude Skills** sample; it self-deletes after copying so a re-import does not duplicate work. It is not part of the package's primary API and is intentionally outside the `PackageTool` namespace.
|
|
@@ -196,11 +196,12 @@ namespace PackageTool.Tools
|
|
|
196
196
|
|
|
197
197
|
/// <summary>
|
|
198
198
|
/// Stages each configured <see cref="PackageManifestConfig.CopyEntry"/> into the project before the
|
|
199
|
-
/// rest of the export runs. A folder source's
|
|
200
|
-
///
|
|
201
|
-
///
|
|
202
|
-
/// <c>destination/{filename}</c>.
|
|
203
|
-
/// destination that does not yet exist is created. Missing sources log a warning and
|
|
199
|
+
/// rest of the export runs. A folder source replaces the destination's contents — the destination
|
|
200
|
+
/// is wiped first, then the source tree is copied in. The exception is a blank destination, which
|
|
201
|
+
/// resolves to the project root and merges instead (same-named files overwritten, unrelated files
|
|
202
|
+
/// left alone) to avoid wiping the repo. A file source overwrites <c>destination/{filename}</c>.
|
|
203
|
+
/// A non-blank destination that does not yet exist is created. Missing sources log a warning and
|
|
204
|
+
/// are skipped.
|
|
204
205
|
/// </summary>
|
|
205
206
|
public static void CopyEntriesToProject(PackageManifestConfig packageManifest)
|
|
206
207
|
{
|
|
@@ -229,6 +230,11 @@ namespace PackageTool.Tools
|
|
|
229
230
|
|
|
230
231
|
if (Directory.Exists(normalizedSourcePath))
|
|
231
232
|
{
|
|
233
|
+
// Skip the wipe when destination resolves to the project root — clearing the repo
|
|
234
|
+
// would be catastrophic. Blank destinations fall back to the merge behavior.
|
|
235
|
+
if (!string.IsNullOrEmpty(entry.destinationPath))
|
|
236
|
+
RecursivelyDeleteDirectoryContents(new DirectoryInfo(destinationDirectory));
|
|
237
|
+
|
|
232
238
|
CopyDirectoryRecursively(normalizedSourcePath, destinationDirectory);
|
|
233
239
|
}
|
|
234
240
|
else if (File.Exists(normalizedSourcePath))
|
package/README.md
CHANGED
|
@@ -1,200 +1,67 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Package Tool
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
[](https://opensource.org/licenses/MIT)
|
|
3
|
+
Tool for create unity packages
|
|
5
4
|
|
|
6
|
-
##
|
|
5
|
+
## Requirements
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
`
|
|
10
|
-
on how to reference it.
|
|
7
|
+
- Unity 2021.3 or newer.
|
|
8
|
+
- `Playdarium.PackageTool.Editor` — runs on Editor only.
|
|
11
9
|
|
|
12
|
-
|
|
10
|
+
## Dependencies
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
| Package | Version |
|
|
13
|
+
|---------|---------|
|
|
14
|
+
| `com.unity.nuget.newtonsoft-json` | `3.2.1` |
|
|
16
15
|
|
|
17
|
-
|
|
16
|
+
## Installation
|
|
18
17
|
|
|
19
|
-
|
|
18
|
+
Add the package to `Packages/manifest.json`:
|
|
19
|
+
|
|
20
|
+
```json
|
|
20
21
|
{
|
|
21
|
-
"dependencies": {
|
|
22
|
-
...
|
|
23
|
-
"com.elestrago.unity.package-tools": "x.x.x",
|
|
24
|
-
...
|
|
25
|
-
},
|
|
26
22
|
"scopedRegistries": [
|
|
27
23
|
{
|
|
28
|
-
"name": "
|
|
29
|
-
"url": "https://
|
|
24
|
+
"name": "Playdarium",
|
|
25
|
+
"url": "https://npm.playdarium.studio",
|
|
30
26
|
"scopes": [
|
|
31
|
-
"com.elestrago
|
|
27
|
+
"com.elestrago"
|
|
32
28
|
]
|
|
33
29
|
}
|
|
34
|
-
]
|
|
30
|
+
],
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"com.elestrago.unity.package-tools": "2.4.0"
|
|
33
|
+
}
|
|
35
34
|
}
|
|
36
35
|
```
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
Creating your first package is a simple process that can be made more complex because information available about Unity
|
|
41
|
-
Package manager is inconsistent right now. This is largely due to it not being widely and officially supported for
|
|
42
|
-
end-users of Unity yet, but starting with 2019.1 will gain more official support.
|
|
43
|
-
|
|
44
|
-
The first step is to create a `PackageManifestConfig` asset that we can use to define the properties and contents of our
|
|
45
|
-
package. This can be done by right-clicking in the `Project` window and
|
|
46
|
-
selecting `Create -> JCMG -> Package Tools -> Package
|
|
47
|
-
Manifest Config`. This will create an asset named `PackageManifestConfig` in that folder.
|
|
48
|
-
|
|
49
|
-
<img src="./Documentation~/Inspector.png" width="500">
|
|
50
|
-
|
|
51
|
-
A `PackageManifestConfig` is broken up into two sections:
|
|
37
|
+
Replace the registry URL above with your scoped registry, or remove the `scopedRegistries` block when consuming a published package.
|
|
52
38
|
|
|
53
|
-
|
|
54
|
-
have in our package root folder. It describes the minimum Unity version that it is compatible with and the version of
|
|
55
|
-
the package itself [Semantic versioning](https://docs.unity3d.com/Manual/upm-semver.html), a
|
|
56
|
-
description of the package, and any dependencies it
|
|
57
|
-
has on other packages. This last part I have the least information about, but is supposed to gain more widespread
|
|
58
|
-
support in 2019.1.
|
|
59
|
-
* **Package Content and Export:** This section focuses on defining the folders/files that make up the content (including
|
|
60
|
-
code and assets) that make up the package itself and a location that the content will be published to when clicking on
|
|
61
|
-
the button labeled `Export Package Source`.
|
|
39
|
+
## Getting Started
|
|
62
40
|
|
|
63
|
-
|
|
64
|
-
|
|
41
|
+
1. Create a `PackageManifestConfig` asset via **Assets > Create > JCMG/PackageTools/PackageManifestConfig**.
|
|
42
|
+
2. Fill in `packageName`, `displayName`, `packageVersion`, `unityVersion`, `sourcePath` (the folder under `Assets/` that holds your package's source), and `packageDestinationPath` (where the assembled package will be written, e.g. `Release`).
|
|
43
|
+
3. Optionally add `dependencies`, `samples`, and `copyEntries` rows in the inspector.
|
|
44
|
+
4. Click **Export Package Source** to assemble the package; **Export as Legacy Package** to emit a `.unitypackage`; or **Generate VersionConstants.cs** to write a versions file at `versionConstantsPath`.
|
|
65
45
|
|
|
66
|
-
|
|
67
|
-
included. This can be useful for example, if there are unit tests or example content located within your package source
|
|
68
|
-
path that you would not want to include directly or indirectly. Folders and files can be excluded by adding them to
|
|
69
|
-
the **ExcludePaths** list.
|
|
70
|
-
|
|
71
|
-
Recently I have found myself manually creating a `VersionConstants` static class containing versioning information about
|
|
72
|
-
the package itself. This can be useful for displaying to a user or checking for updates outside of the native Unity
|
|
73
|
-
PackageManager window.. Since updating this file by hand can be error-prone or easy to forget, this can now be
|
|
74
|
-
configured on a `PackageManifestConfig` and generated using a new action `Generate VersionConstants.cs` on the config's
|
|
75
|
-
inspector.
|
|
76
|
-
|
|
77
|
-
**Example VersionConstants.cs used in JCMG.PackageTools**
|
|
46
|
+
For CI, invoke `PackageTool.CIUtils.Generate` in batch mode and pass `version=<semver>` to override the asset's version on a per-run basis:
|
|
78
47
|
|
|
79
48
|
```csharp
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
/// </summary>
|
|
85
|
-
internal static class VersionConstants
|
|
86
|
-
{
|
|
87
|
-
/// <summary>
|
|
88
|
-
/// The semantic version
|
|
89
|
-
/// </summary>
|
|
90
|
-
public const string VERSION = "1.3.0";
|
|
91
|
-
|
|
92
|
-
/// <summary>
|
|
93
|
-
/// The branch of GIT this package was published from.
|
|
94
|
-
/// </summary>
|
|
95
|
-
public const string GIT_BRANCH = "develop";
|
|
96
|
-
|
|
97
|
-
/// <summary>
|
|
98
|
-
/// The current GIT commit hash this package was published on.
|
|
99
|
-
/// </summary>
|
|
100
|
-
public const string GIT_COMMIT = "57aec574ed19746de42ffa5032358562fb041ebf";
|
|
101
|
-
|
|
102
|
-
/// <summary>
|
|
103
|
-
/// The UTC human-readable date this package was published at.
|
|
104
|
-
/// </summary>
|
|
105
|
-
public const string PUBLISH_DATE = "Friday, May 1, 2020";
|
|
106
|
-
|
|
107
|
-
/// <summary>
|
|
108
|
-
/// The UTC time this package was published at.
|
|
109
|
-
/// </summary>
|
|
110
|
-
public const string PUBLISH_TIME = "05/01/2020 08:26:31";
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
The contents of this file can be configured based on the use of a text template. A default one is provided
|
|
117
|
-
at `JCMG\PackageTools\Scripts\Editor\Templates\VersionConstants.txt` and a custom template can be used instead by
|
|
118
|
-
providing it's meta GUID on the `PackageManifestConfig` `versionTemplateGuid` field. There is an example of this in the
|
|
119
|
-
development project
|
|
49
|
+
// Unity batch-mode CLI:
|
|
50
|
+
// unity -batchmode -quit -projectPath . \
|
|
51
|
+
// -executeMethod PackageTool.CIUtils.Generate \
|
|
52
|
+
// version=1.2.3 generateversionconstants=true
|
|
120
53
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
```csharp
|
|
124
|
-
namespace JCMG.PackageTools.Editor
|
|
125
|
-
{
|
|
126
|
-
/// <summary>
|
|
127
|
-
/// Version info for this library.
|
|
128
|
-
/// </summary>
|
|
129
|
-
internal static class VersionConstants
|
|
130
|
-
{
|
|
131
|
-
/// <summary>
|
|
132
|
-
/// The semantic version
|
|
133
|
-
/// </summary>
|
|
134
|
-
public const string VERSION = "${version}";
|
|
135
|
-
|
|
136
|
-
/// <summary>
|
|
137
|
-
/// The branch of GIT this package was published from.
|
|
138
|
-
/// </summary>
|
|
139
|
-
public const string GIT_BRANCH = "${git_branch}";
|
|
140
|
-
|
|
141
|
-
/// <summary>
|
|
142
|
-
/// The current GIT commit hash this package was published on.
|
|
143
|
-
/// </summary>
|
|
144
|
-
public const string GIT_COMMIT = "${git_commit}";
|
|
145
|
-
|
|
146
|
-
/// <summary>
|
|
147
|
-
/// The UTC human-readable date this package was published at.
|
|
148
|
-
/// </summary>
|
|
149
|
-
public const string PUBLISH_DATE = "${publish_date}";
|
|
150
|
-
|
|
151
|
-
/// <summary>
|
|
152
|
-
/// The UTC time this package was published at.
|
|
153
|
-
/// </summary>
|
|
154
|
-
public const string PUBLISH_TIME = "${publish_utc_time}";
|
|
155
|
-
}
|
|
156
|
-
}
|
|
54
|
+
using PackageTool;
|
|
157
55
|
|
|
56
|
+
CIUtils.Generate();
|
|
158
57
|
```
|
|
159
58
|
|
|
160
|
-
##
|
|
161
|
-
|
|
162
|
-
It can be desirable at times to generate legacy Unity packages and/or package source from the command-line so that they
|
|
163
|
-
can be created and distributed as part of a continuous integration (CI) process. For example, you may want to trigger a
|
|
164
|
-
process every time the repository is updated and source files changed so that a new package is created and made
|
|
165
|
-
available to users. This can be done by launching the Unity Editor from the command line and supplying the appropriate
|
|
166
|
-
arguments.
|
|
167
|
-
|
|
168
|
-
**Example Command-Line Call**
|
|
169
|
-
|
|
170
|
-
`"D:\Program Files\2019.4.11f1\Editor\Unity.exe" -quit -batchmode -executeMethod JCMG.PackageTools.Editor.PackageToolsCI.Generate version=1.0.1 GenerateVersionConstants=true`
|
|
171
|
-
|
|
172
|
-
In this case, the `-executeMethod JCMG.PackageTools.Editor.PackageToolsCI.Generate` is the CLI argument that will
|
|
173
|
-
trigger the PackageTools CI process to execute. By default, this will find all `PackageManifestConfig` instances in the
|
|
174
|
-
project and if they have an appropriate output path will generate the legacy Unity package and/or package source.
|
|
175
|
-
Progress will be output to the Unity Editor player log.
|
|
176
|
-
|
|
177
|
-
### Arguments
|
|
178
|
-
|
|
179
|
-
#### ID
|
|
180
|
-
|
|
181
|
-
An optional `ID` CLI argument (case-insensitive) that can be supplied with one or more `ID` values to limit the package
|
|
182
|
-
generation to a subset of `PackageManifestConfig` instances in the project if so desired. These `ID` values should
|
|
183
|
-
correspond to the `ID` displayed on the `PackageManifestConfig` inspector for that instance. If not supplied, all
|
|
184
|
-
|
|
185
|
-
**Example ID Argument Usage (for three ID values passed)**
|
|
186
|
-
|
|
187
|
-
`id=cb87cda2-0bfa-44dc-b583-ae61ff81efcb,e1725f4a-f9f3-42c0-ac15-756f017c90ed,6a406891-59d5-430a-815d-c252deae5d5b`
|
|
188
|
-
|
|
189
|
-
#### Version
|
|
59
|
+
## Documentation
|
|
190
60
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
61
|
+
- [Manual](Documentation~/manual.md) — concepts and architecture.
|
|
62
|
+
- [API Reference](Documentation~/api.md) — every public type and member.
|
|
63
|
+
- [Samples](Documentation~/samples.md) — how the sample project in this repo uses the package.
|
|
194
64
|
|
|
195
|
-
|
|
65
|
+
## License
|
|
196
66
|
|
|
197
|
-
|
|
198
|
-
the `VersionConstants` file to be written out prior to generating the package (if a path is specified for it on
|
|
199
|
-
the `PackageManifestConfig`). This can be useful where this file is created as a result of a CI build and has it's
|
|
200
|
-
version number set by the `version` argument.
|
|
67
|
+
See [LICENSE](LICENSE).
|
|
@@ -106,10 +106,14 @@ The scanner emits JSON to stdout with this shape:
|
|
|
106
106
|
"packageDir": "Assets/Package/PackageTool",
|
|
107
107
|
"asmdefs": [{"path": "...", "name": "...", "rootNamespace": "...", "includePlatforms": [...], "excludePlatforms": [...], "references": [...], "precompiledReferences": [...], "defineConstraints": [...], "autoReferenced": true}],
|
|
108
108
|
"namespaces": ["PackageTool", "PackageTool.Tools", ...],
|
|
109
|
+
"files": [
|
|
110
|
+
{"path": "Assets/.../Foo.cs", "md5": "916a690462c237734b0cbceb4a8d3de1", "lines": 247}
|
|
111
|
+
],
|
|
109
112
|
"types": [
|
|
110
113
|
{
|
|
111
114
|
"file": "Assets/.../Foo.cs",
|
|
112
115
|
"line": 37,
|
|
116
|
+
"md5": "916a690462c237734b0cbceb4a8d3de1",
|
|
113
117
|
"namespace": "PackageTool",
|
|
114
118
|
"name": "Foo",
|
|
115
119
|
"kind": "class|struct|interface|enum",
|
|
@@ -124,12 +128,18 @@ The scanner emits JSON to stdout with this shape:
|
|
|
124
128
|
}
|
|
125
129
|
],
|
|
126
130
|
"samples": [
|
|
127
|
-
{"path": "Assets/.../Foo.cs", "kind": "script", "namespace": "...", "packageTypesReferenced": ["Foo", "Bar"]},
|
|
128
|
-
{"path": "Assets/.../Scene.unity", "kind": "scene|prefab", "scriptsReferenced": [{"guid": "...", "resolvedTo": "Assets/.../Foo.cs"}]}
|
|
131
|
+
{"path": "Assets/.../Foo.cs", "kind": "script", "namespace": "...", "packageTypesReferenced": ["Foo", "Bar"], "md5": "…", "lines": 42},
|
|
132
|
+
{"path": "Assets/.../Scene.unity", "kind": "scene|prefab", "scriptsReferenced": [{"guid": "...", "resolvedTo": "Assets/.../Foo.cs"}], "md5": "…", "lines": 85}
|
|
129
133
|
]
|
|
130
134
|
}
|
|
131
135
|
```
|
|
132
136
|
|
|
137
|
+
Notes on the new `md5` / `lines` / `files` fields (added in this revision):
|
|
138
|
+
|
|
139
|
+
- `files[]` lists every `.cs` file under the package root that the scanner read, with the MD5 of its raw bytes and its line count. Multiple types from the same file share the same MD5, so this list is the canonical per-file view; `types[i].md5` is a denormalized convenience.
|
|
140
|
+
- `md5` is over **raw bytes** (no CRLF↔LF normalization). A line-ending swap counts as a change, which is intentional — if the bytes differ at all, the doc should be regenerated.
|
|
141
|
+
- `samples[]` carries `md5`/`lines` only for individual sample files (scripts, scenes, prefabs). The scanner does not roll these up into the package `files[]` list.
|
|
142
|
+
|
|
133
143
|
Capture this JSON; the rest of the pipeline consumes it.
|
|
134
144
|
|
|
135
145
|
### Step 3.5 — Plan chunking
|
|
@@ -159,6 +169,30 @@ Build a **`crossRefMap`**: `{ typeAnchor → "<destination-relative-to-Documenta
|
|
|
159
169
|
|
|
160
170
|
Print one line per file decision, e.g. `chunk-plan: api.md → chunked (12 namespaces, draft=2143 lines, threshold=800)` or `chunk-plan: samples.md → single (draft=78 lines)`.
|
|
161
171
|
|
|
172
|
+
### Step 3.6 — Fast-update check (api only)
|
|
173
|
+
|
|
174
|
+
Before rendering, build a **`skipSet`** of api outputs that can be left untouched because their underlying source files are bit-for-bit identical to the last run. This is an optimization, not a correctness step — skipping is always safe to opt out of (and is automatically opted out of below in well-defined situations).
|
|
175
|
+
|
|
176
|
+
The check only applies to `api.md` and its chunks. `manual.md` and `samples.md` are skipped here because their content is synthesized across many files (manual) or driven by sample-side bytes already covered by `samples[i].md5` (samples — left as future work; do not skip samples in this revision).
|
|
177
|
+
|
|
178
|
+
Procedure for **each** prospective api output (the single `api.md` in the single-file branch, or each `api/<Namespace>.md` in the chunked branch):
|
|
179
|
+
|
|
180
|
+
1. **Identify the source files** that contribute to this output:
|
|
181
|
+
- Single-file `api.md` → every file path that appears in any `types[].file`.
|
|
182
|
+
- Chunked `api/<Namespace>.md` → every distinct `types[i].file` where `types[i].namespace == <Namespace>` (nested types use the containing type's namespace, same rule as `crossRefMap`).
|
|
183
|
+
2. **Read the existing output file** if it exists AND starts with the generator marker. Skip the check (do not add to `skipSet`) if the file is absent, lacks the marker, or fails to parse.
|
|
184
|
+
3. **Extract per-file md5s** from the existing file by greppping ``` `path:line` (md5: `<32-hex>`,``` (the exact shape emitted by Step 4). Build `priorMd5: {path → md5}`.
|
|
185
|
+
4. **Compare**: if every source file from step 1 is present in `priorMd5` AND every value equals the current `files[i].md5` from the scanner manifest, add this output's path to `skipSet`.
|
|
186
|
+
5. **Force override**: if `force=true` was passed, `skipSet` is empty (the user asked to overwrite unconditionally).
|
|
187
|
+
|
|
188
|
+
Print one line per check, e.g. `fast-update: api/PackageTool.Tools.md → skipped (3 files unchanged)` or `fast-update: api/PackageTool.md → re-render (FileTools.cs md5 differs)`.
|
|
189
|
+
|
|
190
|
+
Steps 4/5/6 honor `skipSet` as follows:
|
|
191
|
+
|
|
192
|
+
- An output path in `skipSet` is **not rewritten** — the existing file is preserved verbatim, and `crossRefMap` (which was built in Step 3.5 from the scanner manifest, independent of the existing file) is still used for downstream links from `manual.md` and `samples.md`. This works because anchors are derived from type names, which are part of the manifest, not parsed from the existing api file.
|
|
193
|
+
- Stale-chunk removal (Steps 4/5/6) still runs over the full chunk directory; `skipSet` only governs *re-rendering*, not stale cleanup.
|
|
194
|
+
- The Step 8 verifier still walks every emitted `.md` (including skipped ones), so a stale api file with a missing anchor is still caught.
|
|
195
|
+
|
|
162
196
|
### Step 4 — Render `Documentation~/api.md` first
|
|
163
197
|
|
|
164
198
|
Render this file first because `manual.md` and `samples.md` link into its anchors (via `crossRefMap` from Step 3.5) and you want those anchors to exist.
|
|
@@ -169,21 +203,29 @@ For each type entry:
|
|
|
169
203
|
|
|
170
204
|
- Heading: `### {TypeName}` (stable; the anchor is `{typename-lowercase}` by default Markdown rules; for nested types use `### {ContainingType}.{TypeName}`).
|
|
171
205
|
- ` ```csharp ` block with the declaration line copied verbatim from source (use the file + line in the manifest to extract the line; do not paraphrase).
|
|
172
|
-
- `**Source:** ` + `path:line`.
|
|
206
|
+
- `**Source:** ` + `` `path:line` `` + ` (md5: ` + `` `<32-hex>` `` + `, lines: <n>)`. The md5 comes from `types[i].md5`; the line count comes from the matching entry in `files[]`. The trailing parenthetical is the **anchor for fast-update checks** (see "Fast-update check" below) — render it on every type, in this exact shape, so a downstream grep `\(md5: \`([0-9a-f]{32})\`` reliably extracts it.
|
|
173
207
|
- `**Attributes:** ` + comma-separated list (omit the line if none).
|
|
174
208
|
- `**Base:** ` + comma-separated `baseList` (omit if empty).
|
|
175
209
|
- Summary verbatim if present.
|
|
176
|
-
- Members table: only include public/internal/protected members; omit private. Strip XML tags from member summaries.
|
|
210
|
+
- Members table: only include public/internal/protected members; omit private. Strip XML tags from member summaries. The table has a **`Line`** column carrying `members[].line`; the file is the same as the type's Source line above (no need to repeat the path on every row).
|
|
211
|
+
|
|
212
|
+
```
|
|
213
|
+
**Members:**
|
|
214
|
+
|
|
215
|
+
| Kind | Name | Signature | Line | Summary |
|
|
216
|
+
|------|------|-----------|------|---------|
|
|
217
|
+
| method | Bar | `public void Bar()` | 88 | … |
|
|
218
|
+
```
|
|
177
219
|
|
|
178
220
|
Omit types with no public members and no XML summary unless they carry a Unity attribute (`[MenuItem]`, `[CustomEditor]`, etc.). Omit empty namespaces entirely.
|
|
179
221
|
|
|
180
|
-
**Output (single-file branch, default):** if Step 3.5 decided api is single-file, write the
|
|
222
|
+
**Output (single-file branch, default):** if Step 3.5 decided api is single-file, render the draft into a buffer and — if `Documentation~/api.md` is in `skipSet` from Step 3.6 — leave the existing file in place; otherwise write the buffer to `Documentation~/api.md` as-is.
|
|
181
223
|
|
|
182
224
|
**Output (chunked branch):** if Step 3.5 decided api is chunked, split the draft by namespace and emit:
|
|
183
225
|
|
|
184
|
-
1. **One chunk per namespace** at `Documentation~/api/<Namespace>.md` using `${SKILL_DIR}/assets/api-chunk.md.template`. Each chunk contains the H1 (`# {{displayName}} — API Reference: \`{{namespace}}\``), the namespace's section body (same `### TypeName` blocks as the single-file form), and the generator marker on line 1. Anchors inside the chunk stay `{typename-lowercase}` — they do NOT include the namespace prefix, because cross-doc links resolve via `crossRefMap` (which carries the path-plus-anchor pair).
|
|
185
|
-
2. **One index** at `Documentation~/api.md` using `${SKILL_DIR}/assets/api-index.md.template`. The index keeps the generator marker, H1, a `## Contents` Markdown table linking each chunk (`| Namespace | Description |`), and a one-line `## Notes` paragraph: `This API reference is split by namespace; see files under \`api/\`.`. The one-line description per namespace is the same blurb you would have placed in the single-file `{{namespaceContentsList}}`.
|
|
186
|
-
3. **Stale chunks:** before writing, list `Documentation~/api/*.md`. For each existing file that starts with the generator marker and is NOT in the current chunk set, delete it and print `Removed stale: <path>`. (See Idempotency.)
|
|
226
|
+
1. **One chunk per namespace** at `Documentation~/api/<Namespace>.md` using `${SKILL_DIR}/assets/api-chunk.md.template`. Each chunk contains the H1 (`# {{displayName}} — API Reference: \`{{namespace}}\``), the namespace's section body (same `### TypeName` blocks as the single-file form), and the generator marker on line 1. Anchors inside the chunk stay `{typename-lowercase}` — they do NOT include the namespace prefix, because cross-doc links resolve via `crossRefMap` (which carries the path-plus-anchor pair). If the chunk's path is in `skipSet` from Step 3.6, do not rewrite it — the existing file is preserved.
|
|
227
|
+
2. **One index** at `Documentation~/api.md` using `${SKILL_DIR}/assets/api-index.md.template`. The index keeps the generator marker, H1, a `## Contents` Markdown table linking each chunk (`| Namespace | Description |`), and a one-line `## Notes` paragraph: `This API reference is split by namespace; see files under \`api/\`.`. The one-line description per namespace is the same blurb you would have placed in the single-file `{{namespaceContentsList}}`. The index itself is **always rewritten** (never skipped), because its content depends on the chunk set, not on the package source bytes.
|
|
228
|
+
3. **Stale chunks:** before writing, list `Documentation~/api/*.md`. For each existing file that starts with the generator marker and is NOT in the current chunk set, delete it and print `Removed stale: <path>`. (See Idempotency.) Stale removal runs independently of `skipSet`.
|
|
187
229
|
|
|
188
230
|
### Step 5 — Render `Documentation~/manual.md`
|
|
189
231
|
|
|
@@ -18,7 +18,7 @@ in shape to a per-type block in the single-file api.md template:
|
|
|
18
18
|
{declaration line copied verbatim from source}
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
**Source:** `{file}:{line}`
|
|
21
|
+
**Source:** `{file}:{line}` (md5: `{md5}`, lines: {lines})
|
|
22
22
|
**Attributes:** `[Attr1]`, `[Attr2]` (omit line if none)
|
|
23
23
|
**Base:** `{baseList}` (omit if empty)
|
|
24
24
|
|
|
@@ -26,9 +26,9 @@ in shape to a per-type block in the single-file api.md template:
|
|
|
26
26
|
|
|
27
27
|
**Members:**
|
|
28
28
|
|
|
29
|
-
| Kind | Name | Signature | Summary |
|
|
30
|
-
|
|
31
|
-
| method | Foo | `public void Foo()` | … |
|
|
29
|
+
| Kind | Name | Signature | Line | Summary |
|
|
30
|
+
|------|------|-----------|------|---------|
|
|
31
|
+
| method | Foo | `public void Foo()` | 88 | … |
|
|
32
32
|
|
|
33
33
|
Anchors are `{typename-lowercase}` (no namespace prefix). Cross-doc links
|
|
34
34
|
from manual.md / samples.md resolve via crossRefMap, which carries the
|
|
@@ -36,6 +36,12 @@ chunk-relative path-plus-anchor pair (e.g. `api/PackageTool.Tools.md#filetools`)
|
|
|
36
36
|
For nested types use `### {ContainingType}.{TypeName}` and anchor
|
|
37
37
|
`{containingtype}.{typename}`.
|
|
38
38
|
|
|
39
|
+
The Source parenthetical — `(md5: \`<32-hex>\`, lines: <n>)` — is the contract
|
|
40
|
+
the Step 3.6 fast-update check greps for. Emit it on every type in this exact
|
|
41
|
+
shape; otherwise a re-run cannot detect that this chunk's source files are
|
|
42
|
+
unchanged and will needlessly re-render. The Members **Line** column carries
|
|
43
|
+
each member's source line within the type's file.
|
|
44
|
+
|
|
39
45
|
Omit types with no public members and no XML summary unless they carry a
|
|
40
46
|
Unity attribute (`[MenuItem]`, `[CustomEditor]`, etc.).
|
|
41
47
|
-->
|