wgsl-edit 0.0.24 → 0.0.26
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/README.md +49 -9
- package/dist/SaveEndpoint.d.mts +5 -0
- package/dist/SaveEndpoint.mjs +5 -0
- package/dist/SaveMiddleware.d.mts +9 -0
- package/dist/SaveMiddleware.mjs +49 -0
- package/dist/{WgslEdit-ByXfb3R9.js → WgslEdit-CNK80480.js} +252 -118
- package/dist/WgslEdit.d.ts +45 -1
- package/dist/WgslEdit.js +1 -1
- package/dist/autosave.d.mts +11 -0
- package/dist/autosave.mjs +18 -0
- package/dist/index.js +1 -1
- package/dist/jsx-preact.d.ts +12 -0
- package/dist/jsx-preact.js +0 -0
- package/dist/wgsl-edit.js +313 -522
- package/package.json +24 -6
- package/src/SaveEndpoint.ts +2 -0
- package/src/SaveMiddleware.ts +71 -0
- package/src/WgslEdit.ts +288 -157
- package/src/autosave.ts +24 -0
- package/src/jsx-preact.ts +15 -0
- package/src/test/Autosave.e2e.ts +100 -0
- package/src/test/E2eUtil.ts +6 -0
- package/src/test/Undo.e2e.ts +91 -0
- package/src/test/WgslEdit.e2e.ts +1 -4
package/dist/wgsl-edit.js
CHANGED
|
@@ -5073,11 +5073,11 @@ var shift = {
|
|
|
5073
5073
|
};
|
|
5074
5074
|
var mac = typeof navigator != "undefined" && /Mac/.test(navigator.platform);
|
|
5075
5075
|
var ie$1 = typeof navigator != "undefined" && /MSIE \d|Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(navigator.userAgent);
|
|
5076
|
-
for (var i
|
|
5077
|
-
for (var i
|
|
5078
|
-
for (var i
|
|
5079
|
-
base[i
|
|
5080
|
-
shift[i
|
|
5076
|
+
for (var i = 0; i < 10; i++) base[48 + i] = base[96 + i] = String(i);
|
|
5077
|
+
for (var i = 1; i <= 24; i++) base[i + 111] = "F" + i;
|
|
5078
|
+
for (var i = 65; i <= 90; i++) {
|
|
5079
|
+
base[i] = String.fromCharCode(i + 32);
|
|
5080
|
+
shift[i] = String.fromCharCode(i);
|
|
5081
5081
|
}
|
|
5082
5082
|
for (var code in base) if (!shift.hasOwnProperty(code)) shift[code] = base[code];
|
|
5083
5083
|
function keyName(event) {
|
|
@@ -15018,7 +15018,7 @@ tagHighlighter([
|
|
|
15018
15018
|
]);
|
|
15019
15019
|
//#endregion
|
|
15020
15020
|
//#region ../../node_modules/.pnpm/@codemirror+language@6.11.2/node_modules/@codemirror/language/dist/index.js
|
|
15021
|
-
var _a
|
|
15021
|
+
var _a;
|
|
15022
15022
|
/**
|
|
15023
15023
|
Node prop stored in a parser's top syntax node to provide the
|
|
15024
15024
|
facet that stores language-specific data for that language.
|
|
@@ -15479,7 +15479,7 @@ if (typeof requestIdleCallback != "undefined") requestIdle = (callback) => {
|
|
|
15479
15479
|
}, 100);
|
|
15480
15480
|
return () => idle < 0 ? clearTimeout(timeout) : cancelIdleCallback(idle);
|
|
15481
15481
|
};
|
|
15482
|
-
const isInputPending = typeof navigator != "undefined" && ((_a
|
|
15482
|
+
const isInputPending = typeof navigator != "undefined" && ((_a = navigator.scheduling) === null || _a === void 0 ? void 0 : _a.isInputPending) ? () => navigator.scheduling.isInputPending() : null;
|
|
15483
15483
|
const parseWorker = /* @__PURE__ */ ViewPlugin.fromClass(class ParseWorker {
|
|
15484
15484
|
constructor(view) {
|
|
15485
15485
|
this.view = view;
|
|
@@ -19035,12 +19035,13 @@ const isBrowser = "document" in globalThis;
|
|
|
19035
19035
|
/** Throw an error with an embedded source map so that browser users can
|
|
19036
19036
|
* click on the error in the browser debug console and see the wesl source code. */
|
|
19037
19037
|
function throwClickableError(params) {
|
|
19038
|
-
const { url, text, lineNumber, lineColumn, length, error } = params;
|
|
19038
|
+
const { url, text, lineNumber, lineColumn, length, offset, error } = params;
|
|
19039
19039
|
const weslLocation = {
|
|
19040
19040
|
file: url,
|
|
19041
19041
|
line: lineNumber,
|
|
19042
19042
|
column: lineColumn,
|
|
19043
|
-
length
|
|
19043
|
+
length,
|
|
19044
|
+
offset
|
|
19044
19045
|
};
|
|
19045
19046
|
error.weslLocation = weslLocation;
|
|
19046
19047
|
if (!isBrowser) throw error;
|
|
@@ -19101,6 +19102,7 @@ function failIdentElem(identElem, msg = "") {
|
|
|
19101
19102
|
lineNumber,
|
|
19102
19103
|
lineColumn,
|
|
19103
19104
|
length: end - start,
|
|
19105
|
+
offset: start,
|
|
19104
19106
|
error: new Error(detailedMessage)
|
|
19105
19107
|
});
|
|
19106
19108
|
}
|
|
@@ -19376,7 +19378,7 @@ function lowerAndEmitElem(e, ctx) {
|
|
|
19376
19378
|
case "let":
|
|
19377
19379
|
case "statement":
|
|
19378
19380
|
case "continuing":
|
|
19379
|
-
emitStatement
|
|
19381
|
+
emitStatement(e, ctx);
|
|
19380
19382
|
return;
|
|
19381
19383
|
case "override":
|
|
19382
19384
|
case "const":
|
|
@@ -19414,7 +19416,7 @@ function emitModule(e, ctx) {
|
|
|
19414
19416
|
lowerAndEmitElem(child, ctx);
|
|
19415
19417
|
}
|
|
19416
19418
|
}
|
|
19417
|
-
function emitStatement
|
|
19419
|
+
function emitStatement(e, ctx) {
|
|
19418
19420
|
if (!(e.contents.length > 0 && e.contents[0].kind === "attribute")) emitAttributes(e.attributes, ctx);
|
|
19419
19421
|
emitContents(e, ctx);
|
|
19420
19422
|
}
|
|
@@ -22045,9 +22047,8 @@ function flatImports(ast, conditions) {
|
|
|
22045
22047
|
//#region ../wesl/src/BindIdents.ts
|
|
22046
22048
|
/** Bind ref idents to declarations and mangle global declaration names. */
|
|
22047
22049
|
function bindIdents(params) {
|
|
22048
|
-
const { rootAst, resolver, virtuals, accumulateUnbound } = params;
|
|
22050
|
+
const { rootAst, resolver, virtuals, accumulateUnbound, discoveryMode } = params;
|
|
22049
22051
|
const { conditions = {}, mangler = minimalMangle } = params;
|
|
22050
|
-
const { discoveryMode } = params;
|
|
22051
22052
|
const packageName = rootAst.srcModule.modulePath.split("::")[0];
|
|
22052
22053
|
const rootDecls = discoveryMode ? findAllRootDecls(rootAst.rootScope) : findValidRootDecls(rootAst.rootScope, conditions);
|
|
22053
22054
|
const { globalNames, knownDecls } = initRootDecls(rootDecls);
|
|
@@ -22058,6 +22059,7 @@ function bindIdents(params) {
|
|
|
22058
22059
|
virtuals,
|
|
22059
22060
|
mangler,
|
|
22060
22061
|
packageName,
|
|
22062
|
+
rootModulePath: rootAst.srcModule.modulePath,
|
|
22061
22063
|
foundScopes: /* @__PURE__ */ new Set(),
|
|
22062
22064
|
globalNames,
|
|
22063
22065
|
globalStatements: /* @__PURE__ */ new Map(),
|
|
@@ -22068,8 +22070,9 @@ function bindIdents(params) {
|
|
|
22068
22070
|
decls: new Map(rootDecls.map((d) => [d.originalName, d])),
|
|
22069
22071
|
parent: null
|
|
22070
22072
|
};
|
|
22071
|
-
const fromRootDecls = rootDecls.flatMap((
|
|
22072
|
-
const
|
|
22073
|
+
const fromRootDecls = rootDecls.flatMap((d) => processDependentScope(d, bindContext));
|
|
22074
|
+
const { rootScope } = rootAst;
|
|
22075
|
+
const fromRefs = bindIdentsRecursive(rootScope, bindContext, liveDecls);
|
|
22073
22076
|
const newStatements = [...bindContext.globalStatements.values()];
|
|
22074
22077
|
return {
|
|
22075
22078
|
decls: [...fromRootDecls, ...fromRefs],
|
|
@@ -22114,11 +22117,7 @@ function findAllRootDecls(rootScope) {
|
|
|
22114
22117
|
function publicDecl(scope, name, conditions) {
|
|
22115
22118
|
return getValidRootDecls(scope, conditions).find((d) => d.originalName === name);
|
|
22116
22119
|
}
|
|
22117
|
-
/**
|
|
22118
|
-
* Recursively bind references to declarations in this scope and child scopes.
|
|
22119
|
-
* Tracks @else state to ensure filtered @else blocks don't pull in unused declarations.
|
|
22120
|
-
* @return new declarations found
|
|
22121
|
-
*/
|
|
22120
|
+
/** Recursively bind refs to decls in this scope and children. @return new declarations found */
|
|
22122
22121
|
function bindIdentsRecursive(scope, bindContext, liveDecls) {
|
|
22123
22122
|
const { dontFollowDecls, foundScopes } = bindContext;
|
|
22124
22123
|
if (foundScopes.has(scope)) return [];
|
|
@@ -22156,11 +22155,7 @@ function processDependentScope(decl, ctx) {
|
|
|
22156
22155
|
if (!rootDecls) return [];
|
|
22157
22156
|
return bindIdentsRecursive(dependentScope, ctx, makeLiveDecls(rootDecls));
|
|
22158
22157
|
}
|
|
22159
|
-
/**
|
|
22160
|
-
* Trace references to their declarations.
|
|
22161
|
-
* Mutates to mangle declarations and mark std references.
|
|
22162
|
-
* @return found declaration, or undefined if already processed
|
|
22163
|
-
*/
|
|
22158
|
+
/** Resolve a ref to its declaration, mangling globals and marking std refs. */
|
|
22164
22159
|
function handleRef(ident, liveDecls, bindContext) {
|
|
22165
22160
|
if (ident.refersTo || ident.std) return;
|
|
22166
22161
|
if (ident.conditionRef) return;
|
|
@@ -22240,7 +22235,8 @@ function findExport(pathParts, srcModule, ctx) {
|
|
|
22240
22235
|
const modulePath = resolveModulePath(pathParts, srcModule.modulePath.split("::")).slice(0, -1).join("::");
|
|
22241
22236
|
const moduleAst = ctx.resolver.resolveModule(modulePath) ?? virtualModule(pathParts[0], ctx);
|
|
22242
22237
|
if (!moduleAst) return void 0;
|
|
22243
|
-
const
|
|
22238
|
+
const name = last(pathParts);
|
|
22239
|
+
const decl = publicDecl(moduleAst.rootScope, name, ctx.conditions);
|
|
22244
22240
|
if (decl) return {
|
|
22245
22241
|
decl,
|
|
22246
22242
|
moduleAst
|
|
@@ -22251,9 +22247,14 @@ function virtualModule(moduleName, ctx) {
|
|
|
22251
22247
|
const found = ctx.virtuals?.[moduleName];
|
|
22252
22248
|
if (!found) return void 0;
|
|
22253
22249
|
if (found.ast) return found.ast;
|
|
22254
|
-
const
|
|
22250
|
+
const { conditions, rootModulePath, packageName } = ctx;
|
|
22251
|
+
const src = found.fn({
|
|
22252
|
+
conditions,
|
|
22253
|
+
rootModulePath,
|
|
22254
|
+
packageName
|
|
22255
|
+
});
|
|
22255
22256
|
found.ast = parseSrcModule({
|
|
22256
|
-
modulePath:
|
|
22257
|
+
modulePath: packageName + "::" + moduleName,
|
|
22257
22258
|
debugFilePath: moduleName,
|
|
22258
22259
|
src
|
|
22259
22260
|
});
|
|
@@ -22273,8 +22274,8 @@ function rootLiveDecls(decl, conditions) {
|
|
|
22273
22274
|
assertThatDebug(scope.kind === "scope");
|
|
22274
22275
|
const root = scope;
|
|
22275
22276
|
if (!root._scopeDecls) {
|
|
22276
|
-
const
|
|
22277
|
-
root._scopeDecls = { decls: new Map(
|
|
22277
|
+
const decls = findValidRootDecls(scope, conditions);
|
|
22278
|
+
root._scopeDecls = { decls: new Map(decls.map((d) => [d.originalName, d])) };
|
|
22278
22279
|
}
|
|
22279
22280
|
return root._scopeDecls;
|
|
22280
22281
|
}
|
|
@@ -22752,20 +22753,13 @@ async function link(params) {
|
|
|
22752
22753
|
}
|
|
22753
22754
|
/** linker api for benchmarking */
|
|
22754
22755
|
function _linkSync(params) {
|
|
22755
|
-
const { weslSrc, libs = [], packageName, debugWeslRoot } = params;
|
|
22756
|
-
|
|
22757
|
-
const
|
|
22758
|
-
if (resolver) resolvers.push(resolver);
|
|
22759
|
-
else if (weslSrc) resolvers.push(new RecordResolver(weslSrc, {
|
|
22756
|
+
const { weslSrc, libs = [], packageName, debugWeslRoot, resolver } = params;
|
|
22757
|
+
if (!resolver && !weslSrc) throw new Error("Either resolver or weslSrc must be provided");
|
|
22758
|
+
const allResolvers = [resolver ?? new RecordResolver(weslSrc, {
|
|
22760
22759
|
packageName,
|
|
22761
22760
|
debugWeslRoot
|
|
22762
|
-
}));
|
|
22763
|
-
|
|
22764
|
-
if (libs.length > 0) {
|
|
22765
|
-
const libResolvers = createLibraryResolvers(libs, debugWeslRoot);
|
|
22766
|
-
resolvers.push(...libResolvers);
|
|
22767
|
-
}
|
|
22768
|
-
const finalResolver = resolvers.length === 1 ? resolvers[0] : new CompositeResolver(resolvers);
|
|
22761
|
+
}), ...createLibraryResolvers(libs, debugWeslRoot)];
|
|
22762
|
+
const finalResolver = allResolvers.length === 1 ? allResolvers[0] : new CompositeResolver(allResolvers);
|
|
22769
22763
|
return linkRegistry({
|
|
22770
22764
|
...params,
|
|
22771
22765
|
resolver: finalResolver
|
|
@@ -22799,8 +22793,9 @@ function flattenLibraryTree(libs) {
|
|
|
22799
22793
|
* that share some sources.)
|
|
22800
22794
|
*/
|
|
22801
22795
|
function linkRegistry(params) {
|
|
22802
|
-
const { transformedAst, newDecls, newStatements } = bindAndTransform(params);
|
|
22803
|
-
|
|
22796
|
+
const { transformedAst: ast, newDecls, newStatements } = bindAndTransform(params);
|
|
22797
|
+
const builders = emitWgsl(ast.moduleElem, ast.srcModule, newDecls, newStatements, params.conditions);
|
|
22798
|
+
return SrcMapBuilder.build(builders);
|
|
22804
22799
|
}
|
|
22805
22800
|
/** Bind identifiers and apply transform plugins */
|
|
22806
22801
|
function bindAndTransform(params) {
|
|
@@ -22848,6 +22843,7 @@ function setupVirtualLibs(virtualLibs, constants) {
|
|
|
22848
22843
|
}
|
|
22849
22844
|
return libs && mapValues(libs, (fn) => ({ fn }));
|
|
22850
22845
|
}
|
|
22846
|
+
/** Run registered transform plugins over the bound AST. */
|
|
22851
22847
|
function applyTransformPlugins(rootModule, globalNames, config) {
|
|
22852
22848
|
const { moduleElem, srcModule } = rootModule;
|
|
22853
22849
|
const startAst = {
|
|
@@ -22858,54 +22854,40 @@ function applyTransformPlugins(rootModule, globalNames, config) {
|
|
|
22858
22854
|
};
|
|
22859
22855
|
return filterMap(config?.plugins ?? [], (plugin) => plugin.transform).reduce((ast, transform) => transform(ast), startAst);
|
|
22860
22856
|
}
|
|
22857
|
+
/** Assemble WGSL output from prologue statements, root module, and imported declarations. */
|
|
22861
22858
|
function emitWgsl(rootModuleElem, srcModule, newDecls, newStatements, conditions = {}) {
|
|
22862
|
-
const prologueBuilders = newStatements.map((s) =>
|
|
22863
|
-
const rootBuilder =
|
|
22864
|
-
text: srcModule.src,
|
|
22865
|
-
path: srcModule.debugFilePath
|
|
22866
|
-
});
|
|
22859
|
+
const prologueBuilders = newStatements.map((s) => emitElem(s.srcModule, s.elem, conditions, { addNl: true }));
|
|
22860
|
+
const rootBuilder = builderFromModule(srcModule);
|
|
22867
22861
|
lowerAndEmit({
|
|
22868
22862
|
srcBuilder: rootBuilder,
|
|
22869
22863
|
rootElems: [rootModuleElem],
|
|
22870
22864
|
conditions,
|
|
22871
22865
|
extracting: false
|
|
22872
22866
|
});
|
|
22873
|
-
const declBuilders = newDecls.map((decl) =>
|
|
22867
|
+
const declBuilders = newDecls.map((decl) => emitElem(decl.srcModule, decl.declElem, conditions, { skipConditionalFiltering: true }));
|
|
22874
22868
|
return [
|
|
22875
22869
|
...prologueBuilders,
|
|
22876
22870
|
rootBuilder,
|
|
22877
22871
|
...declBuilders
|
|
22878
22872
|
];
|
|
22879
22873
|
}
|
|
22880
|
-
|
|
22881
|
-
|
|
22882
|
-
const
|
|
22883
|
-
const builder = new SrcMapBuilder({
|
|
22884
|
-
text,
|
|
22885
|
-
path
|
|
22886
|
-
});
|
|
22874
|
+
/** Emit a single element (prologue statement or imported declaration) into a SrcMapBuilder. */
|
|
22875
|
+
function emitElem(srcModule, elem, conditions, opts = {}) {
|
|
22876
|
+
const builder = builderFromModule(srcModule);
|
|
22887
22877
|
lowerAndEmit({
|
|
22888
22878
|
srcBuilder: builder,
|
|
22889
22879
|
rootElems: [elem],
|
|
22890
|
-
conditions
|
|
22880
|
+
conditions,
|
|
22881
|
+
skipConditionalFiltering: opts.skipConditionalFiltering
|
|
22891
22882
|
});
|
|
22892
|
-
builder.addNl();
|
|
22883
|
+
if (opts.addNl) builder.addNl();
|
|
22893
22884
|
return builder;
|
|
22894
22885
|
}
|
|
22895
|
-
|
|
22896
|
-
|
|
22897
|
-
|
|
22898
|
-
|
|
22899
|
-
text,
|
|
22900
|
-
path
|
|
22901
|
-
});
|
|
22902
|
-
lowerAndEmit({
|
|
22903
|
-
srcBuilder: builder,
|
|
22904
|
-
rootElems: [decl.declElem],
|
|
22905
|
-
conditions,
|
|
22906
|
-
skipConditionalFiltering: true
|
|
22886
|
+
function builderFromModule(srcModule) {
|
|
22887
|
+
return new SrcMapBuilder({
|
|
22888
|
+
text: srcModule.src,
|
|
22889
|
+
path: srcModule.debugFilePath
|
|
22907
22890
|
});
|
|
22908
|
-
return builder;
|
|
22909
22891
|
}
|
|
22910
22892
|
matchOneOf(textureStorageTypes);
|
|
22911
22893
|
matchOneOf(sampledTextureTypes);
|
|
@@ -27393,338 +27375,6 @@ async function hydrateBundle(path, registry, hydrated, fetcher) {
|
|
|
27393
27375
|
return placeholder;
|
|
27394
27376
|
}
|
|
27395
27377
|
//#endregion
|
|
27396
|
-
//#region ../../node_modules/.pnpm/fflate@0.8.2/node_modules/fflate/esm/browser.js
|
|
27397
|
-
var u8 = Uint8Array, u16 = Uint16Array, i32 = Int32Array;
|
|
27398
|
-
var fleb = new u8([
|
|
27399
|
-
0,
|
|
27400
|
-
0,
|
|
27401
|
-
0,
|
|
27402
|
-
0,
|
|
27403
|
-
0,
|
|
27404
|
-
0,
|
|
27405
|
-
0,
|
|
27406
|
-
0,
|
|
27407
|
-
1,
|
|
27408
|
-
1,
|
|
27409
|
-
1,
|
|
27410
|
-
1,
|
|
27411
|
-
2,
|
|
27412
|
-
2,
|
|
27413
|
-
2,
|
|
27414
|
-
2,
|
|
27415
|
-
3,
|
|
27416
|
-
3,
|
|
27417
|
-
3,
|
|
27418
|
-
3,
|
|
27419
|
-
4,
|
|
27420
|
-
4,
|
|
27421
|
-
4,
|
|
27422
|
-
4,
|
|
27423
|
-
5,
|
|
27424
|
-
5,
|
|
27425
|
-
5,
|
|
27426
|
-
5,
|
|
27427
|
-
0,
|
|
27428
|
-
0,
|
|
27429
|
-
0,
|
|
27430
|
-
0
|
|
27431
|
-
]);
|
|
27432
|
-
var fdeb = new u8([
|
|
27433
|
-
0,
|
|
27434
|
-
0,
|
|
27435
|
-
0,
|
|
27436
|
-
0,
|
|
27437
|
-
1,
|
|
27438
|
-
1,
|
|
27439
|
-
2,
|
|
27440
|
-
2,
|
|
27441
|
-
3,
|
|
27442
|
-
3,
|
|
27443
|
-
4,
|
|
27444
|
-
4,
|
|
27445
|
-
5,
|
|
27446
|
-
5,
|
|
27447
|
-
6,
|
|
27448
|
-
6,
|
|
27449
|
-
7,
|
|
27450
|
-
7,
|
|
27451
|
-
8,
|
|
27452
|
-
8,
|
|
27453
|
-
9,
|
|
27454
|
-
9,
|
|
27455
|
-
10,
|
|
27456
|
-
10,
|
|
27457
|
-
11,
|
|
27458
|
-
11,
|
|
27459
|
-
12,
|
|
27460
|
-
12,
|
|
27461
|
-
13,
|
|
27462
|
-
13,
|
|
27463
|
-
0,
|
|
27464
|
-
0
|
|
27465
|
-
]);
|
|
27466
|
-
var clim = new u8([
|
|
27467
|
-
16,
|
|
27468
|
-
17,
|
|
27469
|
-
18,
|
|
27470
|
-
0,
|
|
27471
|
-
8,
|
|
27472
|
-
7,
|
|
27473
|
-
9,
|
|
27474
|
-
6,
|
|
27475
|
-
10,
|
|
27476
|
-
5,
|
|
27477
|
-
11,
|
|
27478
|
-
4,
|
|
27479
|
-
12,
|
|
27480
|
-
3,
|
|
27481
|
-
13,
|
|
27482
|
-
2,
|
|
27483
|
-
14,
|
|
27484
|
-
1,
|
|
27485
|
-
15
|
|
27486
|
-
]);
|
|
27487
|
-
var freb = function(eb, start) {
|
|
27488
|
-
var b = new u16(31);
|
|
27489
|
-
for (var i = 0; i < 31; ++i) b[i] = start += 1 << eb[i - 1];
|
|
27490
|
-
var r = new i32(b[30]);
|
|
27491
|
-
for (var i = 1; i < 30; ++i) for (var j = b[i]; j < b[i + 1]; ++j) r[j] = j - b[i] << 5 | i;
|
|
27492
|
-
return {
|
|
27493
|
-
b,
|
|
27494
|
-
r
|
|
27495
|
-
};
|
|
27496
|
-
};
|
|
27497
|
-
var _a = freb(fleb, 2), fl = _a.b, revfl = _a.r;
|
|
27498
|
-
fl[28] = 258, revfl[258] = 28;
|
|
27499
|
-
var _b = freb(fdeb, 0), fd = _b.b;
|
|
27500
|
-
_b.r;
|
|
27501
|
-
var rev = new u16(32768);
|
|
27502
|
-
for (var i = 0; i < 32768; ++i) {
|
|
27503
|
-
var x = (i & 43690) >> 1 | (i & 21845) << 1;
|
|
27504
|
-
x = (x & 52428) >> 2 | (x & 13107) << 2;
|
|
27505
|
-
x = (x & 61680) >> 4 | (x & 3855) << 4;
|
|
27506
|
-
rev[i] = ((x & 65280) >> 8 | (x & 255) << 8) >> 1;
|
|
27507
|
-
}
|
|
27508
|
-
var hMap = (function(cd, mb, r) {
|
|
27509
|
-
var s = cd.length;
|
|
27510
|
-
var i = 0;
|
|
27511
|
-
var l = new u16(mb);
|
|
27512
|
-
for (; i < s; ++i) if (cd[i]) ++l[cd[i] - 1];
|
|
27513
|
-
var le = new u16(mb);
|
|
27514
|
-
for (i = 1; i < mb; ++i) le[i] = le[i - 1] + l[i - 1] << 1;
|
|
27515
|
-
var co;
|
|
27516
|
-
if (r) {
|
|
27517
|
-
co = new u16(1 << mb);
|
|
27518
|
-
var rvb = 15 - mb;
|
|
27519
|
-
for (i = 0; i < s; ++i) if (cd[i]) {
|
|
27520
|
-
var sv = i << 4 | cd[i];
|
|
27521
|
-
var r_1 = mb - cd[i];
|
|
27522
|
-
var v = le[cd[i] - 1]++ << r_1;
|
|
27523
|
-
for (var m = v | (1 << r_1) - 1; v <= m; ++v) co[rev[v] >> rvb] = sv;
|
|
27524
|
-
}
|
|
27525
|
-
} else {
|
|
27526
|
-
co = new u16(s);
|
|
27527
|
-
for (i = 0; i < s; ++i) if (cd[i]) co[i] = rev[le[cd[i] - 1]++] >> 15 - cd[i];
|
|
27528
|
-
}
|
|
27529
|
-
return co;
|
|
27530
|
-
});
|
|
27531
|
-
var flt = new u8(288);
|
|
27532
|
-
for (var i = 0; i < 144; ++i) flt[i] = 8;
|
|
27533
|
-
for (var i = 144; i < 256; ++i) flt[i] = 9;
|
|
27534
|
-
for (var i = 256; i < 280; ++i) flt[i] = 7;
|
|
27535
|
-
for (var i = 280; i < 288; ++i) flt[i] = 8;
|
|
27536
|
-
var fdt = new u8(32);
|
|
27537
|
-
for (var i = 0; i < 32; ++i) fdt[i] = 5;
|
|
27538
|
-
var flrm = /* @__PURE__ */ hMap(flt, 9, 1), fdrm = /* @__PURE__ */ hMap(fdt, 5, 1);
|
|
27539
|
-
var max = function(a) {
|
|
27540
|
-
var m = a[0];
|
|
27541
|
-
for (var i = 1; i < a.length; ++i) if (a[i] > m) m = a[i];
|
|
27542
|
-
return m;
|
|
27543
|
-
};
|
|
27544
|
-
var bits = function(d, p, m) {
|
|
27545
|
-
var o = p / 8 | 0;
|
|
27546
|
-
return (d[o] | d[o + 1] << 8) >> (p & 7) & m;
|
|
27547
|
-
};
|
|
27548
|
-
var bits16 = function(d, p) {
|
|
27549
|
-
var o = p / 8 | 0;
|
|
27550
|
-
return (d[o] | d[o + 1] << 8 | d[o + 2] << 16) >> (p & 7);
|
|
27551
|
-
};
|
|
27552
|
-
var shft = function(p) {
|
|
27553
|
-
return (p + 7) / 8 | 0;
|
|
27554
|
-
};
|
|
27555
|
-
var slc = function(v, s, e) {
|
|
27556
|
-
if (s == null || s < 0) s = 0;
|
|
27557
|
-
if (e == null || e > v.length) e = v.length;
|
|
27558
|
-
return new u8(v.subarray(s, e));
|
|
27559
|
-
};
|
|
27560
|
-
var ec = [
|
|
27561
|
-
"unexpected EOF",
|
|
27562
|
-
"invalid block type",
|
|
27563
|
-
"invalid length/literal",
|
|
27564
|
-
"invalid distance",
|
|
27565
|
-
"stream finished",
|
|
27566
|
-
"no stream handler",
|
|
27567
|
-
,
|
|
27568
|
-
"no callback",
|
|
27569
|
-
"invalid UTF-8 data",
|
|
27570
|
-
"extra field too long",
|
|
27571
|
-
"date not in range 1980-2099",
|
|
27572
|
-
"filename too long",
|
|
27573
|
-
"stream finishing",
|
|
27574
|
-
"invalid zip data"
|
|
27575
|
-
];
|
|
27576
|
-
var err = function(ind, msg, nt) {
|
|
27577
|
-
var e = new Error(msg || ec[ind]);
|
|
27578
|
-
e.code = ind;
|
|
27579
|
-
if (Error.captureStackTrace) Error.captureStackTrace(e, err);
|
|
27580
|
-
if (!nt) throw e;
|
|
27581
|
-
return e;
|
|
27582
|
-
};
|
|
27583
|
-
var inflt = function(dat, st, buf, dict) {
|
|
27584
|
-
var sl = dat.length, dl = dict ? dict.length : 0;
|
|
27585
|
-
if (!sl || st.f && !st.l) return buf || new u8(0);
|
|
27586
|
-
var noBuf = !buf;
|
|
27587
|
-
var resize = noBuf || st.i != 2;
|
|
27588
|
-
var noSt = st.i;
|
|
27589
|
-
if (noBuf) buf = new u8(sl * 3);
|
|
27590
|
-
var cbuf = function(l) {
|
|
27591
|
-
var bl = buf.length;
|
|
27592
|
-
if (l > bl) {
|
|
27593
|
-
var nbuf = new u8(Math.max(bl * 2, l));
|
|
27594
|
-
nbuf.set(buf);
|
|
27595
|
-
buf = nbuf;
|
|
27596
|
-
}
|
|
27597
|
-
};
|
|
27598
|
-
var final = st.f || 0, pos = st.p || 0, bt = st.b || 0, lm = st.l, dm = st.d, lbt = st.m, dbt = st.n;
|
|
27599
|
-
var tbts = sl * 8;
|
|
27600
|
-
do {
|
|
27601
|
-
if (!lm) {
|
|
27602
|
-
final = bits(dat, pos, 1);
|
|
27603
|
-
var type = bits(dat, pos + 1, 3);
|
|
27604
|
-
pos += 3;
|
|
27605
|
-
if (!type) {
|
|
27606
|
-
var s = shft(pos) + 4, l = dat[s - 4] | dat[s - 3] << 8, t = s + l;
|
|
27607
|
-
if (t > sl) {
|
|
27608
|
-
if (noSt) err(0);
|
|
27609
|
-
break;
|
|
27610
|
-
}
|
|
27611
|
-
if (resize) cbuf(bt + l);
|
|
27612
|
-
buf.set(dat.subarray(s, t), bt);
|
|
27613
|
-
st.b = bt += l, st.p = pos = t * 8, st.f = final;
|
|
27614
|
-
continue;
|
|
27615
|
-
} else if (type == 1) lm = flrm, dm = fdrm, lbt = 9, dbt = 5;
|
|
27616
|
-
else if (type == 2) {
|
|
27617
|
-
var hLit = bits(dat, pos, 31) + 257, hcLen = bits(dat, pos + 10, 15) + 4;
|
|
27618
|
-
var tl = hLit + bits(dat, pos + 5, 31) + 1;
|
|
27619
|
-
pos += 14;
|
|
27620
|
-
var ldt = new u8(tl);
|
|
27621
|
-
var clt = new u8(19);
|
|
27622
|
-
for (var i = 0; i < hcLen; ++i) clt[clim[i]] = bits(dat, pos + i * 3, 7);
|
|
27623
|
-
pos += hcLen * 3;
|
|
27624
|
-
var clb = max(clt), clbmsk = (1 << clb) - 1;
|
|
27625
|
-
var clm = hMap(clt, clb, 1);
|
|
27626
|
-
for (var i = 0; i < tl;) {
|
|
27627
|
-
var r = clm[bits(dat, pos, clbmsk)];
|
|
27628
|
-
pos += r & 15;
|
|
27629
|
-
var s = r >> 4;
|
|
27630
|
-
if (s < 16) ldt[i++] = s;
|
|
27631
|
-
else {
|
|
27632
|
-
var c = 0, n = 0;
|
|
27633
|
-
if (s == 16) n = 3 + bits(dat, pos, 3), pos += 2, c = ldt[i - 1];
|
|
27634
|
-
else if (s == 17) n = 3 + bits(dat, pos, 7), pos += 3;
|
|
27635
|
-
else if (s == 18) n = 11 + bits(dat, pos, 127), pos += 7;
|
|
27636
|
-
while (n--) ldt[i++] = c;
|
|
27637
|
-
}
|
|
27638
|
-
}
|
|
27639
|
-
var lt = ldt.subarray(0, hLit), dt = ldt.subarray(hLit);
|
|
27640
|
-
lbt = max(lt);
|
|
27641
|
-
dbt = max(dt);
|
|
27642
|
-
lm = hMap(lt, lbt, 1);
|
|
27643
|
-
dm = hMap(dt, dbt, 1);
|
|
27644
|
-
} else err(1);
|
|
27645
|
-
if (pos > tbts) {
|
|
27646
|
-
if (noSt) err(0);
|
|
27647
|
-
break;
|
|
27648
|
-
}
|
|
27649
|
-
}
|
|
27650
|
-
if (resize) cbuf(bt + 131072);
|
|
27651
|
-
var lms = (1 << lbt) - 1, dms = (1 << dbt) - 1;
|
|
27652
|
-
var lpos = pos;
|
|
27653
|
-
for (;; lpos = pos) {
|
|
27654
|
-
var c = lm[bits16(dat, pos) & lms], sym = c >> 4;
|
|
27655
|
-
pos += c & 15;
|
|
27656
|
-
if (pos > tbts) {
|
|
27657
|
-
if (noSt) err(0);
|
|
27658
|
-
break;
|
|
27659
|
-
}
|
|
27660
|
-
if (!c) err(2);
|
|
27661
|
-
if (sym < 256) buf[bt++] = sym;
|
|
27662
|
-
else if (sym == 256) {
|
|
27663
|
-
lpos = pos, lm = null;
|
|
27664
|
-
break;
|
|
27665
|
-
} else {
|
|
27666
|
-
var add = sym - 254;
|
|
27667
|
-
if (sym > 264) {
|
|
27668
|
-
var i = sym - 257, b = fleb[i];
|
|
27669
|
-
add = bits(dat, pos, (1 << b) - 1) + fl[i];
|
|
27670
|
-
pos += b;
|
|
27671
|
-
}
|
|
27672
|
-
var d = dm[bits16(dat, pos) & dms], dsym = d >> 4;
|
|
27673
|
-
if (!d) err(3);
|
|
27674
|
-
pos += d & 15;
|
|
27675
|
-
var dt = fd[dsym];
|
|
27676
|
-
if (dsym > 3) {
|
|
27677
|
-
var b = fdeb[dsym];
|
|
27678
|
-
dt += bits16(dat, pos) & (1 << b) - 1, pos += b;
|
|
27679
|
-
}
|
|
27680
|
-
if (pos > tbts) {
|
|
27681
|
-
if (noSt) err(0);
|
|
27682
|
-
break;
|
|
27683
|
-
}
|
|
27684
|
-
if (resize) cbuf(bt + 131072);
|
|
27685
|
-
var end = bt + add;
|
|
27686
|
-
if (bt < dt) {
|
|
27687
|
-
var shift = dl - dt, dend = Math.min(dt, end);
|
|
27688
|
-
if (shift + bt < 0) err(3);
|
|
27689
|
-
for (; bt < dend; ++bt) buf[bt] = dict[shift + bt];
|
|
27690
|
-
}
|
|
27691
|
-
for (; bt < end; ++bt) buf[bt] = buf[bt - dt];
|
|
27692
|
-
}
|
|
27693
|
-
}
|
|
27694
|
-
st.l = lm, st.p = lpos, st.b = bt, st.f = final;
|
|
27695
|
-
if (lm) final = 1, st.m = lbt, st.d = dm, st.n = dbt;
|
|
27696
|
-
} while (!final);
|
|
27697
|
-
return bt != buf.length && noBuf ? slc(buf, 0, bt) : buf.subarray(0, bt);
|
|
27698
|
-
};
|
|
27699
|
-
var et = /* @__PURE__ */ new u8(0);
|
|
27700
|
-
var gzs = function(d) {
|
|
27701
|
-
if (d[0] != 31 || d[1] != 139 || d[2] != 8) err(6, "invalid gzip data");
|
|
27702
|
-
var flg = d[3];
|
|
27703
|
-
var st = 10;
|
|
27704
|
-
if (flg & 4) st += (d[10] | d[11] << 8) + 2;
|
|
27705
|
-
for (var zs = (flg >> 3 & 1) + (flg >> 4 & 1); zs > 0; zs -= !d[st++]);
|
|
27706
|
-
return st + (flg & 2);
|
|
27707
|
-
};
|
|
27708
|
-
var gzl = function(d) {
|
|
27709
|
-
var l = d.length;
|
|
27710
|
-
return (d[l - 4] | d[l - 3] << 8 | d[l - 2] << 16 | d[l - 1] << 24) >>> 0;
|
|
27711
|
-
};
|
|
27712
|
-
/**
|
|
27713
|
-
* Expands GZIP data
|
|
27714
|
-
* @param data The data to decompress
|
|
27715
|
-
* @param opts The decompression options
|
|
27716
|
-
* @returns The decompressed version of the data
|
|
27717
|
-
*/
|
|
27718
|
-
function gunzipSync(data, opts) {
|
|
27719
|
-
var st = gzs(data);
|
|
27720
|
-
if (st + 8 > data.length) err(6, "invalid gzip data");
|
|
27721
|
-
return inflt(data.subarray(st, -8), { i: 2 }, opts && opts.out || new u8(gzl(data)), opts && opts.dictionary);
|
|
27722
|
-
}
|
|
27723
|
-
var td = typeof TextDecoder != "undefined" && /* @__PURE__ */ new TextDecoder();
|
|
27724
|
-
try {
|
|
27725
|
-
td.decode(et, { stream: true });
|
|
27726
|
-
} catch (e) {}
|
|
27727
|
-
//#endregion
|
|
27728
27378
|
//#region ../../node_modules/.pnpm/nanotar@0.2.0/node_modules/nanotar/dist/index.mjs
|
|
27729
27379
|
const TAR_TYPE_FILE = 0;
|
|
27730
27380
|
const TAR_TYPE_DIR = 5;
|
|
@@ -27776,6 +27426,13 @@ function parseTar(data, opts) {
|
|
|
27776
27426
|
}
|
|
27777
27427
|
return files;
|
|
27778
27428
|
}
|
|
27429
|
+
async function parseTarGzip(data, opts = {}) {
|
|
27430
|
+
const stream = new ReadableStream({ start(controller) {
|
|
27431
|
+
controller.enqueue(new Uint8Array(data));
|
|
27432
|
+
controller.close();
|
|
27433
|
+
} }).pipeThrough(new DecompressionStream(opts.compression ?? "gzip"));
|
|
27434
|
+
return parseTar(await new Response(stream).arrayBuffer(), opts);
|
|
27435
|
+
}
|
|
27779
27436
|
function _readString(buffer, offset, size) {
|
|
27780
27437
|
const view = new Uint8Array(buffer, offset, size);
|
|
27781
27438
|
const i = view.indexOf(0);
|
|
@@ -27812,7 +27469,7 @@ function memoAsync(fn) {
|
|
|
27812
27469
|
async function fetchAndExtractTgzRaw(tgzUrl) {
|
|
27813
27470
|
const response = await fetch(tgzUrl);
|
|
27814
27471
|
if (!response.ok) throw new Error(`Failed to fetch package: HTTP ${response.status}`);
|
|
27815
|
-
return
|
|
27472
|
+
return parseTarGzip(new Uint8Array(await response.arrayBuffer()));
|
|
27816
27473
|
}
|
|
27817
27474
|
async function npmPackageToUrlRaw(packageName) {
|
|
27818
27475
|
const metadataUrl = `https://registry.npmjs.org/${packageName}`;
|
|
@@ -27879,6 +27536,10 @@ async function fetchOnePackage(pkgId, loaded) {
|
|
|
27879
27536
|
throw new Error(`Package not found: ${pkgId}`);
|
|
27880
27537
|
}
|
|
27881
27538
|
//#endregion
|
|
27539
|
+
//#region src/SaveEndpoint.ts
|
|
27540
|
+
/** Shared between client (WgslEdit) and server (SaveMiddleware) so they can't drift. */
|
|
27541
|
+
const saveEndpoint = "/__wgsl-edit/save";
|
|
27542
|
+
//#endregion
|
|
27882
27543
|
//#region src/WgslEdit.css?inline
|
|
27883
27544
|
var WgslEdit_default = ":host {\n --tab-bar-bg: transparent;\n --tab-border: #ccc;\n --tab-color: #999;\n --tab-active-bg: #fff;\n --tab-active-color: #222;\n --tab-accent: #5f61d8;\n\n display: flex;\n flex-direction: column;\n position: relative;\n min-height: 100px;\n}\n\n:host(.dark) {\n --tab-bar-bg: transparent;\n --tab-border: #555;\n --tab-color: #999;\n --tab-active-bg: #1e1e1e;\n --tab-active-color: #fff;\n}\n\n.tab-bar {\n --bar-v: 6px;\n --bar-h: 8px;\n display: flex;\n align-items: center;\n gap: 14px;\n padding: var(--bar-v) var(--bar-h);\n background: var(--tab-bar-bg);\n flex-shrink: 0;\n position: relative;\n}\n\n.tab-bar::after {\n content: \"\";\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 1px;\n background: var(--tab-border);\n}\n\n.tab {\n --tab-v: 5px;\n --tab-h: 12px;\n display: flex;\n align-items: center;\n gap: 16px;\n padding: var(--tab-v) var(--tab-h);\n background: transparent;\n border: none;\n border-radius: 0;\n color: var(--tab-color);\n cursor: pointer;\n position: relative;\n font-size: 15px;\n font-family: system-ui, sans-serif;\n}\n\n.tab.active {\n color: var(--tab-accent);\n font-weight: 600;\n padding-bottom: calc(var(--tab-v) + var(--bar-v) + 0.5px);\n margin-bottom: calc(-1 * (var(--bar-v) + 0.5px));\n position: relative;\n z-index: 1;\n border-bottom: 2px solid var(--tab-accent);\n}\n\n.tab.active:first-child {\n margin-left: calc(-1 * var(--bar-h));\n padding-left: calc(var(--tab-h) + var(--bar-h));\n}\n\n.tab-close {\n position: absolute;\n right: -8px;\n /* top: 2px; */\n width: 16px;\n height: 16px;\n padding: 0;\n border: none;\n background: transparent;\n color: inherit;\n cursor: pointer;\n opacity: 0;\n font-size: 18px;\n line-height: 1;\n}\n\n.tab:hover .tab-close {\n opacity: 0.6;\n}\n\n.tab-close:hover {\n opacity: 1;\n}\n\n.tab-rename {\n background: var(--tab-active-bg);\n border: 1px solid var(--tab-border);\n border-radius: 4px;\n color: var(--tab-active-color);\n font-size: 15px;\n font-family: system-ui, sans-serif;\n padding: 0 4px;\n outline: none;\n}\n\n.tab-add {\n padding: 0 10px;\n background: transparent;\n border: none;\n color: var(--tab-color);\n cursor: pointer;\n font-size: 25px;\n line-height: 1;\n}\n\n.tab-add:hover {\n color: var(--tab-active-color);\n}\n\n.editor-container {\n flex: 1;\n min-height: 0;\n width: 100%;\n padding: var(--editor-padding, 16px 0 0);\n}\n\n.cm-editor {\n height: 100%;\n font-size: var(--editor-font-size, 14px);\n}\n\n.cm-scroller {\n overflow: auto;\n}\n\n.snackbar {\n position: absolute;\n bottom: 16px;\n left: 16px;\n background: #e8e8e8;\n color: #333;\n padding: 10px 20px;\n border-radius: 8px;\n font-size: 14px;\n font-family: system-ui, sans-serif;\n line-height: 1.4;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.2s;\n z-index: 10;\n}\n\n:host(.dark) .snackbar {\n background: #3a3a3a;\n color: #e0e0e0;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);\n}\n\n.snackbar.visible {\n opacity: 1;\n}\n";
|
|
27884
27545
|
//#endregion
|
|
@@ -27917,7 +27578,8 @@ var WgslEdit = class extends HTMLElement {
|
|
|
27917
27578
|
"lint-from",
|
|
27918
27579
|
"line-numbers",
|
|
27919
27580
|
"fetch-libs",
|
|
27920
|
-
"gpu-lint"
|
|
27581
|
+
"gpu-lint",
|
|
27582
|
+
"autosave"
|
|
27921
27583
|
];
|
|
27922
27584
|
editorView = null;
|
|
27923
27585
|
editorContainer;
|
|
@@ -27946,6 +27608,10 @@ var WgslEdit = class extends HTMLElement {
|
|
|
27946
27608
|
_fetchingPkgs = /* @__PURE__ */ new Set();
|
|
27947
27609
|
_fetchedPkgs = /* @__PURE__ */ new Set();
|
|
27948
27610
|
_snackTimer;
|
|
27611
|
+
_devSaveListener = null;
|
|
27612
|
+
_saveTimer;
|
|
27613
|
+
_dirtyFiles = /* @__PURE__ */ new Set();
|
|
27614
|
+
_switchingFile = false;
|
|
27949
27615
|
_externalDiagnostics = [];
|
|
27950
27616
|
_lintFromEl = null;
|
|
27951
27617
|
/** Bound listeners for lint-from element's compile events. */
|
|
@@ -27969,10 +27635,13 @@ var WgslEdit = class extends HTMLElement {
|
|
|
27969
27635
|
connectedCallback() {
|
|
27970
27636
|
this.initEditor();
|
|
27971
27637
|
this.loadInitialContent();
|
|
27972
|
-
|
|
27973
|
-
|
|
27974
|
-
|
|
27975
|
-
|
|
27638
|
+
for (const p of [
|
|
27639
|
+
"conditions",
|
|
27640
|
+
"source",
|
|
27641
|
+
"sources",
|
|
27642
|
+
"project",
|
|
27643
|
+
"autosave"
|
|
27644
|
+
]) upgradeProperty(this, p);
|
|
27976
27645
|
}
|
|
27977
27646
|
disconnectedCallback() {
|
|
27978
27647
|
this.connectLintSource(null);
|
|
@@ -27980,25 +27649,43 @@ var WgslEdit = class extends HTMLElement {
|
|
|
27980
27649
|
this.editorView = null;
|
|
27981
27650
|
}
|
|
27982
27651
|
attributeChangedCallback(name, _old, value) {
|
|
27983
|
-
|
|
27984
|
-
|
|
27985
|
-
|
|
27986
|
-
|
|
27987
|
-
|
|
27988
|
-
|
|
27989
|
-
|
|
27990
|
-
|
|
27991
|
-
|
|
27992
|
-
|
|
27993
|
-
|
|
27994
|
-
|
|
27995
|
-
|
|
27996
|
-
|
|
27997
|
-
|
|
27998
|
-
|
|
27999
|
-
|
|
28000
|
-
|
|
28001
|
-
|
|
27652
|
+
switch (name) {
|
|
27653
|
+
case "src":
|
|
27654
|
+
if (value && this.editorView) this.loadFromUrl(value);
|
|
27655
|
+
break;
|
|
27656
|
+
case "readonly":
|
|
27657
|
+
this.updateReadonly();
|
|
27658
|
+
break;
|
|
27659
|
+
case "theme":
|
|
27660
|
+
this.theme = value || "auto";
|
|
27661
|
+
break;
|
|
27662
|
+
case "tabs":
|
|
27663
|
+
this._tabs = value !== "false";
|
|
27664
|
+
this.renderTabs();
|
|
27665
|
+
break;
|
|
27666
|
+
case "lint":
|
|
27667
|
+
this._lint = value || "on";
|
|
27668
|
+
this.updateLint();
|
|
27669
|
+
break;
|
|
27670
|
+
case "lint-from":
|
|
27671
|
+
this.connectLintSource(value);
|
|
27672
|
+
break;
|
|
27673
|
+
case "line-numbers":
|
|
27674
|
+
this._lineNumbers = value === "true";
|
|
27675
|
+
this.updateLineNumbers();
|
|
27676
|
+
break;
|
|
27677
|
+
case "fetch-libs":
|
|
27678
|
+
this._fetchLibs = value !== "false";
|
|
27679
|
+
this.updateLint();
|
|
27680
|
+
break;
|
|
27681
|
+
case "gpu-lint":
|
|
27682
|
+
this._gpuLint = value !== "off";
|
|
27683
|
+
this.updateLint();
|
|
27684
|
+
break;
|
|
27685
|
+
case "autosave":
|
|
27686
|
+
if (value !== null && value !== "false") this.enableDevSave();
|
|
27687
|
+
else this.disableDevSave();
|
|
27688
|
+
break;
|
|
28002
27689
|
}
|
|
28003
27690
|
}
|
|
28004
27691
|
/** Conditions for conditional compilation (@if/@elif/@else). */
|
|
@@ -28010,6 +27697,10 @@ var WgslEdit = class extends HTMLElement {
|
|
|
28010
27697
|
this.updateLint();
|
|
28011
27698
|
this.dispatchChange();
|
|
28012
27699
|
}
|
|
27700
|
+
/** Reconfigure a compartment via the active editor view (no-op if unmounted). */
|
|
27701
|
+
reconfigure(comp, ext) {
|
|
27702
|
+
this.editorView?.dispatch({ effects: comp.reconfigure(ext) });
|
|
27703
|
+
}
|
|
28013
27704
|
/** Active file content (single-file API). */
|
|
28014
27705
|
get source() {
|
|
28015
27706
|
return this.editorView?.state.doc.toString() ?? this._pendingSource ?? "";
|
|
@@ -28017,27 +27708,30 @@ var WgslEdit = class extends HTMLElement {
|
|
|
28017
27708
|
/** Set active file content (single-file API). Auto-creates a default file entry. */
|
|
28018
27709
|
set source(value) {
|
|
28019
27710
|
if (!this._activeFile && this._files.size === 0) {
|
|
28020
|
-
this._files.set("main.wesl", { doc:
|
|
27711
|
+
this._files.set("main.wesl", { doc: toDoc(value) });
|
|
28021
27712
|
this._activeFile = "main.wesl";
|
|
28022
27713
|
this.renderTabs();
|
|
28023
27714
|
}
|
|
28024
27715
|
if (this.editorView) {
|
|
28025
|
-
const
|
|
28026
|
-
this.editorView.dispatch({
|
|
28027
|
-
|
|
28028
|
-
|
|
28029
|
-
|
|
28030
|
-
|
|
27716
|
+
const docLength = this.editorView.state.doc.length;
|
|
27717
|
+
this.editorView.dispatch({
|
|
27718
|
+
changes: {
|
|
27719
|
+
from: 0,
|
|
27720
|
+
to: docLength,
|
|
27721
|
+
insert: value
|
|
27722
|
+
},
|
|
27723
|
+
annotations: Transaction.addToHistory.of(false)
|
|
27724
|
+
});
|
|
28031
27725
|
} else {
|
|
28032
27726
|
this._pendingSource = value;
|
|
28033
27727
|
const entry = this._files.get(this._activeFile);
|
|
28034
|
-
if (entry) entry.doc =
|
|
27728
|
+
if (entry) entry.doc = toDoc(value);
|
|
28035
27729
|
}
|
|
28036
27730
|
}
|
|
28037
27731
|
/** All file contents keyed by module path (e.g., "package::main"). */
|
|
28038
27732
|
get sources() {
|
|
28039
27733
|
this.saveCurrentFileState();
|
|
28040
|
-
const pkg = this.
|
|
27734
|
+
const pkg = this.pkgName();
|
|
28041
27735
|
const result = {};
|
|
28042
27736
|
for (const [tabName, state] of this._files) result[fileToModulePath(tabName, pkg, false)] = state.doc.toString();
|
|
28043
27737
|
return result;
|
|
@@ -28047,12 +27741,13 @@ var WgslEdit = class extends HTMLElement {
|
|
|
28047
27741
|
this._files.clear();
|
|
28048
27742
|
for (const [key, content] of Object.entries(value)) {
|
|
28049
27743
|
const tabName = toTabName(key);
|
|
28050
|
-
this._files.set(tabName, { doc:
|
|
27744
|
+
this._files.set(tabName, { doc: toDoc(content) });
|
|
28051
27745
|
}
|
|
28052
27746
|
const firstKey = Object.keys(value)[0];
|
|
28053
27747
|
if (firstKey) this.switchToFile(toTabName(firstKey));
|
|
28054
27748
|
this.renderTabs();
|
|
28055
27749
|
}
|
|
27750
|
+
/** Snapshot of all editor state needed to link: sources, conditions, libs, root module. */
|
|
28056
27751
|
get project() {
|
|
28057
27752
|
return {
|
|
28058
27753
|
weslSrc: this.sources,
|
|
@@ -28060,20 +27755,22 @@ var WgslEdit = class extends HTMLElement {
|
|
|
28060
27755
|
conditions: this._conditions,
|
|
28061
27756
|
constants: this._constants,
|
|
28062
27757
|
libs: this._libs,
|
|
28063
|
-
packageName: this._packageName
|
|
27758
|
+
packageName: this._packageName,
|
|
27759
|
+
shaderRoot: this.shaderRoot ?? void 0
|
|
28064
27760
|
};
|
|
28065
27761
|
}
|
|
28066
27762
|
set project(value) {
|
|
28067
27763
|
const { weslSrc, rootModuleName, conditions } = value;
|
|
28068
|
-
const { constants, packageName, libs } = value;
|
|
27764
|
+
const { constants, packageName, libs, shaderRoot } = value;
|
|
28069
27765
|
if (conditions !== void 0) this._conditions = conditions;
|
|
28070
27766
|
if (constants !== void 0) this._constants = constants;
|
|
28071
27767
|
if (packageName !== void 0) this._packageName = packageName;
|
|
28072
27768
|
if (libs !== void 0) this._libs = libs;
|
|
28073
27769
|
if (rootModuleName !== void 0) this._rootModuleName = rootModuleName;
|
|
27770
|
+
if (shaderRoot !== void 0 && !this.hasAttribute("shader-root")) this.shaderRoot = shaderRoot;
|
|
28074
27771
|
if (weslSrc) {
|
|
28075
27772
|
this.sources = weslSrc;
|
|
28076
|
-
const tab = toTabName(
|
|
27773
|
+
const tab = toTabName(this._rootModuleName ?? "");
|
|
28077
27774
|
if (tab) this.activeFile = tab;
|
|
28078
27775
|
}
|
|
28079
27776
|
this.updateLint();
|
|
@@ -28086,14 +27783,13 @@ var WgslEdit = class extends HTMLElement {
|
|
|
28086
27783
|
})).dest;
|
|
28087
27784
|
}
|
|
28088
27785
|
linkParams() {
|
|
28089
|
-
const pkg = this._packageName ?? "package";
|
|
28090
27786
|
return {
|
|
28091
27787
|
weslSrc: this.sources,
|
|
28092
|
-
rootModuleName: this._rootModuleName ??
|
|
27788
|
+
rootModuleName: this._rootModuleName ?? this.activeModulePath(),
|
|
28093
27789
|
conditions: this._conditions,
|
|
28094
27790
|
constants: this._constants,
|
|
28095
27791
|
libs: this._libs,
|
|
28096
|
-
packageName:
|
|
27792
|
+
packageName: this.pkgName()
|
|
28097
27793
|
};
|
|
28098
27794
|
}
|
|
28099
27795
|
get libs() {
|
|
@@ -28149,6 +27845,20 @@ var WgslEdit = class extends HTMLElement {
|
|
|
28149
27845
|
if (!value) this.setAttribute("gpu-lint", "off");
|
|
28150
27846
|
else this.removeAttribute("gpu-lint");
|
|
28151
27847
|
}
|
|
27848
|
+
/** Persist edits to disk via the dev-server save endpoint.
|
|
27849
|
+
* Requires `wgslEditAutosave()` to be installed in vite.config.ts. */
|
|
27850
|
+
get autosave() {
|
|
27851
|
+
return this._devSaveListener !== null;
|
|
27852
|
+
}
|
|
27853
|
+
set autosave(value) {
|
|
27854
|
+
if (value) {
|
|
27855
|
+
this.enableDevSave();
|
|
27856
|
+
this.setAttribute("autosave", "");
|
|
27857
|
+
} else {
|
|
27858
|
+
this.disableDevSave();
|
|
27859
|
+
this.removeAttribute("autosave");
|
|
27860
|
+
}
|
|
27861
|
+
}
|
|
28152
27862
|
/** Whether to auto-fetch missing library packages from npm (default: true). */
|
|
28153
27863
|
get fetchLibs() {
|
|
28154
27864
|
return this._fetchLibs;
|
|
@@ -28198,13 +27908,15 @@ var WgslEdit = class extends HTMLElement {
|
|
|
28198
27908
|
if (value) this.setAttribute("shader-root", value);
|
|
28199
27909
|
else this.removeAttribute("shader-root");
|
|
28200
27910
|
}
|
|
27911
|
+
/** Add a new file and switch to it. No-op if `name` already exists. */
|
|
28201
27912
|
addFile(name, content = "") {
|
|
28202
27913
|
if (this._files.has(name)) return;
|
|
28203
|
-
this._files.set(name, { doc:
|
|
27914
|
+
this._files.set(name, { doc: toDoc(content) });
|
|
28204
27915
|
this.switchToFile(name);
|
|
28205
27916
|
this.renderTabs();
|
|
28206
27917
|
this.dispatchFileChange("add", name);
|
|
28207
27918
|
}
|
|
27919
|
+
/** Remove a file. No-op if it is missing or is the last remaining file. */
|
|
28208
27920
|
removeFile(name) {
|
|
28209
27921
|
if (!this._files.has(name) || this._files.size <= 1) return;
|
|
28210
27922
|
this._files.delete(name);
|
|
@@ -28215,6 +27927,7 @@ var WgslEdit = class extends HTMLElement {
|
|
|
28215
27927
|
this.renderTabs();
|
|
28216
27928
|
this.dispatchFileChange("remove", name);
|
|
28217
27929
|
}
|
|
27930
|
+
/** Rename a file, preserving its document and editor state. No-op on collision. */
|
|
28218
27931
|
renameFile(oldName, newName) {
|
|
28219
27932
|
const state = this._files.get(oldName);
|
|
28220
27933
|
if (!state || this._files.has(newName)) return;
|
|
@@ -28230,28 +27943,36 @@ var WgslEdit = class extends HTMLElement {
|
|
|
28230
27943
|
this.saveCurrentFileState();
|
|
28231
27944
|
this._activeFile = name;
|
|
28232
27945
|
const fileState = this._files.get(name);
|
|
28233
|
-
|
|
28234
|
-
|
|
28235
|
-
|
|
28236
|
-
|
|
28237
|
-
|
|
28238
|
-
|
|
28239
|
-
const effects = EditorView.scrollIntoView(fileState.scrollPos ?? 0);
|
|
28240
|
-
this.editorView.dispatch({
|
|
28241
|
-
changes,
|
|
28242
|
-
selection: fileState.selection,
|
|
28243
|
-
effects
|
|
28244
|
-
});
|
|
27946
|
+
const view = this.editorView;
|
|
27947
|
+
if (view) {
|
|
27948
|
+
const state = fileState.state ?? this.createFileState(fileState.doc);
|
|
27949
|
+
fileState.state = state;
|
|
27950
|
+
view.setState(state);
|
|
27951
|
+
if (fileState.scrollPos != null) view.scrollDOM.scrollTop = fileState.scrollPos;
|
|
28245
27952
|
}
|
|
28246
27953
|
this.renderTabs();
|
|
28247
27954
|
}
|
|
27955
|
+
/** Build a fresh EditorState seeded with `doc` and the current extension set. */
|
|
27956
|
+
createFileState(doc) {
|
|
27957
|
+
return EditorState.create({
|
|
27958
|
+
doc,
|
|
27959
|
+
extensions: this.buildExtensions()
|
|
27960
|
+
});
|
|
27961
|
+
}
|
|
28248
27962
|
saveCurrentFileState() {
|
|
28249
27963
|
const view = this.editorView;
|
|
28250
|
-
const
|
|
28251
|
-
if (!view || !
|
|
28252
|
-
state
|
|
28253
|
-
|
|
28254
|
-
|
|
27964
|
+
const fileState = this._activeFile ? this._files.get(this._activeFile) : void 0;
|
|
27965
|
+
if (!view || !fileState) return;
|
|
27966
|
+
fileState.state = view.state;
|
|
27967
|
+
fileState.doc = view.state.doc;
|
|
27968
|
+
fileState.selection = view.state.selection;
|
|
27969
|
+
fileState.scrollPos = view.scrollDOM.scrollTop;
|
|
27970
|
+
}
|
|
27971
|
+
pkgName() {
|
|
27972
|
+
return this._packageName ?? "package";
|
|
27973
|
+
}
|
|
27974
|
+
activeModulePath() {
|
|
27975
|
+
return fileToModulePath(this._activeFile, this.pkgName(), false);
|
|
28255
27976
|
}
|
|
28256
27977
|
dispatchChange() {
|
|
28257
27978
|
this.dispatchEvent(new CustomEvent("change", { detail: this.project }));
|
|
@@ -28263,25 +27984,86 @@ var WgslEdit = class extends HTMLElement {
|
|
|
28263
27984
|
};
|
|
28264
27985
|
this.dispatchEvent(new CustomEvent("file-change", { detail }));
|
|
28265
27986
|
}
|
|
27987
|
+
scheduleAutosave() {
|
|
27988
|
+
this._dirtyFiles.add(this._activeFile);
|
|
27989
|
+
clearTimeout(this._saveTimer);
|
|
27990
|
+
this._saveTimer = setTimeout(() => this.fireAutosave(), 500);
|
|
27991
|
+
}
|
|
27992
|
+
/** Dispatch an `autosave` event with a fresh project snapshot and the dirty-file list. */
|
|
27993
|
+
fireAutosave() {
|
|
27994
|
+
const dirty = [...this._dirtyFiles];
|
|
27995
|
+
this._dirtyFiles.clear();
|
|
27996
|
+
const detail = {
|
|
27997
|
+
project: this.project,
|
|
27998
|
+
dirty
|
|
27999
|
+
};
|
|
28000
|
+
this.dispatchEvent(new CustomEvent("autosave", { detail }));
|
|
28001
|
+
}
|
|
28002
|
+
enableDevSave() {
|
|
28003
|
+
if (this._devSaveListener) return;
|
|
28004
|
+
this._devSaveListener = (e) => this.devSave(e);
|
|
28005
|
+
this.addEventListener("autosave", this._devSaveListener);
|
|
28006
|
+
}
|
|
28007
|
+
disableDevSave() {
|
|
28008
|
+
if (!this._devSaveListener) return;
|
|
28009
|
+
this.removeEventListener("autosave", this._devSaveListener);
|
|
28010
|
+
this._devSaveListener = null;
|
|
28011
|
+
}
|
|
28012
|
+
/** Built-in `autosave` listener: POST each dirty file to the dev-server save endpoint. */
|
|
28013
|
+
async devSave(e) {
|
|
28014
|
+
const root = this.shaderRoot;
|
|
28015
|
+
if (!root) return;
|
|
28016
|
+
const { project, dirty } = e.detail;
|
|
28017
|
+
const weslSrc = project.weslSrc;
|
|
28018
|
+
if (!weslSrc) return;
|
|
28019
|
+
const pkg = this.pkgName();
|
|
28020
|
+
for (const file of dirty) {
|
|
28021
|
+
const content = weslSrc[fileToModulePath(file, pkg, false)];
|
|
28022
|
+
if (content === void 0) continue;
|
|
28023
|
+
try {
|
|
28024
|
+
const res = await fetch(saveEndpoint, {
|
|
28025
|
+
method: "POST",
|
|
28026
|
+
headers: { "Content-Type": "application/json" },
|
|
28027
|
+
body: JSON.stringify({
|
|
28028
|
+
root,
|
|
28029
|
+
file,
|
|
28030
|
+
content
|
|
28031
|
+
})
|
|
28032
|
+
});
|
|
28033
|
+
if (!res.ok) return this.devSaveFailed(`HTTP ${res.status}`);
|
|
28034
|
+
} catch (err) {
|
|
28035
|
+
return this.devSaveFailed(err instanceof Error ? err.message : String(err));
|
|
28036
|
+
}
|
|
28037
|
+
}
|
|
28038
|
+
}
|
|
28039
|
+
/** One-shot disable on first failure: avoids spamming the console on every keystroke. */
|
|
28040
|
+
devSaveFailed(reason) {
|
|
28041
|
+
this.disableDevSave();
|
|
28042
|
+
console.error(`wgsl-edit: autosave disabled (${reason}). Make sure wgslEditAutosave() is installed in vite.config.ts.`);
|
|
28043
|
+
}
|
|
28044
|
+
/** First-time setup: read attributes, parse inline content, mount the EditorView. */
|
|
28266
28045
|
initEditor() {
|
|
28267
28046
|
this.readInitialAttributes();
|
|
28268
28047
|
this.parseInlineContent();
|
|
28269
28048
|
this._mediaQuery = matchMedia("(prefers-color-scheme: dark)");
|
|
28270
28049
|
this._mediaQuery.addEventListener("change", () => this.updateTheme());
|
|
28271
28050
|
const firstFile = this._files.keys().next().value;
|
|
28272
|
-
const
|
|
28051
|
+
const firstDoc = firstFile && this._files.get(firstFile).doc.toString();
|
|
28052
|
+
const initialDoc = this._pendingSource ?? firstDoc ?? "";
|
|
28273
28053
|
this._pendingSource = null;
|
|
28274
28054
|
if (firstFile) this._activeFile = firstFile;
|
|
28275
28055
|
else if (initialDoc) {
|
|
28276
|
-
this._files.set("main.wesl", { doc:
|
|
28056
|
+
this._files.set("main.wesl", { doc: toDoc(initialDoc) });
|
|
28277
28057
|
this._activeFile = "main.wesl";
|
|
28278
28058
|
}
|
|
28279
|
-
const
|
|
28059
|
+
const state = this.createFileState(initialDoc);
|
|
28060
|
+
const active = this._activeFile ? this._files.get(this._activeFile) : null;
|
|
28061
|
+
if (active) {
|
|
28062
|
+
active.state = state;
|
|
28063
|
+
active.doc = state.doc;
|
|
28064
|
+
}
|
|
28280
28065
|
this.editorView = new EditorView({
|
|
28281
|
-
state
|
|
28282
|
-
doc: initialDoc,
|
|
28283
|
-
extensions
|
|
28284
|
-
}),
|
|
28066
|
+
state,
|
|
28285
28067
|
parent: this.editorContainer
|
|
28286
28068
|
});
|
|
28287
28069
|
this.renderTabs();
|
|
@@ -28298,6 +28080,7 @@ var WgslEdit = class extends HTMLElement {
|
|
|
28298
28080
|
const lintFromAttr = this.getAttribute("lint-from");
|
|
28299
28081
|
if (lintFromAttr) this.connectLintSource(lintFromAttr);
|
|
28300
28082
|
}
|
|
28083
|
+
/** Assemble the full CodeMirror extension set for a fresh EditorState. */
|
|
28301
28084
|
buildExtensions() {
|
|
28302
28085
|
const baseTheme = EditorView.theme({
|
|
28303
28086
|
".cm-content": { padding: "0" },
|
|
@@ -28342,6 +28125,7 @@ var WgslEdit = class extends HTMLElement {
|
|
|
28342
28125
|
this._externalDiagnostics = [];
|
|
28343
28126
|
this.saveCurrentFileState();
|
|
28344
28127
|
this.dispatchChange();
|
|
28128
|
+
if (!this._switchingFile) this.scheduleAutosave();
|
|
28345
28129
|
}
|
|
28346
28130
|
})
|
|
28347
28131
|
];
|
|
@@ -28352,11 +28136,11 @@ var WgslEdit = class extends HTMLElement {
|
|
|
28352
28136
|
return [EditorView.theme({}, { dark: isDark }), isDark ? darkColors : lightColors];
|
|
28353
28137
|
}
|
|
28354
28138
|
updateTheme() {
|
|
28355
|
-
this.
|
|
28139
|
+
this.reconfigure(this.themeCompartment, this.resolveTheme());
|
|
28356
28140
|
}
|
|
28357
28141
|
updateReadonly() {
|
|
28358
28142
|
const ext = EditorState.readOnly.of(this.readonly);
|
|
28359
|
-
this.
|
|
28143
|
+
this.reconfigure(this.readonlyCompartment, ext);
|
|
28360
28144
|
this.renderTabs();
|
|
28361
28145
|
}
|
|
28362
28146
|
resolveLint() {
|
|
@@ -28364,7 +28148,7 @@ var WgslEdit = class extends HTMLElement {
|
|
|
28364
28148
|
const useGpuLint = this._gpuLint && !this._lintFromEl;
|
|
28365
28149
|
return createWeslLinter({
|
|
28366
28150
|
getSources: () => this.sources,
|
|
28367
|
-
rootModule: () =>
|
|
28151
|
+
rootModule: () => this.activeModulePath(),
|
|
28368
28152
|
conditions: () => this._conditions,
|
|
28369
28153
|
packageName: () => this._packageName,
|
|
28370
28154
|
getExternalDiagnostics: () => this._externalDiagnostics,
|
|
@@ -28377,11 +28161,8 @@ var WgslEdit = class extends HTMLElement {
|
|
|
28377
28161
|
/** Link WESL->WGSL and validate via WebGPU, returning CodeMirror diagnostics. */
|
|
28378
28162
|
async gpuValidate() {
|
|
28379
28163
|
const { validateWgsl } = await import("./GpuValidator-D88-VTq9.js");
|
|
28380
|
-
const
|
|
28381
|
-
|
|
28382
|
-
const messages = await validateWgsl(linked.dest);
|
|
28383
|
-
const pkg = params.packageName ?? "package";
|
|
28384
|
-
return mapGpuDiagnostics(messages, linked, this._activeFile, pkg);
|
|
28164
|
+
const linked = await link(this.linkParams());
|
|
28165
|
+
return mapGpuDiagnostics(await validateWgsl(linked.dest), linked, this._activeFile, this.pkgName());
|
|
28385
28166
|
}
|
|
28386
28167
|
/** Fetch missing library packages, deduplicating in-flight requests. */
|
|
28387
28168
|
async fetchLibsOnDemand(names) {
|
|
@@ -28408,14 +28189,15 @@ var WgslEdit = class extends HTMLElement {
|
|
|
28408
28189
|
}
|
|
28409
28190
|
}
|
|
28410
28191
|
updateLint() {
|
|
28411
|
-
this.
|
|
28192
|
+
this.reconfigure(this.lintCompartment, this.resolveLint());
|
|
28412
28193
|
}
|
|
28413
28194
|
/** Listen for compile-error/compile-success events from a lint source element. */
|
|
28414
28195
|
connectLintSource(id) {
|
|
28415
28196
|
const hadExternal = !!this._lintFromEl;
|
|
28416
|
-
|
|
28417
|
-
|
|
28418
|
-
|
|
28197
|
+
const prev = this._lintFromEl;
|
|
28198
|
+
if (prev) {
|
|
28199
|
+
prev.removeEventListener("compile-error", this._boundCompileError);
|
|
28200
|
+
prev.removeEventListener("compile-success", this._boundCompileSuccess);
|
|
28419
28201
|
this._lintFromEl = null;
|
|
28420
28202
|
}
|
|
28421
28203
|
this._externalDiagnostics = [];
|
|
@@ -28427,23 +28209,24 @@ var WgslEdit = class extends HTMLElement {
|
|
|
28427
28209
|
}
|
|
28428
28210
|
if (hadExternal !== !!this._lintFromEl) this.updateLint();
|
|
28429
28211
|
}
|
|
28212
|
+
/** Convert external compile-error locations into CodeMirror diagnostics for the active file. */
|
|
28430
28213
|
onCompileError(e) {
|
|
28431
28214
|
const detail = e.detail;
|
|
28432
28215
|
if (!this.editorView || detail.source === "wesl") return;
|
|
28433
28216
|
const doc = this.editorView.state.doc;
|
|
28434
|
-
const pkg = this.
|
|
28435
|
-
const activeModule =
|
|
28436
|
-
|
|
28437
|
-
|
|
28438
|
-
return fileToModulePath(loc.file, pkg, false) === activeModule;
|
|
28439
|
-
}).map((loc) => {
|
|
28217
|
+
const pkg = this.pkgName();
|
|
28218
|
+
const activeModule = this.activeModulePath();
|
|
28219
|
+
const inActiveFile = (loc) => !loc.file || fileToModulePath(loc.file, pkg, false) === activeModule;
|
|
28220
|
+
this._externalDiagnostics = detail.locations.filter(inActiveFile).map((loc) => {
|
|
28440
28221
|
const line = doc.line(Math.max(1, Math.min(loc.line, doc.lines)));
|
|
28441
28222
|
const from = Math.min(line.from + (loc.column ?? 0), doc.length);
|
|
28223
|
+
const to = Math.min(from + (loc.length ?? 1), doc.length);
|
|
28224
|
+
const { severity, message } = loc;
|
|
28442
28225
|
return {
|
|
28443
28226
|
from,
|
|
28444
|
-
to
|
|
28445
|
-
severity
|
|
28446
|
-
message
|
|
28227
|
+
to,
|
|
28228
|
+
severity,
|
|
28229
|
+
message,
|
|
28447
28230
|
source: "WebGPU"
|
|
28448
28231
|
};
|
|
28449
28232
|
});
|
|
@@ -28458,21 +28241,20 @@ var WgslEdit = class extends HTMLElement {
|
|
|
28458
28241
|
return this._lineNumbers ? [] : EditorView.theme({ ".cm-gutters": { display: "none" } });
|
|
28459
28242
|
}
|
|
28460
28243
|
updateLineNumbers() {
|
|
28461
|
-
|
|
28462
|
-
this.editorView?.dispatch({ effects: this.lineNumbersCompartment.reconfigure(ext) });
|
|
28244
|
+
this.reconfigure(this.lineNumbersCompartment, this.resolveLineNumbers());
|
|
28463
28245
|
}
|
|
28464
28246
|
/** Parse script tags into _files. Supports single or multi-file via data-name. */
|
|
28465
28247
|
parseInlineContent() {
|
|
28466
28248
|
const scripts = Array.from(this.querySelectorAll("script[type=\"text/wgsl\"], script[type=\"text/wesl\"]"));
|
|
28467
28249
|
if (scripts.length === 0) {
|
|
28468
28250
|
const content = this.textContent?.trim() ?? "";
|
|
28469
|
-
if (content) this._files.set("main.wesl", { doc:
|
|
28251
|
+
if (content) this._files.set("main.wesl", { doc: toDoc(content) });
|
|
28470
28252
|
return;
|
|
28471
28253
|
}
|
|
28472
28254
|
for (const script of scripts) {
|
|
28473
28255
|
const name = script.getAttribute("data-name") || "main.wesl";
|
|
28474
28256
|
const content = script.textContent?.trim() ?? "";
|
|
28475
|
-
this._files.set(name, { doc:
|
|
28257
|
+
this._files.set(name, { doc: toDoc(content) });
|
|
28476
28258
|
}
|
|
28477
28259
|
}
|
|
28478
28260
|
renderTabs() {
|
|
@@ -28517,28 +28299,27 @@ var WgslEdit = class extends HTMLElement {
|
|
|
28517
28299
|
});
|
|
28518
28300
|
return btn;
|
|
28519
28301
|
}
|
|
28302
|
+
/** Replace the tab name span with an editable input; commit on Enter/blur, cancel on Escape. */
|
|
28520
28303
|
startRenameTab(tab, nameSpan, oldName) {
|
|
28521
28304
|
const input = document.createElement("input");
|
|
28522
28305
|
input.className = "tab-rename";
|
|
28523
28306
|
input.value = oldName;
|
|
28524
28307
|
input.size = Math.max(oldName.length, 8);
|
|
28308
|
+
const cancelRename = () => {
|
|
28309
|
+
nameSpan.style.display = "";
|
|
28310
|
+
input.remove();
|
|
28311
|
+
};
|
|
28525
28312
|
const finishRename = () => {
|
|
28526
28313
|
const newName = input.value.trim() || oldName;
|
|
28527
28314
|
if (newName !== oldName && !this._files.has(newName)) this.renameFile(oldName, newName);
|
|
28528
|
-
else
|
|
28529
|
-
nameSpan.style.display = "";
|
|
28530
|
-
input.remove();
|
|
28531
|
-
}
|
|
28315
|
+
else cancelRename();
|
|
28532
28316
|
};
|
|
28533
28317
|
input.addEventListener("keydown", (e) => {
|
|
28534
28318
|
if (e.key === "Enter") {
|
|
28535
28319
|
e.preventDefault();
|
|
28536
28320
|
finishRename();
|
|
28537
28321
|
}
|
|
28538
|
-
if (e.key === "Escape")
|
|
28539
|
-
nameSpan.style.display = "";
|
|
28540
|
-
input.remove();
|
|
28541
|
-
}
|
|
28322
|
+
if (e.key === "Escape") cancelRename();
|
|
28542
28323
|
});
|
|
28543
28324
|
input.addEventListener("blur", finishRename);
|
|
28544
28325
|
input.addEventListener("input", () => {
|
|
@@ -28566,6 +28347,7 @@ var WgslEdit = class extends HTMLElement {
|
|
|
28566
28347
|
if (src) this.loadFromUrl(src);
|
|
28567
28348
|
}
|
|
28568
28349
|
};
|
|
28350
|
+
/** Build a CodeMirror highlight style from a WESL color palette. */
|
|
28569
28351
|
function weslColors(c) {
|
|
28570
28352
|
return syntaxHighlighting(HighlightStyle.define([
|
|
28571
28353
|
{
|
|
@@ -28633,24 +28415,7 @@ function weslColors(c) {
|
|
|
28633
28415
|
fontStyle: "normal"
|
|
28634
28416
|
} }));
|
|
28635
28417
|
}
|
|
28636
|
-
/**
|
|
28637
|
-
function mapGpuDiagnostics(messages, linked, activeFile, pkg) {
|
|
28638
|
-
const { sourceMap } = linked;
|
|
28639
|
-
const active = fileToModulePath(activeFile, pkg, false);
|
|
28640
|
-
return messages.flatMap((msg) => {
|
|
28641
|
-
const srcPos = sourceMap.destToSrc(msg.offset);
|
|
28642
|
-
if ((srcPos.src.path ? fileToModulePath(srcPos.src.path, pkg, false) : null) !== active) return [];
|
|
28643
|
-
const endPos = sourceMap.destToSrc(msg.offset + msg.length);
|
|
28644
|
-
const from = srcPos.position;
|
|
28645
|
-
return {
|
|
28646
|
-
from,
|
|
28647
|
-
to: endPos.position > from ? endPos.position : from + 1,
|
|
28648
|
-
severity: msg.severity,
|
|
28649
|
-
message: msg.message,
|
|
28650
|
-
source: "WebGPU"
|
|
28651
|
-
};
|
|
28652
|
-
});
|
|
28653
|
-
}
|
|
28418
|
+
/** Lazily build and cache the shared component stylesheet. */
|
|
28654
28419
|
function getStyles() {
|
|
28655
28420
|
if (!cachedStyleSheet) {
|
|
28656
28421
|
cachedStyleSheet = new CSSStyleSheet();
|
|
@@ -28658,7 +28423,8 @@ function getStyles() {
|
|
|
28658
28423
|
}
|
|
28659
28424
|
return cachedStyleSheet;
|
|
28660
28425
|
}
|
|
28661
|
-
/** Absorb instance properties set before custom element upgrade.
|
|
28426
|
+
/** Absorb instance properties set before custom element upgrade.
|
|
28427
|
+
* Duplicated in WgslPlay.ts. Later, extract to a shared package. */
|
|
28662
28428
|
function upgradeProperty(el, prop) {
|
|
28663
28429
|
if (Object.hasOwn(el, prop)) {
|
|
28664
28430
|
const value = el[prop];
|
|
@@ -28666,11 +28432,36 @@ function upgradeProperty(el, prop) {
|
|
|
28666
28432
|
el[prop] = value;
|
|
28667
28433
|
}
|
|
28668
28434
|
}
|
|
28435
|
+
/** Build a CodeMirror Text doc from a string. */
|
|
28436
|
+
function toDoc(s) {
|
|
28437
|
+
return Text.of(s.split("\n"));
|
|
28438
|
+
}
|
|
28669
28439
|
/** Convert a module path or file path to a tab name: "package::main" -> "main", "main.wesl" -> "main.wesl" */
|
|
28670
28440
|
function toTabName(key) {
|
|
28671
28441
|
if (key.includes("::")) return key.replace(/^[^:]+::/, "").replaceAll("::", "/");
|
|
28672
28442
|
return key.replace(/^\.\//, "");
|
|
28673
28443
|
}
|
|
28444
|
+
/** Map GPU validation messages back to source positions via the source map. */
|
|
28445
|
+
function mapGpuDiagnostics(messages, linked, activeFile, pkg) {
|
|
28446
|
+
const { sourceMap } = linked;
|
|
28447
|
+
const active = fileToModulePath(activeFile, pkg, false);
|
|
28448
|
+
return messages.flatMap((msg) => {
|
|
28449
|
+
const srcPos = sourceMap.destToSrc(msg.offset);
|
|
28450
|
+
const path = srcPos.src.path;
|
|
28451
|
+
if ((path ? fileToModulePath(path, pkg, false) : null) !== active) return [];
|
|
28452
|
+
const endPos = sourceMap.destToSrc(msg.offset + msg.length);
|
|
28453
|
+
const from = srcPos.position;
|
|
28454
|
+
const to = endPos.position > from ? endPos.position : from + 1;
|
|
28455
|
+
const { severity, message } = msg;
|
|
28456
|
+
return {
|
|
28457
|
+
from,
|
|
28458
|
+
to,
|
|
28459
|
+
severity,
|
|
28460
|
+
message,
|
|
28461
|
+
source: "WebGPU"
|
|
28462
|
+
};
|
|
28463
|
+
});
|
|
28464
|
+
}
|
|
28674
28465
|
//#endregion
|
|
28675
28466
|
//#region src/index.ts
|
|
28676
28467
|
if (!customElements.get("wgsl-edit")) customElements.define("wgsl-edit", WgslEdit);
|