Remove the svelte-preprocess dev dependency, keeping global styles with a custom Vite plugin (#4003)

* Remove the svelte-preprocess dev dependency, keeping global styles with a custom Vite plugin

* More robust style tag detection

* Fix CSS regressions
This commit is contained in:
Keavon Chambers 2026-04-03 23:53:46 -07:00 committed by GitHub
parent 55463fe0aa
commit e0212ca4b9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
55 changed files with 99 additions and 144 deletions

View File

@ -27,7 +27,6 @@
"sass": "^1.98.0", "sass": "^1.98.0",
"svelte": "^5.54.1", "svelte": "^5.54.1",
"svelte-check": "^4.4.5", "svelte-check": "^4.4.5",
"svelte-preprocess": "^6.0.3",
"tar": "^7.5.12", "tar": "^7.5.12",
"typescript": "^5.9.3", "typescript": "^5.9.3",
"typescript-eslint": "^8.57.1", "typescript-eslint": "^8.57.1",
@ -6039,62 +6038,6 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/svelte-preprocess": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-6.0.3.tgz",
"integrity": "sha512-PLG2k05qHdhmRG7zR/dyo5qKvakhm8IJ+hD2eFRQmMLHp7X3eJnjeupUtvuRpbNiF31RjVw45W+abDwHEmP5OA==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"engines": {
"node": ">= 18.0.0"
},
"peerDependencies": {
"@babel/core": "^7.10.2",
"coffeescript": "^2.5.1",
"less": "^3.11.3 || ^4.0.0",
"postcss": "^7 || ^8",
"postcss-load-config": ">=3",
"pug": "^3.0.0",
"sass": "^1.26.8",
"stylus": ">=0.55",
"sugarss": "^2.0.0 || ^3.0.0 || ^4.0.0",
"svelte": "^4.0.0 || ^5.0.0-next.100 || ^5.0.0",
"typescript": "^5.0.0"
},
"peerDependenciesMeta": {
"@babel/core": {
"optional": true
},
"coffeescript": {
"optional": true
},
"less": {
"optional": true
},
"postcss": {
"optional": true
},
"postcss-load-config": {
"optional": true
},
"pug": {
"optional": true
},
"sass": {
"optional": true
},
"stylus": {
"optional": true
},
"sugarss": {
"optional": true
},
"typescript": {
"optional": true
}
}
},
"node_modules/synckit": { "node_modules/synckit": {
"version": "0.11.12", "version": "0.11.12",
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz", "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz",

View File

@ -48,7 +48,6 @@
"sass": "^1.98.0", "sass": "^1.98.0",
"svelte": "^5.54.1", "svelte": "^5.54.1",
"svelte-check": "^4.4.5", "svelte-check": "^4.4.5",
"svelte-preprocess": "^6.0.3",
"tar": "^7.5.12", "tar": "^7.5.12",
"typescript": "^5.9.3", "typescript": "^5.9.3",
"typescript-eslint": "^8.57.1", "typescript-eslint": "^8.57.1",

View File

@ -75,7 +75,7 @@
<MainWindow /> <MainWindow />
<style lang="scss" global> <style lang="scss">
// Disable the spinning loading indicator // Disable the spinning loading indicator
body::before, body::before,
body::after { body::after {

View File

@ -732,7 +732,7 @@
</LayoutRow> </LayoutRow>
</FloatingMenu> </FloatingMenu>
<style lang="scss" global> <style lang="scss">
.color-picker { .color-picker {
--widget-height: 24px; --widget-height: 24px;
--picker-size: 256px; --picker-size: 256px;

View File

@ -73,7 +73,7 @@
</LayoutRow> </LayoutRow>
</FloatingMenu> </FloatingMenu>
<style lang="scss" global> <style lang="scss">
.dialog { .dialog {
position: absolute; position: absolute;
pointer-events: none; pointer-events: none;

View File

@ -63,7 +63,7 @@
</div> </div>
</FloatingMenu> </FloatingMenu>
<style lang="scss" global> <style lang="scss">
.eyedropper-preview { .eyedropper-preview {
pointer-events: none; pointer-events: none;

View File

@ -560,7 +560,7 @@
</LayoutCol> </LayoutCol>
</FloatingMenu> </FloatingMenu>
<style lang="scss" global> <style lang="scss">
.menu-list { .menu-list {
.search { .search {
margin: 4px; margin: 4px;

View File

@ -136,7 +136,7 @@
</div> </div>
</LayoutCol> </LayoutCol>
<style lang="scss" global> <style lang="scss">
.node-catalog { .node-catalog {
max-height: 30vh; max-height: 30vh;
min-width: 250px; min-width: 250px;

View File

@ -76,7 +76,7 @@
</div> </div>
{/if} {/if}
<style lang="scss" global> <style lang="scss">
.tooltip { .tooltip {
position: absolute; position: absolute;
pointer-events: none; pointer-events: none;

View File

@ -11,4 +11,4 @@
<slot /> <slot />
{/if} {/if}
<style lang="scss" global></style> <style lang="scss"></style>

View File

@ -500,7 +500,7 @@
{/if} {/if}
</div> </div>
<style lang="scss" global> <style lang="scss">
.floating-menu { .floating-menu {
position: absolute; position: absolute;
width: 0; width: 0;

View File

@ -90,7 +90,7 @@ on:touchcancel
on:touchend on:touchend
--> -->
<style lang="scss" global> <style lang="scss">
.layout-col { .layout-col {
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@ -90,7 +90,7 @@ on:touchcancel
on:touchend on:touchend
--> -->
<style lang="scss" global> <style lang="scss">
.layout-row { .layout-row {
display: flex; display: flex;
flex-direction: row; flex-direction: row;

View File

@ -28,7 +28,7 @@
</LayoutCol> </LayoutCol>
</LayoutCol> </LayoutCol>
<style lang="scss" global> <style lang="scss">
.data-panel { .data-panel {
flex-grow: 1; flex-grow: 1;
padding: 4px; padding: 4px;

View File

@ -703,7 +703,7 @@
</LayoutRow> </LayoutRow>
</LayoutCol> </LayoutCol>
<style lang="scss" global> <style lang="scss">
.document { .document {
height: 100%; height: 100%;

View File

@ -689,7 +689,7 @@
</LayoutRow> </LayoutRow>
</LayoutCol> </LayoutCol>
<style lang="scss" global> <style lang="scss">
.layers { .layers {
// Control bar // Control bar
.control-bar { .control-bar {

View File

@ -28,7 +28,7 @@
</LayoutCol> </LayoutCol>
</LayoutCol> </LayoutCol>
<style lang="scss" global> <style lang="scss">
.properties { .properties {
height: 100%; height: 100%;
flex: 1 1 100%; flex: 1 1 100%;

View File

@ -56,7 +56,7 @@
</LayoutCol> </LayoutCol>
</LayoutCol> </LayoutCol>
<style lang="scss" global> <style lang="scss">
.welcome-panel { .welcome-panel {
background: var(--color-2-mildblack); background: var(--color-2-mildblack);
margin: 4px; margin: 4px;

View File

@ -813,7 +813,7 @@
></div> ></div>
{/if} {/if}
<style lang="scss" global> <style lang="scss">
.graph { .graph {
position: relative; position: relative;
overflow: hidden; overflow: hidden;
@ -996,7 +996,7 @@
z-index: 1; z-index: 1;
// Zero specificity with `:where()` to allow other rules to override `pointer-events` // Zero specificity with `:where()` to allow other rules to override `pointer-events`
:where(.graph-view.open & > *) { :where(.graph-view.open .graph .imports-and-exports > *) {
pointer-events: auto; pointer-events: auto;
} }
@ -1098,7 +1098,7 @@
height: 100%; height: 100%;
// Zero specificity with `:where()` to allow other rules to override `pointer-events` // Zero specificity with `:where()` to allow other rules to override `pointer-events`
:where(.graph-view.open & > *) { :where(.graph-view.open .graph .layers-and-nodes > *) {
pointer-events: auto; pointer-events: auto;
} }
} }

View File

@ -23,4 +23,4 @@
{/if} {/if}
{/each} {/each}
<style lang="scss" global></style> <style lang="scss"></style>

View File

@ -68,7 +68,7 @@
{/if} {/if}
</LayoutCol> </LayoutCol>
<style lang="scss" global> <style lang="scss">
.widget-section { .widget-section {
flex: 0 0 auto; flex: 0 0 auto;
margin: 0 4px; margin: 0 4px;

View File

@ -283,7 +283,7 @@
{/each} {/each}
</div> </div>
<style lang="scss" global> <style lang="scss">
.widget-span.column { .widget-span.column {
flex: 0 0 auto; flex: 0 0 auto;
display: flex; display: flex;

View File

@ -22,7 +22,7 @@
</tbody> </tbody>
</table> </table>
<style lang="scss" global> <style lang="scss">
table:not(.unstyled) { table:not(.unstyled) {
background: var(--color-3-darkgray); background: var(--color-3-darkgray);
border: none; border: none;

View File

@ -20,7 +20,7 @@
{/each} {/each}
</LayoutRow> </LayoutRow>
<style lang="scss" global> <style lang="scss">
.breadcrumb-trail-buttons { .breadcrumb-trail-buttons {
.text-button { .text-button {
position: relative; position: relative;

View File

@ -45,7 +45,7 @@
{/if} {/if}
</button> </button>
<style lang="scss" global> <style lang="scss">
.icon-button { .icon-button {
display: flex; display: flex;
justify-content: center; justify-content: center;

View File

@ -34,7 +34,7 @@
on:click={action} on:click={action}
/> />
<style lang="scss" global> <style lang="scss">
.image-button { .image-button {
width: auto; width: auto;
height: auto; height: auto;

View File

@ -44,7 +44,7 @@
</button> </button>
</LayoutRow> </LayoutRow>
<style lang="scss" global> <style lang="scss">
.parameter-expose-button { .parameter-expose-button {
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -54,7 +54,7 @@
</FloatingMenu> </FloatingMenu>
</LayoutRow> </LayoutRow>
<style lang="scss" global> <style lang="scss">
.popover-button { .popover-button {
position: relative; position: relative;
width: 16px; width: 16px;

View File

@ -105,7 +105,7 @@
{/if} {/if}
</ConditionalWrapper> </ConditionalWrapper>
<style lang="scss" global> <style lang="scss">
.text-button-container { .text-button-container {
display: flex; display: flex;
position: relative; position: relative;
@ -194,15 +194,15 @@
.text-label { .text-label {
overflow: hidden; overflow: hidden;
} }
}
// Custom styling for when multiple TextButton widgets are used next to one another in a row or column // Custom styling for when multiple TextButton widgets are used next to one another in a row or column
.widget-span.row > & + .text-button, .widget-span.row > .text-button + .text-button,
.layout-row > & + .text-button { .layout-row > .text-button + .text-button {
margin-left: 8px; margin-left: 8px;
} }
.widget-span.column > & + .text-button, .widget-span.column > .text-button + .text-button,
.layout-column > & + .text-button { .layout-column > .text-button + .text-button {
margin-top: 8px; margin-top: 8px;
}
} }
</style> </style>

View File

@ -63,7 +63,7 @@
</label> </label>
</LayoutRow> </LayoutRow>
<style lang="scss" global> <style lang="scss">
.checkbox-input { .checkbox-input {
flex: 0 0 auto; flex: 0 0 auto;
align-items: center; align-items: center;

View File

@ -56,7 +56,7 @@
/> />
</LayoutCol> </LayoutCol>
<style lang="scss" global> <style lang="scss">
.color-button { .color-button {
position: relative; position: relative;
min-width: 80px; min-width: 80px;

View File

@ -209,7 +209,7 @@
<slot /> <slot />
</LayoutRow> </LayoutRow>
<style lang="scss" global> <style lang="scss">
.curve-input { .curve-input {
background: var(--color-1-nearblack); background: var(--color-1-nearblack);
display: flex; display: flex;

View File

@ -161,7 +161,7 @@
/> />
</LayoutRow> </LayoutRow>
<style lang="scss" global> <style lang="scss">
.dropdown-input { .dropdown-input {
position: relative; position: relative;
--widget-height: 24px; --widget-height: 24px;

View File

@ -120,7 +120,7 @@
<slot /> <slot />
</LayoutRow> </LayoutRow>
<style lang="scss" global> <style lang="scss">
.field-input { .field-input {
min-width: 80px; min-width: 80px;
height: auto; height: auto;

View File

@ -794,7 +794,7 @@
{/if} {/if}
</FieldInput> </FieldInput>
<style lang="scss" global> <style lang="scss">
.number-input { .number-input {
&.narrow { &.narrow {
--widget-height: 20px; --widget-height: 20px;

View File

@ -46,7 +46,7 @@
{/each} {/each}
</LayoutRow> </LayoutRow>
<style lang="scss" global> <style lang="scss">
.radio-input { .radio-input {
background: var(--color-4-dimgray); background: var(--color-4-dimgray);
border-radius: 2px; border-radius: 2px;

View File

@ -35,7 +35,7 @@
<button on:click={() => setValue("BottomRight")} class="row-3 col-3" class:active={value === "BottomRight"} tabindex="-1" {disabled}><div></div></button> <button on:click={() => setValue("BottomRight")} class="row-3 col-3" class:active={value === "BottomRight"} tabindex="-1" {disabled}><div></div></button>
</div> </div>
<style lang="scss" global> <style lang="scss">
.reference-point-input { .reference-point-input {
position: relative; position: relative;
flex: 0 0 auto; flex: 0 0 auto;

View File

@ -111,7 +111,7 @@
</svg> </svg>
</div> </div>
<style lang="scss" global> <style lang="scss">
.ruler-input { .ruler-input {
flex: 1 1 100%; flex: 1 1 100%;
background: var(--color-2-mildblack); background: var(--color-2-mildblack);

View File

@ -214,7 +214,7 @@
<button class="arrow increase" on:pointerdown={() => pressArrow(1)} tabindex="-1" data-scrollbar-arrow></button> <button class="arrow increase" on:pointerdown={() => pressArrow(1)} tabindex="-1" data-scrollbar-arrow></button>
</div> </div>
<style lang="scss" global> <style lang="scss">
.scrollbar-input { .scrollbar-input {
display: flex; display: flex;
flex: 1 1 100%; flex: 1 1 100%;

View File

@ -414,7 +414,7 @@
</LayoutRow> </LayoutRow>
</LayoutCol> </LayoutCol>
<style lang="scss" global> <style lang="scss">
.spectrum-input { .spectrum-input {
position: relative; position: relative;
--marker-half-width: 6px; --marker-half-width: 6px;

View File

@ -63,5 +63,5 @@
bind:this={self} bind:this={self}
/> />
<style lang="scss" global> <style lang="scss">
</style> </style>

View File

@ -87,7 +87,7 @@
bind:this={self} bind:this={self}
/> />
<style lang="scss" global> <style lang="scss">
.text-input { .text-input {
flex-shrink: 0; flex-shrink: 0;

View File

@ -63,7 +63,7 @@
</LayoutRow> </LayoutRow>
</LayoutCol> </LayoutCol>
<style lang="scss" global> <style lang="scss">
.working-colors-button { .working-colors-button {
flex: 0 0 auto; flex: 0 0 auto;

View File

@ -37,7 +37,7 @@
{@html ICON_SVG_STRINGS[icon] || "<22>"} {@html ICON_SVG_STRINGS[icon] || "<22>"}
</LayoutRow> </LayoutRow>
<style lang="scss" global> <style lang="scss">
.icon-label { .icon-label {
flex: 0 0 auto; flex: 0 0 auto;
fill: var(--color-e-nearwhite); fill: var(--color-e-nearwhite);

View File

@ -30,7 +30,7 @@
alt="" alt=""
/> />
<style lang="scss" global> <style lang="scss">
.image-label { .image-label {
width: auto; width: auto;
height: auto; height: auto;

View File

@ -12,7 +12,7 @@
{/if} {/if}
</div> </div>
<style lang="scss" global> <style lang="scss">
.separator { .separator {
&.vertical { &.vertical {
flex: 0 0 auto; flex: 0 0 auto;

View File

@ -130,7 +130,7 @@
{/each} {/each}
</LayoutRow> </LayoutRow>
<style lang="scss" global> <style lang="scss">
.shortcut-label { .shortcut-label {
align-items: center; align-items: center;
@ -156,34 +156,34 @@
fill: var(--color-8-uppergray); fill: var(--color-8-uppergray);
} }
} }
}
.floating-menu-content .row > & { .floating-menu-content .row > .shortcut-label {
.key-label, .key-label,
.mouse-icon { .mouse-icon {
color: var(--color-8-uppergray); color: var(--color-8-uppergray);
background: none; background: none;
&:first-child { &:first-child {
padding-left: 0; padding-left: 0;
}
&:last-child {
padding-right: 0;
}
} }
.key-label svg { &:last-child {
fill: var(--color-8-uppergray); padding-right: 0;
} }
}
.mouse-icon svg { .key-label svg {
// 3 shades brighter than the 8-uppergray of key labels/icons fill: var(--color-8-uppergray);
fill: var(--color-b-lightgray); }
.dim { .mouse-icon svg {
// 3 shades darker than the 8-uppergray of key labels/icons // 3 shades brighter than the 8-uppergray of key labels/icons
fill: var(--color-5-dullgray); fill: var(--color-b-lightgray);
}
.dim {
// 3 shades darker than the 8-uppergray of key labels/icons
fill: var(--color-5-dullgray);
} }
} }
} }

View File

@ -88,7 +88,7 @@
<slot /> <slot />
</label> </label>
<style lang="scss" global> <style lang="scss">
.text-label { .text-label {
line-height: 18px; line-height: 18px;
white-space: nowrap; white-space: nowrap;

View File

@ -41,7 +41,7 @@
{/if} {/if}
</LayoutCol> </LayoutCol>
<style lang="scss" global> <style lang="scss">
.main-window { .main-window {
height: 100%; height: 100%;
overflow: auto; overflow: auto;

View File

@ -250,7 +250,7 @@
</LayoutCol> </LayoutCol>
</LayoutCol> </LayoutCol>
<style lang="scss" global> <style lang="scss">
.panel { .panel {
background: var(--color-1-nearblack); background: var(--color-1-nearblack);
border-radius: 6px; border-radius: 6px;

View File

@ -36,7 +36,7 @@
<WidgetLayout class="info" layout={statusBarInfoLayout} layoutTarget="StatusBarInfo" /> <WidgetLayout class="info" layout={statusBarInfoLayout} layoutTarget="StatusBarInfo" />
</LayoutRow> </LayoutRow>
<style lang="scss" global> <style lang="scss">
.status-bar { .status-bar {
height: 24px; height: 24px;
width: 100%; width: 100%;

View File

@ -79,7 +79,7 @@
</LayoutRow> </LayoutRow>
</LayoutRow> </LayoutRow>
<style lang="scss" global> <style lang="scss">
.title-bar { .title-bar {
flex: 0 0 auto; flex: 0 0 auto;
height: var(--height); height: var(--height);

View File

@ -203,7 +203,7 @@
</LayoutRow> </LayoutRow>
</LayoutRow> </LayoutRow>
<style lang="scss" global> <style lang="scss">
.workspace { .workspace {
position: relative; position: relative;
flex: 1 1 100%; flex: 1 1 100%;

View File

@ -1,7 +1,7 @@
import { sveltePreprocess } from "svelte-preprocess"; import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";
export default { export default {
preprocess: sveltePreprocess(), preprocess: [vitePreprocess()],
compilerOptions: /** @type {import("svelte/compiler").ModuleCompileOptions} */ ({ compilerOptions: /** @type {import("svelte/compiler").ModuleCompileOptions} */ ({
warningFilter: (warning) => !warning.code.startsWith("a11y_") && !["css_unused_selector"].includes(warning.code), warningFilter: (warning) => !warning.code.startsWith("a11y_") && !["css_unused_selector"].includes(warning.code),
}), }),

View File

@ -11,7 +11,7 @@ const projectRootDir = path.resolve(__dirname);
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig(({ mode }) => { export default defineConfig(({ mode }) => {
return { return {
plugins: [svelte(), staticAssets(), mode !== "native" && thirdPartyLicenses(), mode !== "native" && serviceWorker()], plugins: [svelteGlobalStyles(), svelte(), staticAssets(), mode !== "native" && thirdPartyLicenses(), mode !== "native" && serviceWorker()],
resolve: { resolve: {
alias: [{ find: /\/..\/branding\/(.*\.svg)/, replacement: path.resolve(projectRootDir, "../branding", "$1?raw") }], alias: [{ find: /\/..\/branding\/(.*\.svg)/, replacement: path.resolve(projectRootDir, "../branding", "$1?raw") }],
}, },
@ -22,6 +22,19 @@ export default defineConfig(({ mode }) => {
}; };
}); });
// Wraps the content of every `<style lang="scss">...</style>` block in Svelte components with `:global { ... }` to work around Svelte's unwanted scoped styles
function svelteGlobalStyles(): PluginOption {
return {
name: "svelte-global-styles",
enforce: "pre",
transform(code, id) {
if (!id.endsWith(".svelte")) return;
return code.replace(/<style(?=\s|>)([^>]*)>(.*?)<\/style>/gs, (_, attrs, content) => `<style${attrs}>\n:global {\n${content}\n}\n</style>`);
},
};
}
function staticAssets(): PluginOption { function staticAssets(): PluginOption {
const STATIC_ASSET_DIRS: { source: string; urlPrefix: string }[] = [ const STATIC_ASSET_DIRS: { source: string; urlPrefix: string }[] = [
{ source: "../demo-artwork", urlPrefix: "/demo-artwork" }, { source: "../demo-artwork", urlPrefix: "/demo-artwork" },