com.elestrago.unity.package-tools 2.4.0 → 2.5.2
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 +37 -0
- package/Documentation~/examples/ciutils-generate.md +41 -0
- package/Documentation~/examples/create-packagemanifestconfig.md +47 -0
- package/Documentation~/examples/init-package.md +30 -0
- package/Documentation~/examples/preparedll.md +39 -0
- package/Documentation~/examples.md +25 -0
- package/Documentation~/manual.md +4 -4
- package/Editor/Tools/CommandLineTools.cs +2 -2
- package/Editor/Tools/GitTools.cs +7 -13
- package/Editor/Utils/PackageInitialize/PackageInitializeTemplates.cs +1 -1
- package/Editor/Utils/PackageInitialize/PackageInitializeUtil.cs +1 -1
- package/README.md +2 -2
- package/Samples~/ClaudeSkills/unity-package-docs/SKILL.md +104 -49
- package/Samples~/ClaudeSkills/unity-package-docs/assets/examples-chunk.md.template +40 -0
- package/Samples~/ClaudeSkills/unity-package-docs/assets/examples.md.template +36 -0
- package/Samples~/ClaudeSkills/unity-package-docs/scripts/scan_package.py +6 -2
- package/Samples~/ClaudeSkills/unity-package-release/SKILL.md +1 -1
- package/package.json +4 -4
- package/Documentation~/samples.md +0 -107
- package/Samples~/ClaudeSkills/unity-package-docs/assets/samples.md.template +0 -56
package/CAHNGELOG.md
CHANGED
|
@@ -2,6 +2,43 @@
|
|
|
2
2
|
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
+
## [2.5.2](https://gitlab.com/elestrago-pkg/package-tool/-/tags/2.5.2)
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Fixed `unity-package-docs` scanner dropping public `readonly struct` and `ref struct` types.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## [2.5.1](https://gitlab.com/elestrago-pkg/package-tool/-/tags/2.5.1)
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- Broadened `unity-package-release` skill triggers to cover generic commit phrasings such as "commit all changes".
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## [2.5.0](https://gitlab.com/elestrago-pkg/package-tool/-/tags/2.5.0)
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- Added `examples` section to `unity-package-docs` driven by `[CreateAssetMenu]`/`[MenuItem]`/public-static API entry points, one chunk per entry under `Documentation~/examples/`.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- Made `CommandLineTools`, `GitTools`, `PackageInitializeTemplates`, `PackageInitializeUtil`, and `GitTools.Run` non-public so the supported entry points are `CIUtils.Generate` and `Tools/PackageTools/Init Package`.
|
|
30
|
+
|
|
31
|
+
### Removed
|
|
32
|
+
|
|
33
|
+
- Removed `samples` section from `unity-package-docs` (replaced by `examples`).
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
- Fixed `unity-package-docs` scanner missing expression-bodied methods (`... => Body();`).
|
|
38
|
+
- Fixed broken nested-type anchor references in `Documentation~/manual.md` (e.g. `PackageManifestConfig.CopyEntry`).
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
5
42
|
## [2.4.0](https://gitlab.com/elestrago-pkg/package-tool/-/tags/2.4.0)
|
|
6
43
|
|
|
7
44
|
### Added
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<!-- generated by unity-package-docs; safe to regenerate -->
|
|
2
|
+
|
|
3
|
+
# Package Tool — Example: CIUtils.Generate
|
|
4
|
+
|
|
5
|
+
**Kind:** static-method
|
|
6
|
+
|
|
7
|
+
**Entry point:** [CIUtils](../api.md#ciutils)
|
|
8
|
+
|
|
9
|
+
**Declared at:** `Assets/Package/PackageTool/Editor/CIUtils.cs:65`
|
|
10
|
+
|
|
11
|
+
## What it does
|
|
12
|
+
|
|
13
|
+
The CI entry point. Reads `id=<guid>[,<guid>...]`, `version=<semver>`, `preview=<bool>`, and `generateversionconstants=<bool>` from the command line (case-insensitive `key=value` pairs), filters the [PackageManifestConfig](../api.md#packagemanifestconfig) assets to process, optionally overrides each config's `packageVersion`, optionally runs [CodeGenTools.GenerateVersionConstants](../api.md#codegentools), and exports the package source via [FileTools.CreateOrUpdatePackageSource](../api.md#filetools). Wraps the work in `LockReloadAssemblies` + `StartAssetEditing` to avoid mid-export refreshes.
|
|
14
|
+
|
|
15
|
+
## Snippet
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Headless build — call from CI after PrepareDll has fixed plugin flags.
|
|
19
|
+
"$UNITY_PATH" \
|
|
20
|
+
-batchmode \
|
|
21
|
+
-quit \
|
|
22
|
+
-projectPath "$PROJECT_PATH" \
|
|
23
|
+
-executeMethod PackageTool.CIUtils.Generate \
|
|
24
|
+
-id ea4351b5-3f49-4afc-8996-ec7b9eb43204 \
|
|
25
|
+
-version 2.4.1 \
|
|
26
|
+
-generateversionconstants true \
|
|
27
|
+
-logFile -
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
```csharp
|
|
31
|
+
// Or invoke directly from an editor script — Generate() reads -id / -version /
|
|
32
|
+
// -generateversionconstants from Environment.GetCommandLineArgs itself.
|
|
33
|
+
PackageTool.CIUtils.Generate();
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Observable effect
|
|
37
|
+
|
|
38
|
+
- `Release/<packageName>/` is created or updated with the exported package layout (sources, package.json, README, CHANGELOG, LICENSE, Samples~, Documentation~).
|
|
39
|
+
- `Release/package.json` is rewritten with the version, dependencies, and samples block derived from the config.
|
|
40
|
+
- If `generateversionconstants=true`, a new `VersionConstants.cs` is emitted at the configured path before export.
|
|
41
|
+
- Console prints `[Package Tools]` lines summarizing what was processed; the editor does not exit (unlike `PrepareDll`).
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<!-- generated by unity-package-docs; safe to regenerate -->
|
|
2
|
+
|
|
3
|
+
# Package Tool — Example: Create a PackageManifestConfig
|
|
4
|
+
|
|
5
|
+
**Kind:** create-asset
|
|
6
|
+
|
|
7
|
+
**Entry point:** [PackageManifestConfig](../api.md#packagemanifestconfig)
|
|
8
|
+
|
|
9
|
+
**Declared at:** `Assets/Package/PackageTool/Editor/PackageManifestConfig.cs:37`
|
|
10
|
+
|
|
11
|
+
**Create menu:** `Assets > Create > JCMG/PackageTools/PackageManifestConfig`
|
|
12
|
+
|
|
13
|
+
## What it does
|
|
14
|
+
|
|
15
|
+
Creates the ScriptableObject that drives every other entry point — package name, version, sources, dependencies, samples, and the destination path the **Export Package Source** inspector button and `CIUtils.Generate` both read. One config asset per Unity package; everything else (CHANGELOG, README, asmdef wiring, exported `package.json`) is derived from its fields.
|
|
16
|
+
|
|
17
|
+
## Snippet
|
|
18
|
+
|
|
19
|
+
```csharp
|
|
20
|
+
using PackageTool;
|
|
21
|
+
using UnityEditor;
|
|
22
|
+
using UnityEngine;
|
|
23
|
+
|
|
24
|
+
public static class CreatePackageManifestConfigExample
|
|
25
|
+
{
|
|
26
|
+
[MenuItem("Tools/Examples/Create PackageManifestConfig")]
|
|
27
|
+
public static void Run()
|
|
28
|
+
{
|
|
29
|
+
var config = ScriptableObject.CreateInstance<PackageManifestConfig>();
|
|
30
|
+
config.packageName = "com.example.foo";
|
|
31
|
+
config.displayName = "Example Foo";
|
|
32
|
+
config.packageVersion = "0.1.0";
|
|
33
|
+
config.unityVersion = "2021.3";
|
|
34
|
+
config.sourcePath = "Assets/Package/Foo";
|
|
35
|
+
config.packageDestinationPath = "Release";
|
|
36
|
+
|
|
37
|
+
AssetDatabase.CreateAsset(config, "Assets/PackageManifest/PackageManifestConfig.asset");
|
|
38
|
+
AssetDatabase.SaveAssets();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Observable effect
|
|
44
|
+
|
|
45
|
+
- A new asset appears at `Assets/PackageManifest/PackageManifestConfig.asset`.
|
|
46
|
+
- Selecting it in the Project view renders the inspector with **Generate VersionConstants.cs**, **Export Package Source**, and **Export as Legacy Package** buttons.
|
|
47
|
+
- The same `Assets > Create > JCMG/PackageTools/PackageManifestConfig` menu entry yields the same asset interactively if you prefer GUI.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<!-- generated by unity-package-docs; safe to regenerate -->
|
|
2
|
+
|
|
3
|
+
# Package Tool — Example: Init Package
|
|
4
|
+
|
|
5
|
+
**Kind:** menu-item
|
|
6
|
+
|
|
7
|
+
**Entry point:** [MenuItems](../api.md#menuitems)
|
|
8
|
+
|
|
9
|
+
**Declared at:** `Assets/Package/PackageTool/Editor/MenuItems.cs:9`
|
|
10
|
+
|
|
11
|
+
**Menu path:** `Tools/PackageTools/Init Package`
|
|
12
|
+
|
|
13
|
+
## What it does
|
|
14
|
+
|
|
15
|
+
Opens the **Init Package** editor window ([PackageInitializeWindow](../api.md#packageinitializewindow)), which scaffolds a new Unity package: creates `Assets/Package/<scope>/` with `Editor/` (and optionally `Runtime/`), root files (`README.md`, `CAHNGELOG.md`, `LICENSE`), `Documentation~/`, and a sibling `PackageManifestConfig.asset` populated from the form's fields. The internal helpers that do the on-disk work are intentionally not part of the public surface — the window is the supported entry point.
|
|
16
|
+
|
|
17
|
+
## Snippet
|
|
18
|
+
|
|
19
|
+
```csharp
|
|
20
|
+
// MenuItems is internal, so other assemblies can't invoke OpenAboutModalDialog
|
|
21
|
+
// directly. Open the window via PackageInitializeWindow.Open(), or use the menu.
|
|
22
|
+
PackageTool.Utils.PackageInitialize.PackageInitializeWindow.Open();
|
|
23
|
+
// Or interactively: Tools > PackageTools > Init Package
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Observable effect
|
|
27
|
+
|
|
28
|
+
- The **Init Package** editor window opens. Fill in package name, display name, scope, author, license, and unity version, then click **Create**.
|
|
29
|
+
- On Create: `Assets/Package/<scope>/` and `Assets/PackageManifest/PackageManifestConfig.asset` are written; the inspector for the new config asset shows the **Generate VersionConstants.cs** / **Export Package Source** / **Export as Legacy Package** buttons.
|
|
30
|
+
- The project compiles after the next assembly reload.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<!-- generated by unity-package-docs; safe to regenerate -->
|
|
2
|
+
|
|
3
|
+
# Package Tool — Example: PrepareDll
|
|
4
|
+
|
|
5
|
+
**Kind:** menu-item
|
|
6
|
+
|
|
7
|
+
**Entry point:** [CIUtils](../api.md#ciutils)
|
|
8
|
+
|
|
9
|
+
**Declared at:** `Assets/Package/PackageTool/Editor/CIUtils.cs:197`
|
|
10
|
+
|
|
11
|
+
**Menu path:** `Tools/PackageTools/PrepareDll`
|
|
12
|
+
|
|
13
|
+
## What it does
|
|
14
|
+
|
|
15
|
+
Fixes the platform flags on every plugin (`.dll`) under the configured package source before export, so the published package's `PluginImporter` settings match what the Editor needs (no spurious `Any Platform` toggles that would otherwise leak into consumers). When the `CI` environment variable is set, the method calls `EditorApplication.Exit` with code 0 on success or 1 on failure — designed to be the final step of a batch-mode build before the export job moves on.
|
|
16
|
+
|
|
17
|
+
## Snippet
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Run from CI or any shell — replace UNITY_PATH and PROJECT_PATH with your values.
|
|
21
|
+
"$UNITY_PATH" \
|
|
22
|
+
-batchmode \
|
|
23
|
+
-quit \
|
|
24
|
+
-projectPath "$PROJECT_PATH" \
|
|
25
|
+
-executeMethod PackageTool.CIUtils.PrepareDll \
|
|
26
|
+
-logFile -
|
|
27
|
+
# Or interactively: Tools > PackageTools > PrepareDll
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
```csharp
|
|
31
|
+
// Same call from an editor script (no Exit when CI env var is unset):
|
|
32
|
+
PackageTool.CIUtils.PrepareDll();
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Observable effect
|
|
36
|
+
|
|
37
|
+
- Every `.dll` under each `PackageManifestConfig.sourcePath` has its `PluginImporter` flags normalized; meta files are rewritten as a result and may show up in `git status`.
|
|
38
|
+
- Console prints `[Package Tools]` log lines for each plugin touched.
|
|
39
|
+
- In CI (`CI=1` or similar), the editor exits 0 on success or 1 if any plugin processing throws — wire this into your pipeline as the gate before `CIUtils.Generate`.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<!-- generated by unity-package-docs; safe to regenerate -->
|
|
2
|
+
|
|
3
|
+
# Package Tool — Examples
|
|
4
|
+
|
|
5
|
+
Short, focused usage examples that exercise this package's public API. Each example is independent and links into the API reference (`api.md`) for the type or member it calls. Snippets are paste-ready and use only public API — copy one into a fresh project to reach the same observable effect.
|
|
6
|
+
|
|
7
|
+
## Quick start
|
|
8
|
+
|
|
9
|
+
Start with **Create a PackageManifestConfig** to produce the config asset that drives every other entry point, then run **Tools > PackageTools > Init Package** (`init-package`) to scaffold a new package skeleton against it. For automated builds, **CIUtils.Generate** is the batch-mode entry point and **Tools > PackageTools > PrepareDll** (`preparedll`) is the DLL platform-flag fix-up step that typically runs immediately before it.
|
|
10
|
+
|
|
11
|
+
## Contents
|
|
12
|
+
|
|
13
|
+
| Example | Kind | Entry point |
|
|
14
|
+
|---------|------|-------------|
|
|
15
|
+
| [Create a PackageManifestConfig](examples/create-packagemanifestconfig.md) | create-asset | [PackageManifestConfig](api.md#packagemanifestconfig) |
|
|
16
|
+
| [Init Package](examples/init-package.md) | menu-item | [MenuItems](api.md#menuitems) |
|
|
17
|
+
| [PrepareDll](examples/preparedll.md) | menu-item | [CIUtils](api.md#ciutils) |
|
|
18
|
+
| [CIUtils.Generate](examples/ciutils-generate.md) | static-method | [CIUtils](api.md#ciutils) |
|
|
19
|
+
|
|
20
|
+
This package also ships Unity samples importable from Package Manager → Package Tool → Samples → `Example Sample`, `Claude Skills`. Those samples are not duplicated here — import them via Package Manager if you want the full asset content.
|
|
21
|
+
|
|
22
|
+
## Notes
|
|
23
|
+
|
|
24
|
+
- The `PackageTool.Tools.*` (`CommandLineTools`, `GitTools`) and `PackageTool.Utils.PackageInitialize.*` (`PackageInitializeTemplates`, `PackageInitializeUtil`) helpers were public in earlier revisions and dropped to `internal` to make the public surface intentional. They still exist and are used by `CIUtils.Generate`/`Init Package` internally; they're just no longer documented as consumer-facing entry points.
|
|
25
|
+
- All entry points listed here are editor-only (single asmdef `Playdarium.PackageTool.Editor`, `includePlatforms: ["Editor"]`); call them from editor scripts or batch mode, not from runtime code.
|
package/Documentation~/manual.md
CHANGED
|
@@ -64,16 +64,16 @@ 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#sample)), `copyEntries` ([`CopyEntry[]`](api.md#
|
|
67
|
+
- **Staging:** `samples` ([`Sample[]`](api.md#sample)), `copyEntries` ([`CopyEntry[]`](api.md#packagemanifestconfig-copyentry)).
|
|
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
73
|
- [`Author`](api.md#author) — `name`, `email`, `url` (`string`).
|
|
74
|
-
- [`Dependency`](api.md#
|
|
74
|
+
- [`Dependency`](api.md#packagemanifestconfig-dependency) — `packageName`, `packageVersion` (`string`); `IsEmpty()` is true when either is blank.
|
|
75
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#
|
|
76
|
+
- [`CopyEntry`](api.md#packagemanifestconfig-copyentry) — `sourcePath`, `destinationPath` (`string`); `IsEmpty()` is true when `sourcePath` is blank. See **Copy Entries staging** below.
|
|
77
77
|
|
|
78
78
|
### Export pipeline
|
|
79
79
|
|
|
@@ -89,7 +89,7 @@ Nested `[Serializable]` types, each with a `PropertyDrawer` in `PackageTool.Draw
|
|
|
89
89
|
|
|
90
90
|
### Copy Entries staging
|
|
91
91
|
|
|
92
|
-
`copyEntries` is a `PackageManifestConfig` field added in 2.0.12. Each [`CopyEntry`](api.md#
|
|
92
|
+
`copyEntries` is a `PackageManifestConfig` field added in 2.0.12. Each [`CopyEntry`](api.md#packagemanifestconfig-copyentry) names a source path and a destination folder; entries run **first** in the export pipeline (step 4 above) so downstream steps — including the recursive source copy and the `CopySamplesToDirectory` step — can pick up the staged content and ship it into `packageDestinationPath`.
|
|
93
93
|
|
|
94
94
|
**Folder source.** The folder's *content* is merged directly into `destinationPath` (no `destinationPath/{sourceName}` wrapper). Same-named files are overwritten via `File.Copy(..., overwrite: true)`; unrelated files already in the destination are left in place. This is the merge semantics needed to chain into a `Sample` whose `sourcePath` is the same folder.
|
|
95
95
|
|
|
@@ -30,7 +30,7 @@ namespace PackageTool.Tools
|
|
|
30
30
|
/// <summary>
|
|
31
31
|
/// Helper methods for command-line usage
|
|
32
32
|
/// </summary>
|
|
33
|
-
|
|
33
|
+
internal static class CommandLineTools
|
|
34
34
|
{
|
|
35
35
|
// Command-Line Delimiters
|
|
36
36
|
private const string ARGUMENT_DELIMITER_STR = "=";
|
|
@@ -65,4 +65,4 @@ namespace PackageTool.Tools
|
|
|
65
65
|
return dict;
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
|
-
}
|
|
68
|
+
}
|
package/Editor/Tools/GitTools.cs
CHANGED
|
@@ -30,11 +30,15 @@ namespace PackageTool.Tools
|
|
|
30
30
|
/// <summary>
|
|
31
31
|
/// Helper methods for retrieving git information
|
|
32
32
|
/// </summary>
|
|
33
|
-
|
|
33
|
+
internal static class GitTools
|
|
34
34
|
{
|
|
35
35
|
private const string GIT_APPLICATION = "git";
|
|
36
36
|
|
|
37
|
-
public static string Run(
|
|
37
|
+
public static string GetBranch() => Run("rev-parse --abbrev-ref HEAD");
|
|
38
|
+
|
|
39
|
+
public static string GetLongHeadHash() => Run("rev-parse HEAD");
|
|
40
|
+
|
|
41
|
+
private static string Run(string cmd)
|
|
38
42
|
{
|
|
39
43
|
// NOTE: This currently expects that you have git included in your PATH.
|
|
40
44
|
var p = new Process();
|
|
@@ -52,15 +56,5 @@ namespace PackageTool.Tools
|
|
|
52
56
|
|
|
53
57
|
return output;
|
|
54
58
|
}
|
|
55
|
-
|
|
56
|
-
public static string GetBranch()
|
|
57
|
-
{
|
|
58
|
-
return Run("rev-parse --abbrev-ref HEAD");
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
public static string GetLongHeadHash()
|
|
62
|
-
{
|
|
63
|
-
return Run("rev-parse HEAD");
|
|
64
|
-
}
|
|
65
59
|
}
|
|
66
|
-
}
|
|
60
|
+
}
|
|
@@ -4,7 +4,7 @@ using UnityEngine;
|
|
|
4
4
|
|
|
5
5
|
namespace PackageTool.Utils.PackageInitialize
|
|
6
6
|
{
|
|
7
|
-
|
|
7
|
+
internal static class PackageInitializeUtil
|
|
8
8
|
{
|
|
9
9
|
public const string ASSETS_FOLDER_NAME = "Assets";
|
|
10
10
|
public const string RELEASE_FOLDER_NAME = "Release";
|
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ Add the package to `Packages/manifest.json`:
|
|
|
29
29
|
}
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"com.elestrago.unity.package-tools": "2.
|
|
32
|
+
"com.elestrago.unity.package-tools": "2.5.2"
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
```
|
|
@@ -60,7 +60,7 @@ CIUtils.Generate();
|
|
|
60
60
|
|
|
61
61
|
- [Manual](Documentation~/manual.md) — concepts and architecture.
|
|
62
62
|
- [API Reference](Documentation~/api.md) — every public type and member.
|
|
63
|
-
- [
|
|
63
|
+
- [Examples](Documentation~/examples.md) — short usage examples for the public API.
|
|
64
64
|
|
|
65
65
|
## License
|
|
66
66
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: unity-package-docs
|
|
3
|
-
description: Create or update AI-first documentation for a Unity package at the repository root — README.md plus Documentation~/manual.md, api.md,
|
|
3
|
+
description: Create or update AI-first documentation for a Unity package at the repository root — README.md plus Documentation~/manual.md, api.md, examples.md, all structured for dense AI ingestion with explicit file paths and explicit links from each usage example into the API reference. Auto-chunks large API/manual by namespace/section, and emits one chunk per public API entry point (each `[CreateAssetMenu]`, `[MenuItem]`, and public static entry-point method) under Documentation~/examples/ as a focused short snippet, so a consumer reading the published docs learns how to call the package without importing Samples~/ via Package Manager. Use when the user wants to generate or refresh Unity package docs from source. Works in any Unity package repo with one package per repo (discovered via package.json, with a fallback to PackageManifestConfig.asset for package-tool-based projects).
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# unity-package-docs
|
|
@@ -15,12 +15,16 @@ Files created/updated at the repository root — **never** inside the package fo
|
|
|
15
15
|
<repo-root>/
|
|
16
16
|
├── README.md
|
|
17
17
|
└── Documentation~/
|
|
18
|
-
├── manual.md
|
|
19
|
-
├── api.md
|
|
20
|
-
|
|
18
|
+
├── manual.md (or manual/<slug>.md chunks when over threshold)
|
|
19
|
+
├── api.md (or api/<Namespace>.md chunks when over threshold)
|
|
20
|
+
├── examples.md (always an index — see below)
|
|
21
|
+
└── examples/
|
|
22
|
+
└── <slug>.md (one chunk per public API entry point)
|
|
21
23
|
```
|
|
22
24
|
|
|
23
|
-
The `Documentation~` folder name MUST include the trailing tilde (Unity convention — excludes it from asset import). Pre-existing files inside `Documentation~/` (e.g. screenshots) are left untouched; only the
|
|
25
|
+
The `Documentation~` folder name MUST include the trailing tilde (Unity convention — excludes it from asset import). Pre-existing files inside `Documentation~/` (e.g. screenshots) are left untouched; only the managed `.md` files (and their parent dirs under `manual/`, `api/`, `examples/`) are managed.
|
|
26
|
+
|
|
27
|
+
`examples.md` is always a small index linking to per-entry-point chunks. Each chunk under `examples/<slug>.md` is a short usage example (1 paragraph + ≤ ~20-line snippet) that calls into the public API documented in `api.md`. This is distinct from Unity's `Samples~/` folder, which the package author may ship for Package Manager → Samples → Import; the docs do **not** embed `Samples~/` source verbatim — examples are curated for "how do I use this API?", and `README.md` carries a one-line pointer at the available Unity samples for anyone who wants the importable content.
|
|
24
28
|
|
|
25
29
|
Every generated `.md` file begins with this exact marker on line 1:
|
|
26
30
|
|
|
@@ -34,8 +38,8 @@ Every generated `.md` file begins with this exact marker on line 1:
|
|
|
34
38
|
2. **Predictable structure.** Use the exact section names and order specified in each step below. Same anchor slugs every run so agents crawling multiple package docs can rely on the shape.
|
|
35
39
|
3. **Explicit paths everywhere.** Every reference to source code uses `path/to/File.cs` relative to the repo root, with `:line` when pointing at a specific declaration. Never write "see the inspector class" — write `see Assets/Package/.../Inspectors/Foo.cs:33`.
|
|
36
40
|
4. **Complete, tagged code blocks.** Every fenced block has a language tag (` ```csharp `, ` ```json `, ` ```yaml `, ` ```bash `). Snippets are paste-ready — no `// ...` elisions that lose context.
|
|
37
|
-
5. **
|
|
38
|
-
6. **No forward references to undocumented things.** If `manual.md` mentions a type, that type appears in `api.md` with a stable anchor. `
|
|
41
|
+
5. **Examples link into the API.** In `examples.md` and its chunks, every code example is anchored on a discoverable public API entry point (a `[CreateAssetMenu]`, `[MenuItem]`, or public static entry method) and links into the corresponding `api.md` anchor. Snippets are short, paste-ready, and call only public API. An agent reading the docs must be able to take any example, paste it into a fresh project, and reach the same observable effect.
|
|
42
|
+
6. **No forward references to undocumented things.** If `manual.md` mentions a type, that type appears in `api.md` with a stable anchor. `examples.md` and chunks link into `api.md` rather than re-describing types.
|
|
39
43
|
|
|
40
44
|
## Skill args
|
|
41
45
|
|
|
@@ -44,8 +48,8 @@ Parse from the user input (default values shown):
|
|
|
44
48
|
- `force=false` — when `true`, overwrite files even if they lack the generator marker.
|
|
45
49
|
- `dry-run=false` — when `true`, print the would-be output to the conversation without writing any files.
|
|
46
50
|
- `package=<path>` — override package-root auto-discovery (for repos with multiple packages or a non-standard layout).
|
|
47
|
-
- `chunk-threshold-lines=800` — when a rendered
|
|
48
|
-
- `chunk-threshold-api=<n>`, `chunk-threshold-manual=<n
|
|
51
|
+
- `chunk-threshold-lines=800` — when a rendered `api.md` or `manual.md` draft exceeds this many lines, the file is split into chunks (see Step 3.5). Below the threshold, output is the single-file form. Set very high (e.g. `100000`) to disable chunking for those two files. **Does not gate `examples.md`** — examples are always per-entry-point chunked (see Step 6); the granularity is fixed by the API surface, not by line count.
|
|
52
|
+
- `chunk-threshold-api=<n>`, `chunk-threshold-manual=<n>` — per-file overrides of `chunk-threshold-lines`. Each defaults to the global value. `chunk-threshold-samples` and `chunk-threshold-examples` are accepted for backward compatibility but ignored.
|
|
49
53
|
|
|
50
54
|
## Pipeline (execute these steps in order)
|
|
51
55
|
|
|
@@ -86,7 +90,7 @@ From `package.json` (preferred) or `PackageManifestConfig.asset`, extract:
|
|
|
86
90
|
| Samples | `samples` (array of `{path, displayName, description}`) | `samples` (array of `{sourcePath, folderName, displayName, description}`) |
|
|
87
91
|
| Registry | `publishConfig.registry` | (not in config; omit) |
|
|
88
92
|
|
|
89
|
-
|
|
93
|
+
The `samples[]` block is read for **README only** — it drives the one-line Unity Samples~/ pointer described in Step 7 ("This package ships the following Package Manager samples: …"). It does NOT drive any content under `Documentation~/`. The docs section is `examples`, generated from the public API surface in Step 6, not from `Samples~/` files. Earlier revisions of this skill mirrored `Samples~/` source into the docs; that's been deprecated because the embedded source is duplicative of what Package Manager → Samples → Import already provides, and most `Samples~/` content (scenes, prefabs, internal post-import scripts) doesn't teach API usage.
|
|
90
94
|
|
|
91
95
|
### Step 3 — Scan source
|
|
92
96
|
|
|
@@ -95,10 +99,11 @@ Run the bundled Python scanner. Its absolute path is `${SKILL_DIR}/scripts/scan_
|
|
|
95
99
|
```bash
|
|
96
100
|
python3 "${SKILL_DIR}/scripts/scan_package.py" \
|
|
97
101
|
--package "<package-root>" \
|
|
98
|
-
--samples "<sample-dir-1>" --samples "<sample-dir-2>" \
|
|
99
102
|
--repo-root .
|
|
100
103
|
```
|
|
101
104
|
|
|
105
|
+
The scanner still accepts `--samples <dir>` (and emits `samples[]` in its output) for backward compatibility, but **do not pass it** in this revision — the `examples` pipeline (Step 6) derives chunks from the public API surface (`types[]`, member `attributes`), not from `samples[]`. If `samples[]` happens to be non-empty in a stale invocation, the pipeline ignores it.
|
|
106
|
+
|
|
102
107
|
The scanner emits JSON to stdout with this shape:
|
|
103
108
|
|
|
104
109
|
```json
|
|
@@ -127,38 +132,47 @@ The scanner emits JSON to stdout with this shape:
|
|
|
127
132
|
]
|
|
128
133
|
}
|
|
129
134
|
],
|
|
130
|
-
"samples": [
|
|
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}
|
|
133
|
-
]
|
|
135
|
+
"samples": []
|
|
134
136
|
}
|
|
135
137
|
```
|
|
136
138
|
|
|
137
|
-
Notes on the
|
|
139
|
+
Notes on the `md5` / `lines` / `files` fields:
|
|
138
140
|
|
|
139
141
|
- `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
142
|
- `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[]`
|
|
143
|
+
- `samples[]` is present in the scanner's output schema but, in this revision of the skill, is not consumed by any step downstream of Step 3. Treat the field as legacy.
|
|
142
144
|
|
|
143
145
|
Capture this JSON; the rest of the pipeline consumes it.
|
|
144
146
|
|
|
145
147
|
### Step 3.5 — Plan chunking
|
|
146
148
|
|
|
147
|
-
|
|
149
|
+
`api.md` and `manual.md` use a size-gated decision; `examples.md` is always chunked, one chunk per discovered entry point.
|
|
150
|
+
|
|
151
|
+
**For `api.md` and `manual.md`:**
|
|
148
152
|
|
|
149
|
-
1. **Render to an in-memory buffer first.** Run the full Step 4/5
|
|
150
|
-
2. **Resolve the threshold** for this file: use the file-specific arg if supplied (`chunk-threshold-api`, `chunk-threshold-manual
|
|
153
|
+
1. **Render to an in-memory buffer first.** Run the full Step 4/5 rendering logic into a string. Count its lines (`\n`-separated, EOF-trimmed).
|
|
154
|
+
2. **Resolve the threshold** for this file: use the file-specific arg if supplied (`chunk-threshold-api`, `chunk-threshold-manual`), else the global `chunk-threshold-lines` (default 800).
|
|
151
155
|
3. **Apply the structural floor.** Skip chunking even when the threshold is exceeded if the file is structurally unsplittable:
|
|
152
156
|
- `api.md`: chunk only when `namespaces.length > 1`.
|
|
153
|
-
- `samples.md`: chunk only when the sample mapping covers more than one file (i.e. `samples.length > 1`).
|
|
154
157
|
- `manual.md`: chunk only when at least one H2 section in the draft individually exceeds the threshold. (Splitting a single oversized section yields no benefit.)
|
|
155
|
-
4. **Decide:** if `linesDrafted > threshold` AND the structural floor passes → **chunked**; else → **single-file** (write the draft as-is at Step 4/5
|
|
158
|
+
4. **Decide:** if `linesDrafted > threshold` AND the structural floor passes → **chunked**; else → **single-file** (write the draft as-is at Step 4/5's write step).
|
|
159
|
+
|
|
160
|
+
**For `examples.md`: always chunked, one chunk per public API entry point.** No threshold check. The chunk set is computed directly from the scanner manifest's `types[]`/members, not from any line-count heuristic.
|
|
156
161
|
|
|
157
162
|
For each file decided to chunk, plan the chunk set:
|
|
158
163
|
|
|
159
164
|
- `api.md` → one chunk per namespace: `Documentation~/api/<Namespace>.md` (literal namespace, no slugification — e.g. `Documentation~/api/PackageTool.Tools.md`). Do NOT sub-split a single huge namespace.
|
|
160
|
-
- `samples.md` → one chunk per top-level sample folder: `Documentation~/samples/<SampleFolderName>.md`. Sanitize `<SampleFolderName>` to `[A-Za-z0-9._-]` (replace any other character with `-`).
|
|
161
165
|
- `manual.md` → one chunk per H2 section using this fixed slug set: `overview.md`, `architecture.md`, `assemblies.md`, `entry-points.md`, `data-model.md`, `editor-ui.md`, `extension-points.md` (these correspond 1:1 to the H2 sections in `manual.md.template`). Sections that render empty are omitted from the chunk set.
|
|
166
|
+
- `examples.md` → one chunk per discovered entry point. Enumerate, in this order (`exampleKind` shown in parens):
|
|
167
|
+
1. **`[CreateAssetMenu]` types** (`exampleKind = create-asset`). Source: every `types[i]` with `attributes` containing `CreateAssetMenu(...)`. Slug = `create-` + `<TypeName>` lowercased + sanitized to `[a-z0-9-]`.
|
|
168
|
+
2. **`[MenuItem]` methods** (`exampleKind = menu-item`). Source: every `members[]` member with an attribute matching `MenuItem("<path>")`. Slug = the last `/`-separated segment of the menu path, lowercased + sanitized to `[a-z0-9-]` (spaces collapse to `-`). Example: `Tools/PackageTools/Init Package` → `init-package`.
|
|
169
|
+
3. **Public static entry-point methods** (`exampleKind = static-method`). Source: every `members[]` method on a `public static` type, with the method itself `public static`, that is NOT also already produced by rules 1 or 2 above. Slug = `<TypeName-lower>-<MethodName-lower>` sanitized. Example: `CIUtils.Generate` → `ciutils-generate`.
|
|
170
|
+
|
|
171
|
+
Chunk paths: `Documentation~/examples/<slug>.md` (flat directory, single level — no nesting). Disambiguation: if two entry points produce the same slug, append `-2`, `-3`, … in discovery order. Print one line per discovered example, e.g. `example-plan: create-packagemanifestconfig ← PackageManifestConfig [CreateAssetMenu]`.
|
|
172
|
+
|
|
173
|
+
Cap: if more than 20 candidates result from rule 3 (rare in tightly-scoped editor tools, common in libraries with many public statics), emit the first 20 sorted by `TypeName, MethodName` and warn `example-plan: capped at 20 static-method entry points (N skipped). Hand-author additional chunks under Documentation~/examples/ as needed (marker-gated, preserved on regen).`
|
|
174
|
+
|
|
175
|
+
**Sample inputs the skill should NOT promote to examples** (avoid noise): private/internal members, methods with `[Obsolete]`, partial-class internals, generated code (files under `Generated/`). Filter these out before the rules above.
|
|
162
176
|
|
|
163
177
|
Build a **`crossRefMap`**: `{ typeAnchor → "<destination-relative-to-Documentation~>#<anchor>" }`, populated during the api decision:
|
|
164
178
|
|
|
@@ -167,13 +181,13 @@ Build a **`crossRefMap`**: `{ typeAnchor → "<destination-relative-to-Documenta
|
|
|
167
181
|
|
|
168
182
|
`crossRefMap` is consumed by Steps 5 and 6 when emitting `[Type](…)` references. Renderers MUST NOT hard-code `api.md` in link destinations — always resolve via `crossRefMap`.
|
|
169
183
|
|
|
170
|
-
Print one line per file decision
|
|
184
|
+
Print one line per file decision. Examples: `chunk-plan: api.md → chunked (12 namespaces, draft=2143 lines, threshold=800)`, `chunk-plan: manual.md → single (draft=312 lines)`, `chunk-plan: examples.md → chunked (always: 7 entry points → 7 chunks under Documentation~/examples/)`.
|
|
171
185
|
|
|
172
186
|
### Step 3.6 — Fast-update check (api only)
|
|
173
187
|
|
|
174
188
|
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
189
|
|
|
176
|
-
The check only applies to `api.md` and its chunks. `manual.md`
|
|
190
|
+
The check only applies to `api.md` and its chunks. `manual.md` is skipped here because its content is synthesized across many files. `examples.md` and its chunks are skipped because each example chunk is small and re-deriving it from the manifest is cheap — adding fast-update for examples is left as future work.
|
|
177
191
|
|
|
178
192
|
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
193
|
|
|
@@ -189,13 +203,13 @@ Print one line per check, e.g. `fast-update: api/PackageTool.Tools.md → skippe
|
|
|
189
203
|
|
|
190
204
|
Steps 4/5/6 honor `skipSet` as follows:
|
|
191
205
|
|
|
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 `
|
|
206
|
+
- 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 `examples.md`. This works because anchors are derived from type names, which are part of the manifest, not parsed from the existing api file.
|
|
193
207
|
- Stale-chunk removal (Steps 4/5/6) still runs over the full chunk directory; `skipSet` only governs *re-rendering*, not stale cleanup.
|
|
194
208
|
- 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
209
|
|
|
196
210
|
### Step 4 — Render `Documentation~/api.md` first
|
|
197
211
|
|
|
198
|
-
Render this file first because `manual.md` and `
|
|
212
|
+
Render this file first because `manual.md` and `examples.md` link into its anchors (via `crossRefMap` from Step 3.5) and you want those anchors to exist.
|
|
199
213
|
|
|
200
214
|
Read `${SKILL_DIR}/assets/api.md.template`. Replace `{{displayName}}` with the discovered value. Replace `{{namespaceContentsList}}` with a bulleted index of namespaces, each linking to its anchor. Replace `{{perNamespaceSections}}` with one section per namespace following the structure documented in the template's HTML comment block.
|
|
201
215
|
|
|
@@ -240,7 +254,14 @@ Read `${SKILL_DIR}/assets/manual.md.template`. Fill each placeholder:
|
|
|
240
254
|
- `{{editorUiProse}}` — Detect IMGUI vs UI Toolkit by checking for `.uxml`/`.uss` files under the package root and for types inheriting `EditorWindow` / `PropertyDrawer` / `UnityEditor.Editor`. State which approach is used and list representative file paths.
|
|
241
255
|
- `{{extensionPointsList}}` — Public abstract types, public virtual methods, types ending in `Base`, or those marked `partial`. If none, write `None.`.
|
|
242
256
|
|
|
243
|
-
**Resolving `[Type](…)` links.** When rendering any link to a package type, look it up in `crossRefMap` (built in Step 3.5). Use the value verbatim
|
|
257
|
+
**Resolving `[Type](…)` links.** When rendering any link to a package type, look it up in `crossRefMap` (built in Step 3.5). Use the value verbatim, then prefix it based on the *depth* of the emitting file under `Documentation~/`:
|
|
258
|
+
|
|
259
|
+
- Top-level index files (`Documentation~/api.md`, `Documentation~/manual.md`, `Documentation~/examples.md`): depth 0, no prefix — emit the bare `crossRefMap` value.
|
|
260
|
+
- `Documentation~/manual/<slug>.md`: depth 1, prepend `../`.
|
|
261
|
+
- `Documentation~/api/<Namespace>.md`: depth 1, prepend `../`.
|
|
262
|
+
- `Documentation~/examples/<slug>.md`: depth 1, prepend `../`.
|
|
263
|
+
|
|
264
|
+
The depth rule generalizes for any future nesting: `depth = (number of "/" segments in the chunk path under Documentation~) - 1`, and the renderer prepends `"../" * depth`. Do NOT hard-code `api.md#anchor` anywhere — always go through `crossRefMap` + depth-prefix. Same rule applies to Step 6 example chunks.
|
|
244
265
|
|
|
245
266
|
**Output (single-file branch, default):** if Step 3.5 decided manual is single-file, write the rendered draft to `Documentation~/manual.md` as-is.
|
|
246
267
|
|
|
@@ -250,27 +271,58 @@ Read `${SKILL_DIR}/assets/manual.md.template`. Fill each placeholder:
|
|
|
250
271
|
2. **One index** at `Documentation~/manual.md` containing the generator marker, the H1 (`# {{displayName}} — Manual`), a `## Contents` Markdown table (`| Section | Description |`) linking each chunk (one row per emitted slug; description = the first sentence of that section's body), and one-line `## Notes`: `This manual is split by section; see files under \`manual/\`.`
|
|
251
272
|
3. **Stale chunks:** before writing, list `Documentation~/manual/*.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>`.
|
|
252
273
|
|
|
253
|
-
### Step 6 — Render `Documentation~/
|
|
274
|
+
### Step 6 — Render `Documentation~/examples.md` + per-entry-point chunks
|
|
275
|
+
|
|
276
|
+
`examples.md` is always emitted as a light **index**, with one chunk per public API entry point under `Documentation~/examples/<slug>.md`. The chunk set is computed in Step 3.5.
|
|
277
|
+
|
|
278
|
+
**Why examples, not sample-source mirroring.** Unity's `Samples~/` is shipped via Package Manager → Samples → Import; the source is reachable that way for anyone who wants the full importable content. Embedding `Samples~/` source verbatim under `Documentation~/` is duplicative and inflates what every consumer downloads. The high-value docs content is "**how do I use this package's API**" — short snippets that exercise a single entry point and link into `api.md` for the deeper reference. That is what every chunk under `Documentation~/examples/` is: a focused, paste-ready usage example.
|
|
279
|
+
|
|
280
|
+
#### Render the index — `Documentation~/examples.md`
|
|
281
|
+
|
|
282
|
+
Read `${SKILL_DIR}/assets/examples.md.template` (the index template). Fill placeholders:
|
|
283
|
+
|
|
284
|
+
- `{{contentsTableRows}}` — One Markdown table row per chunk: `| [<title>](examples/<slug>.md) | <exampleKind> | <entry-point> |` where:
|
|
285
|
+
- `<title>` is the human-readable title (see chunk titling below).
|
|
286
|
+
- `<exampleKind>` is `create-asset`, `menu-item`, or `static-method` from Step 3.5.
|
|
287
|
+
- `<entry-point>` is the link into `api.md` for the type or member, rendered via the bare `crossRefMap` value (depth 0).
|
|
288
|
+
- `{{quickStartProse}}` — one short paragraph (≤ 4 sentences) framing how a downstream consumer should approach these examples: each one is independent, all snippets target the public API only, and every example has a single observable effect listed in its chunk. If there is exactly one `[CreateAssetMenu]` and one `[MenuItem]`-tagged entry point, mention them by name as the recommended starting points.
|
|
289
|
+
- `{{samplesNote}}` — if the package declares any Unity `Samples~/` entries (`samples[]` in `package.json` or the config asset is non-empty), render a one-line paragraph: ``This package also ships Unity samples importable from Package Manager → <displayName> → Samples → `<sample1.displayName>`, `<sample2.displayName>`. Those samples are not duplicated here — import them via Package Manager if you want the full asset content.`` Otherwise omit the paragraph entirely (the placeholder expands to an empty line).
|
|
290
|
+
- `{{notesList}}` — conventions worth knowing at the index level. If none, write `None.`.
|
|
291
|
+
|
|
292
|
+
Type links in the index use the bare `crossRefMap` value (depth 0).
|
|
293
|
+
|
|
294
|
+
Write `Documentation~/examples.md`.
|
|
295
|
+
|
|
296
|
+
#### Render the per-entry-point chunks — `Documentation~/examples/<slug>.md`
|
|
297
|
+
|
|
298
|
+
For each entry point from Step 3.5, read `${SKILL_DIR}/assets/examples-chunk.md.template` and fill it. The chunk path is `Documentation~/examples/<slug>.md` (flat single level).
|
|
254
299
|
|
|
255
|
-
|
|
300
|
+
Placeholders:
|
|
256
301
|
|
|
257
|
-
- `{{
|
|
258
|
-
- `{{
|
|
259
|
-
- `
|
|
260
|
-
- `
|
|
261
|
-
- `
|
|
302
|
+
- `{{displayName}}` — package display name.
|
|
303
|
+
- `{{exampleTitle}}` — the human-readable title:
|
|
304
|
+
- `create-asset`: `Create a <TypeName>` (e.g. `Create a PackageManifestConfig`).
|
|
305
|
+
- `menu-item`: derive from the last menu-path segment, Title-Cased (e.g. `Init Package`, `Prepare DLLs`).
|
|
306
|
+
- `static-method`: `<TypeName>.<MethodName>` (e.g. `CIUtils.Generate`).
|
|
307
|
+
- `{{exampleKind}}` — `create-asset` | `menu-item` | `static-method`.
|
|
308
|
+
- `{{entryPointLink}}` — link into `api.md` for the target type or member, via the depth-prefixed `crossRefMap` value (depth 1, prepend `../`). For `create-asset` and `static-method`, target the **type** anchor. For `menu-item`, target the type that declares the method (the method itself doesn't get its own anchor in `api.md`, but its `Line` shows up in the type's Members table).
|
|
309
|
+
- `{{sourceRef}}` — `**Declared at:** \`path:line\`` pointing at the underlying member (for menu-item) or type (for create-asset / static-method). For menu-item, also include the menu path: `**Menu path:** \`Tools/PackageTools/Init Package\``. For create-asset, include the `menuName` argument from the attribute: `**Create menu:** \`Assets > Create > <menuName>\``.
|
|
310
|
+
- `{{exampleProse}}` — 1-3 short sentences: what this entry point does, what observable effect to expect, and (where relevant) which other public types it commonly composes with. Avoid restating what's in `api.md`; the link covers that. The reader should come away knowing **when** to call this entry point and **why**.
|
|
311
|
+
- `{{exampleSnippet}}` — a fenced code block (`csharp` for create-asset and static-method; `csharp` or `bash` for menu-item depending on context — see below). ≤ ~20 lines. Uses **only** public API from the package and Unity. Paste-ready: complete `using` directives at the top if the snippet would not compile without them, no `// ...` elisions.
|
|
312
|
+
- `create-asset`: snippet shows the API call (`ScriptableObject.CreateInstance<T>()` + minimal field setup + `AssetDatabase.CreateAsset(...)`) as the programmatic equivalent of the menu entry. Prefer this over describing the menu click — agents need code.
|
|
313
|
+
- `menu-item`: when the menu does work the consumer might also want to script (e.g. CI/CLI), emit a `csharp` snippet calling the same method directly. When the menu is GUI-only (opens a window, runs an editor flow that requires user input), emit a `bash` snippet showing how to invoke it via Unity batch mode (`Unity -batchmode -quit -executeMethod <TypeName>.<MethodName> ...`) and a 1-line note `// Or interactively: <Menu path>`.
|
|
314
|
+
- `static-method`: snippet shows a direct call to the method with believable arguments, plus the surrounding setup needed to make the call compile.
|
|
315
|
+
- `{{observableEffectList}}` — bulleted list of what the consumer will see/find after running the snippet (`- <project>/Assets/.../Foo.asset is created`, `- A new package skeleton appears at <packageDestinationPath>/<packageName>/`, `- The console prints \`[Package Tools]\` Done. lines`, etc.). 1-4 bullets.
|
|
262
316
|
|
|
263
|
-
|
|
317
|
+
Type links inside chunk files use the **depth-prefixed** `crossRefMap` value per Step 5's rule (i.e. `../api.md#foo` for the single-file api branch, or `../api/PackageTool.Tools.md#foo` for the chunked branch).
|
|
264
318
|
|
|
265
|
-
|
|
319
|
+
#### Stale chunks
|
|
266
320
|
|
|
267
|
-
|
|
321
|
+
Before writing, list `Documentation~/examples/*.md` (flat, no recursion — examples chunks live one level deep). For each existing `.md` file that starts with the generator marker and is **not** in the current chunk set, delete it and print `Removed stale: <path>`. Files without the marker are left in place and a warning is printed; same rule as elsewhere — never silently destroy hand-edited content. Hand-authored chunks the maintainer added (without the marker) are preserved across re-runs and remain linked from the index only if they're explicitly added to `{{contentsTableRows}}` by hand — the auto-generator does not enumerate non-marker files.
|
|
268
322
|
|
|
269
|
-
|
|
323
|
+
#### Edge case — no entry points
|
|
270
324
|
|
|
271
|
-
|
|
272
|
-
2. **One index** at `Documentation~/samples.md` containing the generator marker, H1, the global `## Sample Layout` tree, a `## Contents` Markdown table (`| Sample | Description |`) linking each chunk, and `## Notes`: `Samples are split by sample folder; see files under \`samples/\`.`
|
|
273
|
-
3. **Stale chunks:** before writing, list `Documentation~/samples/*.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>`.
|
|
325
|
+
If the API surface yields zero entry points across rules 1-3 (rare; would mean no `[CreateAssetMenu]`, no `[MenuItem]`, and no public-static-method on a public type), emit only the index `Documentation~/examples.md` with the generator marker, the H1, the `{{samplesNote}}` line if applicable, and a single section `## No public entry points detected` containing one sentence: ``This package exposes no `[CreateAssetMenu]`, `[MenuItem]`, or public static entry-point methods. Hand-author example chunks under `Documentation~/examples/` describing how a downstream consumer should compose the public types in `api.md`.`` Do not create the `Documentation~/examples/` directory in this case.
|
|
274
326
|
|
|
275
327
|
### Step 7 — Render `README.md`
|
|
276
328
|
|
|
@@ -285,6 +337,7 @@ Read `${SKILL_DIR}/assets/README.md.template`. Fill placeholders:
|
|
|
285
337
|
2. Else the first class with a `[MenuItem]` method → describe the menu path.
|
|
286
338
|
3. Else the first public static method on a public type → describe a direct call.
|
|
287
339
|
- `{{gettingStartedSnippet}}` — minimal `csharp` snippet exercising the primary entry point.
|
|
340
|
+
- `{{unitySamplesBullets}}` — if `samples[]` (from Step 2 metadata) is non-empty, render one bullet per declared Unity sample: ``- **<displayName>** — <description>. Import via Package Manager → <package displayName> → Samples → Import.`` If `samples[]` is empty or absent, replace the entire `## Unity Samples` section's content (including the placeholder line) with the single line `None — this package does not ship importable samples.` Use the README template's `{{unitySamplesSection}}` block guard if you prefer; the goal either way is a stable, predictable shape.
|
|
288
341
|
- `{{licensePath}}` — path to the root `LICENSE` file (typically `LICENSE`).
|
|
289
342
|
|
|
290
343
|
Write `README.md` at the repo root.
|
|
@@ -293,10 +346,11 @@ Write `README.md` at the repo root.
|
|
|
293
346
|
|
|
294
347
|
After all files (including any chunks) are written:
|
|
295
348
|
|
|
296
|
-
1. Grep `README.md` for `Documentation~/manual.md`, `Documentation~/api.md`, `Documentation~/
|
|
297
|
-
2. Walk every emitted `.md` under `Documentation~/` (index files and chunk files). For each `[Type](…)` link extract the destination path (relative to the link's own file) and anchor. Resolve the destination to an absolute path under `Documentation~/`; confirm the file exists and contains an `### {anchor}` heading (case-insensitive, hyphen-normalized per Markdown's auto-slug rule). Print warnings (not errors) for any broken anchors.
|
|
298
|
-
3. Confirm every generated file — including every chunk under `Documentation~/api/`, `Documentation~/manual/`, `Documentation~/
|
|
349
|
+
1. Grep `README.md` for `Documentation~/manual.md`, `Documentation~/api.md`, `Documentation~/examples.md`. Confirm each file exists. Abort with a clear error if any link is broken. (These three top-level paths are unchanged whether the file is single or chunked — when chunked the file is a Contents-table index, but the path still resolves.)
|
|
350
|
+
2. Walk every emitted `.md` under `Documentation~/` (index files and chunk files: `api/<Namespace>.md`, `manual/<slug>.md`, `examples/<slug>.md`). For each `[Type](…)` link extract the destination path (relative to the link's own file) and anchor. Resolve the destination to an absolute path under `Documentation~/`; confirm the file exists and contains an `### {anchor}` heading (case-insensitive, hyphen-normalized per Markdown's auto-slug rule). Print warnings (not errors) for any broken anchors.
|
|
351
|
+
3. Confirm every generated file — including every chunk under `Documentation~/api/`, `Documentation~/manual/`, and `Documentation~/examples/` — starts with the generator marker on line 1.
|
|
299
352
|
4. Confirm no chunk file outside the current chunk set survived (the stale-removal in Steps 4/5/6 should have deleted them; this is a safety re-check).
|
|
353
|
+
5. For each chunk in `Documentation~/examples/`, confirm the example snippet block (` ```csharp ` or ` ```bash `) is present and non-empty. This catches the regression where a chunk would be written without its snippet body.
|
|
300
354
|
|
|
301
355
|
Print a summary: which files were created vs updated, which were skipped (and why), and which chunks were removed as stale.
|
|
302
356
|
|
|
@@ -312,11 +366,12 @@ For each output file:
|
|
|
312
366
|
|
|
313
367
|
### Stale chunks
|
|
314
368
|
|
|
315
|
-
Chunk files (under `Documentation~/api/`, `Documentation~/manual/`, `Documentation~/
|
|
369
|
+
Chunk files (under `Documentation~/api/`, `Documentation~/manual/`, `Documentation~/examples/`) follow the same marker-on-line-1 contract as top-level generated files. Additionally:
|
|
316
370
|
|
|
317
|
-
4. **Stale removal (marker-gated).** Before writing the chunk set for an area, list every `.md` file in that area's chunk directory. 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>`. Files without the marker are left in place and a warning is printed (matches rule 3 — never silently destroy hand-edited content).
|
|
318
|
-
5. **Mode flip (single ↔ chunked).** When
|
|
319
|
-
6. **
|
|
371
|
+
4. **Stale removal (marker-gated).** Before writing the chunk set for an area, list every `.md` file in that area's chunk directory (flat — all three chunk dirs are single-level). 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>`. Files without the marker are left in place and a warning is printed (matches rule 3 — never silently destroy hand-edited content). Hand-authored example chunks (no marker) are preserved across re-runs; they show up under `examples/` but are not linked from `examples.md`'s auto-generated Contents table unless the maintainer adds the row by hand.
|
|
372
|
+
5. **Mode flip (single ↔ chunked).** Applies to `api.md` and `manual.md` only — `examples.md` is always chunked and never flips. When `api.md` or `manual.md` flips from chunked to single-file between runs (e.g. the user removes namespaces until the threshold is no longer exceeded), every file in that area's chunk directory is treated as stale by rule 4: marker-bearing chunks are deleted, marker-absent files are warned about. The chunk directory itself is left in place even when empty (Unity treats empty directories as no-ops; do not `rmdir` api/manual dirs).
|
|
373
|
+
6. **Migration from the legacy samples layout.** If `Documentation~/samples.md` or any path under `Documentation~/samples/` exists at the start of a run, delete every marker-bearing file in that tree and print `Removed legacy: <path>`. After deletion, `rmdir` any emptied directories under `Documentation~/samples/` and then the dir itself if empty. Files without the marker (i.e. hand-authored content the maintainer placed under `Documentation~/samples/`) are left alone and a warning is printed; the maintainer can move them under `Documentation~/examples/` manually. This migration runs once-per-repo — once the legacy paths are gone, subsequent runs see nothing to delete.
|
|
374
|
+
7. **Force.** `force=true` extends rules 3 and 4 — marker-absent files are overwritten (rule 3) and marker-absent chunks are also deleted when stale (rule 4 extension), matching the existing semantics for top-level files.
|
|
320
375
|
|
|
321
376
|
The pipeline as a whole is idempotent: re-running on an unchanged repo produces a no-op diff.
|
|
322
377
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<!-- generated by unity-package-docs; safe to regenerate -->
|
|
2
|
+
|
|
3
|
+
# {{displayName}} — Example: {{exampleTitle}}
|
|
4
|
+
|
|
5
|
+
**Kind:** {{exampleKind}}
|
|
6
|
+
|
|
7
|
+
**Entry point:** {{entryPointLink}}
|
|
8
|
+
|
|
9
|
+
{{sourceRef}}
|
|
10
|
+
|
|
11
|
+
## What it does
|
|
12
|
+
|
|
13
|
+
{{exampleProse}}
|
|
14
|
+
|
|
15
|
+
## Snippet
|
|
16
|
+
|
|
17
|
+
{{exampleSnippet}}
|
|
18
|
+
|
|
19
|
+
## Observable effect
|
|
20
|
+
|
|
21
|
+
{{observableEffectList}}
|
|
22
|
+
|
|
23
|
+
<!--
|
|
24
|
+
Slug rule (Step 3.5):
|
|
25
|
+
create-asset → create-<TypeName-lower> e.g. create-packagemanifestconfig
|
|
26
|
+
menu-item → <last-menu-path-segment-slug> e.g. init-package
|
|
27
|
+
static-method → <TypeName-lower>-<MethodName-lower> e.g. ciutils-generate
|
|
28
|
+
|
|
29
|
+
Snippet rule (Step 6 chunk section):
|
|
30
|
+
create-asset → ```csharp ... ScriptableObject.CreateInstance<T>() + AssetDatabase.CreateAsset(...) ...
|
|
31
|
+
menu-item → ```csharp direct call if the method is callable from code,
|
|
32
|
+
else ```bash with `Unity -batchmode -quit -executeMethod ...`.
|
|
33
|
+
Add a one-line `// Or interactively: <Menu path>` comment in either case.
|
|
34
|
+
static-method → ```csharp direct call with believable arguments + minimal compile-ready surroundings.
|
|
35
|
+
|
|
36
|
+
≤ ~20 lines. No `// ...` elisions. `using` directives included when the snippet would not compile without them.
|
|
37
|
+
|
|
38
|
+
Hand-edit this chunk freely — it has the generator marker, so a re-run will overwrite it.
|
|
39
|
+
To preserve manual edits, delete the marker on line 1 (the regen will then skip-with-warning and your version stays).
|
|
40
|
+
-->
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<!-- generated by unity-package-docs; safe to regenerate -->
|
|
2
|
+
|
|
3
|
+
# {{displayName}} — Examples
|
|
4
|
+
|
|
5
|
+
Short, focused usage examples that exercise this package's public API. Each example is independent and links into the API reference (`api.md`) for the type or member it calls. Snippets are paste-ready and use only public API — copy one into a fresh project to reach the same observable effect.
|
|
6
|
+
|
|
7
|
+
## Quick start
|
|
8
|
+
|
|
9
|
+
{{quickStartProse}}
|
|
10
|
+
|
|
11
|
+
## Contents
|
|
12
|
+
|
|
13
|
+
| Example | Kind | Entry point |
|
|
14
|
+
|---------|------|-------------|
|
|
15
|
+
{{contentsTableRows}}
|
|
16
|
+
|
|
17
|
+
<!--
|
|
18
|
+
One row per chunk under Documentation~/examples/<slug>.md.
|
|
19
|
+
Row format:
|
|
20
|
+
| [<title>](examples/<slug>.md) | create-asset | menu-item | static-method | [<TypeName>](crossRefMap[TypeName]) |
|
|
21
|
+
|
|
22
|
+
`<entry-point>` column links into api.md (depth 0, bare crossRefMap value).
|
|
23
|
+
For menu-item, the entry-point link targets the **type** that declares the
|
|
24
|
+
method (the method itself is shown in that type's Members table at the
|
|
25
|
+
referenced line).
|
|
26
|
+
|
|
27
|
+
Hand-authored chunks (no generator marker) are preserved across regens but
|
|
28
|
+
do NOT appear in this auto-generated table — add their rows by hand if you
|
|
29
|
+
want them indexed.
|
|
30
|
+
-->
|
|
31
|
+
|
|
32
|
+
{{samplesNote}}
|
|
33
|
+
|
|
34
|
+
## Notes
|
|
35
|
+
|
|
36
|
+
{{notesList}}
|
|
@@ -112,7 +112,7 @@ def normalize(src: str) -> str:
|
|
|
112
112
|
NAMESPACE_RE = re.compile(r"^\s*namespace\s+(?P<name>[\w.]+)\s*[{;]?\s*$")
|
|
113
113
|
|
|
114
114
|
TYPE_DECL_RE = re.compile(
|
|
115
|
-
r"^\s*(?P<mods>(?:(?:public|internal|private|protected|sealed|static|abstract|partial|new|unsafe)\s+)*)"
|
|
115
|
+
r"^\s*(?P<mods>(?:(?:public|internal|private|protected|sealed|static|abstract|partial|new|unsafe|readonly|ref)\s+)*)"
|
|
116
116
|
r"(?P<kind>class|struct|interface|enum)\s+"
|
|
117
117
|
r"(?P<name>[A-Za-z_]\w*)"
|
|
118
118
|
r"(?P<generic><[^>]*>)?"
|
|
@@ -128,7 +128,11 @@ METHOD_RE = re.compile(
|
|
|
128
128
|
r"(?P<generic><[^>]*>)?\s*"
|
|
129
129
|
r"\((?P<params>[^)]*)\)\s*"
|
|
130
130
|
r"(?:where\s+[^{;=]+)?"
|
|
131
|
-
|
|
131
|
+
# Accept any of: nothing (open brace on next line), `;` (declaration only / abstract),
|
|
132
|
+
# `{ … }` (single-line body), or `=> …;` (expression-bodied method, possibly with the
|
|
133
|
+
# whole right-hand side on the same line). Without `=>.*`, the regex misses
|
|
134
|
+
# `internal static void X() => Y();`-style declarations.
|
|
135
|
+
r"\s*(?:\{.*|;|=>.*)?\s*$"
|
|
132
136
|
)
|
|
133
137
|
|
|
134
138
|
PROPERTY_RE = re.compile(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: unity-package-release
|
|
3
|
-
description: Cut a release commit for any Unity package that uses the `com.elestrago.unity.package-tools` editor tool (the one that drives a `PackageManifestConfig` ScriptableObject and exports via the **Export Package Source** Inspector button). Discovers the config asset, package name, changelog filename, README install snippet, and publish flow at runtime via `scripts/discover_package.py`, so the same skill works in every package-tool consumer regardless of layout. Bumps the SO's `packageVersion`, updates the consumer-install version line in the project-root README (if one exists), prepends or appends an entry to the changelog (whatever filename the config's `changelogPath` resolves to), prompts the maintainer to run **Export Package Source** in Unity so the exported `Assets/Package/<X>/` artifacts and `Release/package.json` regenerate, stages exactly the touched files, and proposes a `V-{version} {summary}` commit. Detects the publish flow (GitLab elestrago CI, GitLab generic, GitHub Actions, or manual) and prints the matching handoff block — the skill never tags or pushes itself. Use whenever a package-tool maintainer wants to wrap pending changes into a release — phrasings
|
|
3
|
+
description: Cut a release commit for any Unity package that uses the `com.elestrago.unity.package-tools` editor tool (the one that drives a `PackageManifestConfig` ScriptableObject and exports via the **Export Package Source** Inspector button). Discovers the config asset, package name, changelog filename, README install snippet, and publish flow at runtime via `scripts/discover_package.py`, so the same skill works in every package-tool consumer regardless of layout. Bumps the SO's `packageVersion`, updates the consumer-install version line in the project-root README (if one exists), prepends or appends an entry to the changelog (whatever filename the config's `changelogPath` resolves to), prompts the maintainer to run **Export Package Source** in Unity so the exported `Assets/Package/<X>/` artifacts and `Release/package.json` regenerate, stages exactly the touched files, and proposes a `V-{version} {summary}` commit. Detects the publish flow (GitLab elestrago CI, GitLab generic, GitHub Actions, or manual) and prints the matching handoff block — the skill never tags or pushes itself. Use whenever a package-tool maintainer wants to wrap pending changes into a release — both release-specific phrasings ("bump the version", "cut a release", "update changelog and commit", "ship this as 2.x.y", "make a V- commit", "release this", "finalize the changes", "publish this version") and generic commit phrasings ("commit all changes", "commit changes", "commit this", "let's commit", "make a commit", "create a commit", "stage and commit", "wrap this up"), and also after a `/unity-package-tool-developer` run finishes its code edits. In a package-tool repo, treat any plain "commit" request as a release-commit request — these repos do not have non-release commits, every shipped commit is a `V-{version}` release commit, so a bare "commit" phrasing from the maintainer is the cue to run the full version-bump → changelog → Export Package Source → commit flow rather than a raw `git commit`. Refuses to run if no `PackageManifestConfig.asset` is found under `Assets/`.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# unity-package-release
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "com.elestrago.unity.package-tools",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.2",
|
|
4
4
|
"displayName": "Package Tool",
|
|
5
5
|
"description": "Tool for create unity packages",
|
|
6
6
|
"category": "unity",
|
|
7
7
|
"unity": "2021.3",
|
|
8
8
|
"homepage": "https://gitlab.com/elestrago-pkg/package-tool",
|
|
9
|
-
"documentationUrl": "https://gitlab.com/elestrago-pkg/package-tool/-/blob/2.
|
|
10
|
-
"changelogUrl": "https://gitlab.com/elestrago-pkg/package-tool/-/blob/2.
|
|
11
|
-
"licensesUrl": "https://gitlab.com/elestrago-pkg/package-tool/-/blob/2.
|
|
9
|
+
"documentationUrl": "https://gitlab.com/elestrago-pkg/package-tool/-/blob/2.5.2/README.md",
|
|
10
|
+
"changelogUrl": "https://gitlab.com/elestrago-pkg/package-tool/-/blob/2.5.2/CHANGELOG.md",
|
|
11
|
+
"licensesUrl": "https://gitlab.com/elestrago-pkg/package-tool/-/blob/2.5.2/LICENSE",
|
|
12
12
|
"license": "MIT",
|
|
13
13
|
"keywords": [
|
|
14
14
|
"unity",
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
<!-- generated by unity-package-docs; safe to regenerate -->
|
|
2
|
-
|
|
3
|
-
# Package Tool — Samples
|
|
4
|
-
|
|
5
|
-
How the sample content in this repository uses the package. Each entry maps a sample file to the package types it exercises, so a reader can recreate the same setup against the public API.
|
|
6
|
-
|
|
7
|
-
## Sample Layout
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
Assets/Example/Sample
|
|
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
|
|
25
|
-
```
|
|
26
|
-
|
|
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.
|
|
28
|
-
|
|
29
|
-
## Sample -> Package Type Mapping
|
|
30
|
-
|
|
31
|
-
### `Assets/Example/Sample/Prefabs/ExamplePrefab.prefab`
|
|
32
|
-
|
|
33
|
-
Kind: prefab
|
|
34
|
-
|
|
35
|
-
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.
|
|
36
|
-
|
|
37
|
-
### `Assets/Example/Sample/Scene/SampleScene.unity`
|
|
38
|
-
|
|
39
|
-
Kind: scene
|
|
40
|
-
|
|
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.
|
|
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
|
-
|
|
55
|
-
## Reproducing the Sample
|
|
56
|
-
|
|
57
|
-
**Example Sample (`Assets/Example/Sample`)** — structural only, no MonoBehaviour scripts to instantiate. To reproduce from scratch:
|
|
58
|
-
|
|
59
|
-
1. Create an empty Unity scene and a primitive prefab; both can live anywhere in `Assets/`.
|
|
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}`.
|
|
62
|
-
|
|
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:
|
|
66
|
-
|
|
67
|
-
```csharp
|
|
68
|
-
using PackageTool;
|
|
69
|
-
using PackageTool.Tools;
|
|
70
|
-
using UnityEditor;
|
|
71
|
-
using UnityEngine;
|
|
72
|
-
|
|
73
|
-
var config = ScriptableObject.CreateInstance<PackageManifestConfig>();
|
|
74
|
-
config.packageName = "com.example.sample";
|
|
75
|
-
config.displayName = "Example Sample Package";
|
|
76
|
-
config.packageVersion = "1.0.0";
|
|
77
|
-
config.unityVersion = "2021.3";
|
|
78
|
-
config.sourcePath = "Assets/Example/Source";
|
|
79
|
-
config.packageDestinationPath = "Release";
|
|
80
|
-
config.samples = new[]
|
|
81
|
-
{
|
|
82
|
-
new PackageManifestConfig.Sample
|
|
83
|
-
{
|
|
84
|
-
sourcePath = "Assets/Example/Sample",
|
|
85
|
-
displayName = "Example Sample",
|
|
86
|
-
folderName = "ExampleSample",
|
|
87
|
-
description = "This is example for check test samples",
|
|
88
|
-
},
|
|
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
|
-
};
|
|
99
|
-
AssetDatabase.CreateAsset(config, "Assets/Example/PackageManifestConfig.asset");
|
|
100
|
-
FileTools.CreateOrUpdatePackageSource(config);
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
## Notes
|
|
104
|
-
|
|
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.
|
|
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.
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
<!-- generated by unity-package-docs; safe to regenerate -->
|
|
2
|
-
|
|
3
|
-
# {{displayName}} — Samples
|
|
4
|
-
|
|
5
|
-
How the sample content in this repository uses the package. Each entry maps a sample file to the package types it exercises, so a reader can recreate the same setup against the public API.
|
|
6
|
-
|
|
7
|
-
## Sample Layout
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
{{sampleTree}}
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## Sample → Package Type Mapping
|
|
14
|
-
|
|
15
|
-
{{sampleMappingSections}}
|
|
16
|
-
|
|
17
|
-
<!--
|
|
18
|
-
Each sample entry follows this exact shape:
|
|
19
|
-
|
|
20
|
-
### `{sample file path}`
|
|
21
|
-
|
|
22
|
-
Kind: script | scene | prefab
|
|
23
|
-
|
|
24
|
-
Package types referenced:
|
|
25
|
-
|
|
26
|
-
- [`{TypeName}`]({crossRefMap[TypeName]}) — `{package source path}:{line}`
|
|
27
|
-
|
|
28
|
-
For scenes/prefabs, list each MonoBehaviour script resolved via m_Script.guid:
|
|
29
|
-
|
|
30
|
-
- GameObject `{name}` uses [`{TypeName}`]({crossRefMap[TypeName]}) — `{package source path}`
|
|
31
|
-
|
|
32
|
-
Type links resolve through crossRefMap (Step 3.5), NOT a hard-coded
|
|
33
|
-
api.md anchor — the destination may be api.md#foo (api single-file) or
|
|
34
|
-
api/PackageTool.Tools.md#foo (api chunked).
|
|
35
|
-
|
|
36
|
-
Omit "Package types referenced" if the file references none from this package.
|
|
37
|
-
|
|
38
|
-
Chunking note (Step 6 chunked branch): when this file is split, entries
|
|
39
|
-
are grouped by top-level sample folder into Documentation~/samples/<SampleFolderName>.md
|
|
40
|
-
(filename sanitized to [A-Za-z0-9._-], non-matching chars replaced with `-`).
|
|
41
|
-
Each chunk carries its own `## Reproducing the Sample` and `## Notes`
|
|
42
|
-
sections. Inside chunk files, every `[Type](…)` link prepends `../` to
|
|
43
|
-
the crossRefMap value.
|
|
44
|
-
-->
|
|
45
|
-
|
|
46
|
-
## Reproducing the Sample
|
|
47
|
-
|
|
48
|
-
{{reproductionProse}}
|
|
49
|
-
|
|
50
|
-
```csharp
|
|
51
|
-
{{reproductionSnippet}}
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
## Notes
|
|
55
|
-
|
|
56
|
-
{{notesList}}
|