vite-plugin-fvtt 0.2.0 → 0.2.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/CHANGELOG.md CHANGED
@@ -1,6 +1,18 @@
1
1
  # Changelog
2
2
 
3
- ## [Unreleased]
3
+ ## [0.2.2]
4
+
5
+ ## Fixed
6
+
7
+ - Improve windows path resolution.
8
+
9
+ ## [0.2.1] - 2025-09-09
10
+
11
+ ### Fixed
12
+
13
+ - Fixed language generation to not error out on mixed entries.
14
+
15
+ ## [0.2.0] - 2025-09-08
4
16
 
5
17
  ### Added
6
18
 
@@ -63,7 +75,10 @@
63
75
 
64
76
  - Initial Release
65
77
 
66
- [unreleased]: https://github.com/MatyeusM/vite-plugin-fvtt/compare/v0.1.4...HEAD
78
+ [unreleased]: https://github.com/MatyeusM/vite-plugin-fvtt/compare/v0.2.2...HEAD
79
+ [0.2.2]: https://github.com/MatyeusM/vite-plugin-fvtt/compare/v0.2.1...v0.2.2
80
+ [0.2.1]: https://github.com/MatyeusM/vite-plugin-fvtt/compare/v0.2.0...v0.2.1
81
+ [0.2.0]: https://github.com/MatyeusM/vite-plugin-fvtt/compare/v0.1.4...v0.2.0
67
82
  [0.1.4]: https://github.com/MatyeusM/vite-plugin-fvtt/compare/v0.1.3...v0.1.4
68
83
  [0.1.3]: https://github.com/MatyeusM/vite-plugin-fvtt/compare/v0.1.2...v0.1.3
69
84
  [0.1.2]: https://github.com/MatyeusM/vite-plugin-fvtt/compare/v0.1.1...v0.1.2
package/README.md CHANGED
@@ -102,7 +102,11 @@ Supports both complete and partial translation workflows:
102
102
 
103
103
  Merging follows your manifest’s declared language paths, searching in root or source directories.
104
104
 
105
- ⚠️ **Note:** HMR works for language files, but non-English locales may not reload as expected.
105
+ ### **6. Packs**
106
+
107
+ Packs are tried to be auto-discovered in the source directory. If the paths match, they are automatically compiled.
108
+
109
+ **Note:** Packs are currently not watched for changes.
106
110
 
107
111
  ### **Example Project Structure**
108
112
 
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import fs from "fs-extra";
2
2
  import posix from "path/posix";
3
3
  import dotenv from "dotenv";
4
+ import path from "path";
4
5
  import { globSync } from "tinyglobby";
5
6
  import { compilePack } from "@foundryvtt/foundryvtt-cli";
6
7
  import { Server } from "socket.io";
@@ -12,7 +13,7 @@ const context = {};
12
13
  //#endregion
13
14
  //#region src/config/env.ts
