feat(bgm): support role= on code block info strings

Parse role.type#id from the fence info string and merge it into each
parsed object, erroring on conflicts with the content. id on the info
string can't combine with $variants. Auto-named blocks now hash their
content instead of the info string, so identical blocks dedupe.
This commit is contained in:
2026-08-10 16:09:12 +08:00
parent c41c266ac1
commit aab0b66ee8
7 changed files with 207 additions and 10 deletions
+38
View File
@@ -39,6 +39,44 @@ describe('scanMarkdown', () => {
expect(files[0]!.kind).toBe('yaml');
});
it('hashes identical blocks to the same auto-name', () => {
const md = ['```yaml\nrole: part\n```', '', '```yaml\nrole: part\n```'].join('\n');
const { files } = scanMarkdown(md, 'harbor/harbor.md');
expect(files).toHaveLength(2);
expect(files[0]!.name).toBe(files[1]!.name);
});
it('parses role= metadata from the info string', () => {
const md = '```yaml file=cards.yaml role=part.poker-card\nid: 2s\n```';
const { files } = scanMarkdown(md, 'poker/poker.md');
expect(files[0]).toMatchObject({
name: 'poker/cards.yaml',
role: { role: 'part', type: 'poker-card' },
});
});
it('parses role= with type and id', () => {
const md = '```yaml file=board.yaml role=surface.game#main\n```';
const { files } = scanMarkdown(md, 'poker/poker.md');
expect(files[0]!.role).toEqual({ role: 'surface', type: 'game', id: 'main' });
});
it('parses role=package without type or id', () => {
const md = '```yaml file=game.yaml role=package\n```';
const { files } = scanMarkdown(md, 'poker/poker.md');
expect(files[0]!.role).toEqual({ role: 'package' });
});
it('throws on an unknown role=', () => {
const md = '```yaml file=a.yaml role=widget\n```';
expect(() => scanMarkdown(md, 'poker/poker.md')).toThrow(/Invalid role/);
});
it('throws on role=package with a type', () => {
const md = '```yaml file=a.yaml role=package.foo\n```';
expect(() => scanMarkdown(md, 'poker/poker.md')).toThrow(/Package role takes no type/);
});
it('ignores non-definition languages', () => {
const md = '```js\nconst x = 1;\n```';
const { files, fences } = scanMarkdown(md, 'harbor/harbor.md');