move to rsbuild over webpack
This commit is contained in:
@@ -4,8 +4,8 @@
|
||||
"description": "an IC10 emulator for IC10 mips from Stationeers",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "webpack --config webpack.config.prod.js",
|
||||
"start": "webpack-dev-server"
|
||||
"build": "rsbuild build",
|
||||
"start": "rsbuild dev"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -25,39 +25,24 @@
|
||||
"homepage": "https://github.com/ryex/ic10emu#readme",
|
||||
"devDependencies": {
|
||||
"@oneidentity/zstd-js": "^1.0.3",
|
||||
"@rsbuild/core": "^0.6.4",
|
||||
"@rsbuild/plugin-image-compress": "^0.6.4",
|
||||
"@rsbuild/plugin-type-check": "^0.6.4",
|
||||
"@rspack/cli": "^0.6.2",
|
||||
"@rspack/core": "^0.6.2",
|
||||
"@swc/helpers": "^0.5.10",
|
||||
"@types/ace": "^0.0.52",
|
||||
"@types/bootstrap": "^5.2.10",
|
||||
"@types/wicg-file-system-access": "^2023.10.5",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"copy-webpack-plugin": "^12.0.2",
|
||||
"css-loader": "^6.11.0",
|
||||
"css-minimizer-webpack-plugin": "^6.0.0",
|
||||
"esbuild": "^0.20.2",
|
||||
"esbuild-loader": "^4.1.0",
|
||||
"extract-loader": "^5.1.0",
|
||||
"fork-ts-checker-webpack-plugin": "^9.0.2",
|
||||
"hello-wasm-pack": "^0.1.0",
|
||||
"html-webpack-plugin": "^5.6.0",
|
||||
"image-minimizer-webpack-plugin": "^4.0.0",
|
||||
"imagemin": "^8.0.1",
|
||||
"imagemin-gifsicle": "^7.0.0",
|
||||
"imagemin-jpegtran": "^7.0.0",
|
||||
"imagemin-optipng": "^8.0.0",
|
||||
"imagemin-svgo": "^10.0.1",
|
||||
"lit-scss-loader": "^2.0.1",
|
||||
"mini-css-extract-plugin": "^2.9.0",
|
||||
"postcss-loader": "^8.1.1",
|
||||
"sass": "^1.75.0",
|
||||
"sass-loader": "^14.2.1",
|
||||
"style-loader": "^3.3.4",
|
||||
"thread-loader": "^4.0.2",
|
||||
"ts-lit-plugin": "^2.0.2",
|
||||
"ts-loader": "^9.5.1",
|
||||
"typescript": "^5.4.5",
|
||||
"typescript-lit-html-plugin": "^0.9.0",
|
||||
"webpack": "^5.91.0",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack-dev-server": "^5.0.4"
|
||||
"typescript-lit-html-plugin": "^0.9.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@leeoniya/ufuzzy": "^1.0.14",
|
||||
|
||||
4589
www/pnpm-lock.yaml
generated
4589
www/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
70
www/rsbuild.config.ts
Normal file
70
www/rsbuild.config.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { defineConfig } from "@rsbuild/core";
|
||||
import { pluginTypeCheck } from "@rsbuild/plugin-type-check";
|
||||
import { pluginImageCompress } from '@rsbuild/plugin-image-compress';
|
||||
|
||||
const rspack = require("@rspack/core");
|
||||
|
||||
const path = require("path");
|
||||
const commitHash = require("child_process")
|
||||
.execSync("git rev-parse --short HEAD")
|
||||
.toString()
|
||||
.trim();
|
||||
|
||||
export default defineConfig({
|
||||
output: {
|
||||
targets: ["web"],
|
||||
},
|
||||
source: {
|
||||
entry: {
|
||||
index: "./src/ts/index.ts",
|
||||
},
|
||||
},
|
||||
tools: {
|
||||
rspack: {
|
||||
plugins: [
|
||||
new rspack.CopyRspackPlugin({
|
||||
patterns: [
|
||||
// "src/index.html",
|
||||
"img/*.png",
|
||||
"img/*/*.png",
|
||||
// { from: "data/database.json", to: "data" },
|
||||
// Copy Shoelace assets to dist/shoelace
|
||||
{
|
||||
from: path.resolve(
|
||||
__dirname,
|
||||
"node_modules/@shoelace-style/shoelace/dist/assets",
|
||||
),
|
||||
to: "shoelace/assets",
|
||||
},
|
||||
],
|
||||
}),
|
||||
new rspack.DefinePlugin({
|
||||
__COMMIT_HASH__: JSON.stringify(commitHash),
|
||||
__BUILD_DATE__: JSON.stringify(new Date()),
|
||||
}),
|
||||
],
|
||||
},
|
||||
swc: {
|
||||
jsc: {
|
||||
parser: {
|
||||
syntax: "typescript",
|
||||
// dynamicImport: true,
|
||||
decorators: true,
|
||||
},
|
||||
transform: {
|
||||
legacyDecorator: true,
|
||||
decoratorMetadata: true,
|
||||
// decoratorVersion: "2022-03",
|
||||
},
|
||||
// target: "es2021",
|
||||
},
|
||||
},
|
||||
htmlPlugin: {
|
||||
template: "./src/index.html",
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
pluginTypeCheck(),
|
||||
pluginImageCompress(),
|
||||
],
|
||||
});
|
||||
@@ -12,6 +12,7 @@
|
||||
<meta property="og:url" content="https://ryex.github.io/ic10emu/" />
|
||||
|
||||
<link rel="stylesheet" href="./main.css">
|
||||
<script src="./main.js"></script>
|
||||
<style>
|
||||
body {
|
||||
opacity: 0;
|
||||
|
||||
@@ -2,14 +2,14 @@ import { HTMLTemplateResult, html, css } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
import { BaseElement, defaultCss } from "../components";
|
||||
|
||||
import '@shoelace-style/shoelace/dist/components/icon/icon.js';
|
||||
import "@shoelace-style/shoelace/dist/components/icon/icon.js";
|
||||
import "@shoelace-style/shoelace/dist/components/icon-button/icon-button.js";
|
||||
import "@shoelace-style/shoelace/dist/components/menu/menu.js";
|
||||
import "@shoelace-style/shoelace/dist/components/divider/divider.js";
|
||||
import "@shoelace-style/shoelace/dist/components/menu-item/menu-item.js";
|
||||
import "@shoelace-style/shoelace/dist/components/dropdown/dropdown.js";
|
||||
import '@shoelace-style/shoelace/dist/components/relative-time/relative-time.js';
|
||||
import '@shoelace-style/shoelace/dist/components/tooltip/tooltip.js';
|
||||
import "@shoelace-style/shoelace/dist/components/relative-time/relative-time.js";
|
||||
import "@shoelace-style/shoelace/dist/components/tooltip/tooltip.js";
|
||||
import SlMenuItem from "@shoelace-style/shoelace/dist/components/menu-item/menu-item.js";
|
||||
|
||||
@customElement("app-nav")
|
||||
@@ -99,9 +99,9 @@ export class Nav extends BaseElement {
|
||||
super();
|
||||
}
|
||||
|
||||
@property() accessor gitVer: string;
|
||||
@property() accessor appVer: string;
|
||||
@property() accessor buildDate: string;
|
||||
@property() gitVer: string;
|
||||
@property() appVer: string;
|
||||
@property() buildDate: string;
|
||||
protected render(): HTMLTemplateResult {
|
||||
return html`
|
||||
<nav id="navBar" class="navbar navbar-default">
|
||||
@@ -114,7 +114,11 @@ export class Nav extends BaseElement {
|
||||
label="Main Menu"
|
||||
></sl-icon-button>
|
||||
|
||||
<sl-menu class="menu" @sl-select=${this._menuClickHandler} style="z-index: 10">
|
||||
<sl-menu
|
||||
class="menu"
|
||||
@sl-select=${this._menuClickHandler}
|
||||
style="z-index: 10"
|
||||
>
|
||||
<sl-menu-item value="share">
|
||||
Share
|
||||
<sl-icon name="share" slot="prefix"></sl-icon>
|
||||
@@ -150,9 +154,7 @@ export class Nav extends BaseElement {
|
||||
Presets
|
||||
<sl-icon name="code-square" slot="prefix"></sl-icon>
|
||||
<sl-menu slot="submenu">
|
||||
<sl-menu-item value="preset-demo">
|
||||
Demo
|
||||
</sl-menu-item>
|
||||
<sl-menu-item value="preset-demo"> Demo </sl-menu-item>
|
||||
</sl-menu>
|
||||
</sl-menu-item>
|
||||
</sl-menu>
|
||||
@@ -167,7 +169,9 @@ export class Nav extends BaseElement {
|
||||
</div>
|
||||
<div class="hstack version mt-auto mb-auto">
|
||||
<small>v${this.appVer}-${this.gitVer}</small>
|
||||
<small class="ms-2"><sl-relative-time date=${this.buildDate}></sl-relative-time></small>
|
||||
<small class="ms-2">
|
||||
<sl-relative-time date=${this.buildDate}></sl-relative-time>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -175,7 +179,8 @@ export class Nav extends BaseElement {
|
||||
<a
|
||||
class="navbar-text mt-auto mb-auto align-self-center"
|
||||
href="https://github.com/ryex/ic10emu"
|
||||
>View on Github <sl-icon library="fa" name="fab-github"></sl-icon>
|
||||
>View on Github
|
||||
<sl-icon library="fa" name="fab-github"></sl-icon>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -239,7 +244,7 @@ export class Nav extends BaseElement {
|
||||
case "keyboardShortcuts":
|
||||
window.Editor.kbShortcuts.show();
|
||||
break;
|
||||
case 'preset-demo':
|
||||
case "preset-demo":
|
||||
window.location.hash = "demo";
|
||||
default:
|
||||
console.log("Unknown main menu item", item.value);
|
||||
|
||||
@@ -3,11 +3,11 @@ import { customElement, property, query, state } from "lit/decorators.js";
|
||||
import { BaseElement, defaultCss } from "../components";
|
||||
import { VMState } from "../session";
|
||||
|
||||
import '@shoelace-style/shoelace/dist/components/dialog/dialog.js';
|
||||
import '@shoelace-style/shoelace/dist/components/format-date/format-date.js';
|
||||
import '@shoelace-style/shoelace/dist/components/relative-time/relative-time.js';
|
||||
import '@shoelace-style/shoelace/dist/components/format-bytes/format-bytes.js';
|
||||
import SlInput from '@shoelace-style/shoelace/dist/components/input/input.js';
|
||||
import "@shoelace-style/shoelace/dist/components/dialog/dialog.js";
|
||||
import "@shoelace-style/shoelace/dist/components/format-date/format-date.js";
|
||||
import "@shoelace-style/shoelace/dist/components/relative-time/relative-time.js";
|
||||
import "@shoelace-style/shoelace/dist/components/format-bytes/format-bytes.js";
|
||||
import SlInput from "@shoelace-style/shoelace/dist/components/input/input.js";
|
||||
import { repeat } from "lit/directives/repeat.js";
|
||||
import SlDialog from "@shoelace-style/shoelace/dist/components/dialog/dialog.js";
|
||||
import { when } from "lit/directives/when.js";
|
||||
@@ -16,12 +16,10 @@ export type SaveDialogMode = "save" | "load";
|
||||
|
||||
@customElement("save-dialog")
|
||||
export class SaveDialog extends BaseElement {
|
||||
static styles = [
|
||||
...defaultCss,
|
||||
];
|
||||
static styles = [...defaultCss];
|
||||
|
||||
@state() accessor saves: { name: string, date: Date, session: VMState }[];
|
||||
@state() accessor mode: SaveDialogMode;
|
||||
@state() saves: { name: string; date: Date; session: VMState }[];
|
||||
@state() mode: SaveDialogMode;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
@@ -29,8 +27,13 @@ export class SaveDialog extends BaseElement {
|
||||
}
|
||||
|
||||
connectedCallback(): void {
|
||||
super.connectedCallback()
|
||||
window.App.get().then(app => app.session.addEventListener("sessions-local-update", this._handleSessionsUpdate.bind(this)));
|
||||
super.connectedCallback();
|
||||
window.App.get().then((app) =>
|
||||
app.session.addEventListener(
|
||||
"sessions-local-update",
|
||||
this._handleSessionsUpdate.bind(this),
|
||||
),
|
||||
);
|
||||
this.loadsaves();
|
||||
}
|
||||
|
||||
@@ -45,7 +48,7 @@ export class SaveDialog extends BaseElement {
|
||||
});
|
||||
}
|
||||
|
||||
@query("sl-dialog") accessor dialog: SlDialog;
|
||||
@query("sl-dialog") dialog: SlDialog;
|
||||
|
||||
show(mode: SaveDialogMode) {
|
||||
this.mode = mode;
|
||||
@@ -59,16 +62,27 @@ export class SaveDialog extends BaseElement {
|
||||
render() {
|
||||
return html`
|
||||
<sl-dialog label="Save Session">
|
||||
${when(this.mode === "save",
|
||||
${when(
|
||||
this.mode === "save",
|
||||
() => html`
|
||||
<div class="hstack mb-2">
|
||||
<sl-input class="save-name-input" autofocus></sl-input>
|
||||
<sl-button class="ms-2" variant="success" @click=${this._handleSaveClick}>Save</sl-button>
|
||||
</div>
|
||||
`
|
||||
<div class="hstack mb-2">
|
||||
<sl-input class="save-name-input" autofocus></sl-input>
|
||||
<sl-button
|
||||
class="ms-2"
|
||||
variant="success"
|
||||
@click=${this._handleSaveClick}
|
||||
>Save</sl-button
|
||||
>
|
||||
</div>
|
||||
`,
|
||||
)}
|
||||
<sl-input class="filter-input" ?autofocus=${this.mode === "load"} placeholder="Filter Saves" clearable
|
||||
@sl-input=${this._handleSearchInput}>
|
||||
<sl-input
|
||||
class="filter-input"
|
||||
?autofocus=${this.mode === "load"}
|
||||
placeholder="Filter Saves"
|
||||
clearable
|
||||
@sl-input=${this._handleSearchInput}
|
||||
>
|
||||
<sl-icon slot="suffix" name="search"></sl-icon>
|
||||
</sl-input>
|
||||
<table>
|
||||
@@ -77,22 +91,26 @@ export class SaveDialog extends BaseElement {
|
||||
<th>Date</th>
|
||||
<th>Size</th>
|
||||
</tr>
|
||||
${when(
|
||||
typeof this.saves !== "undefined",
|
||||
() => repeat(this.saves, (save) => save.name, (save) => {
|
||||
const size = JSON.stringify(save.session).length
|
||||
return html`
|
||||
<tr>
|
||||
<td>${save.name}</td>
|
||||
<td>
|
||||
<sl-format-date .date=${save.date}></sl-format-date>
|
||||
<sl-relative-time .date=${save.date}></sl-relative-time>
|
||||
</td>
|
||||
<td><sl-format-bytes .value=${size}></sl-format-bytes></td>
|
||||
</tr>
|
||||
`;
|
||||
},
|
||||
)
|
||||
${when(typeof this.saves !== "undefined", () =>
|
||||
repeat(
|
||||
this.saves,
|
||||
(save) => save.name,
|
||||
(save) => {
|
||||
const size = JSON.stringify(save.session).length;
|
||||
return html`
|
||||
<tr>
|
||||
<td>${save.name}</td>
|
||||
<td>
|
||||
<sl-format-date .date=${save.date}></sl-format-date>
|
||||
<sl-relative-time .date=${save.date}></sl-relative-time>
|
||||
</td>
|
||||
<td>
|
||||
<sl-format-bytes .value=${size}></sl-format-bytes>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
},
|
||||
),
|
||||
)}
|
||||
</table>
|
||||
</sl-dialog>
|
||||
@@ -108,7 +126,5 @@ export class SaveDialog extends BaseElement {
|
||||
await app.session.saveLocal(name);
|
||||
}
|
||||
|
||||
_handleSearchInput() {
|
||||
|
||||
}
|
||||
_handleSearchInput() {}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,9 @@ import SlInput from "@shoelace-style/shoelace/dist/components/input/input.js";
|
||||
|
||||
@customElement("session-share-dialog")
|
||||
export class ShareSessionDialog extends BaseElement {
|
||||
@query(".dialog") accessor dialog: SlDialog;
|
||||
@query(".input") accessor input: SlInput;
|
||||
@property({ type: String }) accessor link: string;
|
||||
@query(".dialog") dialog: SlDialog;
|
||||
@query(".input") input: SlInput;
|
||||
@property({ type: String }) link: string;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
@@ -11,7 +11,7 @@ import SlDetails from "@shoelace-style/shoelace/dist/components/details/details.
|
||||
|
||||
@customElement("ic10-details")
|
||||
export class IC10Details extends SlDetails {
|
||||
@query(".details__summary-icon") accessor summaryIcon: HTMLSpanElement;
|
||||
@query(".details__summary-icon") summaryIcon: HTMLSpanElement;
|
||||
|
||||
static styles = [
|
||||
SlDetails.styles,
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
import {
|
||||
ace,
|
||||
Ace,
|
||||
Range,
|
||||
AceLanguageClient,
|
||||
setupLspWorker,
|
||||
} from "./ace";
|
||||
import { ace, Ace, Range, AceLanguageClient, setupLspWorker } from "./ace";
|
||||
|
||||
import { LanguageProvider } from "ace-linters/types/language-provider";
|
||||
|
||||
@@ -32,7 +26,10 @@ import { customElement, state, query } from "lit/decorators.js";
|
||||
import { editorStyles } from "./styles";
|
||||
import "./shortcuts_ui";
|
||||
import { AceKeyboardShortcuts } from "./shortcuts_ui";
|
||||
import { LanguageClientConfig, ProviderOptions } from "ace-linters/types/types/language-service";
|
||||
import {
|
||||
LanguageClientConfig,
|
||||
ProviderOptions,
|
||||
} from "ace-linters/types/types/language-service";
|
||||
|
||||
@customElement("ace-ic10")
|
||||
export class IC10Editor extends BaseElement {
|
||||
@@ -69,9 +66,9 @@ export class IC10Editor extends BaseElement {
|
||||
stylesAdded: string[];
|
||||
tooltipObserver: MutationObserver;
|
||||
|
||||
@query(".e-kb-shortcuts") accessor kbShortcuts: AceKeyboardShortcuts;
|
||||
@query(".e-kb-shortcuts") kbShortcuts: AceKeyboardShortcuts;
|
||||
|
||||
@query(".e-settings-dialog") accessor settingDialog: SlDialog;
|
||||
@query(".e-settings-dialog") settingDialog: SlDialog;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
@@ -137,8 +134,9 @@ export class IC10Editor extends BaseElement {
|
||||
<sl-switch
|
||||
id="editorRelativeLineNumbers"
|
||||
?checked=${this.settings.relativeLineNumbers}
|
||||
>Relative Line Numbers</sl-switch
|
||||
>
|
||||
>
|
||||
Relative Line Numbers
|
||||
</sl-switch>
|
||||
</sl-dialog>
|
||||
<ace-kb-menu class="e-kb-shortcuts"></ace-kb-menu>
|
||||
`;
|
||||
@@ -513,9 +511,9 @@ export class IC10Editor extends BaseElement {
|
||||
};
|
||||
const options: ProviderOptions = {
|
||||
functionality: {
|
||||
semanticTokens: true
|
||||
}
|
||||
}
|
||||
semanticTokens: true,
|
||||
},
|
||||
};
|
||||
// Create a language provider for web worker
|
||||
this.languageProvider = AceLanguageClient.for(serverData, options);
|
||||
this.languageProvider.registerEditor(this.editor);
|
||||
@@ -589,7 +587,9 @@ export class IC10Editor extends BaseElement {
|
||||
if (session) {
|
||||
session.on("change", () => {
|
||||
var val = session.getValue();
|
||||
window.App.get().then(app => app.session.setProgramCode(session_id, val));
|
||||
window.App.get().then((app) =>
|
||||
app.session.setProgramCode(session_id, val),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ export class AceKeyboardShortcuts extends BaseElement {
|
||||
];
|
||||
|
||||
editor?: Ace.Editor;
|
||||
@query('.drawer') accessor drawer: SlDrawer;
|
||||
@query(".drawer") drawer: SlDrawer;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
@@ -47,7 +47,6 @@ export const VMDeviceMixin = <T extends Constructor<LitElement>>(
|
||||
superClass: T,
|
||||
) => {
|
||||
class VMDeviceMixinClass extends superClass {
|
||||
|
||||
_deviceID: number;
|
||||
get deviceID() {
|
||||
return this._deviceID;
|
||||
@@ -60,33 +59,37 @@ export const VMDeviceMixin = <T extends Constructor<LitElement>>(
|
||||
|
||||
device: DeviceRef;
|
||||
|
||||
@state() accessor name: string | null = null;
|
||||
@state() accessor nameHash: number | null = null;
|
||||
@state() accessor prefabName: string | null;
|
||||
@state() accessor fields: LogicFields;
|
||||
@state() accessor slots: Slot[];
|
||||
@state() accessor reagents: Reagents;
|
||||
@state() accessor connections: Connection[];
|
||||
@state() accessor icIP: number;
|
||||
@state() accessor icOpCount: number;
|
||||
@state() accessor icState: string;
|
||||
@state() accessor errors: ICError[];
|
||||
@state() accessor registers: Registers | null;
|
||||
@state() accessor stack: Stack | null;
|
||||
@state() accessor aliases: Aliases | null;
|
||||
@state() accessor defines: Defines | null;
|
||||
@state() accessor pins: Pins | null;
|
||||
@state() name: string | null = null;
|
||||
@state() nameHash: number | null = null;
|
||||
@state() prefabName: string | null;
|
||||
@state() fields: LogicFields;
|
||||
@state() slots: Slot[];
|
||||
@state() reagents: Reagents;
|
||||
@state() connections: Connection[];
|
||||
@state() icIP: number;
|
||||
@state() icOpCount: number;
|
||||
@state() icState: string;
|
||||
@state() errors: ICError[];
|
||||
@state() registers: Registers | null;
|
||||
@state() stack: Stack | null;
|
||||
@state() aliases: Aliases | null;
|
||||
@state() defines: Defines | null;
|
||||
@state() pins: Pins | null;
|
||||
|
||||
connectedCallback(): void {
|
||||
const root = super.connectedCallback();
|
||||
window.VM.get().then(vm => vm.addEventListener(
|
||||
"vm-device-modified",
|
||||
this._handleDeviceModified.bind(this),
|
||||
));
|
||||
window.VM.get().then(vm => vm.addEventListener(
|
||||
"vm-devices-update",
|
||||
this._handleDevicesModified.bind(this),
|
||||
));
|
||||
window.VM.get().then((vm) =>
|
||||
vm.addEventListener(
|
||||
"vm-device-modified",
|
||||
this._handleDeviceModified.bind(this),
|
||||
),
|
||||
);
|
||||
window.VM.get().then((vm) =>
|
||||
vm.addEventListener(
|
||||
"vm-devices-update",
|
||||
this._handleDevicesModified.bind(this),
|
||||
),
|
||||
);
|
||||
this.updateDevice();
|
||||
return root;
|
||||
}
|
||||
@@ -194,10 +197,9 @@ export const VMActiveICMixin = <T extends Constructor<LitElement>>(
|
||||
|
||||
connectedCallback(): void {
|
||||
const root = super.connectedCallback();
|
||||
window.VM.get().then(vm => vm.addEventListener(
|
||||
"vm-run-ic",
|
||||
this._handleDeviceModified.bind(this),
|
||||
));
|
||||
window.VM.get().then((vm) =>
|
||||
vm.addEventListener("vm-run-ic", this._handleDeviceModified.bind(this)),
|
||||
);
|
||||
window.App.app.session.addEventListener(
|
||||
"session-active-ic",
|
||||
this._handleActiveIC.bind(this),
|
||||
|
||||
@@ -65,7 +65,7 @@ export class VMICControls extends VMActiveICMixin(BaseElement) {
|
||||
`,
|
||||
];
|
||||
|
||||
@query(".active-ic-select") accessor activeICSelect: SlSelect;
|
||||
@query(".active-ic-select") activeICSelect: SlSelect;
|
||||
|
||||
protected render() {
|
||||
const ics = Array.from(window.VM.vm.ics);
|
||||
@@ -125,7 +125,11 @@ export class VMICControls extends VMActiveICMixin(BaseElement) {
|
||||
>
|
||||
${ics.map(
|
||||
([id, device], _index) =>
|
||||
html`<sl-option name=${device.name} prefabName=${device.prefabName} value=${id}>
|
||||
html`<sl-option
|
||||
name=${device.name}
|
||||
prefabName=${device.prefabName}
|
||||
value=${id}
|
||||
>
|
||||
${device.name
|
||||
? html`<span slot="suffix">${device.prefabName}</span>`
|
||||
: ""}
|
||||
@@ -170,13 +174,13 @@ export class VMICControls extends VMActiveICMixin(BaseElement) {
|
||||
}
|
||||
|
||||
_handleRunClick() {
|
||||
window.VM.get().then(vm => vm.run());
|
||||
window.VM.get().then((vm) => vm.run());
|
||||
}
|
||||
_handleStepClick() {
|
||||
window.VM.get().then(vm => vm.step());
|
||||
window.VM.get().then((vm) => vm.step());
|
||||
}
|
||||
_handleResetClick() {
|
||||
window.VM.get().then(vm => vm.reset());
|
||||
window.VM.get().then((vm) => vm.reset());
|
||||
}
|
||||
|
||||
updateIC(): void {
|
||||
|
||||
@@ -53,7 +53,7 @@ import { cache } from "lit/directives/cache.js";
|
||||
export class VMDeviceCard extends VMDeviceMixin(BaseElement) {
|
||||
image_err: boolean;
|
||||
|
||||
@property({ type: Boolean }) accessor open: boolean;
|
||||
@property({ type: Boolean }) open: boolean;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
@@ -200,68 +200,31 @@ export class VMDeviceCard extends VMDeviceMixin(BaseElement) {
|
||||
}, this);
|
||||
return html`
|
||||
<sl-tooltip content="${this.prefabName}">
|
||||
<img
|
||||
class="image"
|
||||
src="img/stationpedia/${this.prefabName}.png"
|
||||
onerror="this.src = '${VMDeviceCard.transparentImg}'"
|
||||
/>
|
||||
<img class="image" src="img/stationpedia/${this.prefabName}.png"
|
||||
onerror="this.src = '${VMDeviceCard.transparentImg}'" />
|
||||
</sl-tooltip>
|
||||
<div class="header-name">
|
||||
<sl-input
|
||||
id="vmDeviceCard${this.deviceID}Id"
|
||||
class="device-id"
|
||||
size="small"
|
||||
pill
|
||||
value=${this.deviceID}
|
||||
@sl-change=${this._handleChangeID}
|
||||
>
|
||||
<sl-input id="vmDeviceCard${this.deviceID}Id" class="device-id" size="small" pill value=${this.deviceID}
|
||||
@sl-change=${this._handleChangeID}>
|
||||
<span slot="prefix">Id</span>
|
||||
<sl-copy-button slot="suffix" value=${this.deviceID}></sl-copy-button>
|
||||
</sl-input>
|
||||
<sl-input
|
||||
id="vmDeviceCard${this.deviceID}Name"
|
||||
class="device-name"
|
||||
size="small"
|
||||
pill
|
||||
placeholder=${this.prefabName}
|
||||
value=${this.name}
|
||||
@sl-change=${this._handleChangeName}
|
||||
>
|
||||
<sl-input id="vmDeviceCard${this.deviceID}Name" class="device-name" size="small" pill placeholder=${this.prefabName}
|
||||
value=${this.name} @sl-change=${this._handleChangeName}>
|
||||
<span slot="prefix">Name</span>
|
||||
<sl-copy-button
|
||||
slot="suffix"
|
||||
from="vmDeviceCard${this.deviceID}Name.value"
|
||||
></sl-copy-button>
|
||||
<sl-copy-button slot="suffix" from="vmDeviceCard${this.deviceID}Name.value"></sl-copy-button>
|
||||
</sl-input>
|
||||
<sl-input
|
||||
id="vmDeviceCard${this.deviceID}NameHash"
|
||||
size="small"
|
||||
pill
|
||||
class="device-name-hash"
|
||||
value="${this.nameHash}"
|
||||
disabled
|
||||
>
|
||||
<sl-input id="vmDeviceCard${this.deviceID}NameHash" size="small" pill class="device-name-hash"
|
||||
value="${this.nameHash}" disabled>
|
||||
<span slot="prefix">Hash</span>
|
||||
<sl-copy-button
|
||||
slot="suffix"
|
||||
from="vmDeviceCard${this.deviceID}NameHash.value"
|
||||
></sl-copy-button>
|
||||
<sl-copy-button slot="suffix" from="vmDeviceCard${this.deviceID}NameHash.value"></sl-copy-button>
|
||||
</sl-input>
|
||||
${badges.map((badge) => badge)}
|
||||
</div>
|
||||
<div class="ms-auto mt-auto mb-auto me-2">
|
||||
<sl-tooltip
|
||||
content=${thisIsActiveIc
|
||||
? "Removing the selected Active IC is disabled"
|
||||
: "Remove Device"}
|
||||
>
|
||||
<sl-icon-button
|
||||
class="remove-button"
|
||||
name="trash"
|
||||
label="Remove Device"
|
||||
?disabled=${thisIsActiveIc}
|
||||
@click=${this._handleDeviceRemoveButton}
|
||||
></sl-icon-button>
|
||||
<sl-tooltip content=${thisIsActiveIc ? "Removing the selected Active IC is disabled" : "Remove Device" }>
|
||||
<sl-icon-button class="remove-button" name="trash" label="Remove Device" ?disabled=${thisIsActiveIc}
|
||||
@click=${this._handleDeviceRemoveButton}></sl-icon-button>
|
||||
</sl-tooltip>
|
||||
</div>
|
||||
`;
|
||||
@@ -272,20 +235,12 @@ export class VMDeviceCard extends VMDeviceMixin(BaseElement) {
|
||||
const inputIdBase = `vmDeviceCard${this.deviceID}Field`;
|
||||
return html`
|
||||
${fields.map(([name, field], _index, _fields) => {
|
||||
return html` <sl-input
|
||||
id="${inputIdBase}${name}"
|
||||
key="${name}"
|
||||
value="${displayNumber(field.value)}"
|
||||
size="small"
|
||||
@sl-change=${this._handleChangeField}
|
||||
>
|
||||
<span slot="prefix">${name}</span>
|
||||
<sl-copy-button
|
||||
slot="suffix"
|
||||
from="${inputIdBase}${name}.value"
|
||||
></sl-copy-button>
|
||||
<span slot="suffix">${field.field_type}</span>
|
||||
</sl-input>`;
|
||||
return html` <sl-input id="${inputIdBase}${name}" key="${name}" value="${displayNumber(field.value)}" size="small"
|
||||
@sl-change=${this._handleChangeField}>
|
||||
<span slot="prefix">${name}</span>
|
||||
<sl-copy-button slot="suffix" from="${inputIdBase}${name}.value"></sl-copy-button>
|
||||
<span slot="suffix">${field.field_type}</span>
|
||||
</sl-input>`;
|
||||
})}
|
||||
`;
|
||||
}
|
||||
@@ -396,8 +351,8 @@ export class VMDeviceCard extends VMDeviceMixin(BaseElement) {
|
||||
(pin, index) =>
|
||||
html`
|
||||
<sl-select hoist placement="top" clearable key=${index} value=${pin} @sl-change=${this._handleChangePin}>
|
||||
<span slot="prefix">d${index}</span>
|
||||
${visibleDevices.map(
|
||||
<span slot="prefix">d${index}</span>
|
||||
${visibleDevices.map(
|
||||
(device, _index) =>
|
||||
html`
|
||||
<sl-option value=${device.id}>
|
||||
@@ -425,47 +380,31 @@ export class VMDeviceCard extends VMDeviceMixin(BaseElement) {
|
||||
<sl-tab slot="nav" panel="networks">Networks</sl-tab>
|
||||
<sl-tab slot="nav" panel="pins" ?disabled=${!this.pins}>Pins</sl-tab>
|
||||
|
||||
<sl-tab-panel name="fields" active
|
||||
>${this.renderFields()}</sl-tab-panel
|
||||
>
|
||||
<sl-tab-panel name="fields" active>${this.renderFields()}</sl-tab-panel>
|
||||
<sl-tab-panel name="slots">${this.renderSlots()}</sl-tab-panel>
|
||||
<sl-tab-panel name="reagents">${this.renderReagents()}</sl-tab-panel>
|
||||
<sl-tab-panel name="networks">${this.renderNetworks()}</sl-tab-panel>
|
||||
<sl-tab-panel name="pins">${this.renderPins()}</sl-tab-panel>
|
||||
</sl-tab-group>
|
||||
</ic10-details>
|
||||
<sl-dialog
|
||||
class="remove-device-dialog"
|
||||
no-header
|
||||
@sl-request-close=${this._preventOverlayClose}
|
||||
>
|
||||
<sl-dialog class="remove-device-dialog" no-header @sl-request-close=${this._preventOverlayClose}>
|
||||
<div class="remove-dialog-body">
|
||||
<img
|
||||
class="dialog-image mt-auto mb-auto me-2"
|
||||
src="img/stationpedia/${this.prefabName}.png"
|
||||
onerror="this.src = '${VMDeviceCard.transparentImg}'"
|
||||
/>
|
||||
<img class="dialog-image mt-auto mb-auto me-2" src="img/stationpedia/${this.prefabName}.png"
|
||||
onerror="this.src = '${VMDeviceCard.transparentImg}'" />
|
||||
<div class="flex-g">
|
||||
<p><strong>Are you sure you want to remove this device?</strong></p>
|
||||
<span>Id ${this.deviceID} : ${this.name ?? this.prefabName}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div slot="footer">
|
||||
<sl-button
|
||||
variant="primary"
|
||||
autofocus
|
||||
@click=${this._closeRemoveDialog}
|
||||
>Close</sl-button
|
||||
>
|
||||
<sl-button variant="danger" @click=${this._removeDialogRemove}
|
||||
>Remove</sl-button
|
||||
>
|
||||
<sl-button variant="primary" autofocus @click=${this._closeRemoveDialog}>Close</sl-button>
|
||||
<sl-button variant="danger" @click=${this._removeDialogRemove}>Remove</sl-button>
|
||||
</div>
|
||||
</sl-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
@query(".remove-device-dialog") accessor removeDialog: SlDialog;
|
||||
@query(".remove-device-dialog") removeDialog: SlDialog;
|
||||
|
||||
_preventOverlayClose(event: CustomEvent) {
|
||||
if (event.detail.source === "overlay") {
|
||||
@@ -557,7 +496,7 @@ export class VMDeviceCard extends VMDeviceMixin(BaseElement) {
|
||||
|
||||
@customElement("vm-device-list")
|
||||
export class VMDeviceList extends BaseElement {
|
||||
@state() accessor devices: number[];
|
||||
@state() devices: number[];
|
||||
|
||||
static styles = [
|
||||
...defaultCss,
|
||||
@@ -650,7 +589,7 @@ export class VMDeviceList extends BaseElement {
|
||||
private _filteredDeviceIds: number[] | undefined;
|
||||
private _filter: string = "";
|
||||
|
||||
@query(".device-filter-input") accessor filterInput: SlInput;
|
||||
@query(".device-filter-input") filterInput: SlInput;
|
||||
get filter() {
|
||||
return this._filter;
|
||||
}
|
||||
@@ -729,8 +668,8 @@ export class VMAddDeviceButton extends BaseElement {
|
||||
`,
|
||||
];
|
||||
|
||||
@query("sl-drawer") accessor drawer: SlDrawer;
|
||||
@query(".device-search-input") accessor searchInput: SlInput;
|
||||
@query("sl-drawer") drawer: SlDrawer;
|
||||
@query(".device-search-input") searchInput: SlInput;
|
||||
|
||||
private _deviceDB: DeviceDB;
|
||||
private _strutures: Map<string, DeviceDBEntry> = new Map();
|
||||
@@ -828,11 +767,7 @@ export class VMAddDeviceButton extends BaseElement {
|
||||
this._searchResults ?? [],
|
||||
(result) => result.name,
|
||||
(result) => cache(html`
|
||||
<vm-device-template
|
||||
prefab_name=${result.name}
|
||||
class="card"
|
||||
@add-device-template=${this._handleDeviceAdd}
|
||||
>
|
||||
<vm-device-template prefab_name=${result.name} class="card" @add-device-template=${this._handleDeviceAdd}>
|
||||
</vm-device-template>
|
||||
`)
|
||||
);
|
||||
@@ -845,33 +780,20 @@ export class VMAddDeviceButton extends BaseElement {
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<sl-button
|
||||
variant="neutral"
|
||||
outline
|
||||
pill
|
||||
@click=${this._handleAddButtonClick}
|
||||
>
|
||||
<sl-button variant="neutral" outline pill @click=${this._handleAddButtonClick}>
|
||||
Add Device
|
||||
</sl-button>
|
||||
<sl-drawer class="add-device-drawer" placement="bottom" no-header>
|
||||
<sl-input
|
||||
class="device-search-input"
|
||||
autofocus
|
||||
placeholder="Search For Device"
|
||||
clearable
|
||||
@sl-input=${this._handleSearchInput}
|
||||
>
|
||||
<sl-input class="device-search-input" autofocus placeholder="Search For Device" clearable
|
||||
@sl-input=${this._handleSearchInput}>
|
||||
<span slot="prefix">Search Structures</span>
|
||||
<sl-icon slot="suffix" name="search"></sl-icon>
|
||||
</sl-input>
|
||||
<div class="search-results">${this.renderSearchResults()}</div>
|
||||
<sl-button
|
||||
slot="footer"
|
||||
variant="primary"
|
||||
@click=${() => {
|
||||
this.drawer.hide();
|
||||
<sl-button slot="footer" variant="primary" @click=${()=> {
|
||||
this.drawer.hide();
|
||||
}}
|
||||
>
|
||||
>
|
||||
Close
|
||||
</sl-button>
|
||||
</sl-drawer>
|
||||
@@ -928,12 +850,12 @@ export class VmDeviceTemplate extends BaseElement {
|
||||
`,
|
||||
];
|
||||
|
||||
@state() accessor fields: { [key in LogicType]?: LogicField };
|
||||
@state() accessor slots: SlotTemplate[];
|
||||
@state() accessor template: DeviceTemplate;
|
||||
@state() accessor device_id: number | undefined;
|
||||
@state() accessor device_name: string | undefined;
|
||||
@state() accessor connections: Connection[];
|
||||
@state() fields: { [key in LogicType]?: LogicField };
|
||||
@state() slots: SlotTemplate[];
|
||||
@state() template: DeviceTemplate;
|
||||
@state() device_id: number | undefined;
|
||||
@state() device_name: string | undefined;
|
||||
@state() connections: Connection[];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
@@ -24,7 +24,7 @@ class VirtualMachine extends EventTarget {
|
||||
_devices: Map<number, DeviceRef>;
|
||||
_ics: Map<number, DeviceRef>;
|
||||
|
||||
accessor db: DeviceDB;
|
||||
db: DeviceDB;
|
||||
dbPromise: Promise<{ default: DeviceDB }>;
|
||||
|
||||
private app: App;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"esModuleInterop": true,
|
||||
"isolatedModules": true,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"useDefineForClassFields": false,
|
||||
"types": ["@types/wicg-file-system-access", "@types/ace"],
|
||||
"plugins": [
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
const CopyWebpackPlugin = require("copy-webpack-plugin");
|
||||
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
||||
const miniCssExtractPlugin = require("mini-css-extract-plugin");
|
||||
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
|
||||
const { SourceMap } = require("module");
|
||||
const webpack = require("webpack");
|
||||
|
||||
const path = require("path");
|
||||
const commitHash = require('child_process')
|
||||
.execSync('git rev-parse --short HEAD')
|
||||
.toString()
|
||||
.trim();
|
||||
|
||||
module.exports = {
|
||||
entry: "./src/ts/main.ts",
|
||||
output: {
|
||||
path: path.resolve(__dirname, "dist"),
|
||||
filename: "main.js",
|
||||
clean: true,
|
||||
},
|
||||
devServer: {
|
||||
static: path.resolve(__dirname, "dist"),
|
||||
port: 8080,
|
||||
hot: true,
|
||||
},
|
||||
mode: "development",
|
||||
devtool: "eval-source-map",
|
||||
plugins: [
|
||||
new ForkTsCheckerWebpackPlugin(),
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
"img/*.png",
|
||||
"img/*/*.png",
|
||||
// { from: "data/database.json", to: "data" },
|
||||
// Copy Shoelace assets to dist/shoelace
|
||||
{
|
||||
from: path.resolve(
|
||||
__dirname,
|
||||
"node_modules/@shoelace-style/shoelace/dist/assets",
|
||||
),
|
||||
to: "shoelace/assets",
|
||||
},
|
||||
],
|
||||
}),
|
||||
new HtmlWebpackPlugin({ template: "./src/index.html" }),
|
||||
new miniCssExtractPlugin(),
|
||||
new webpack.DefinePlugin({
|
||||
__COMMIT_HASH__: JSON.stringify(commitHash),
|
||||
__BUILD_DATE__: JSON.stringify(new Date),
|
||||
}),
|
||||
],
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.[jt]sx?$/,
|
||||
exclude: /node_modules/,
|
||||
loader: "esbuild-loader",
|
||||
options: {
|
||||
target: "es2021",
|
||||
tsconfig: "./tsconfig.json",
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.(jpg|png|svg|gif)$/,
|
||||
type: "asset/resource",
|
||||
},
|
||||
{
|
||||
test: /\.css|\.s(c|a)ss$/,
|
||||
use: [
|
||||
{
|
||||
// inject CSS to page
|
||||
loader: miniCssExtractPlugin.loader,
|
||||
},
|
||||
{
|
||||
// translates CSS into CommonJS modules
|
||||
loader: "css-loader",
|
||||
options: {
|
||||
sourceMap: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
// Run postcss actions
|
||||
loader: "postcss-loader",
|
||||
options: {
|
||||
// `postcssOptions` is needed for postcss 8.x;
|
||||
// if you use postcss 7.x skip the key
|
||||
postcssOptions: {
|
||||
// postcss plugins, can be exported to postcss.config.js
|
||||
plugins: function () {
|
||||
return [require("autoprefixer")];
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
// compiles Sass to CSS
|
||||
loader: "sass-loader",
|
||||
options: {
|
||||
sourceMap: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
// parser: {
|
||||
// javascript : { importMeta: false }
|
||||
// }
|
||||
},
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
extensions: [".tsx", ".ts", ".js", ".json"],
|
||||
fallback: {
|
||||
crypto: require.resolve("crypto-browserify"),
|
||||
buffer: require.resolve("buffer"),
|
||||
stream: require.resolve("stream-browserify"),
|
||||
vm: require.resolve("vm-browserify"),
|
||||
},
|
||||
},
|
||||
experiments: {
|
||||
asyncWebAssembly: true,
|
||||
syncWebAssembly: true,
|
||||
},
|
||||
watchOptions: {
|
||||
aggregateTimeout: 200,
|
||||
poll: 200,
|
||||
},
|
||||
optimization: {
|
||||
chunkIds: "named",
|
||||
},
|
||||
};
|
||||
@@ -1,162 +0,0 @@
|
||||
const CopyWebpackPlugin = require("copy-webpack-plugin");
|
||||
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
||||
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
|
||||
const miniCssExtractPlugin = require("mini-css-extract-plugin");
|
||||
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
|
||||
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
|
||||
const { EsbuildPlugin } = require("esbuild-loader");
|
||||
const webpack = require("webpack");
|
||||
|
||||
const path = require("path");
|
||||
const commitHash = require('child_process')
|
||||
.execSync('git rev-parse --short HEAD')
|
||||
.toString()
|
||||
.trim();
|
||||
|
||||
module.exports = {
|
||||
entry: "./src/ts/main.ts",
|
||||
output: {
|
||||
path: path.resolve(__dirname, "dist"),
|
||||
filename: "main.js",
|
||||
clean: true,
|
||||
},
|
||||
mode: "production",
|
||||
devtool: "source-map",
|
||||
plugins: [
|
||||
new ForkTsCheckerWebpackPlugin(),
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
"img/*.png",
|
||||
"img/*/*.png",
|
||||
// { from: "data/database.json", to: "data" },
|
||||
// Copy Shoelace assets to dist/shoelace
|
||||
{
|
||||
from: path.resolve(
|
||||
__dirname,
|
||||
"node_modules/@shoelace-style/shoelace/dist/assets",
|
||||
),
|
||||
to: "shoelace/assets",
|
||||
},
|
||||
],
|
||||
}),
|
||||
new HtmlWebpackPlugin({ template: "./src/index.html" }),
|
||||
new miniCssExtractPlugin(),
|
||||
new webpack.DefinePlugin({
|
||||
__COMMIT_HASH__: JSON.stringify(commitHash),
|
||||
__BUILD_DATE__: JSON.stringify(new Date),
|
||||
}),
|
||||
],
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.[jt]sx?$/,
|
||||
exclude: /node_modules/,
|
||||
loader: "esbuild-loader",
|
||||
options: {
|
||||
target: "es2021",
|
||||
tsconfig: "./tsconfig.json",
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.(jpg|png|svg|gif)$/,
|
||||
type: "asset/resource",
|
||||
},
|
||||
{
|
||||
test: /\.(scss)$/,
|
||||
use: [
|
||||
{
|
||||
// inject CSS to page
|
||||
loader: miniCssExtractPlugin.loader,
|
||||
},
|
||||
{
|
||||
// translates CSS into CommonJS modules
|
||||
loader: "css-loader",
|
||||
},
|
||||
{
|
||||
loader: "esbuild-loader",
|
||||
options: {
|
||||
loader: 'css',
|
||||
minify: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
// Run postcss actions
|
||||
loader: "postcss-loader",
|
||||
options: {
|
||||
// `postcssOptions` is needed for postcss 8.x;
|
||||
// if you use postcss 7.x skip the key
|
||||
postcssOptions: {
|
||||
// postcss plugins, can be exported to postcss.config.js
|
||||
plugins: function () {
|
||||
return [require("autoprefixer")];
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
// compiles Sass to CSS
|
||||
loader: "sass-loader",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
extensions: [".tsx", ".ts", ".js"],
|
||||
fallback: {
|
||||
crypto: require.resolve("crypto-browserify"),
|
||||
buffer: require.resolve("buffer"),
|
||||
stream: require.resolve("stream-browserify"),
|
||||
vm: require.resolve("vm-browserify"),
|
||||
},
|
||||
},
|
||||
experiments: {
|
||||
asyncWebAssembly: true,
|
||||
syncWebAssembly: true,
|
||||
},
|
||||
optimization: {
|
||||
minimizer: [
|
||||
new EsbuildPlugin({
|
||||
target: "es2021", // Syntax to transpile to (see options below for possible values)
|
||||
css: true,
|
||||
}),
|
||||
new ImageMinimizerPlugin({
|
||||
minimizer: {
|
||||
implementation: ImageMinimizerPlugin.imageminMinify,
|
||||
options: {
|
||||
// Lossless optimization with custom option
|
||||
// Feel free to experiment with options for better result for you
|
||||
plugins: [
|
||||
["gifsicle", { interlaced: true }],
|
||||
["jpegtran", { progressive: true }],
|
||||
["optipng", { optimizationLevel: 5 }],
|
||||
// Svgo configuration here https://github.com/svg/svgo#configuration
|
||||
[
|
||||
"svgo",
|
||||
{
|
||||
plugins: [
|
||||
{
|
||||
name: "preset-default",
|
||||
params: {
|
||||
overrides: {
|
||||
removeViewBox: false,
|
||||
addAttributesToSVGElement: {
|
||||
params: {
|
||||
attributes: [
|
||||
{ xmlns: "http://www.w3.org/2000/svg" },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user