14
15
  function loadEnv() {
15
- const envPath = posix.resolve(process.cwd(), ".env.foundryvtt.local");
16
+ const envPath = path.resolve(process.cwd(), ".env.foundryvtt.local");
16
17
  const { parsed } = dotenv.config({
17
18
  path: envPath,
18
19
  quiet: true
@@ -67,7 +68,7 @@ function loadManifest(config) {
67
68
  `${publicDir}/system.json`,
68
69
  `${publicDir}/module.json`
69
70
  ];
70
- const foundPath = MANIFEST_LOCATIONS.map((relPath) => posix.resolve(process.cwd(), relPath)).find((absPath) => fs.pathExistsSync(absPath));
71
+ const foundPath = MANIFEST_LOCATIONS.map((relPath) => path.resolve(process.cwd(), relPath)).find((absPath) => fs.pathExistsSync(absPath));
71
72
  if (!foundPath) logger_default.fail(`Could not find a manifest file (system.json or module.json) in project root or ${publicDir}/.`);
72
73
  try {
73
74
  const data = fs.readJsonSync(foundPath);
@@ -171,7 +172,7 @@ var AbstractFileTracker = class {
171
172
  });
172
173
  }
173
174
  addFile(value, filePath) {
174
- const absPath = posix.resolve(filePath);
175
+ const absPath = path.resolve(filePath);
175
176
  if (!this.tracked.has(absPath)) {
176
177
  this.tracked.set(absPath, value);
177
178
  this.watcher?.add(absPath);
@@ -212,75 +213,72 @@ var PathUtils = class PathUtils {
212
213
  static getDecodedBase() {
213
214
  if (!PathUtils._decodedBase) {
214
215
  const config = PathUtils.getConfig();
215
- PathUtils._decodedBase = PathUtils.normalize(decodeURI(config.base));
216
+ PathUtils._decodedBase = path.posix.normalize(decodeURI(config.base));
216
217
  }
217
218
  return PathUtils._decodedBase;
218
219
  }
219
220
  static getSourceDirectory() {
220
221
  if (!PathUtils._sourceDirectory) {
221
222
  const config = PathUtils.getConfig();
222
- const normalizedEntry = PathUtils.normalize(config.build.lib.entry.toString());
223
- const segments = normalizedEntry.split(posix.sep).filter(Boolean).filter((s) => s !== ".");
223
+ const normalizedEntry = path.normalize(config.build.lib.entry.toString());
224
+ const segments = normalizedEntry.split(path.sep).filter(Boolean).filter((s) => s !== ".");
224
225
  const firstFolder = segments.length > 0 ? segments[0] : ".";
225
- PathUtils._sourceDirectory = posix.join(config.root, firstFolder);
226
+ PathUtils._sourceDirectory = path.join(config.root, firstFolder);
226
227
  }
227
228
  return PathUtils._sourceDirectory;
228
229
  }
229
230
  static getPublicDir() {
230
231
  if (!PathUtils._publicDir) {
231
232
  const config = PathUtils.getConfig();
232
- PathUtils._publicDir = PathUtils.normalize(posix.resolve(config.publicDir));
233
+ PathUtils._publicDir = path.resolve(config.publicDir);
233
234
  }
234
235
  return PathUtils._publicDir;
235
236
  }
236
237
  static getOutDir() {
237
238
  if (!PathUtils._outDir) {
238
239
  const config = PathUtils.getConfig();
239
- PathUtils._outDir = PathUtils.normalize(posix.resolve(config.build.outDir));
240
+ PathUtils._outDir = path.resolve(config.build.outDir);
240
241
  }
241
242
  return PathUtils._outDir;
242
243
  }
243
244
  static getRoot() {
244
245
  if (!PathUtils._root) {
245
246
  const config = PathUtils.getConfig();
246
- PathUtils._root = PathUtils.normalize(config.root);
247
+ PathUtils._root = path.resolve(config.root);
247
248
  }
248
249
  return PathUtils._root;
249
250
  }
250
251
  static getOutDirFile(p) {
251
- const file = posix.join(PathUtils.getOutDir(), p);
252
+ const file = path.join(PathUtils.getOutDir(), p);
252
253
  return fs.existsSync(file) ? file : "";
253
254
  }
254
255
  static getPublicDirFile(p) {
255
- const file = posix.join(PathUtils.getPublicDir(), p);
256
+ const file = path.join(PathUtils.getPublicDir(), p);
256
257
  return fs.existsSync(file) ? file : "";
257
258
  }
258
- static normalize(p) {
259
- return posix.normalize(p);
260
- }
261
259
  static findLocalFilePath(p) {
262
260
  const fileCandidates = [
263
261
  PathUtils.getPublicDir(),
264
262
  PathUtils.getSourceDirectory(),
265
263
  PathUtils.getRoot()
266
- ].map((pth) => posix.join(pth, p));
264
+ ].map((pth) => path.join(pth, p));
267
265
  return fileCandidates.find((pth) => fs.existsSync(pth)) ?? null;
268
266
  }
269
267
  static isFoundryVTTUrl(p) {
270
268
  const decodedBase = PathUtils.getDecodedBase();
271
- const pathToCheck = PathUtils.normalize(p);
269
+ const pathToCheck = path.posix.normalize(p);
272
270
  return pathToCheck.startsWith(decodedBase);
273
271
  }
274
272
  static foundryVTTUrlToLocal(p) {
275
273
  const decodedBase = PathUtils.getDecodedBase();
276
- let pathToTransform = PathUtils.normalize("/" + p);
274
+ let pathToTransform = path.posix.normalize("/" + p);
277
275
  if (!pathToTransform.startsWith(decodedBase)) return null;
278
- pathToTransform = posix.relative(decodedBase, pathToTransform);
276
+ pathToTransform = path.relative(decodedBase, pathToTransform);
279
277
  return PathUtils.findLocalFilePath(pathToTransform);
280
278
  }
281
279
  static localToFoundryVTTUrl(p) {
282
280
  const decodedBase = PathUtils.getDecodedBase();
283
- let pathToTransform = PathUtils.normalize(p);
281
+ let pathToTransform = path.normalize(p);
284
282
  [
285
283
  PathUtils.getPublicDir(),
286
284
  PathUtils.getSourceDirectory(),
@@ -288,13 +286,13 @@ var PathUtils = class PathUtils {
288
286
  ].forEach((pth) => {
289
287
  if (pathToTransform.startsWith(pth)) pathToTransform = pathToTransform.slice(pth.length);
290
288
  });
291
- return posix.join(decodedBase, pathToTransform);
289
+ return path.join(decodedBase, pathToTransform);
292
290
  }
293
291
  static getLanguageSourcePath(p, lang) {
294
- const dir = posix.parse(p).dir;
295
- const lastDirName = posix.basename(dir);
296
- const finalSegments = lastDirName === lang ? dir : posix.join(dir, lang);
297
- return posix.join(PathUtils.getSourceDirectory(), finalSegments);
292
+ const dir = path.parse(p).dir;
293
+ const lastDirName = path.basename(dir);
294
+ const finalSegments = lastDirName === lang ? dir : path.join(dir, lang);
295
+ return path.join(PathUtils.getSourceDirectory(), finalSegments);
298
296
  }
299
297
  };
300
298
  var path_utils_default = PathUtils;
@@ -396,8 +394,8 @@ function validator() {
396
394
  async function compileManifestPacks() {
397
395
  if (!context.manifest?.packs) return;
398
396
  for (const pack of context.manifest.packs) {
399
- const srcCandidates = [posix.resolve(path_utils_default.getSourceDirectory(), pack.path), posix.resolve(path_utils_default.getRoot(), pack.path)];
400
- const dest = posix.resolve(path_utils_default.getOutDir(), pack.path);
397
+ const srcCandidates = [path.resolve(path_utils_default.getSourceDirectory(), pack.path), path.resolve(path_utils_default.getRoot(), pack.path)];
398
+ const dest = path.resolve(path_utils_default.getOutDir(), pack.path);
401
399
  const chosenSrc = srcCandidates.find((candidate) => fs.existsSync(candidate) && fs.statSync(candidate).isDirectory());
402
400
  if (!chosenSrc) {
403
401
  logger_default.warn(`Pack path not found for ${pack.path}, skipped.`);
@@ -440,13 +438,13 @@ function httpMiddlewareHook(server) {
440
438
  }
441
439
  const cssFileName = config.build.lib.cssFileName;
442
440
  const cssEntry = cssFileName ? path_utils_default.localToFoundryVTTUrl(`${cssFileName}.css`) : null;
443
- if (path_utils_default.normalize(req.url ?? "") === cssEntry) {
441
+ if (path.posix.normalize(req.url ?? "") === cssEntry) {
444
442
  logger_default.info(`Blocking CSS entry to ${req.url}`);
445
443
  res.setHeader("Content-Type", "text/css");
446
444
  res.end("/* The cake is in another castle. */");
447
445
  return;
448
446
  }
449
- const languages = context.manifest.languages.filter((lang) => path_utils_default.localToFoundryVTTUrl(lang.path) === path_utils_default.normalize(req.url ?? ""));
447
+ const languages = context.manifest.languages.filter((lang) => path_utils_default.localToFoundryVTTUrl(lang.path) === path.posix.normalize(req.url ?? ""));
450
448
  if (languages.length === 1) {
451
449
  const lang = languages[0].lang;
452
450
  const language = loadLanguage(lang);
@@ -598,17 +596,18 @@ function foundryVTTPlugin(options = { buildPacks: true }) {
598
596
  configResolved(config) {
599
597
  context.config = config;
600
598
  },
601
- async writeBundle() {
602
- if (!context.config) return;
603
- const outDir = path_utils_default.getOutDir();
604
- const candidates = ["system.json", "module.json"];
605
- for (const file of candidates) {
599
+ async generateBundle() {
600
+ const manifestCandidates = ["system.json", "module.json"];
601
+ for (const file of manifestCandidates) {
606
602
  const src = posix.resolve(file);
607
- if (!path_utils_default.getOutDirFile(file) && fs.existsSync(src)) {
603
+ if (!path_utils_default.getPublicDirFile(file) && fs.existsSync(src)) {
608
604
  this.addWatchFile(src);
609
- const dest = posix.join(outDir, file);
610
- await fs.copy(src, dest);
611
- logger_default.info(`Copied ${file} >>> ${dest}`);
605
+ const manifest = fs.readJsonSync(src);
606
+ this.emitFile({
607
+ type: "asset",
608
+ fileName: file,
609
+ source: JSON.stringify(manifest, null, 2)
610
+ });
612
611
  }
613
612
  }
614
613
  const languages = context.manifest?.languages ?? [];
@@ -617,8 +616,14 @@ function foundryVTTPlugin(options = { buildPacks: true }) {
617
616
  getLocalLanguageFiles(language.lang).forEach((langFile) => this.addWatchFile(langFile));
618
617
  const languageDataRaw = loadLanguage(language.lang);
619
618
  const languageData = transform(languageDataRaw);
620
- fs.writeJSONSync(posix.join(outDir, language.path), languageData);
619
+ this.emitFile({
620
+ type: "asset",
621
+ fileName: posix.join(language.path),
622
+ source: JSON.stringify(languageData, null, 2)
623
+ });
621
624
  }
625
+ },
626
+ async writeBundle() {
622
627
  if (options.buildPacks) await compileManifestPacks();
623
628
  },
624
629
  closeBundle() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-fvtt",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "A Vite plugin for module and system development for Foundry VTT",
5
5
  "keywords": [
6
6
  "vite",
@@ -47,7 +47,7 @@
47
47
  "fs-extra": "^11.3.1",
48
48
  "socket.io": "^4.8.1",
49
49
  "socket.io-client": "^4.8.1",
50
- "tinyglobby": "^0.2.14"
50
+ "tinyglobby": "^0.2.15"
51
51
  },
52
52
  "peerDependencies": {
53
53
  "vite": "^7.0.0"