wesl-plugin 0.6.2 → 0.6.7
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/dist/PluginExtension-B9OlwcsY.d.ts +511 -0
- package/dist/WeslPlugin-DjY8zodn.js +6137 -0
- package/dist/pluginIndex.d.ts +7 -4
- package/dist/pluginIndex.js +71 -62
- package/dist/plugins/astro.d.ts +4 -4
- package/dist/plugins/astro.js +10 -15
- package/dist/plugins/esbuild.d.ts +6 -6
- package/dist/plugins/esbuild.js +6 -9
- package/dist/plugins/farm.d.ts +6 -6
- package/dist/plugins/farm.js +6 -9
- package/dist/plugins/nuxt.d.ts +7 -8
- package/dist/plugins/nuxt.js +17 -24
- package/dist/plugins/rollup.d.ts +6 -6
- package/dist/plugins/rollup.js +6 -9
- package/dist/plugins/rspack.d.ts +5 -5
- package/dist/plugins/rspack.js +6 -9
- package/dist/plugins/vite.d.ts +6 -6
- package/dist/plugins/vite.js +4 -8
- package/dist/plugins/webpack.d.ts +6 -6
- package/dist/plugins/webpack.js +4 -8
- package/dist/vite-Bx_gff8v.js +8 -0
- package/dist/webpack-Bq0QiCAt.js +8 -0
- package/package.json +11 -10
- package/src/BindingLayoutExtension.ts +4 -4
- package/src/PluginApi.ts +201 -0
- package/src/PluginExtension.ts +3 -2
- package/src/WeslPlugin.ts +17 -198
- package/src/WeslPluginOptions.ts +1 -1
- package/src/defaultSuffixTypes.d.ts +1 -1
- package/src/extensions/LinkExtension.ts +9 -6
- package/src/extensions/StaticExtension.ts +9 -5
- package/src/plugins/nuxt.ts +1 -1
- package/dist/PluginExtension-B_oge2T3.d.ts +0 -48
- package/dist/WeslPluginOptions-ZzGgegv3.d.ts +0 -8
- package/dist/chunk-3YZCYXZ7.js +0 -11
- package/dist/chunk-JSBRDJBE.js +0 -30
- package/dist/chunk-LHNI4JI3.js +0 -6820
- package/dist/chunk-ZK6IKQOJ.js +0 -11
package/src/PluginApi.ts
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { glob } from "glob";
|
|
4
|
+
import toml from "toml";
|
|
5
|
+
import type { UnpluginBuildContext, UnpluginContext } from "unplugin";
|
|
6
|
+
import { type ParsedRegistry, parseIntoRegistry, parsedRegistry } from "wesl";
|
|
7
|
+
import { parseDependencies } from "wesl-tooling";
|
|
8
|
+
import type { PluginExtensionApi } from "./PluginExtension.js";
|
|
9
|
+
import type { PluginContext, WeslToml, WeslTomlInfo } from "./WeslPlugin.js";
|
|
10
|
+
|
|
11
|
+
export function buildApi(
|
|
12
|
+
context: PluginContext,
|
|
13
|
+
unpluginCtx: UnpluginBuildContext & UnpluginContext,
|
|
14
|
+
): PluginExtensionApi {
|
|
15
|
+
return {
|
|
16
|
+
weslToml: async () => getWeslToml(context, unpluginCtx),
|
|
17
|
+
weslSrc: async () => loadWesl(context, unpluginCtx),
|
|
18
|
+
weslRegistry: async () => getRegistry(context, unpluginCtx),
|
|
19
|
+
weslMain: makeGetWeslMain(context, unpluginCtx),
|
|
20
|
+
weslDependencies: async () => findDependencies(context, unpluginCtx),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** load the wesl.toml */
|
|
25
|
+
export async function getWeslToml(
|
|
26
|
+
context: PluginContext,
|
|
27
|
+
unpluginCtx: UnpluginBuildContext & UnpluginContext,
|
|
28
|
+
): Promise<WeslTomlInfo> {
|
|
29
|
+
const { cache } = context;
|
|
30
|
+
if (cache.weslToml) return cache.weslToml;
|
|
31
|
+
|
|
32
|
+
// find the wesl.toml file if it exists
|
|
33
|
+
const specifiedToml = context.options.weslToml;
|
|
34
|
+
let tomlFile: string | undefined;
|
|
35
|
+
if (specifiedToml) {
|
|
36
|
+
fs.access(specifiedToml);
|
|
37
|
+
tomlFile = specifiedToml;
|
|
38
|
+
} else {
|
|
39
|
+
tomlFile = await fs
|
|
40
|
+
.access("wesl.toml")
|
|
41
|
+
.then(() => "wesl.toml")
|
|
42
|
+
.catch(() => {
|
|
43
|
+
return undefined;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// load the toml contents
|
|
48
|
+
let parsedToml: WeslToml;
|
|
49
|
+
let tomlDir: string;
|
|
50
|
+
if (tomlFile) {
|
|
51
|
+
unpluginCtx.addWatchFile(tomlFile); // The cache gets cleared by the watchChange hook
|
|
52
|
+
parsedToml = await loadWeslToml(tomlFile);
|
|
53
|
+
tomlDir = path.dirname(tomlFile);
|
|
54
|
+
context.weslToml = tomlFile;
|
|
55
|
+
} else {
|
|
56
|
+
parsedToml = defaultWeslToml;
|
|
57
|
+
tomlDir = process.cwd();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const tomlToWeslRoot = path.resolve(tomlDir, parsedToml.weslRoot);
|
|
61
|
+
const resolvedWeslRoot = path.relative(process.cwd(), tomlToWeslRoot);
|
|
62
|
+
cache.weslToml = { tomlFile, tomlDir, resolvedWeslRoot, toml: parsedToml };
|
|
63
|
+
return cache.weslToml;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const defaultWeslToml: WeslToml = {
|
|
67
|
+
weslFiles: ["shaders/**/*.w[eg]sl"],
|
|
68
|
+
weslRoot: "shaders",
|
|
69
|
+
dependencies: ["auto"],
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Load and parse a wesl.toml file from the fs.
|
|
74
|
+
* Provide default values for any required WeslToml fields.
|
|
75
|
+
*/
|
|
76
|
+
async function loadWeslToml(tomlFile: string): Promise<WeslToml> {
|
|
77
|
+
const tomlString = await fs.readFile(tomlFile, "utf-8");
|
|
78
|
+
const parsed = toml.parse(tomlString) as WeslToml;
|
|
79
|
+
const weslToml = { ...defaultWeslToml, ...parsed };
|
|
80
|
+
return weslToml;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** load and parse all the wesl files into a ParsedRegistry */
|
|
84
|
+
async function getRegistry(
|
|
85
|
+
context: PluginContext,
|
|
86
|
+
unpluginCtx: UnpluginBuildContext & UnpluginContext,
|
|
87
|
+
): Promise<ParsedRegistry> {
|
|
88
|
+
const { cache } = context;
|
|
89
|
+
let { registry } = cache;
|
|
90
|
+
if (registry) return registry;
|
|
91
|
+
|
|
92
|
+
// load wesl files into registry
|
|
93
|
+
const loaded = await loadWesl(context, unpluginCtx);
|
|
94
|
+
const { resolvedWeslRoot } = await getWeslToml(context, unpluginCtx);
|
|
95
|
+
|
|
96
|
+
registry = parsedRegistry();
|
|
97
|
+
parseIntoRegistry(loaded, registry);
|
|
98
|
+
|
|
99
|
+
// The paths are relative to the weslRoot, but vite needs actual filesystem paths
|
|
100
|
+
const fullPaths = Object.keys(loaded).map(p =>
|
|
101
|
+
path.resolve(resolvedWeslRoot, p),
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
// trigger clearing cache on shader file change
|
|
105
|
+
fullPaths.forEach(f => {
|
|
106
|
+
unpluginCtx.addWatchFile(f);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
cache.registry = registry;
|
|
110
|
+
return registry;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** if the dependency list includes "auto", fill in the missing dependencies
|
|
114
|
+
* by parsing the source files to find references to packages
|
|
115
|
+
* @return the list of dependencies with "auto" replaced by the found dependencies
|
|
116
|
+
*/
|
|
117
|
+
async function findDependencies(
|
|
118
|
+
context: PluginContext,
|
|
119
|
+
unpluginCtx: UnpluginBuildContext & UnpluginContext,
|
|
120
|
+
): Promise<string[]> {
|
|
121
|
+
const { toml, tomlDir: projectDir } = await getWeslToml(context, unpluginCtx);
|
|
122
|
+
const weslSrc = await loadWesl(context, unpluginCtx);
|
|
123
|
+
const { dependencies = [] } = toml;
|
|
124
|
+
const hasAuto = dependencies.includes("auto");
|
|
125
|
+
if (!hasAuto) return dependencies;
|
|
126
|
+
|
|
127
|
+
const base = dependencies.filter(dep => dep !== "auto");
|
|
128
|
+
const deps = parseDependencies(weslSrc, projectDir);
|
|
129
|
+
const combined = new Set([...base, ...deps]);
|
|
130
|
+
return [...combined];
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function makeGetWeslMain(
|
|
134
|
+
context: PluginContext,
|
|
135
|
+
unpluginContext: UnpluginBuildContext & UnpluginContext,
|
|
136
|
+
): (baseId: string) => Promise<string> {
|
|
137
|
+
return getWeslMain;
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* @param shaderPath is an absolute path to the shader file
|
|
141
|
+
* @return the / separated path to the shader file, relative to the weslRoot
|
|
142
|
+
*/
|
|
143
|
+
async function getWeslMain(shaderPath: string): Promise<string> {
|
|
144
|
+
const { resolvedWeslRoot } = await getWeslToml(context, unpluginContext);
|
|
145
|
+
await fs.access(shaderPath); // if file doesn't exist, report now when the user problem is clear.
|
|
146
|
+
|
|
147
|
+
const absRoot = path.join(process.cwd(), resolvedWeslRoot);
|
|
148
|
+
const weslRootToMain = path.relative(absRoot, shaderPath);
|
|
149
|
+
return toUnixPath(weslRootToMain);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Load the wesl files referenced in the wesl.toml file
|
|
155
|
+
*
|
|
156
|
+
* @return a record of wesl files with
|
|
157
|
+
* keys as wesl file paths, and
|
|
158
|
+
* values as wesl file contents.
|
|
159
|
+
*/
|
|
160
|
+
async function loadWesl(
|
|
161
|
+
context: PluginContext,
|
|
162
|
+
unpluginCtx: UnpluginBuildContext & UnpluginContext,
|
|
163
|
+
): Promise<Record<string, string>> {
|
|
164
|
+
const {
|
|
165
|
+
toml: { weslFiles },
|
|
166
|
+
resolvedWeslRoot,
|
|
167
|
+
tomlDir,
|
|
168
|
+
} = await getWeslToml(context, unpluginCtx);
|
|
169
|
+
const futureFiles = weslFiles.map(g =>
|
|
170
|
+
glob(g, { cwd: tomlDir, absolute: true }),
|
|
171
|
+
);
|
|
172
|
+
const files = (await Promise.all(futureFiles)).flat();
|
|
173
|
+
|
|
174
|
+
// trigger rebuild on shader file change
|
|
175
|
+
files.forEach(f => unpluginCtx.addWatchFile(f));
|
|
176
|
+
|
|
177
|
+
return await loadFiles(files, resolvedWeslRoot);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/** load a set of shader files, converting to paths relative to the weslRoot directory */
|
|
181
|
+
async function loadFiles(
|
|
182
|
+
files: string[],
|
|
183
|
+
weslRoot: string,
|
|
184
|
+
): Promise<Record<string, string>> {
|
|
185
|
+
const loaded: [string, string][] = [];
|
|
186
|
+
|
|
187
|
+
for (const fullPath of files) {
|
|
188
|
+
const data = await fs.readFile(fullPath, "utf-8");
|
|
189
|
+
const relativePath = path.relative(weslRoot, fullPath);
|
|
190
|
+
loaded.push([toUnixPath(relativePath), data]);
|
|
191
|
+
}
|
|
192
|
+
return Object.fromEntries(loaded);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function toUnixPath(p: string): string {
|
|
196
|
+
if (path.sep !== "/") {
|
|
197
|
+
return p.replaceAll(path.sep, "/");
|
|
198
|
+
} else {
|
|
199
|
+
return p;
|
|
200
|
+
}
|
|
201
|
+
}
|
package/src/PluginExtension.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ParsedRegistry, WeslJsPlugin } from "wesl";
|
|
2
|
-
import { WeslTomlInfo } from "./WeslPlugin.ts";
|
|
1
|
+
import type { ParsedRegistry, WeslJsPlugin } from "wesl";
|
|
2
|
+
import type { WeslTomlInfo } from "./WeslPlugin.ts";
|
|
3
3
|
|
|
4
4
|
/** function type required for for emit extensions */
|
|
5
5
|
export type ExtensionEmitFn = (
|
|
@@ -29,4 +29,5 @@ export interface PluginExtensionApi {
|
|
|
29
29
|
weslSrc: () => Promise<Record<string, string>>;
|
|
30
30
|
weslRegistry: () => Promise<ParsedRegistry>;
|
|
31
31
|
weslMain: (baseId: string) => Promise<string>;
|
|
32
|
+
weslDependencies: () => Promise<string[]>;
|
|
32
33
|
}
|
package/src/WeslPlugin.ts
CHANGED
|
@@ -1,24 +1,17 @@
|
|
|
1
|
-
import { glob } from "glob";
|
|
2
|
-
import fs from "node:fs/promises";
|
|
3
1
|
import path from "node:path";
|
|
4
|
-
import toml from "toml";
|
|
5
|
-
import type {
|
|
6
|
-
ExternalIdResult,
|
|
7
|
-
Thenable,
|
|
8
|
-
TransformResult,
|
|
9
|
-
UnpluginBuildContext,
|
|
10
|
-
UnpluginContext,
|
|
11
|
-
UnpluginContextMeta,
|
|
12
|
-
UnpluginOptions
|
|
13
|
-
} from "unplugin";
|
|
14
|
-
import { createUnplugin } from "unplugin";
|
|
15
2
|
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
3
|
+
type ExternalIdResult,
|
|
4
|
+
type Thenable,
|
|
5
|
+
type TransformResult,
|
|
6
|
+
type UnpluginBuildContext,
|
|
7
|
+
type UnpluginContext,
|
|
8
|
+
type UnpluginContextMeta,
|
|
9
|
+
type UnpluginOptions,
|
|
10
|
+
createUnplugin,
|
|
11
|
+
} from "unplugin";
|
|
12
|
+
import type { Conditions, ParsedRegistry } from "wesl";
|
|
13
|
+
import { buildApi } from "./PluginApi.js";
|
|
14
|
+
import type { PluginExtension } from "./PluginExtension.js";
|
|
22
15
|
import type { WeslPluginOptions } from "./WeslPluginOptions.js";
|
|
23
16
|
|
|
24
17
|
/** loaded (or synthesized) info from .toml */
|
|
@@ -74,7 +67,7 @@ type Loader = (
|
|
|
74
67
|
) => Thenable<TransformResult>;
|
|
75
68
|
|
|
76
69
|
/** convenient state for local functions */
|
|
77
|
-
interface PluginContext {
|
|
70
|
+
export interface PluginContext {
|
|
78
71
|
cache: PluginCache;
|
|
79
72
|
options: WeslPluginOptions;
|
|
80
73
|
meta: UnpluginContextMeta;
|
|
@@ -93,7 +86,7 @@ interface PluginContext {
|
|
|
93
86
|
* 2. `import "./shaders/bar.wesl?link"` - produces a javascript file for preconstructed link functions
|
|
94
87
|
*/
|
|
95
88
|
export function weslPlugin(
|
|
96
|
-
options: WeslPluginOptions
|
|
89
|
+
options: WeslPluginOptions,
|
|
97
90
|
meta: UnpluginContextMeta,
|
|
98
91
|
): UnpluginOptions {
|
|
99
92
|
const cache: PluginCache = {};
|
|
@@ -103,7 +96,7 @@ export function weslPlugin(
|
|
|
103
96
|
name: "wesl-plugin",
|
|
104
97
|
resolveId: buildResolver(options, context),
|
|
105
98
|
load: buildLoader(context),
|
|
106
|
-
watchChange(id,
|
|
99
|
+
watchChange(id, _change) {
|
|
107
100
|
if (id.endsWith("wesl.toml")) {
|
|
108
101
|
// The cache is shared for multiple imports
|
|
109
102
|
cache.weslToml = undefined;
|
|
@@ -204,18 +197,6 @@ function pluginSuffixMatch(id: string, suffixes: string[]): PluginMatch | null {
|
|
|
204
197
|
};
|
|
205
198
|
}
|
|
206
199
|
|
|
207
|
-
function buildApi(
|
|
208
|
-
context: PluginContext,
|
|
209
|
-
unpluginCtx: UnpluginBuildContext & UnpluginContext,
|
|
210
|
-
): PluginExtensionApi {
|
|
211
|
-
return {
|
|
212
|
-
weslToml: async () => getWeslToml(context, unpluginCtx),
|
|
213
|
-
weslSrc: async () => loadWesl(context, unpluginCtx),
|
|
214
|
-
weslRegistry: async () => getRegistry(context, unpluginCtx),
|
|
215
|
-
weslMain: makeGetWeslMain(context, unpluginCtx),
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
|
|
219
200
|
/** build plugin function for serving a javascript module in response to
|
|
220
201
|
* an import of of our virtual import modules. */
|
|
221
202
|
function buildLoader(context: PluginContext): Loader {
|
|
@@ -234,9 +215,8 @@ function buildLoader(context: PluginContext): Loader {
|
|
|
234
215
|
const plugin = pluginsMap[matched.pluginName];
|
|
235
216
|
const { baseId, importParams } = matched;
|
|
236
217
|
const conditions = importParamsToConditions(importParams);
|
|
237
|
-
const shaderPath =
|
|
238
|
-
baseId.
|
|
239
|
-
baseId.slice(resolvedPrefix.length)
|
|
218
|
+
const shaderPath = baseId.startsWith(resolvedPrefix)
|
|
219
|
+
? baseId.slice(resolvedPrefix.length)
|
|
240
220
|
: baseId;
|
|
241
221
|
|
|
242
222
|
return await plugin.emitFn(shaderPath, buildPluginApi, conditions);
|
|
@@ -271,167 +251,6 @@ function importParamsToConditions(
|
|
|
271
251
|
return conditions;
|
|
272
252
|
}
|
|
273
253
|
|
|
274
|
-
export const defaultTomlMessage = `no wesl.toml found: assuming .wesl files are in ./shaders`;
|
|
275
|
-
|
|
276
|
-
/** load the wesl.toml */
|
|
277
|
-
async function getWeslToml(
|
|
278
|
-
context: PluginContext,
|
|
279
|
-
unpluginCtx: UnpluginBuildContext & UnpluginContext,
|
|
280
|
-
): Promise<WeslTomlInfo> {
|
|
281
|
-
const { cache } = context;
|
|
282
|
-
if (cache.weslToml) return cache.weslToml;
|
|
283
|
-
|
|
284
|
-
// find the wesl.toml file if it exists
|
|
285
|
-
const specifiedToml = context.options.weslToml;
|
|
286
|
-
let tomlFile: string | undefined;
|
|
287
|
-
if (specifiedToml) {
|
|
288
|
-
fs.access(specifiedToml);
|
|
289
|
-
tomlFile = specifiedToml;
|
|
290
|
-
} else {
|
|
291
|
-
tomlFile = await fs
|
|
292
|
-
.access("wesl.toml")
|
|
293
|
-
.then(() => "wesl.toml")
|
|
294
|
-
.catch(() => {
|
|
295
|
-
return undefined;
|
|
296
|
-
});
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
// load the toml contents
|
|
300
|
-
let parsedToml: WeslToml;
|
|
301
|
-
let tomlDir: string;
|
|
302
|
-
if (tomlFile) {
|
|
303
|
-
unpluginCtx.addWatchFile(tomlFile); // The cache gets cleared by the watchChange hook
|
|
304
|
-
parsedToml = await loadWeslToml(tomlFile);
|
|
305
|
-
tomlDir = path.dirname(tomlFile);
|
|
306
|
-
context.weslToml = tomlFile;
|
|
307
|
-
} else {
|
|
308
|
-
console.log(defaultTomlMessage);
|
|
309
|
-
parsedToml = defaultWeslToml;
|
|
310
|
-
tomlDir = process.cwd();
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
const tomlToWeslRoot = path.resolve(tomlDir, parsedToml.weslRoot);
|
|
314
|
-
const resolvedWeslRoot = path.relative(process.cwd(), tomlToWeslRoot);
|
|
315
|
-
cache.weslToml = { tomlFile, tomlDir, resolvedWeslRoot, toml: parsedToml };
|
|
316
|
-
return cache.weslToml;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
const defaultWeslToml: WeslToml = {
|
|
320
|
-
weslFiles: ["shaders/**/*.w[eg]sl"],
|
|
321
|
-
weslRoot: "shaders",
|
|
322
|
-
};
|
|
323
|
-
|
|
324
|
-
/**
|
|
325
|
-
* Load and parse a wesl.toml file from the fs.
|
|
326
|
-
* Provide default values for any required WeslToml fields.
|
|
327
|
-
*/
|
|
328
|
-
async function loadWeslToml(tomlFile: string): Promise<WeslToml> {
|
|
329
|
-
const tomlString = await fs.readFile(tomlFile, "utf-8");
|
|
330
|
-
const parsed = toml.parse(tomlString) as WeslToml;
|
|
331
|
-
const weslToml = { ...defaultWeslToml, ...parsed };
|
|
332
|
-
return weslToml;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
/** load and parse all the wesl files into a ParsedRegistry */
|
|
336
|
-
async function getRegistry(
|
|
337
|
-
context: PluginContext,
|
|
338
|
-
unpluginCtx: UnpluginBuildContext & UnpluginContext,
|
|
339
|
-
): Promise<ParsedRegistry> {
|
|
340
|
-
const { cache } = context;
|
|
341
|
-
let { registry } = cache;
|
|
342
|
-
if (registry) return registry;
|
|
343
|
-
|
|
344
|
-
// load wesl files into registry
|
|
345
|
-
const loaded = await loadWesl(context, unpluginCtx);
|
|
346
|
-
const { resolvedWeslRoot } = await getWeslToml(context, unpluginCtx);
|
|
347
|
-
|
|
348
|
-
registry = parsedRegistry();
|
|
349
|
-
parseIntoRegistry(loaded, registry);
|
|
350
|
-
|
|
351
|
-
// The paths are relative to the weslRoot, but vite needs actual filesystem paths
|
|
352
|
-
const fullPaths = Object.keys(loaded).map(p =>
|
|
353
|
-
path.resolve(resolvedWeslRoot, p),
|
|
354
|
-
);
|
|
355
|
-
|
|
356
|
-
// trigger clearing cache on shader file change
|
|
357
|
-
fullPaths.forEach(f => {
|
|
358
|
-
unpluginCtx.addWatchFile(f);
|
|
359
|
-
});
|
|
360
|
-
|
|
361
|
-
cache.registry = registry;
|
|
362
|
-
return registry;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
function makeGetWeslMain(
|
|
366
|
-
context: PluginContext,
|
|
367
|
-
unpluginContext: UnpluginBuildContext & UnpluginContext,
|
|
368
|
-
): (baseId: string) => Promise<string> {
|
|
369
|
-
return getWeslMain;
|
|
370
|
-
|
|
371
|
-
/**
|
|
372
|
-
* @param shaderPath is an absolute path to the shader file
|
|
373
|
-
* @return the / separated path to the shader file, relative to the weslRoot
|
|
374
|
-
*/
|
|
375
|
-
async function getWeslMain(shaderPath: string): Promise<string> {
|
|
376
|
-
const { resolvedWeslRoot } = await getWeslToml(context, unpluginContext);
|
|
377
|
-
await fs.access(shaderPath); // if file doesn't exist, report now when the user problem is clear.
|
|
378
|
-
|
|
379
|
-
const absRoot = path.join(process.cwd(), resolvedWeslRoot);
|
|
380
|
-
const weslRootToMain = path.relative(absRoot, shaderPath);
|
|
381
|
-
return toUnixPath(weslRootToMain);
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
/**
|
|
386
|
-
* Load the wesl files referenced in the wesl.toml file
|
|
387
|
-
*
|
|
388
|
-
* @return a record of wesl files with
|
|
389
|
-
* keys as wesl file paths, and
|
|
390
|
-
* values as wesl file contents.
|
|
391
|
-
*/
|
|
392
|
-
async function loadWesl(
|
|
393
|
-
context: PluginContext,
|
|
394
|
-
unpluginCtx: UnpluginBuildContext & UnpluginContext,
|
|
395
|
-
): Promise<Record<string, string>> {
|
|
396
|
-
const {
|
|
397
|
-
toml: { weslFiles },
|
|
398
|
-
resolvedWeslRoot,
|
|
399
|
-
tomlDir,
|
|
400
|
-
} = await getWeslToml(context, unpluginCtx);
|
|
401
|
-
const futureFiles = weslFiles.map(g =>
|
|
402
|
-
glob(g, { cwd: tomlDir, absolute: true }),
|
|
403
|
-
);
|
|
404
|
-
const files = (await Promise.all(futureFiles)).flat();
|
|
405
|
-
|
|
406
|
-
// trigger rebuild on shader file change
|
|
407
|
-
files.forEach(f => unpluginCtx.addWatchFile(f));
|
|
408
|
-
|
|
409
|
-
return await loadFiles(files, resolvedWeslRoot);
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
/** load a set of shader files, converting to paths relative to the weslRoot directory */
|
|
413
|
-
async function loadFiles(
|
|
414
|
-
files: string[],
|
|
415
|
-
weslRoot: string,
|
|
416
|
-
): Promise<Record<string, string>> {
|
|
417
|
-
const loaded: [string, string][] = [];
|
|
418
|
-
|
|
419
|
-
for (const fullPath of files) {
|
|
420
|
-
const data = await fs.readFile(fullPath, "utf-8");
|
|
421
|
-
const relativePath = path.relative(weslRoot, fullPath);
|
|
422
|
-
loaded.push([toUnixPath(relativePath), data]);
|
|
423
|
-
}
|
|
424
|
-
return Object.fromEntries(loaded);
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
function toUnixPath(p: string): string {
|
|
428
|
-
if (path.sep !== "/") {
|
|
429
|
-
return p.replaceAll(path.sep, "/");
|
|
430
|
-
} else {
|
|
431
|
-
return p;
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
|
|
435
254
|
export const unplugin = createUnplugin(
|
|
436
255
|
(options: WeslPluginOptions, meta: UnpluginContextMeta) => {
|
|
437
256
|
return weslPlugin(options, meta);
|
package/src/WeslPluginOptions.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import { LinkParams, noSuffix } from "wesl";
|
|
3
|
-
import {
|
|
2
|
+
import { type LinkParams, noSuffix } from "wesl";
|
|
3
|
+
import type {
|
|
4
|
+
PluginExtension,
|
|
5
|
+
PluginExtensionApi,
|
|
6
|
+
} from "../PluginExtension.ts";
|
|
4
7
|
|
|
5
8
|
export const linkBuildExtension: PluginExtension = {
|
|
6
9
|
extensionName: "link",
|
|
@@ -12,8 +15,7 @@ async function emitLinkJs(
|
|
|
12
15
|
baseId: string,
|
|
13
16
|
api: PluginExtensionApi,
|
|
14
17
|
): Promise<string> {
|
|
15
|
-
const { resolvedWeslRoot,
|
|
16
|
-
const { dependencies = [] } = toml;
|
|
18
|
+
const { resolvedWeslRoot, tomlDir } = await api.weslToml();
|
|
17
19
|
|
|
18
20
|
const weslSrc = await api.weslSrc();
|
|
19
21
|
|
|
@@ -23,9 +25,10 @@ async function emitLinkJs(
|
|
|
23
25
|
const tomlRelative = path.relative(tomlDir, resolvedWeslRoot);
|
|
24
26
|
const debugWeslRoot = tomlRelative.replaceAll(path.sep, "/");
|
|
25
27
|
|
|
26
|
-
const
|
|
28
|
+
const autoDeps = await api.weslDependencies();
|
|
29
|
+
const sanitizedDeps = autoDeps.map(dep => dep.replaceAll("/", "_"));
|
|
27
30
|
|
|
28
|
-
const bundleImports =
|
|
31
|
+
const bundleImports = autoDeps
|
|
29
32
|
.map((p, i) => `import ${sanitizedDeps[i]} from "${p}";`)
|
|
30
33
|
.join("\n");
|
|
31
34
|
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import { resolve } from "import-meta-resolve";
|
|
2
1
|
import path from "node:path";
|
|
3
2
|
import url from "node:url";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { resolve } from "import-meta-resolve";
|
|
4
|
+
import { type Conditions, link, noSuffix } from "wesl";
|
|
5
|
+
import type {
|
|
6
|
+
PluginExtension,
|
|
7
|
+
PluginExtensionApi,
|
|
8
|
+
} from "../PluginExtension.ts";
|
|
6
9
|
|
|
7
10
|
/**
|
|
8
11
|
* a wesl-js ?static build extension that statically links from the root file
|
|
@@ -25,13 +28,14 @@ async function emitStaticJs(
|
|
|
25
28
|
api: PluginExtensionApi,
|
|
26
29
|
conditions?: Conditions,
|
|
27
30
|
): Promise<string> {
|
|
28
|
-
const { resolvedWeslRoot,
|
|
29
|
-
const { dependencies = [] } = toml;
|
|
31
|
+
const { resolvedWeslRoot, tomlDir } = await api.weslToml();
|
|
30
32
|
|
|
31
33
|
// resolve import module relative to the root of the shader project
|
|
32
34
|
const parentModule = url
|
|
33
35
|
.pathToFileURL(path.join(tomlDir, "wesl.toml"))
|
|
34
36
|
.toString();
|
|
37
|
+
|
|
38
|
+
const dependencies = await api.weslDependencies();
|
|
35
39
|
const libFileUrls = dependencies.map(d => resolve(d, parentModule));
|
|
36
40
|
|
|
37
41
|
// load the lib modules
|
package/src/plugins/nuxt.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { addVitePlugin, addWebpackPlugin, defineNuxtModule } from "@nuxt/kit";
|
|
2
|
+
import type { WeslPluginOptions } from "../WeslPluginOptions";
|
|
2
3
|
import vite from "./vite";
|
|
3
4
|
import webpack from "./webpack";
|
|
4
|
-
import type { WeslPluginOptions } from "../WeslPluginOptions";
|
|
5
5
|
import "@nuxt/schema";
|
|
6
6
|
|
|
7
7
|
export interface ModuleOptions extends WeslPluginOptions {}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { WeslJsPlugin, ParsedRegistry } from 'wesl';
|
|
2
|
-
|
|
3
|
-
/** loaded (or synthesized) info from .toml */
|
|
4
|
-
interface WeslToml {
|
|
5
|
-
/** glob search strings to find .wesl/.wgsl files. Relative to the toml directory. */
|
|
6
|
-
weslFiles: string[];
|
|
7
|
-
/** base directory for wesl files. Relative to the toml directory. */
|
|
8
|
-
weslRoot: string;
|
|
9
|
-
/** names of directly referenced wesl shader packages (e.g. npm package names) */
|
|
10
|
-
dependencies?: string[];
|
|
11
|
-
}
|
|
12
|
-
interface WeslTomlInfo {
|
|
13
|
-
/** The path to the toml file, relative to the cwd, undefined if no toml file */
|
|
14
|
-
tomlFile: string | undefined;
|
|
15
|
-
/** The absolute path to the directory that contains the toml.
|
|
16
|
-
* Paths inside the toml are relative to this. */
|
|
17
|
-
tomlDir: string;
|
|
18
|
-
/** The wesl root, relative to the cwd.
|
|
19
|
-
* This lets us correctly do `path.resolve(resolvedWeslRoot, someShaderFile)` */
|
|
20
|
-
resolvedWeslRoot: string;
|
|
21
|
-
/** The underlying toml file */
|
|
22
|
-
toml: WeslToml;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/** function type required for for emit extensions */
|
|
26
|
-
type ExtensionEmitFn = (
|
|
27
|
-
/** absolute path to the shader to which the extension is attached */
|
|
28
|
-
shaderPath: string,
|
|
29
|
-
/** support functions available to plugin extensions */
|
|
30
|
-
pluginApi: PluginExtensionApi,
|
|
31
|
-
/** static conditions specified on the js import */ conditions?: Record<string, boolean>) => Promise<string>;
|
|
32
|
-
/** an extension that runs inside the wesl-js build plugin */
|
|
33
|
-
interface PluginExtension extends WeslJsPlugin {
|
|
34
|
-
/** javascript imports with this suffix will trigger the plugin */
|
|
35
|
-
extensionName: string;
|
|
36
|
-
/** generate javascript text for js/ts importers to use.
|
|
37
|
-
* e.g. import myPluginJs from "./foo.wesl?myPlugin"; */
|
|
38
|
-
emitFn: ExtensionEmitFn;
|
|
39
|
-
}
|
|
40
|
-
/** api supplied to plugin extensions */
|
|
41
|
-
interface PluginExtensionApi {
|
|
42
|
-
weslToml: () => Promise<WeslTomlInfo>;
|
|
43
|
-
weslSrc: () => Promise<Record<string, string>>;
|
|
44
|
-
weslRegistry: () => Promise<ParsedRegistry>;
|
|
45
|
-
weslMain: (baseId: string) => Promise<string>;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export type { ExtensionEmitFn as E, PluginExtension as P, PluginExtensionApi as a };
|
package/dist/chunk-3YZCYXZ7.js
DELETED
package/dist/chunk-JSBRDJBE.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
var __create = Object.create;
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __commonJS = (cb, mod) => function __require() {
|
|
8
|
-
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
19
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
20
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
21
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
22
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
23
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
24
|
-
mod
|
|
25
|
-
));
|
|
26
|
-
|
|
27
|
-
export {
|
|
28
|
-
__commonJS,
|
|
29
|
-
__toESM
|
|
30
|
-
};
|