From 242af52ca5f6c2e5fce7802b195dc585f64b1eeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=96=A4=20ShadowNine=20=F0=9F=92=9B?= Date: Tue, 8 Sep 2026 04:55:33 +0200 Subject: [PATCH] fix: always emit project properties --- CHANGELOG.md | 6 ++++ packages/wallpaper-engine/src/plugin/index.ts | 11 +++---- .../wallpaper-engine/tests/plugin.test.ts | 30 ++++++++++++++----- .../wallpaper-engine/tests/workshop.test.ts | 3 ++ 4 files changed, 35 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b54558..d9072fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,12 @@ migration); tags are used where they exist. ## [Unreleased] +### Fixed + +- Always emit `general.properties` in generated `project.json` files, including + an empty object when no wallpaper properties are configured, to prevent + Wallpaper Engine from crashing while loading the project. + ## [1.3.1] - 2026-08-07 ### Added diff --git a/packages/wallpaper-engine/src/plugin/index.ts b/packages/wallpaper-engine/src/plugin/index.ts index c0990e6..d5abaa2 100644 --- a/packages/wallpaper-engine/src/plugin/index.ts +++ b/packages/wallpaper-engine/src/plugin/index.ts @@ -479,7 +479,7 @@ export function wallpaperEnginePlugin( generateBundle(_outputOptions, bundle) { let properties = options.properties ? assignIndices(options.properties) - : undefined; + : {}; if (options.schemeColor !== undefined) { properties = { ...properties, @@ -488,13 +488,11 @@ export function wallpaperEnginePlugin( } else { const preserved = preservationState?.schemeColor; - if (preserved !== undefined && properties?.schemecolor === undefined) + if (preserved !== undefined && properties.schemecolor === undefined) properties = { schemecolor: preserved, ...properties }; } - const general: WallpaperProjectGeneral = {}; - if (properties) - general.properties = properties; + const general: WallpaperProjectGeneral = { properties }; if (options.localization) general.localization = options.localization; if ( @@ -511,8 +509,7 @@ export function wallpaperEnginePlugin( title: options.title, type: 'web', }; - if (Object.keys(general).length > 0) - project.general = general; + project.general = general; const restoredPreview = preservationState === undefined ? undefined diff --git a/packages/wallpaper-engine/tests/plugin.test.ts b/packages/wallpaper-engine/tests/plugin.test.ts index 0424e14..e4661fe 100644 --- a/packages/wallpaper-engine/tests/plugin.test.ts +++ b/packages/wallpaper-engine/tests/plugin.test.ts @@ -319,6 +319,7 @@ describe('wallpaperEnginePlugin', () => { file: 'index.html', title: 'T', type: 'web', + general: { properties: {} }, }); expect(source).toBe(JSON.stringify(project)); }); @@ -434,7 +435,9 @@ describe('wallpaperEnginePlugin', () => { } as never); const { source } = runGenerateBundle(plugin); - expect(source).toBe('{"file":"index.html","title":"T","type":"web"}'); + expect(source).toBe( + '{"file":"index.html","title":"T","type":"web","general":{"properties":{}}}', + ); }); it('minifies project.json by default for builds', () => { @@ -442,7 +445,9 @@ describe('wallpaperEnginePlugin', () => { wallpaperEnginePlugin({ title: 'T' }), ); - expect(source).toBe('{"file":"index.html","title":"T","type":"web"}'); + expect(source).toBe( + '{"file":"index.html","title":"T","type":"web","general":{"properties":{}}}', + ); }); it('pretty-prints project.json when minification is disabled', () => { @@ -468,7 +473,10 @@ describe('wallpaperEnginePlugin', () => { const { project } = runGenerateBundle( wallpaperEnginePlugin({ title: 'T', supportsAudioProcessing: true }), ); - expect(project.general).toEqual({ supportsaudioprocessing: true }); + expect(project.general).toEqual({ + properties: {}, + supportsaudioprocessing: true, + }); expect(project.supportsaudioprocessing).toBeUndefined(); }); @@ -498,7 +506,10 @@ describe('wallpaperEnginePlugin', () => { }, ); - expect(project.general).toEqual({ supportsaudioprocessing: true }); + expect(project.general).toEqual({ + properties: {}, + supportsaudioprocessing: true, + }); }); it('detects a listener call in an emitted script asset', () => { @@ -515,7 +526,10 @@ describe('wallpaperEnginePlugin', () => { }, ); - expect(project.general).toEqual({ supportsaudioprocessing: true }); + expect(project.general).toEqual({ + properties: {}, + supportsaudioprocessing: true, + }); }); it('allows automatic audio processing detection to be disabled', () => { @@ -533,7 +547,7 @@ describe('wallpaperEnginePlugin', () => { }, ); - expect(project.general).toBeUndefined(); + expect(project.general).toEqual({ properties: {} }); }); it('omits supportsaudioprocessing when not set', () => { @@ -544,11 +558,11 @@ describe('wallpaperEnginePlugin', () => { expect(project.supportsaudioprocessing).toBeUndefined(); }); - it('omits the general block when there are no properties or localization', () => { + it('emits an empty properties record when no properties are configured', () => { const { project } = runGenerateBundle( wallpaperEnginePlugin({ title: 'T' }), ); - expect(project.general).toBeUndefined(); + expect(project.general).toEqual({ properties: {} }); }); it('emits derived and explicit slider steps in project.json', () => { diff --git a/packages/wallpaper-engine/tests/workshop.test.ts b/packages/wallpaper-engine/tests/workshop.test.ts index 95a6f5f..2f39bc7 100644 --- a/packages/wallpaper-engine/tests/workshop.test.ts +++ b/packages/wallpaper-engine/tests/workshop.test.ts @@ -209,6 +209,7 @@ describe('steam Workshop project preservation', () => { file: 'wallpaper.html', title: 'Second generated title', type: 'web', + general: { properties: {} }, }); }); @@ -249,6 +250,7 @@ describe('steam Workshop project preservation', () => { file: 'index.html', title: 'Clean clone', type: 'web', + general: { properties: {} }, }); expect([...await readFile(join(root, 'dist', 'previews', 'clean.png'))]) .toEqual([...previewBytes]); @@ -458,6 +460,7 @@ describe('steam Workshop project preservation', () => { file: 'index.html', title: 'Generated', type: 'web', + general: { properties: {} }, }); });