diff --git a/docs/bgm-format.md b/docs/bgm-format.md index 2b2760d..f8fccff 100644 --- a/docs/bgm-format.md +++ b/docs/bgm-format.md @@ -84,50 +84,51 @@ declaration, then uses its `include` paths to find the definitions. ### Code blocks as virtual files -A code block is a virtual definition file. To give it a name — so `include:` -and `$variants` paths can resolve against it — add a `file=` segment to the -code block's info string. The name is relative to the current markdown file: +A code block is a virtual definition file. Its name is derived from the +`role=` on its info string — `role.type.lang` — so it is discoverable by the +default `include: ./**/*.yaml` and addressable by that name: ````md -```yaml file=parts/cargo.yaml +```yaml role=part.cargo ... ``` -```csv file=parts/cargo.csv +```yaml role=surface.game#main +... +``` + +```yaml role=package ... ``` ```` -- A block with `file=` is addressable by that path. -- A block without `file=` is auto-named `./${hash}.yaml`, where `hash` - is derived from its content. This makes every yaml block naturally - discoverable by the default `include: ./**/*.yaml`. Identical blocks dedupe - to the same hash. -- The `file=` name is what `$variants: ./cargo.csv` and `include: parts/*.yaml` - resolve against. When there is a real file in that path, the codeblock wins. -- `file=` implies the file type from its extension; the language tag is - optional and only for editor highlighting. -- **Hash vs explicit `file=`:** a hashed name is for auto-discovery, not for - referencing. To point at a specific yaml block by name, give it an explicit - `file=`; otherwise its name is content-derived and unstable. +- `role=part.cargo` names the block `part.cargo.yaml`. +- `role=surface.game#main` names it `surface.game.yaml`. +- `role=package` names it `package.yaml`. +- The name is what `$variants: ./cargo.csv` and `include: parts/*.yaml` + resolve against. When there is a real file in that path, the codeblock wins. +- `file=` overrides the auto-name when present, e.g. `file=parts/cargo.yaml` + names the block `parts/cargo.yaml` regardless of its role. +- A block without `role=` is **not** a definition — it is ignored. Discovery + is explicit: a block is a definition only when its `role=` (or, for real + files, its filename) declares a known `role.type`. ### role= on the info string -A block's `role` can be declared on the info string instead of in the content, -using the same `role.type#id` shape as the block's identity. `type` and `id` -are optional — anything not given comes from the content (or from `$variants` -rows): +A block's role is declared on the info string, using the same `role.type#id` +shape as the block's identity. `type` and `id` are optional — anything not +given comes from the content (or from `$variants` rows): ````md -```yaml file=parts/cargo.yaml role=part.cargo +```yaml role=part.cargo ... ``` -```yaml file=board.yaml role=surface.game#main +```yaml role=surface.game#main ... ``` -```yaml file=game.yaml role=package +```yaml role=package ... ``` ```` @@ -139,8 +140,21 @@ rows): - A `role`/`type`/`id` given on the info string **conflicts** with the same key in the content and errors. `id` on the info string cannot combine with `$variants`, since every row supplies its own `id`. -- Without `role=`, discovery works exactly as before: the role comes from the - content's `role:` field. +- A block without `role=` is not a definition — discovery is explicit (see + above). + +### Real files + +A real `role.type.lang` file (e.g. `part.cargo.yaml`) is a definition by its +filename, with no `role=` needed. `role` and `type` are parsed from the name; +`id` comes from the content or `$variants`. A real file and a code block with +the same name are the same definition; the code block wins. + +### Duplicates + +Two definitions with the same `role.type` are grouped under the same name. +They must not define the same `id` — a duplicate `type#id` errors. Blocks with +the same `role.type` but different ids are fine. ### include @@ -160,7 +174,8 @@ package can use a `../`-relative pattern or an absolute-from-root pattern ## 3. Roles -json objects in yaml blocks are handled if they have a `role:` field for either +json objects in yaml blocks are handled if they are declared as a definition +by their `role=` (or, for real files, their filename) for either - `package` - `part` - `surface` @@ -171,9 +186,10 @@ a valid object can either be the root or in the list of the yaml block. for all roles except package, `type` and `id` are needed. `type#id` is used for identification so that combo must be unique in the package. -A block may declare its role on the info string instead — `role=part.cargo` is -equivalent to `role: part` + `type: cargo` in the content (see §2). The info -string and content must not both set the same key. +A block declares its role on the info string — `role=part.cargo` is equivalent +to `role: part` + `type: cargo` in the content (see §2). A real file declares +it in its filename. The info string/filename and content must not both set the +same key. ### package