Merge pull request 'pinia-migration' (#2) from pinia-migration into master

Reviewed-on: #2
This commit is contained in:
Ali Gator 2022-12-02 18:22:53 +01:00
commit 1264c2fbbe
19 changed files with 664 additions and 731 deletions

9
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,9 @@
repos:
- repo: https://github.com/pre-commit/mirrors-eslint
rev: "v8.28.0"
hooks:
- id: eslint
- repo: https://github.com/pre-commit/mirrors-prettier
rev: "v2.7.1"
hooks:
- id: prettier

View File

@ -1 +1,3 @@
{}
{
"vueIndentScriptAndStyle": true
}

View File

@ -2,6 +2,8 @@
Explore 1D and 2D cellular automata, with a few bells and whistles.
![rules73](./example.png)
## Project setup
```
@ -11,7 +13,7 @@ npm install
### Compiles and hot-reloads for development
```
npm run serve
npm run dev
```
### Compiles and minifies for production
@ -26,9 +28,15 @@ npm run build
npm run lint
```
### Format files
```
npm run format
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
See [Configuration Reference](https://vitejs.dev/guide/).
### References

BIN
example.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

90
package-lock.json generated
View File

@ -10,9 +10,9 @@
"dependencies": {
"@vitejs/plugin-vue": "^3.2.0",
"install": "^0.13.0",
"pinia": "^2.0.27",
"vite": "^3.2.4",
"vue": "3.2",
"vuex": "4.1"
"vue": "3.2"
},
"devDependencies": {
"eslint": "^8.28.0",
@ -1548,6 +1548,56 @@
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
},
"node_modules/pinia": {
"version": "2.0.27",
"resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.27.tgz",
"integrity": "sha512-nOnXP0OFeL8R4WjAHsterU+11vptda643gH02xKNtSCDPiRzVfRYodOLihLDoa0gL1KKuQKV+KOzEgdt3YvqEw==",
"dependencies": {
"@vue/devtools-api": "^6.4.5",
"vue-demi": "*"
},
"funding": {
"url": "https://github.com/sponsors/posva"
},
"peerDependencies": {
"@vue/composition-api": "^1.4.0",
"typescript": ">=4.4.4",
"vue": "^2.6.14 || ^3.2.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
},
"typescript": {
"optional": true
}
}
},
"node_modules/pinia/node_modules/vue-demi": {
"version": "0.13.11",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz",
"integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/postcss": {
"version": "8.4.19",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.19.tgz",
@ -1969,17 +2019,6 @@
"eslint": ">=6.0.0"
}
},
"node_modules/vuex": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/vuex/-/vuex-4.1.0.tgz",
"integrity": "sha512-hmV6UerDrPcgbSy9ORAtNXDr9M4wlNP4pEFKye4ujJF8oqgFFuxDCdOLS3eNoRTtq5O3hoBDh9Doj1bQMYHRbQ==",
"dependencies": {
"@vue/devtools-api": "^6.0.0-beta.11"
},
"peerDependencies": {
"vue": "^3.2.0"
}
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@ -3083,6 +3122,23 @@
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
},
"pinia": {
"version": "2.0.27",
"resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.27.tgz",
"integrity": "sha512-nOnXP0OFeL8R4WjAHsterU+11vptda643gH02xKNtSCDPiRzVfRYodOLihLDoa0gL1KKuQKV+KOzEgdt3YvqEw==",
"requires": {
"@vue/devtools-api": "^6.4.5",
"vue-demi": "*"
},
"dependencies": {
"vue-demi": {
"version": "0.13.11",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz",
"integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==",
"requires": {}
}
}
},
"postcss": {
"version": "8.4.19",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.19.tgz",
@ -3324,14 +3380,6 @@
"semver": "^7.3.6"
}
},
"vuex": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/vuex/-/vuex-4.1.0.tgz",
"integrity": "sha512-hmV6UerDrPcgbSy9ORAtNXDr9M4wlNP4pEFKye4ujJF8oqgFFuxDCdOLS3eNoRTtq5O3hoBDh9Doj1bQMYHRbQ==",
"requires": {
"@vue/devtools-api": "^6.0.0-beta.11"
}
},
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",

View File

@ -12,9 +12,9 @@
"dependencies": {
"@vitejs/plugin-vue": "^3.2.0",
"install": "^0.13.0",
"pinia": "^2.0.27",
"vite": "^3.2.4",
"vue": "3.2",
"vuex": "4.1"
"vue": "3.2"
},
"devDependencies": {
"eslint": "^8.28.0",

View File

@ -9,6 +9,8 @@
</main>
</template>
<script>
import { mapActions, mapState, mapWritableState } from "pinia";
import { globalStore } from "../stores/index.js";
import {
create1dState,
create1dStateOneCell,
@ -18,7 +20,7 @@ import {
evolve2d,
} from "../modules/automata.js";
import { getRandomInt, sleep } from "../modules/common.js";
import { mapGetters } from "vuex";
export default {
name: "CanvasBoard",
data() {
@ -28,20 +30,22 @@ export default {
};
},
computed: {
...mapGetters({
cellProperties: "getCellProperties",
rules: "get1dRules",
canvasWidth: "getCanvasWidth",
canvasHeight: "getCanvasHeight",
refreshRate: "getRefreshRate",
initial1dState: "getInitial1dState",
drawingDirection: "getDrawingDirection",
canDraw: "getCanDraw",
lastBoard: "getLastBoard",
getDraw1d: "getDraw1d",
getDraw2d: "getDraw2d",
getDraw2dLast: "getDraw2dLast",
getReset: "getReset",
...mapState(globalStore, {
cellProperties: "cellProperties",
rules: "rules1d",
refreshRate: "refreshRate",
initial1dState: "initial1dState",
drawingDirection: "drawingDirection",
canDraw: "canDraw",
getDraw1d: "draw1d",
getDraw2d: "draw2d",
getDraw2dLast: "draw2dLast",
}),
...mapWritableState(globalStore, {
lastBoard: "lastBoard",
canvasWidth: "canvasWidth",
canvasHeight: "canvasHeight",
getReset: "reset",
}),
boardWidth: function () {
return Math.floor(this.canvasWidth / this.cellProperties.size);
@ -67,13 +71,11 @@ export default {
mounted() {
this.canvas = Object.freeze(document.getElementById("canvas-board"));
this.ctx = this.canvas.getContext("2d");
this.$store.commit("setCanvasWidth", this.canvas.parentElement.clientWidth);
this.$store.commit(
"setCanvasHeight",
this.canvas.parentElement.clientHeight
);
this.canvasWidth = this.canvas.parentElement.clientWidth;
this.canvasHeight = this.canvas.parentElement.clientHeight;
},
methods: {
...mapActions(globalStore, ["toggleStop"]),
drawCanvas(board) {
const props = this.cellProperties;
board.map((row, y) => {
@ -102,9 +104,9 @@ export default {
this.rules.rules,
this.boardWidth
);
this.$store.commit("setLastBoard", Object.freeze(board));
this.lastBoard = Object.freeze(board);
this.drawCanvas(board);
this.$store.dispatch("stop");
this.toggleStop();
},
draw2d(board) {
if (!this.canDraw) return;
@ -125,16 +127,16 @@ export default {
[0, 2]
);
const board = evolve2d(initialState, conwayRules);
this.$store.commit("setLastBoard", Object.freeze(board));
this.lastBoard = Object.freeze(board);
this.draw2d(board);
},
async draw2dLast() {
this.draw2d(this.lastBoard);
if (this.lastBoard != undefined) this.draw2d(this.lastBoard);
},
reset() {
this.$store.dispatch("stop");
this.toggleStop();
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.$store.commit("toggleReset", 0);
this.getReset = 0;
},
},
};

View File

@ -2,55 +2,50 @@
<MenuRow row-title="2D Cellular Automata">
<div class="form-field">
<label>Start from last result</label>
<input type="button" value="start" @click="draw2dLast" />
<input type="button" value="start" @click="toggleDraw2dLast()" />
</div>
<div class="form-field">
<input type="button" name="start2d" value="start" @click="draw2d" />
<input
type="button"
name="start2d"
value="start"
@click="toggleDraw2d()"
/>
<input
type="button"
name="stop"
class="stop"
value="stop"
@click="stop"
@click="toggleStop()"
/>
<input
type="button"
name="reset"
class="reset"
value="reset"
@click="reset"
@click="toggleReset()"
/>
</div>
</MenuRow>
</template>
<script>
import { mapActions } from "pinia";
import MenuRow from "./MenuRow.vue";
import { mapGetters } from "vuex";
import { globalStore } from "../stores/index.js";
export default {
name: "Menu2dCA",
components: {
MenuRow,
},
computed: {
...mapGetters({
lastBoard: "getLastBoard",
}),
},
methods: {
draw2d() {
this.$store.dispatch("draw2d");
},
draw2dLast() {
this.$store.dispatch("draw2dLast");
},
reset() {
this.$store.dispatch("reset");
},
stop() {
this.$store.dispatch("stop");
},
...mapActions(globalStore, [
"toggleDraw2d",
"toggleDraw2dLast",
"toggleReset",
"toggleStop",
]),
},
};
</script>

View File

@ -34,28 +34,26 @@
</template>
<script>
import { mapWritableState } from "pinia";
import { globalStore } from "../stores/index.js";
import MenuRow from "./MenuRow.vue";
export default {
name: "MainMenu",
components: {
MenuRow,
},
data() {
return {
cellProperties: this.$store.state.cellProperties,
};
computed: {
...mapWritableState(globalStore, ["cellProperties"]),
},
methods: {
getCellProperties(event) {
const elem = event.target;
const prop = this.$store.state.cellProperties;
const prop = this.cellProperties;
return prop[elem.name];
},
updateCellProperties(event) {
const elem = event.target;
const prop = { name: elem.name, value: elem.value };
//console.log(prop)
this.$store.commit("setCellProperties", prop);
this.cellProperties[elem.name] = elem.value;
},
},
};

View File

@ -63,20 +63,22 @@
</div>
</form>
<div class="form-field">
<input type="button" name="start" value="start" @click="draw1d" />
<input type="button" name="start" value="start" @click="toggleDraw1d()" />
<input
type="button"
name="reset"
class="reset"
value="reset"
@click="reset"
@click="toggleReset"
/>
</div>
</MenuRow>
</template>
<script>
import { mapGetters } from "vuex";
import { mapActions, mapWritableState } from "pinia";
import { presetRules, initialStates } from "./preset.js";
import { globalStore } from "../stores/index.js";
import MenuRow from "./MenuRow.vue";
export default {
name: "MenuElementaryCA",
@ -84,108 +86,18 @@ export default {
MenuRow,
},
data() {
// TODO: Why not a getter in the store?
return {
presetRules: [
{
name: "rule 73",
rules: {
100: 0,
101: 0,
110: 1,
111: 0,
"011": 1,
"010": 0,
"001": 0,
"000": 1,
},
},
{
name: "rule 86",
rules: {
100: 1,
101: 0,
110: 0,
111: 1,
"011": 0,
"010": 1,
"001": 0,
"000": 1,
},
},
{
name: "rule 90",
rules: {
100: 1,
101: 0,
110: 1,
111: 0,
"011": 0,
"010": 0,
"001": 1,
"000": 0,
},
},
{
name: "rule 45?",
rules: {
100: 0,
101: 0,
110: 1,
111: 0,
"011": 1,
"010": 0,
"001": 1,
"000": 1,
},
},
{
name: "rule 54?",
rules: {
100: 1,
101: 0,
110: 1,
111: 1,
"011": 0,
"010": 1,
"001": 1,
"000": 0,
},
},
{
name: "unknown rule",
rules: {
100: 0,
101: 0,
110: 0,
111: 1,
"011": 0,
"010": 0,
"001": 1,
"000": 1,
},
},
],
initialStates: [
{
id: "onecell",
name: "One cell at center",
description: "State with a single cell in the middle",
},
{
id: "random",
name: "Random cell",
description: "State populated with random cells",
},
],
presetRules: presetRules,
initialStates: initialStates,
};
},
computed: {
...mapGetters({
initialState: "getInitial1dState",
rules: "get1dRules",
...mapWritableState(globalStore, {
initialState: "initial1dState",
rules: "rules1d",
}),
rules1dFileName() {
// TODO: broken
return (
Object.keys(this.rules)
.map((index) => {
@ -196,6 +108,7 @@ export default {
},
},
methods: {
...mapActions(globalStore, ["toggleDraw1d", "toggleReset"]),
copyRules() {
const rules = JSON.stringify(this.rules);
navigator.clipboard.writeText(rules);
@ -207,30 +120,19 @@ export default {
updateSingleRule(event) {
const elem = event.target;
const value = elem.checked ? 1 : 0;
const data = { rule: elem.name, value: value };
this.$store.commit("update1dSingleRule", data);
this.rules.rules[elem.name] = value;
},
updateRules(event) {
// TODO : change this, awfully confusing
const elem = event.target;
const name = elem.value;
const rules = this.presetRules.find((ruleset) => {
const newRuleset = this.presetRules.find((ruleset) => {
return ruleset.name === name;
});
Object.keys(rules.rules).map((value) => {
const data = { name: name, rule: value, value: rules.rules[value] };
this.$store.commit("update1dSingleRule", data);
});
this.rules.rules = newRuleset.rules;
},
updateInitialState(event) {
const elem = event.target;
this.$store.commit("setInitial1dState", elem.value);
},
draw1d() {
this.$store.dispatch("draw1d");
},
reset() {
this.$store.dispatch("reset");
this.initialState = elem.value;
},
},
};

View File

@ -56,39 +56,39 @@
</template>
<script>
import { mapWritableState } from "pinia";
import { globalStore } from "../stores/index.js";
import MenuRow from "./MenuRow.vue";
import { mapGetters } from "vuex";
export default {
name: "MenuGeneralOptions",
components: {
MenuRow,
},
computed: {
...mapGetters({
canvasWidth: "getCanvasWidth",
canvasHeight: "getCanvasHeight",
refreshRate: "getRefreshRate",
drawingDirection: "getDrawingDirection",
}),
...mapWritableState(globalStore, [
"canvasWidth",
"canvasHeight",
"refreshRate",
"drawingDirection",
]),
},
methods: {
updateCanvasHeight: function (event) {
const elem = event.target;
this.$store.commit("setCanvasHeight", elem.value);
this.canvasHeight = elem.value;
},
updateCanvasWidth: function (event) {
const elem = event.target;
this.$store.commit("setCanvasWidth", elem.value);
this.canvasWidth = elem.value;
},
updateRefreshRate: function (event) {
const elem = event.target;
this.$store.commit("setRefreshRate", elem.value);
this.refreshRate = elem.value;
},
updateDrawingDirection: function (event) {
const elem = event.target;
const value = elem.checked ? "x" : "y";
this.$store.commit("setDrawingDirection", value);
console.log(this.drawingDirection);
this.drawingDirection = value;
},
},
};

View File

@ -10,8 +10,6 @@
</template>
<script>
import { mapGetters } from "vuex";
export default {
name: "MenuRow",
props: {
@ -20,17 +18,17 @@ export default {
default: "",
},
},
computed: {
...mapGetters({
activeMenu: "getActiveMenu",
}),
data() {
return {
activeMenu: "",
};
},
methods: {
updateActiveMenu(event) {
const elem = event.target;
const value = elem.id;
if (value == this.activeMenu) this.$store.commit("setActiveMenu", "");
else this.$store.commit("setActiveMenu", value);
if (value == this.activeMenu) this.activeMenu = "";
else this.activeMenu = value;
},
},
};

95
src/components/preset.js Normal file
View File

@ -0,0 +1,95 @@
const presetRules = [
{
name: "rule 73",
rules: {
100: 0,
101: 0,
110: 1,
111: 0,
"011": 1,
"010": 0,
"001": 0,
"000": 1,
},
},
{
name: "rule 86",
rules: {
100: 1,
101: 0,
110: 0,
111: 1,
"011": 0,
"010": 1,
"001": 0,
"000": 1,
},
},
{
name: "rule 90",
rules: {
100: 1,
101: 0,
110: 1,
111: 0,
"011": 0,
"010": 0,
"001": 1,
"000": 0,
},
},
{
name: "rule 45?",
rules: {
100: 0,
101: 0,
110: 1,
111: 0,
"011": 1,
"010": 0,
"001": 1,
"000": 1,
},
},
{
name: "rule 54?",
rules: {
100: 1,
101: 0,
110: 1,
111: 1,
"011": 0,
"010": 1,
"001": 1,
"000": 0,
},
},
{
name: "unknown rule",
rules: {
100: 0,
101: 0,
110: 0,
111: 1,
"011": 0,
"010": 0,
"001": 1,
"000": 1,
},
},
];
const initialStates = [
{
id: "onecell",
name: "One cell at center",
description: "State with a single cell in the middle",
},
{
id: "random",
name: "Random cell",
description: "State populated with random cells",
},
];
export { presetRules, initialStates };

View File

@ -1,9 +1,10 @@
import { createApp } from "vue";
import App from "./App.vue";
import { store } from "./store";
import { createPinia } from "pinia";
const app = createApp(App);
const pinia = createPinia();
app.use(store);
app.use(pinia);
app.mount("#app");

View File

@ -1,174 +0,0 @@
/* TODO: terminology is to be changed for :
canvas/board :
currently, the canvas object is named board,
while the structure used to store automata current state is named "board" as well. This is confusing
drawing board could be enough to lift any ambiguity
rules:
confusion bewteen ruleset and rules.
it's never clear if we refers to a rule or the whole (named) set
*/
import { createStore } from "vuex";
export const store = createStore({
strict: process.env.NODE_ENV !== "production",
state: {
rules1d: {
name: "rule 73",
rules: {
111: 0,
110: 1,
101: 0,
100: 0,
"011": 1,
"010": 0,
"001": 0,
"000": 1,
},
},
cellProperties: {
size: 3,
liveColor: "#000000",
deadColor: "#F5F5F5",
},
canvasWidth: 0,
canvasHeight: 0,
boardWidth: 0,
boardHeight: 0,
refreshRate: 300,
initial1dState: "onecell",
activeMenu: "",
drawingDirection: "y",
lastBoard: {},
draw1d: false,
draw2d: false,
draw2dLast: false,
reset: false,
canDraw: true,
},
mutations: {
update1dSingleRule(state, data) {
state.rules1d.name = data.name;
state.rules1d.rules[data.rule] = data.value;
},
update1dRules(state, data) {
state.rules1d = data;
},
setCellProperties(state, data) {
state.cellProperties[data.name] = data.value;
},
setCanvasWidth(state, data) {
state.canvasWidth = data;
},
setCanvasHeight(state, data) {
state.canvasHeight = data;
},
setRefreshRate(state, data) {
state.refreshRate = data;
},
setInitial1dState(state, data) {
state.initial1dState = data;
},
setActiveMenu(state, data) {
state.activeMenu = data;
},
setDrawingDirection(state, data) {
state.drawingDirection = data;
},
setLastBoard(state, data) {
state.lastBoard = data;
},
setCanvas(state, data) {
state.canvas = data;
},
setContext(state, data) {
state.ctx = data;
},
toggleDraw1d(state, data) {
state.draw1d = data;
},
toggleDraw2d(state, data) {
state.draw2d = data;
},
toggleDraw2dLast(state, data) {
state.draw2dLast = data;
},
toggleReset(state, data) {
state.reset = data;
},
canDraw(state, data) {
state.canDraw = data;
},
},
getters: {
getCellProperties(state) {
return state.cellProperties;
},
get1dRules(state) {
return state.rules1d;
},
getRule1d(state) {
return state.rules1d;
},
getCanvasWidth(state) {
return state.canvasWidth;
},
getCanvasHeight(state) {
return state.canvasHeight;
},
getRefreshRate(state) {
return state.refreshRate;
},
getInitial1dState(state) {
return state.initial1dState;
},
getActiveMenu(state) {
return state.activeMenu;
},
getDrawingDirection(state) {
return state.drawingDirection;
},
getLastBoard(state) {
return state.lastBoard;
},
getDraw1d(state) {
return state.draw1d;
},
getDraw2d(state) {
return state.draw2d;
},
getDraw2dLast(state) {
return state.draw2dLast;
},
getReset(state) {
return state.reset;
},
getCanDraw(state) {
return state.canDraw;
},
},
actions: {
draw1d({ commit }) {
commit("toggleDraw1d", true);
},
draw2d({ commit }) {
commit("canDraw", true);
commit("toggleDraw2d", true);
},
draw2dLast({ commit }) {
commit("canDraw", true);
commit("toggleDraw2dLast", true);
},
reset({ dispatch, commit }) {
dispatch("stop");
commit("toggleReset", true);
},
stop({ commit }) {
commit("toggleDraw1d", false);
commit("toggleDraw2d", false);
commit("toggleDraw2dLast", false);
commit("canDraw", false);
},
},
modules: {},
});

62
src/stores/index.js Normal file
View File

@ -0,0 +1,62 @@
import { defineStore } from "pinia";
export const globalStore = defineStore("globalStore", {
state: () => {
return {
rules1d: {
name: "rule 73",
rules: {
111: 0,
110: 1,
101: 0,
100: 0,
"011": 1,
"010": 0,
"001": 0,
"000": 1,
},
},
cellProperties: {
size: 3,
liveColor: "#000000",
deadColor: "#F5F5F5",
},
canvasWidth: 0,
canvasHeight: 0,
boardWidth: 0,
boardHeight: 0,
refreshRate: 300,
initial1dState: "onecell",
drawingDirection: "y",
lastBoard: {},
draw1d: false,
draw2d: false,
draw2dLast: false,
reset: false,
canDraw: true,
};
},
actions: {
toggleDraw1d() {
this.draw1d = true;
},
toggleDraw2d() {
this.canDraw = true;
this.draw2d = true;
},
toggleDraw2dLast() {
this.canDraw = true;
this.draw2dLast = true;
},
toggleReset() {
this.toggleStop();
this.reset = true;
},
toggleStop() {
this.draw1d = false;
this.draw2d = false;
this.draw2dLast = false;
this.canDraw = false;
},
},
});

View File

@ -1,13 +0,0 @@
module.exports = {
configureWebpack: {
devServer: {
overlay: {
warnings: true,
errors: true,
},
watchOptions: {
ignored: [/node_modules/, /public/, /\.#/],
},
},
},
};