fix(bgm): hot-reload markdown definition edits
Normalize the games root to POSIX separators so the HMR path guard matches on Windows, and watch the real on-disk markdown files (which defMap.files omits in favor of their virtual code blocks) so edits trigger a re-collect instead of a manual restart.
This commit is contained in:
@@ -16,8 +16,9 @@
|
||||
* hot-reloads the app via `addWatchFile`.
|
||||
*/
|
||||
import * as path from 'node:path';
|
||||
import type { ModuleNode, Plugin } from 'vite';
|
||||
import { normalizePath, type ModuleNode, type Plugin } from 'vite';
|
||||
import { collectPackages, loadDefs } from './collect.js';
|
||||
import { readDefFiles } from './parse.js';
|
||||
import type { Package, SerializedPackage } from './types.js';
|
||||
|
||||
const VIRTUAL_PREFIX = '\0bgm:';
|
||||
@@ -32,7 +33,10 @@ export interface BgmOptions {
|
||||
}
|
||||
|
||||
export function bgm(options: BgmOptions): Plugin {
|
||||
const root = options.root;
|
||||
// Vite normalizes `ctx.file` to POSIX separators before HMR hooks run, but
|
||||
// `fileURLToPath` retains backslashes on Windows. Normalize `root` to the
|
||||
// same form so `ctx.file.startsWith(root)` matches regardless of platform.
|
||||
const root = normalizePath(options.root);
|
||||
|
||||
const collect = (): Package[] => {
|
||||
const defMap = loadDefs('', root);
|
||||
@@ -42,11 +46,18 @@ export function bgm(options: BgmOptions): Plugin {
|
||||
return {
|
||||
name: 'bgm',
|
||||
buildStart() {
|
||||
// Watch every source file so edits trigger a reload/re-collect.
|
||||
// Watch every real definition source under the games root so edits
|
||||
// trigger a re-collect. `defMap.files` only holds the virtual code-block
|
||||
// files plus real non-markdown files; the markdown files themselves are
|
||||
// consumed for their code blocks and never appear there, so watch the
|
||||
// real files on disk too (markdown and anything else the loader reads).
|
||||
const defMap = loadDefs('', root);
|
||||
for (const name of defMap.files.keys()) {
|
||||
this.addWatchFile(path.join(root, name));
|
||||
}
|
||||
for (const file of readDefFiles(root, '')) {
|
||||
this.addWatchFile(file.source);
|
||||
}
|
||||
},
|
||||
resolveId(id) {
|
||||
if (id === PACKAGES) return VIRTUAL_PREFIX + PACKAGES;
|
||||
|
||||
@@ -85,10 +85,13 @@ describe('bgm vite plugin', () => {
|
||||
(plugin.buildStart as Callable<typeof plugin.buildStart>).call(context, {} as never);
|
||||
|
||||
// Every def file (real + virtual code blocks) is watched so edits
|
||||
// trigger a re-collect.
|
||||
// trigger a re-collect. The real markdown source must be watched too:
|
||||
// `defMap.files` only lists virtual code-block files, so without watching
|
||||
// the on-disk `.md` file the dev server would never notice an edit.
|
||||
expect(watched.length).toBeGreaterThan(0);
|
||||
expect(watched.some((f) => f.endsWith('.yaml'))).toBe(true);
|
||||
expect(watched.some((f) => f.endsWith('.csv'))).toBe(true);
|
||||
expect(watched.some((f) => f.endsWith('.md'))).toBe(true);
|
||||
expect(watched.every((f) => path.isAbsolute(f))).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user