mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-09-19 20:38:42 +02:00
EDITOR: Reorganization and minor efficiency improvements (#886)
This commit is contained in:
parent
e339b5dc5f
commit
87925f1900
186
package-lock.json
generated
186
package-lock.json
generated
@ -10,30 +10,30 @@
|
|||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "SEE LICENSE IN license.txt",
|
"license": "SEE LICENSE IN license.txt",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.4.1",
|
"@emotion/react": "^11.11.1",
|
||||||
"@emotion/styled": "^11.10.5",
|
"@emotion/styled": "^11.11.0",
|
||||||
"@material-ui/core": "^4.12.4",
|
"@material-ui/core": "^4.12.4",
|
||||||
"@mui/icons-material": "^5.11.0",
|
"@mui/icons-material": "^5.14.12",
|
||||||
"@mui/material": "^5.14.12",
|
"@mui/material": "^5.14.12",
|
||||||
"@mui/styles": "^5.11.2",
|
"@mui/styles": "^5.14.12",
|
||||||
"@mui/system": "^5.0.3",
|
"@mui/system": "^5.14.12",
|
||||||
"@types/estree": "^1.0.0",
|
"@types/estree": "^1.0.2",
|
||||||
"@types/react-syntax-highlighter": "^15.5.7",
|
"@types/react-syntax-highlighter": "^15.5.8",
|
||||||
"acorn": "^8.8.1",
|
"acorn": "^8.10.0",
|
||||||
"acorn-walk": "^8.2.0",
|
"acorn-walk": "^8.2.0",
|
||||||
"arg": "^5.0.2",
|
"arg": "^5.0.2",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
"better-react-mathjax": "^2.0.2",
|
"better-react-mathjax": "^2.0.3",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
"date-fns": "^2.29.3",
|
"date-fns": "^2.30.0",
|
||||||
"escodegen": "^2.0.0",
|
"escodegen": "^2.1.0",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"jquery": "^3.6.3",
|
"jquery": "^3.7.1",
|
||||||
"js-sha256": "^0.9.0",
|
"js-sha256": "^0.9.0",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
"material-ui-color": "^1.2.0",
|
"material-ui-color": "^1.2.0",
|
||||||
"material-ui-popup-state": "^1.5.3",
|
"material-ui-popup-state": "^1.9.3",
|
||||||
"monaco-vim": "^0.3.5",
|
"monaco-vim": "^0.3.5",
|
||||||
"notistack": "^2.0.8",
|
"notistack": "^2.0.8",
|
||||||
"numeral": "^2.0.6",
|
"numeral": "^2.0.6",
|
||||||
@ -41,62 +41,62 @@
|
|||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-beautiful-dnd": "^13.1.1",
|
"react-beautiful-dnd": "^13.1.1",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-draggable": "^4.4.4",
|
"react-draggable": "^4.4.6",
|
||||||
"react-markdown": "^8.0.7",
|
"react-markdown": "^8.0.7",
|
||||||
"react-resizable": "^3.0.4",
|
"react-resizable": "^3.0.5",
|
||||||
"react-syntax-highlighter": "^15.5.0",
|
"react-syntax-highlighter": "^15.5.0",
|
||||||
"remark-gfm": "^3.0.1",
|
"remark-gfm": "^3.0.1",
|
||||||
"sprintf-js": "^1.1.2"
|
"sprintf-js": "^1.1.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.20.12",
|
"@babel/core": "^7.23.0",
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.22.20",
|
||||||
"@babel/preset-react": "^7.18.6",
|
"@babel/preset-react": "^7.22.15",
|
||||||
"@babel/preset-typescript": "^7.18.6",
|
"@babel/preset-typescript": "^7.23.0",
|
||||||
"@microsoft/api-documenter": "^7.21.3",
|
"@microsoft/api-documenter": "^7.23.9",
|
||||||
"@microsoft/api-extractor": "^7.34.2",
|
"@microsoft/api-extractor": "^7.38.0",
|
||||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.10",
|
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.11",
|
||||||
"@types/bcryptjs": "^2.4.2",
|
"@types/bcryptjs": "^2.4.4",
|
||||||
"@types/escodegen": "^0.0.7",
|
"@types/escodegen": "^0.0.7",
|
||||||
"@types/file-saver": "^2.0.5",
|
"@types/file-saver": "^2.0.5",
|
||||||
"@types/jest": "^29.4.0",
|
"@types/jest": "^29.5.5",
|
||||||
"@types/jquery": "^3.5.16",
|
"@types/jquery": "^3.5.22",
|
||||||
"@types/lodash": "^4.14.191",
|
"@types/lodash": "^4.14.199",
|
||||||
"@types/numeral": "^2.0.2",
|
"@types/numeral": "^2.0.3",
|
||||||
"@types/react": "^17.0.52",
|
"@types/react": "^17.0.67",
|
||||||
"@types/react-beautiful-dnd": "^13.1.3",
|
"@types/react-beautiful-dnd": "^13.1.5",
|
||||||
"@types/react-dom": "^17.0.20",
|
"@types/react-dom": "^17.0.21",
|
||||||
"@types/react-resizable": "^3.0.3",
|
"@types/react-resizable": "^3.0.5",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.48.0",
|
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
||||||
"@typescript-eslint/parser": "^5.48.0",
|
"@typescript-eslint/parser": "^5.62.0",
|
||||||
"babel-jest": "^29.3.1",
|
"babel-jest": "^29.7.0",
|
||||||
"babel-loader": "^9.1.2",
|
"babel-loader": "^9.1.3",
|
||||||
"css-loader": "^6.7.3",
|
"css-loader": "^6.8.1",
|
||||||
"electron": "^26.2.4",
|
"electron": "^26.3.0",
|
||||||
"electron-packager": "^17.1.1",
|
"electron-packager": "^17.1.2",
|
||||||
"eslint": "^8.51.0",
|
"eslint": "^8.51.0",
|
||||||
"eslint-plugin-react": "^7.32.2",
|
"eslint-plugin-react": "^7.33.2",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
"fork-ts-checker-webpack-plugin": "^7.2.14",
|
"fork-ts-checker-webpack-plugin": "^7.3.0",
|
||||||
"html-webpack-plugin": "^5.5.0",
|
"html-webpack-plugin": "^5.5.3",
|
||||||
"http-server": "^14.1.1",
|
"http-server": "^14.1.1",
|
||||||
"jest": "^29.4.3",
|
"jest": "^29.7.0",
|
||||||
"jest-environment-jsdom": "^29.4.3",
|
"jest-environment-jsdom": "^29.7.0",
|
||||||
"jsdom": "^20.0.3",
|
"jsdom": "^20.0.3",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"monaco-editor": "^0.35.0",
|
"monaco-editor": "^0.35.0",
|
||||||
"monaco-editor-webpack-plugin": "^7.0.1",
|
"monaco-editor-webpack-plugin": "^7.1.0",
|
||||||
"prettier": "^2.8.1",
|
"prettier": "^2.8.8",
|
||||||
"raw-loader": "^4.0.2",
|
"raw-loader": "^4.0.2",
|
||||||
"react-refresh": "^0.14.0",
|
"react-refresh": "^0.14.0",
|
||||||
"source-map": "^0.7.4",
|
"source-map": "^0.7.4",
|
||||||
"start-server-and-test": "^1.15.2",
|
"start-server-and-test": "^1.15.4",
|
||||||
"style-loader": "^3.3.1",
|
"style-loader": "^3.3.3",
|
||||||
"typescript": "^5.2.2",
|
"typescript": "^4.9.5",
|
||||||
"webpack": "^5.75.0",
|
"webpack": "^5.88.2",
|
||||||
"webpack-cli": "^5.0.1",
|
"webpack-cli": "^5.1.4",
|
||||||
"webpack-dev-server": "^4.11.1"
|
"webpack-dev-server": "^4.15.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
@ -2345,9 +2345,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/eslintrc/node_modules/globals": {
|
"node_modules/@eslint/eslintrc/node_modules/globals": {
|
||||||
"version": "13.22.0",
|
"version": "13.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/globals/-/globals-13.22.0.tgz",
|
"resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz",
|
||||||
"integrity": "sha512-H1Ddc/PbZHTDVJSnj8kWptIRSD6AM3pK+mKytuIVF4uoBV7rshFlhhvA58ceJ5wp3Er58w6zj7bykMpYXt3ETw==",
|
"integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"type-fest": "^0.20.2"
|
"type-fest": "^0.20.2"
|
||||||
@ -4440,9 +4440,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/jquery": {
|
"node_modules/@types/jquery": {
|
||||||
"version": "3.5.21",
|
"version": "3.5.22",
|
||||||
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.21.tgz",
|
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.22.tgz",
|
||||||
"integrity": "sha512-BgCalH4OX2JcjbnD9E86L+WeN6IcCGZle+Iy0I6eOMuraAfcMb0Z1x9E51rC2Dqq+m8KexEoDBW6GIJxUPmLEg==",
|
"integrity": "sha512-ISQFeUK5GwRftLK4PVvKTWEVCxZ2BpaqBz0TWkIq5w4vGojxZP9+XkqgcPjxoqmPeew+HLyWthCBvK7GdF5NYA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/sizzle": "*"
|
"@types/sizzle": "*"
|
||||||
@ -4500,9 +4500,9 @@
|
|||||||
"integrity": "sha512-xPSg0jm4mqgEkNhowKgZFBNtwoEwF6gJ4Dhww+GFpm3IgtNseHQZ5IqdNwnquZEoANxyDAKDRAdVo4Z72VvD/g=="
|
"integrity": "sha512-xPSg0jm4mqgEkNhowKgZFBNtwoEwF6gJ4Dhww+GFpm3IgtNseHQZ5IqdNwnquZEoANxyDAKDRAdVo4Z72VvD/g=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "18.18.3",
|
"version": "18.18.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.4.tgz",
|
||||||
"integrity": "sha512-0OVfGupTl3NBFr8+iXpfZ8NR7jfFO+P1Q+IO/q0wbo02wYkP5gy36phojeYWpLQ6WAMjl+VfmqUk2YbUfp0irA==",
|
"integrity": "sha512-t3rNFBgJRugIhackit2mVcLfF6IRc0JE4oeizPQL8Zrm8n2WY/0wOdpOPhdtG0V9Q2TlW/axbF1MJ6z+Yj/kKQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@types/numeral": {
|
"node_modules/@types/numeral": {
|
||||||
@ -4582,9 +4582,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/react-syntax-highlighter": {
|
"node_modules/@types/react-syntax-highlighter": {
|
||||||
"version": "15.5.7",
|
"version": "15.5.8",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.7.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.8.tgz",
|
||||||
"integrity": "sha512-bo5fEO5toQeyCp0zVHBeggclqf5SQ/Z5blfFmjwO5dkMVGPgmiwZsJh9nu/Bo5L7IHTuGWrja6LxJVE2uB5ZrQ==",
|
"integrity": "sha512-GT1PLGzhF3ilGaQiCHFDShxDBb014s01MQi0nWfXJ23efjWfUrZ2i0g4tH1JGdfnIGBtQDge/k3ON3fLoAuU/w==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
@ -4695,9 +4695,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/yargs": {
|
"node_modules/@types/yargs": {
|
||||||
"version": "17.0.26",
|
"version": "17.0.28",
|
||||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.26.tgz",
|
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.28.tgz",
|
||||||
"integrity": "sha512-Y3vDy2X6zw/ZCumcwLpdhM5L7jmyGpmBCTYMHDLqT2IKVMYRRLdv6ZakA+wxhra6Z/3bwhNbNl9bDGXaFU+6rw==",
|
"integrity": "sha512-N3e3fkS86hNhtk6BEnc0rj3zcehaxx8QWhCROJkqpl5Zaoi7nAic3jH8q94jVD3zu5LGk+PUB6KAiDmimYOEQw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/yargs-parser": "*"
|
"@types/yargs-parser": "*"
|
||||||
@ -5962,9 +5962,9 @@
|
|||||||
"integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ=="
|
"integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ=="
|
||||||
},
|
},
|
||||||
"node_modules/better-react-mathjax": {
|
"node_modules/better-react-mathjax": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/better-react-mathjax/-/better-react-mathjax-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/better-react-mathjax/-/better-react-mathjax-2.0.3.tgz",
|
||||||
"integrity": "sha512-GSU/c+LhnMVClkduWpO7fr9Ac2KMOxWs/ePwdFgpffidK3Zg9Vyd3scO6XZbd2QgMUcKnpjEG6hE1sM/EFekSQ==",
|
"integrity": "sha512-wfifT8GFOKb1TWm2+E50I6DJpLZ5kLbch283Lu043EJtwSv0XvZDjr4YfR4d2MjAhqP6SH4VjjrKgbX8R00oCQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"mathjax-full": "^3.2.2"
|
"mathjax-full": "^3.2.2"
|
||||||
},
|
},
|
||||||
@ -7582,9 +7582,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/electron-to-chromium": {
|
"node_modules/electron-to-chromium": {
|
||||||
"version": "1.4.542",
|
"version": "1.4.544",
|
||||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.542.tgz",
|
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.544.tgz",
|
||||||
"integrity": "sha512-6+cpa00G09N3sfh2joln4VUXHquWrOFx3FLZqiVQvl45+zS9DskDBTPvob+BhvFRmTBkyDSk0vvLMMRo/qc6mQ==",
|
"integrity": "sha512-54z7squS1FyFRSUqq/knOFSptjjogLZXbKcYk3B0qkE1KZzvqASwRZnY2KzZQJqIYLVD38XZeoiMRflYSwyO4w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/emittery": {
|
"node_modules/emittery": {
|
||||||
@ -8109,9 +8109,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint/node_modules/globals": {
|
"node_modules/eslint/node_modules/globals": {
|
||||||
"version": "13.22.0",
|
"version": "13.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/globals/-/globals-13.22.0.tgz",
|
"resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz",
|
||||||
"integrity": "sha512-H1Ddc/PbZHTDVJSnj8kWptIRSD6AM3pK+mKytuIVF4uoBV7rshFlhhvA58ceJ5wp3Er58w6zj7bykMpYXt3ETw==",
|
"integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"type-fest": "^0.20.2"
|
"type-fest": "^0.20.2"
|
||||||
@ -8704,12 +8704,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/flat-cache": {
|
"node_modules/flat-cache": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz",
|
||||||
"integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==",
|
"integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"flatted": "^3.2.7",
|
"flatted": "^3.2.9",
|
||||||
"keyv": "^4.5.3",
|
"keyv": "^4.5.3",
|
||||||
"rimraf": "^3.0.2"
|
"rimraf": "^3.0.2"
|
||||||
},
|
},
|
||||||
@ -12706,9 +12706,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/keyv": {
|
"node_modules/keyv": {
|
||||||
"version": "4.5.3",
|
"version": "4.5.4",
|
||||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
||||||
"integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==",
|
"integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"json-buffer": "3.0.1"
|
"json-buffer": "3.0.1"
|
||||||
@ -12733,13 +12733,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/launch-editor": {
|
"node_modules/launch-editor": {
|
||||||
"version": "2.6.0",
|
"version": "2.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.1.tgz",
|
||||||
"integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==",
|
"integrity": "sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"picocolors": "^1.0.0",
|
"picocolors": "^1.0.0",
|
||||||
"shell-quote": "^1.7.3"
|
"shell-quote": "^1.8.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/lazy-ass": {
|
"node_modules/lazy-ass": {
|
||||||
@ -16469,9 +16469,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/spdx-license-ids": {
|
"node_modules/spdx-license-ids": {
|
||||||
"version": "3.0.15",
|
"version": "3.0.16",
|
||||||
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.15.tgz",
|
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz",
|
||||||
"integrity": "sha512-lpT8hSQp9jAKp9mhtBU4Xjon8LPGBvLIuBiSVhMEtmLecTh2mO0tlqrAMp47tBXzMr13NJMQ2lf7RpQGLJ3HsQ==",
|
"integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/spdy": {
|
"node_modules/spdy": {
|
||||||
@ -17586,9 +17586,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/v8-to-istanbul": {
|
"node_modules/v8-to-istanbul": {
|
||||||
"version": "9.1.2",
|
"version": "9.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.3.tgz",
|
||||||
"integrity": "sha512-ZGBe7VAivuuoQXTeckpbYKTdtjXGcm3ZUHXC0PAk0CzFyuYvwi73a58iEKI3GkGD1c3EHc+EgfR1w5pgbfzJlQ==",
|
"integrity": "sha512-9lDD+EVI2fjFsMWXc6dy5JJzBsVTcQ2fVkfBvncZ6xJWG9wtBhOldG+mHkSL0+V1K/xgZz0JDO5UT5hFwHUghg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/trace-mapping": "^0.3.12",
|
"@jridgewell/trace-mapping": "^0.3.12",
|
||||||
|
102
package.json
102
package.json
@ -10,30 +10,30 @@
|
|||||||
"url": "https://github.com/bitburner-official/bitburner-src/issues"
|
"url": "https://github.com/bitburner-official/bitburner-src/issues"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.4.1",
|
"@emotion/react": "^11.11.1",
|
||||||
"@emotion/styled": "^11.10.5",
|
"@emotion/styled": "^11.11.0",
|
||||||
"@material-ui/core": "^4.12.4",
|
"@material-ui/core": "^4.12.4",
|
||||||
"@mui/icons-material": "^5.11.0",
|
"@mui/icons-material": "^5.14.12",
|
||||||
"@mui/material": "^5.14.12",
|
"@mui/material": "^5.14.12",
|
||||||
"@mui/styles": "^5.11.2",
|
"@mui/styles": "^5.14.12",
|
||||||
"@mui/system": "^5.0.3",
|
"@mui/system": "^5.14.12",
|
||||||
"@types/estree": "^1.0.0",
|
"@types/estree": "^1.0.2",
|
||||||
"@types/react-syntax-highlighter": "^15.5.7",
|
"@types/react-syntax-highlighter": "^15.5.8",
|
||||||
"acorn": "^8.8.1",
|
"acorn": "^8.10.0",
|
||||||
"acorn-walk": "^8.2.0",
|
"acorn-walk": "^8.2.0",
|
||||||
"arg": "^5.0.2",
|
"arg": "^5.0.2",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
"better-react-mathjax": "^2.0.2",
|
"better-react-mathjax": "^2.0.3",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
"date-fns": "^2.29.3",
|
"date-fns": "^2.30.0",
|
||||||
"escodegen": "^2.0.0",
|
"escodegen": "^2.1.0",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"jquery": "^3.6.3",
|
"jquery": "^3.7.1",
|
||||||
"js-sha256": "^0.9.0",
|
"js-sha256": "^0.9.0",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
"material-ui-color": "^1.2.0",
|
"material-ui-color": "^1.2.0",
|
||||||
"material-ui-popup-state": "^1.5.3",
|
"material-ui-popup-state": "^1.9.3",
|
||||||
"monaco-vim": "^0.3.5",
|
"monaco-vim": "^0.3.5",
|
||||||
"notistack": "^2.0.8",
|
"notistack": "^2.0.8",
|
||||||
"numeral": "^2.0.6",
|
"numeral": "^2.0.6",
|
||||||
@ -41,63 +41,63 @@
|
|||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-beautiful-dnd": "^13.1.1",
|
"react-beautiful-dnd": "^13.1.1",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-draggable": "^4.4.4",
|
"react-draggable": "^4.4.6",
|
||||||
"react-markdown": "^8.0.7",
|
"react-markdown": "^8.0.7",
|
||||||
"react-resizable": "^3.0.4",
|
"react-resizable": "^3.0.5",
|
||||||
"react-syntax-highlighter": "^15.5.0",
|
"react-syntax-highlighter": "^15.5.0",
|
||||||
"remark-gfm": "^3.0.1",
|
"remark-gfm": "^3.0.1",
|
||||||
"sprintf-js": "^1.1.2"
|
"sprintf-js": "^1.1.3"
|
||||||
},
|
},
|
||||||
"description": "A cyberpunk-themed incremental game",
|
"description": "A cyberpunk-themed incremental game",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.20.12",
|
"@babel/core": "^7.23.0",
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.22.20",
|
||||||
"@babel/preset-react": "^7.18.6",
|
"@babel/preset-react": "^7.22.15",
|
||||||
"@babel/preset-typescript": "^7.18.6",
|
"@babel/preset-typescript": "^7.23.0",
|
||||||
"@microsoft/api-documenter": "^7.21.3",
|
"@microsoft/api-documenter": "^7.23.9",
|
||||||
"@microsoft/api-extractor": "^7.34.2",
|
"@microsoft/api-extractor": "^7.38.0",
|
||||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.10",
|
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.11",
|
||||||
"@types/bcryptjs": "^2.4.2",
|
"@types/bcryptjs": "^2.4.4",
|
||||||
"@types/escodegen": "^0.0.7",
|
"@types/escodegen": "^0.0.7",
|
||||||
"@types/file-saver": "^2.0.5",
|
"@types/file-saver": "^2.0.5",
|
||||||
"@types/jest": "^29.4.0",
|
"@types/jest": "^29.5.5",
|
||||||
"@types/jquery": "^3.5.16",
|
"@types/jquery": "^3.5.22",
|
||||||
"@types/lodash": "^4.14.191",
|
"@types/lodash": "^4.14.199",
|
||||||
"@types/numeral": "^2.0.2",
|
"@types/numeral": "^2.0.3",
|
||||||
"@types/react": "^17.0.52",
|
"@types/react": "^17.0.67",
|
||||||
"@types/react-beautiful-dnd": "^13.1.3",
|
"@types/react-beautiful-dnd": "^13.1.5",
|
||||||
"@types/react-dom": "^17.0.20",
|
"@types/react-dom": "^17.0.21",
|
||||||
"@types/react-resizable": "^3.0.3",
|
"@types/react-resizable": "^3.0.5",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.48.0",
|
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
||||||
"@typescript-eslint/parser": "^5.48.0",
|
"@typescript-eslint/parser": "^5.62.0",
|
||||||
"babel-jest": "^29.3.1",
|
"babel-jest": "^29.7.0",
|
||||||
"babel-loader": "^9.1.2",
|
"babel-loader": "^9.1.3",
|
||||||
"css-loader": "^6.7.3",
|
"css-loader": "^6.8.1",
|
||||||
"electron": "^26.2.4",
|
"electron": "^26.3.0",
|
||||||
"electron-packager": "^17.1.1",
|
"electron-packager": "^17.1.2",
|
||||||
"eslint": "^8.51.0",
|
"eslint": "^8.51.0",
|
||||||
"eslint-plugin-react": "^7.32.2",
|
"eslint-plugin-react": "^7.33.2",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
"fork-ts-checker-webpack-plugin": "^7.2.14",
|
"fork-ts-checker-webpack-plugin": "^7.3.0",
|
||||||
"html-webpack-plugin": "^5.5.0",
|
"html-webpack-plugin": "^5.5.3",
|
||||||
"http-server": "^14.1.1",
|
"http-server": "^14.1.1",
|
||||||
"jest": "^29.4.3",
|
"jest": "^29.7.0",
|
||||||
"jest-environment-jsdom": "^29.4.3",
|
"jest-environment-jsdom": "^29.7.0",
|
||||||
"jsdom": "^20.0.3",
|
"jsdom": "^20.0.3",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"monaco-editor": "^0.35.0",
|
"monaco-editor": "^0.35.0",
|
||||||
"monaco-editor-webpack-plugin": "^7.0.1",
|
"monaco-editor-webpack-plugin": "^7.1.0",
|
||||||
"prettier": "^2.8.1",
|
"prettier": "^2.8.8",
|
||||||
"raw-loader": "^4.0.2",
|
"raw-loader": "^4.0.2",
|
||||||
"react-refresh": "^0.14.0",
|
"react-refresh": "^0.14.0",
|
||||||
"source-map": "^0.7.4",
|
"source-map": "^0.7.4",
|
||||||
"start-server-and-test": "^1.15.2",
|
"start-server-and-test": "^1.15.4",
|
||||||
"style-loader": "^3.3.1",
|
"style-loader": "^3.3.3",
|
||||||
"typescript": "^5.2.2",
|
"typescript": "^5.2.2",
|
||||||
"webpack": "^5.75.0",
|
"webpack": "^5.88.2",
|
||||||
"webpack-cli": "^5.0.1",
|
"webpack-cli": "^5.1.4",
|
||||||
"webpack-dev-server": "^4.11.1"
|
"webpack-dev-server": "^4.15.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
|
70
src/ScriptEditor/ScriptEditor.ts
Normal file
70
src/ScriptEditor/ScriptEditor.ts
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
import type { ContentFilePath } from "../Paths/ContentFile";
|
||||||
|
|
||||||
|
import { EventEmitter } from "../utils/EventEmitter";
|
||||||
|
import * as monaco from "monaco-editor";
|
||||||
|
import { loadThemes, makeTheme, sanitizeTheme } from "./ui/themes";
|
||||||
|
import libSource from "!!raw-loader!./NetscriptDefinitions.d.ts";
|
||||||
|
import { Settings } from "../Settings/Settings";
|
||||||
|
import { NetscriptExtra } from "../NetscriptFunctions/Extra";
|
||||||
|
import * as enums from "../Enums";
|
||||||
|
import { ns } from "../NetscriptFunctions";
|
||||||
|
|
||||||
|
/** Event emitter used for tracking when changes have been made to a content file. */
|
||||||
|
export const fileEditEvents = new EventEmitter<[hostname: string, filename: ContentFilePath]>();
|
||||||
|
|
||||||
|
export class ScriptEditor {
|
||||||
|
// TODO: This will store info about currently open scripts.
|
||||||
|
// Among other things, this will allow informing the script editor of changes made elsewhere, even if the script editor is not being rendered.
|
||||||
|
// openScripts: OpenScript[] = [];
|
||||||
|
|
||||||
|
// Currently, this object is only used for initialization.
|
||||||
|
isInitialized = false;
|
||||||
|
initialize() {
|
||||||
|
if (this.isInitialized) return;
|
||||||
|
this.isInitialized = true;
|
||||||
|
// populate API keys for adding tokenization
|
||||||
|
const apiKeys: string[] = [];
|
||||||
|
const api = { args: [], pid: 1, enums, ...ns };
|
||||||
|
const hiddenAPI = NetscriptExtra();
|
||||||
|
function populate(apiLayer: object = api) {
|
||||||
|
for (const [apiKey, apiValue] of Object.entries(apiLayer)) {
|
||||||
|
if (apiLayer === api && apiKey in hiddenAPI) continue;
|
||||||
|
apiKeys.push(apiKey);
|
||||||
|
if (typeof apiValue === "object") populate(apiValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
populate();
|
||||||
|
// Add api keys to tokenization
|
||||||
|
(async function () {
|
||||||
|
// We have to improve the default js language otherwise theme sucks
|
||||||
|
const jsLanguage = monaco.languages.getLanguages().find((l) => l.id === "javascript");
|
||||||
|
// Unsupported function is not exposed in monaco public API.
|
||||||
|
const l = await (jsLanguage as any).loader();
|
||||||
|
// replaced the bare tokens with regexes surrounded by \b, e.g. \b{token}\b which matches a word-break on either side
|
||||||
|
// this prevents the highlighter from highlighting pieces of variables that start with a reserved token name
|
||||||
|
l.language.tokenizer.root.unshift([new RegExp("\\bns\\b"), { token: "ns" }]);
|
||||||
|
for (const symbol of apiKeys)
|
||||||
|
l.language.tokenizer.root.unshift([new RegExp(`\\b${symbol}\\b`), { token: "netscriptfunction" }]);
|
||||||
|
const otherKeywords = ["let", "const", "var", "function"];
|
||||||
|
const otherKeyvars = ["true", "false", "null", "undefined"];
|
||||||
|
otherKeywords.forEach((k) =>
|
||||||
|
l.language.tokenizer.root.unshift([new RegExp(`\\b${k}\\b`), { token: "otherkeywords" }]),
|
||||||
|
);
|
||||||
|
otherKeyvars.forEach((k) =>
|
||||||
|
l.language.tokenizer.root.unshift([new RegExp(`\\b${k}\\b`), { token: "otherkeyvars" }]),
|
||||||
|
);
|
||||||
|
l.language.tokenizer.root.unshift([new RegExp("\\bthis\\b"), { token: "this" }]);
|
||||||
|
})();
|
||||||
|
|
||||||
|
// Add ts definitions for API
|
||||||
|
const source = (libSource + "").replace(/export /g, "");
|
||||||
|
monaco.languages.typescript.javascriptDefaults.addExtraLib(source, "netscript.d.ts");
|
||||||
|
monaco.languages.typescript.typescriptDefaults.addExtraLib(source, "netscript.d.ts");
|
||||||
|
// Load themes
|
||||||
|
loadThemes(monaco.editor.defineTheme);
|
||||||
|
sanitizeTheme(Settings.EditorTheme);
|
||||||
|
monaco.editor.defineTheme("customTheme", makeTheme(Settings.EditorTheme));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const scriptEditor = new ScriptEditor();
|
@ -3,17 +3,16 @@ import React, { useEffect, useRef } from "react";
|
|||||||
import * as monaco from "monaco-editor";
|
import * as monaco from "monaco-editor";
|
||||||
|
|
||||||
import { useScriptEditorContext } from "./ScriptEditorContext";
|
import { useScriptEditorContext } from "./ScriptEditorContext";
|
||||||
|
import { scriptEditor } from "../ScriptEditor";
|
||||||
|
|
||||||
interface EditorProps {
|
interface EditorProps {
|
||||||
/** Function to be ran prior to mounting editor */
|
|
||||||
beforeMount: () => void;
|
|
||||||
/** Function to be ran after mounting editor */
|
/** Function to be ran after mounting editor */
|
||||||
onMount: (editor: monaco.editor.IStandaloneCodeEditor) => void;
|
onMount: (editor: monaco.editor.IStandaloneCodeEditor) => void;
|
||||||
/** Function to be ran every time the code is updated */
|
/** Function to be ran every time the code is updated */
|
||||||
onChange: (newCode?: string) => void;
|
onChange: (newCode?: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Editor({ beforeMount, onMount, onChange }: EditorProps) {
|
export function Editor({ onMount, onChange }: EditorProps) {
|
||||||
const containerDiv = useRef<HTMLDivElement | null>(null);
|
const containerDiv = useRef<HTMLDivElement | null>(null);
|
||||||
const editorRef = useRef<monaco.editor.IStandaloneCodeEditor | null>(null);
|
const editorRef = useRef<monaco.editor.IStandaloneCodeEditor | null>(null);
|
||||||
const subscription = useRef<monaco.IDisposable | null>(null);
|
const subscription = useRef<monaco.IDisposable | null>(null);
|
||||||
@ -23,7 +22,7 @@ export function Editor({ beforeMount, onMount, onChange }: EditorProps) {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!containerDiv.current) return;
|
if (!containerDiv.current) return;
|
||||||
// Before initializing monaco editor
|
// Before initializing monaco editor
|
||||||
beforeMount();
|
scriptEditor.initialize();
|
||||||
|
|
||||||
// Initialize monaco editor
|
// Initialize monaco editor
|
||||||
editorRef.current = monaco.editor.create(containerDiv.current, {
|
editorRef.current = monaco.editor.create(containerDiv.current, {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import type { editor, Position } from "monaco-editor";
|
|
||||||
|
|
||||||
import type { ContentFilePath } from "../../Paths/ContentFile";
|
import type { ContentFilePath } from "../../Paths/ContentFile";
|
||||||
|
import { editor, Position } from "monaco-editor";
|
||||||
|
|
||||||
type ITextModel = editor.ITextModel;
|
type ITextModel = editor.ITextModel;
|
||||||
|
|
||||||
@ -12,6 +11,8 @@ export class OpenScript {
|
|||||||
lastPosition: Position;
|
lastPosition: Position;
|
||||||
model: ITextModel;
|
model: ITextModel;
|
||||||
isTxt: boolean;
|
isTxt: boolean;
|
||||||
|
// TODO: Adding actual external update notifications for the OpenScript class
|
||||||
|
// hasExternalUpdate = false;
|
||||||
|
|
||||||
constructor(path: ContentFilePath, code: string, hostname: string, lastPosition: Position, model: ITextModel) {
|
constructor(path: ContentFilePath, code: string, hostname: string, lastPosition: Position, model: ITextModel) {
|
||||||
this.path = path;
|
this.path = path;
|
||||||
@ -21,4 +22,8 @@ export class OpenScript {
|
|||||||
this.model = model;
|
this.model = model;
|
||||||
this.isTxt = path.endsWith(".txt");
|
this.isTxt = path.endsWith(".txt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
regenerateModel(): void {
|
||||||
|
this.model = editor.createModel(this.code, this.isTxt ? "plaintext" : "javascript");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import type { ContentFilePath } from "../../Paths/ContentFile";
|
||||||
|
|
||||||
import React, { useEffect, useRef } from "react";
|
import React, { useEffect, useRef } from "react";
|
||||||
import * as monaco from "monaco-editor";
|
import * as monaco from "monaco-editor";
|
||||||
|
|
||||||
@ -8,23 +10,17 @@ type IStandaloneCodeEditor = monaco.editor.IStandaloneCodeEditor;
|
|||||||
import { Router } from "../../ui/GameRoot";
|
import { Router } from "../../ui/GameRoot";
|
||||||
import { Page } from "../../ui/Router";
|
import { Page } from "../../ui/Router";
|
||||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
||||||
import { ScriptFilePath } from "../../Paths/ScriptFilePath";
|
|
||||||
import { checkInfiniteLoop } from "../../Script/RamCalculations";
|
import { checkInfiniteLoop } from "../../Script/RamCalculations";
|
||||||
|
|
||||||
import { ns, enums } from "../../NetscriptFunctions";
|
|
||||||
import { Settings } from "../../Settings/Settings";
|
import { Settings } from "../../Settings/Settings";
|
||||||
import { iTutorialNextStep, ITutorial, iTutorialSteps } from "../../InteractiveTutorial";
|
import { iTutorialNextStep, ITutorial, iTutorialSteps } from "../../InteractiveTutorial";
|
||||||
import { debounce } from "lodash";
|
import { debounce } from "lodash";
|
||||||
import { saveObject } from "../../SaveObject";
|
import { saveObject } from "../../SaveObject";
|
||||||
import { loadThemes, makeTheme, sanitizeTheme } from "./themes";
|
|
||||||
import { GetServer } from "../../Server/AllServers";
|
import { GetServer } from "../../Server/AllServers";
|
||||||
|
|
||||||
import { PromptEvent } from "../../ui/React/PromptManager";
|
import { PromptEvent } from "../../ui/React/PromptManager";
|
||||||
|
|
||||||
import libSource from "!!raw-loader!../NetscriptDefinitions.d.ts";
|
|
||||||
import { useRerender } from "../../ui/React/hooks";
|
import { useRerender } from "../../ui/React/hooks";
|
||||||
import { NetscriptExtra } from "../../NetscriptFunctions/Extra";
|
|
||||||
import { TextFilePath } from "../../Paths/TextFilePath";
|
|
||||||
|
|
||||||
import { dirty, getServerCode } from "./utils";
|
import { dirty, getServerCode } from "./utils";
|
||||||
import { OpenScript } from "./OpenScript";
|
import { OpenScript } from "./OpenScript";
|
||||||
@ -33,31 +29,14 @@ import { Toolbar } from "./Toolbar";
|
|||||||
import { NoOpenScripts } from "./NoOpenScripts";
|
import { NoOpenScripts } from "./NoOpenScripts";
|
||||||
import { ScriptEditorContextProvider, useScriptEditorContext } from "./ScriptEditorContext";
|
import { ScriptEditorContextProvider, useScriptEditorContext } from "./ScriptEditorContext";
|
||||||
import { useVimEditor } from "./useVimEditor";
|
import { useVimEditor } from "./useVimEditor";
|
||||||
|
import { useCallback } from "react";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
// Map of filename -> code
|
// Map of filename -> code
|
||||||
files: Map<ScriptFilePath | TextFilePath, string>;
|
files: Map<ContentFilePath, string>;
|
||||||
hostname: string;
|
hostname: string;
|
||||||
vim: boolean;
|
vim: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: try to remove global symbols
|
|
||||||
let symbolsLoaded = false;
|
|
||||||
const apiKeys: string[] = [];
|
|
||||||
export function SetupTextEditor(): void {
|
|
||||||
// Function for populating apiKeys using a given layer of the API.
|
|
||||||
const api = { args: [], pid: 1, enums, ...ns };
|
|
||||||
const hiddenAPI = NetscriptExtra();
|
|
||||||
function populate(apiLayer: object = api) {
|
|
||||||
for (const [apiKey, apiValue] of Object.entries(apiLayer)) {
|
|
||||||
if (apiLayer === api && apiKey in hiddenAPI) continue;
|
|
||||||
apiKeys.push(apiKey);
|
|
||||||
if (typeof apiValue === "object") populate(apiValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
populate();
|
|
||||||
}
|
|
||||||
|
|
||||||
const openScripts: OpenScript[] = [];
|
const openScripts: OpenScript[] = [];
|
||||||
let currentScript: OpenScript | null = null;
|
let currentScript: OpenScript | null = null;
|
||||||
|
|
||||||
@ -77,6 +56,42 @@ function Root(props: IProps): React.ReactElement {
|
|||||||
currentScript = openScripts[0] ?? null;
|
currentScript = openScripts[0] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const save = useCallback(() => {
|
||||||
|
if (currentScript === null) {
|
||||||
|
console.error("currentScript is null when it shouldn't be. Unable to save script");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// this is duplicate code with saving later.
|
||||||
|
if (ITutorial.isRunning && ITutorial.currStep === iTutorialSteps.TerminalTypeScript) {
|
||||||
|
//Make sure filename + code properly follow tutorial
|
||||||
|
if (currentScript.path !== "n00dles.script" && currentScript.path !== "n00dles.js") {
|
||||||
|
dialogBoxCreate("Don't change the script name for now.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const cleanCode = currentScript.code.replace(/\s/g, "");
|
||||||
|
const ns1 = "while(true){hack('n00dles');}";
|
||||||
|
const ns2 = `exportasyncfunctionmain(ns){while(true){awaitns.hack('n00dles');}}`;
|
||||||
|
if (!cleanCode.includes(ns1) && !cleanCode.includes(ns2)) {
|
||||||
|
dialogBoxCreate("Please copy and paste the code from the tutorial!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Save the script
|
||||||
|
saveScript(currentScript);
|
||||||
|
Router.toPage(Page.Terminal);
|
||||||
|
|
||||||
|
iTutorialNextStep();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const server = GetServer(currentScript.hostname);
|
||||||
|
if (server === null) throw new Error("Server should not be null but it is.");
|
||||||
|
server.writeToContentFile(currentScript.path, currentScript.code);
|
||||||
|
if (Settings.SaveGameOnFileSave) saveObject.saveGame();
|
||||||
|
rerender();
|
||||||
|
}, [rerender]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function keydown(event: KeyboardEvent): void {
|
function keydown(event: KeyboardEvent): void {
|
||||||
if (Settings.DisableHotkeys) return;
|
if (Settings.DisableHotkeys) return;
|
||||||
@ -95,12 +110,7 @@ function Root(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
document.addEventListener("keydown", keydown);
|
document.addEventListener("keydown", keydown);
|
||||||
return () => document.removeEventListener("keydown", keydown);
|
return () => document.removeEventListener("keydown", keydown);
|
||||||
});
|
}, [save]);
|
||||||
|
|
||||||
// Generates a new model for the script
|
|
||||||
function regenerateModel(script: OpenScript): void {
|
|
||||||
script.model = monaco.editor.createModel(script.code, script.isTxt ? "plaintext" : "javascript");
|
|
||||||
}
|
|
||||||
|
|
||||||
function infLoop(newCode: string): void {
|
function infLoop(newCode: string): void {
|
||||||
if (editorRef.current === null || currentScript === null) return;
|
if (editorRef.current === null || currentScript === null) return;
|
||||||
@ -142,56 +152,15 @@ function Root(props: IProps): React.ReactElement {
|
|||||||
debouncedCodeParsing(newCode);
|
debouncedCodeParsing(newCode);
|
||||||
};
|
};
|
||||||
|
|
||||||
// How to load function definition in monaco
|
|
||||||
// https://github.com/Microsoft/monaco-editor/issues/1415
|
|
||||||
// https://microsoft.github.io/monaco-editor/api/modules/monaco.languages.html
|
|
||||||
// https://www.npmjs.com/package/@monaco-editor/react#development-playground
|
|
||||||
// https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-custom-languages
|
|
||||||
// https://github.com/threehams/typescript-error-guide/blob/master/stories/components/Editor.tsx#L11-L39
|
|
||||||
// https://blog.checklyhq.com/customizing-monaco/
|
|
||||||
// Before the editor is mounted
|
|
||||||
function beforeMount(): void {
|
|
||||||
if (symbolsLoaded) return;
|
|
||||||
// Setup monaco auto completion
|
|
||||||
symbolsLoaded = true;
|
|
||||||
(async function () {
|
|
||||||
// We have to improve the default js language otherwise theme sucks
|
|
||||||
const jsLanguage = monaco.languages.getLanguages().find((l) => l.id === "javascript");
|
|
||||||
// Unsupported function is not exposed in monaco public API.
|
|
||||||
const l = await (jsLanguage as any).loader();
|
|
||||||
// replaced the bare tokens with regexes surrounded by \b, e.g. \b{token}\b which matches a word-break on either side
|
|
||||||
// this prevents the highlighter from highlighting pieces of variables that start with a reserved token name
|
|
||||||
l.language.tokenizer.root.unshift([new RegExp("\\bns\\b"), { token: "ns" }]);
|
|
||||||
for (const symbol of apiKeys)
|
|
||||||
l.language.tokenizer.root.unshift([new RegExp(`\\b${symbol}\\b`), { token: "netscriptfunction" }]);
|
|
||||||
const otherKeywords = ["let", "const", "var", "function"];
|
|
||||||
const otherKeyvars = ["true", "false", "null", "undefined"];
|
|
||||||
otherKeywords.forEach((k) =>
|
|
||||||
l.language.tokenizer.root.unshift([new RegExp(`\\b${k}\\b`), { token: "otherkeywords" }]),
|
|
||||||
);
|
|
||||||
otherKeyvars.forEach((k) =>
|
|
||||||
l.language.tokenizer.root.unshift([new RegExp(`\\b${k}\\b`), { token: "otherkeyvars" }]),
|
|
||||||
);
|
|
||||||
l.language.tokenizer.root.unshift([new RegExp("\\bthis\\b"), { token: "this" }]);
|
|
||||||
})();
|
|
||||||
|
|
||||||
const source = (libSource + "").replace(/export /g, "");
|
|
||||||
monaco.languages.typescript.javascriptDefaults.addExtraLib(source, "netscript.d.ts");
|
|
||||||
monaco.languages.typescript.typescriptDefaults.addExtraLib(source, "netscript.d.ts");
|
|
||||||
loadThemes(monaco.editor.defineTheme);
|
|
||||||
sanitizeTheme(Settings.EditorTheme);
|
|
||||||
monaco.editor.defineTheme("customTheme", makeTheme(Settings.EditorTheme));
|
|
||||||
}
|
|
||||||
|
|
||||||
// When the editor is mounted
|
// When the editor is mounted
|
||||||
function onMount(editor: IStandaloneCodeEditor): void {
|
function onMount(editor: IStandaloneCodeEditor): void {
|
||||||
// Required when switching between site navigation (e.g. from Script Editor -> Terminal and back)
|
// Required when switching between site navigation (e.g. from Script Editor -> Terminal and back)
|
||||||
// the `useEffect()` for vim mode is called before editor is mounted.
|
// the `useEffect()` for vim mode is called before editor is mounted.
|
||||||
editorRef.current = editor;
|
editorRef.current = editor;
|
||||||
|
|
||||||
if (!props.files && currentScript !== null) {
|
if (props.files.size === 0 && currentScript !== null) {
|
||||||
// Open currentscript
|
// Open currentscript
|
||||||
regenerateModel(currentScript);
|
currentScript.regenerateModel();
|
||||||
editorRef.current.setModel(currentScript.model);
|
editorRef.current.setModel(currentScript.model);
|
||||||
editorRef.current.setPosition(currentScript.lastPosition);
|
editorRef.current.setPosition(currentScript.lastPosition);
|
||||||
editorRef.current.revealLineInCenter(currentScript.lastPosition.lineNumber);
|
editorRef.current.revealLineInCenter(currentScript.lastPosition.lineNumber);
|
||||||
@ -199,42 +168,35 @@ function Root(props: IProps): React.ReactElement {
|
|||||||
editorRef.current.focus();
|
editorRef.current.focus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (props.files) {
|
const files = props.files;
|
||||||
const files = props.files;
|
|
||||||
|
|
||||||
if (!files.size) {
|
for (const [filename, code] of files) {
|
||||||
editorRef.current.focus();
|
// Check if file is already opened
|
||||||
return;
|
const openScript = openScripts.find((script) => script.path === filename && script.hostname === props.hostname);
|
||||||
}
|
if (openScript) {
|
||||||
|
// Script is already opened
|
||||||
for (const [filename, code] of files) {
|
if (openScript.model === undefined || openScript.model === null || openScript.model.isDisposed()) {
|
||||||
// Check if file is already opened
|
openScript.regenerateModel();
|
||||||
const openScript = openScripts.find((script) => script.path === filename && script.hostname === props.hostname);
|
|
||||||
if (openScript) {
|
|
||||||
// Script is already opened
|
|
||||||
if (openScript.model === undefined || openScript.model === null || openScript.model.isDisposed()) {
|
|
||||||
regenerateModel(openScript);
|
|
||||||
}
|
|
||||||
|
|
||||||
currentScript = openScript;
|
|
||||||
editorRef.current.setModel(openScript.model);
|
|
||||||
editorRef.current.setPosition(openScript.lastPosition);
|
|
||||||
editorRef.current.revealLineInCenter(openScript.lastPosition.lineNumber);
|
|
||||||
parseCode(openScript.code);
|
|
||||||
} else {
|
|
||||||
// Open script
|
|
||||||
const newScript = new OpenScript(
|
|
||||||
filename,
|
|
||||||
code,
|
|
||||||
props.hostname,
|
|
||||||
new monaco.Position(0, 0),
|
|
||||||
monaco.editor.createModel(code, filename.endsWith(".txt") ? "plaintext" : "javascript"),
|
|
||||||
);
|
|
||||||
openScripts.push(newScript);
|
|
||||||
currentScript = newScript;
|
|
||||||
editorRef.current.setModel(newScript.model);
|
|
||||||
parseCode(newScript.code);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
currentScript = openScript;
|
||||||
|
editorRef.current.setModel(openScript.model);
|
||||||
|
editorRef.current.setPosition(openScript.lastPosition);
|
||||||
|
editorRef.current.revealLineInCenter(openScript.lastPosition.lineNumber);
|
||||||
|
parseCode(openScript.code);
|
||||||
|
} else {
|
||||||
|
// Open script
|
||||||
|
const newScript = new OpenScript(
|
||||||
|
filename,
|
||||||
|
code,
|
||||||
|
props.hostname,
|
||||||
|
new monaco.Position(0, 0),
|
||||||
|
monaco.editor.createModel(code, filename.endsWith(".txt") ? "plaintext" : "javascript"),
|
||||||
|
);
|
||||||
|
openScripts.push(newScript);
|
||||||
|
currentScript = newScript;
|
||||||
|
editorRef.current.setModel(newScript.model);
|
||||||
|
parseCode(newScript.code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,42 +225,6 @@ function Root(props: IProps): React.ReactElement {
|
|||||||
if (Settings.SaveGameOnFileSave) saveObject.saveGame();
|
if (Settings.SaveGameOnFileSave) saveObject.saveGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
function save(): void {
|
|
||||||
if (currentScript === null) {
|
|
||||||
console.error("currentScript is null when it shouldn't be. Unable to save script");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// this is duplicate code with saving later.
|
|
||||||
if (ITutorial.isRunning && ITutorial.currStep === iTutorialSteps.TerminalTypeScript) {
|
|
||||||
//Make sure filename + code properly follow tutorial
|
|
||||||
if (currentScript.path !== "n00dles.script" && currentScript.path !== "n00dles.js") {
|
|
||||||
dialogBoxCreate("Don't change the script name for now.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const cleanCode = currentScript.code.replace(/\s/g, "");
|
|
||||||
const ns1 = "while(true){hack('n00dles');}";
|
|
||||||
const ns2 = `exportasyncfunctionmain(ns){while(true){awaitns.hack('n00dles');}}`;
|
|
||||||
if (!cleanCode.includes(ns1) && !cleanCode.includes(ns2)) {
|
|
||||||
dialogBoxCreate("Please copy and paste the code from the tutorial!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Save the script
|
|
||||||
saveScript(currentScript);
|
|
||||||
Router.toPage(Page.Terminal);
|
|
||||||
|
|
||||||
iTutorialNextStep();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const server = GetServer(currentScript.hostname);
|
|
||||||
if (server === null) throw new Error("Server should not be null but it is.");
|
|
||||||
server.writeToContentFile(currentScript.path, currentScript.code);
|
|
||||||
if (Settings.SaveGameOnFileSave) saveObject.saveGame();
|
|
||||||
rerender();
|
|
||||||
}
|
|
||||||
|
|
||||||
function currentTabIndex(): number | undefined {
|
function currentTabIndex(): number | undefined {
|
||||||
if (currentScript) return openScripts.findIndex((openScript) => currentScript === openScript);
|
if (currentScript) return openScripts.findIndex((openScript) => currentScript === openScript);
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -316,8 +242,8 @@ function Root(props: IProps): React.ReactElement {
|
|||||||
currentScript = openScripts[index];
|
currentScript = openScripts[index];
|
||||||
|
|
||||||
if (editorRef.current !== null && openScripts[index] !== null) {
|
if (editorRef.current !== null && openScripts[index] !== null) {
|
||||||
if (currentScript.model === undefined || currentScript.model.isDisposed()) {
|
if (!currentScript.model || currentScript.model.isDisposed()) {
|
||||||
regenerateModel(currentScript);
|
currentScript.regenerateModel();
|
||||||
}
|
}
|
||||||
editorRef.current.setModel(currentScript.model);
|
editorRef.current.setModel(currentScript.model);
|
||||||
editorRef.current.setPosition(currentScript.lastPosition);
|
editorRef.current.setPosition(currentScript.lastPosition);
|
||||||
@ -361,7 +287,7 @@ function Root(props: IProps): React.ReactElement {
|
|||||||
currentScript = openScripts[index + indexOffset];
|
currentScript = openScripts[index + indexOffset];
|
||||||
if (editorRef.current !== null) {
|
if (editorRef.current !== null) {
|
||||||
if (currentScript.model.isDisposed() || !currentScript.model) {
|
if (currentScript.model.isDisposed() || !currentScript.model) {
|
||||||
regenerateModel(currentScript);
|
currentScript.regenerateModel();
|
||||||
}
|
}
|
||||||
editorRef.current.setModel(currentScript.model);
|
editorRef.current.setModel(currentScript.model);
|
||||||
editorRef.current.setPosition(currentScript.lastPosition);
|
editorRef.current.setPosition(currentScript.lastPosition);
|
||||||
@ -393,7 +319,7 @@ function Root(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
if (editorRef.current !== null && openScript !== null) {
|
if (editorRef.current !== null && openScript !== null) {
|
||||||
if (openScript.model === undefined || openScript.model.isDisposed()) {
|
if (openScript.model === undefined || openScript.model.isDisposed()) {
|
||||||
regenerateModel(openScript);
|
openScript.regenerateModel();
|
||||||
}
|
}
|
||||||
editorRef.current.setModel(openScript.model);
|
editorRef.current.setModel(openScript.model);
|
||||||
|
|
||||||
@ -464,7 +390,7 @@ function Root(props: IProps): React.ReactElement {
|
|||||||
onTabUpdate={onTabUpdate}
|
onTabUpdate={onTabUpdate}
|
||||||
/>
|
/>
|
||||||
<div style={{ flex: "0 0 5px" }} />
|
<div style={{ flex: "0 0 5px" }} />
|
||||||
<Editor beforeMount={beforeMount} onMount={onMount} onChange={updateCode} />
|
<Editor onMount={onMount} onChange={updateCode} />
|
||||||
|
|
||||||
{VimStatus}
|
{VimStatus}
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { dialogBoxCreate } from "./ui/React/DialogBox";
|
|
||||||
import { BaseServer } from "./Server/BaseServer";
|
import { BaseServer } from "./Server/BaseServer";
|
||||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, constructorsForReviver } from "./utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, constructorsForReviver } from "./utils/JSONReviver";
|
||||||
import { TextFilePath } from "./Paths/TextFilePath";
|
import { TextFilePath } from "./Paths/TextFilePath";
|
||||||
@ -25,11 +24,6 @@ export class TextFile implements ContentFile {
|
|||||||
this.text = txt;
|
this.text = txt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Concatenates the raw values to the end of current content. */
|
|
||||||
append(txt: string): void {
|
|
||||||
this.text += txt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Serves the file to the user as a downloadable resource through the browser. */
|
/** Serves the file to the user as a downloadable resource through the browser. */
|
||||||
download(): void {
|
download(): void {
|
||||||
const file: Blob = new Blob([this.text], { type: "text/plain" });
|
const file: Blob = new Blob([this.text], { type: "text/plain" });
|
||||||
@ -41,30 +35,15 @@ export class TextFile implements ContentFile {
|
|||||||
a.click();
|
a.click();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
document.body.removeChild(a);
|
document.body.removeChild(a);
|
||||||
window.URL.revokeObjectURL(url);
|
URL.revokeObjectURL(url);
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Retrieve the content of the file. */
|
|
||||||
read(): string {
|
|
||||||
return this.text;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Shows the content to the user via the game's dialog box. */
|
|
||||||
show(): void {
|
|
||||||
dialogBoxCreate(`${this.filename}\n\n${this.text}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Serialize the current file to a JSON save state. */
|
/** Serialize the current file to a JSON save state. */
|
||||||
toJSON(): IReviverValue {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("TextFile", this);
|
return Generic_toJSON("TextFile", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Replaces the current content with the text provided. */
|
|
||||||
write(txt: string): void {
|
|
||||||
this.text = txt;
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteFromServer(server: BaseServer): boolean {
|
deleteFromServer(server: BaseServer): boolean {
|
||||||
if (!server.textFiles.has(this.filename)) return false;
|
if (!server.textFiles.has(this.filename)) return false;
|
||||||
server.textFiles.delete(this.filename);
|
server.textFiles.delete(this.filename);
|
||||||
|
@ -9,7 +9,6 @@ import { staneksGift } from "./CotMG/Helper";
|
|||||||
import { processPassiveFactionRepGain, inviteToFaction } from "./Faction/FactionHelpers";
|
import { processPassiveFactionRepGain, inviteToFaction } from "./Faction/FactionHelpers";
|
||||||
import { Router } from "./ui/GameRoot";
|
import { Router } from "./ui/GameRoot";
|
||||||
import { Page } from "./ui/Router";
|
import { Page } from "./ui/Router";
|
||||||
import { SetupTextEditor } from "./ScriptEditor/ui/ScriptEditorRoot";
|
|
||||||
import "./PersonObjects/Player/PlayerObject"; // For side-effect of creating Player
|
import "./PersonObjects/Player/PlayerObject"; // For side-effect of creating Player
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -377,7 +376,6 @@ const Engine: {
|
|||||||
// Start interactive tutorial
|
// Start interactive tutorial
|
||||||
iTutorialStart();
|
iTutorialStart();
|
||||||
}
|
}
|
||||||
SetupTextEditor();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
start: function () {
|
start: function () {
|
||||||
|
Loading…
Reference in New Issue
Block a user