From b2779756564c2dd01474ffd3e14709f618ee244d Mon Sep 17 00:00:00 2001 From: Tom Prince Date: Sun, 7 Jul 2024 01:08:33 -0600 Subject: [PATCH] EDITOR: Provide type definitions for `React` and `ReactDOM` in in-game editor. (#1458) * Fix the type declaration of `!!raw-loader!` modules. Instead of declaring them to export an object with a single key `default` which is a string, the modules have a default export, which is a string. Note, that this doesn't actually change the generated code, just the types that typescript sees. The code worked before because the only thing done to the values was to coerce the values to a string, which turned into a no-op. * Switch from using `raw-loader` to using a source asset module. `raw-loader` was deprecated in webpack v5. --- jest.config.js | 2 +- package-lock.json | 21 ----- package.json | 1 - src/Documentation/pages.ts | 127 +++++++++++++-------------- src/Documentation/root.ts | 8 +- src/RemoteFileAPI/MessageHandlers.ts | 4 +- src/ScriptEditor/ScriptEditor.ts | 19 +++- src/ScriptEditor/raw-loader.d.ts | 6 +- src/ui/MD/MD.tsx | 2 +- test/jest/StockMarket.test.ts | 4 - tools/bundle-doc/index.js | 7 +- webpack.config.js | 5 ++ 12 files changed, 95 insertions(+), 111 deletions(-) diff --git a/jest.config.js b/jest.config.js index 56a4cf455..c09b6cdc2 100644 --- a/jest.config.js +++ b/jest.config.js @@ -12,7 +12,7 @@ module.exports = { "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "/test/__mocks__/fileMock.js", "\\.(css|less)$": "/test/__mocks__/NullMock.js", - "\\!!raw-loader!.*$": "/test/__mocks__/NullMock.js", + ".*?raw$": "/test/__mocks__/fileMock.js", "@player": "/src/Player", "@enums": "/src/Enums", "@nsdefs": "/src/ScriptEditor/NetscriptDefinitions", diff --git a/package-lock.json b/package-lock.json index 438ea9797..b7fe179b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -84,7 +84,6 @@ "monaco-editor": "^0.35.0", "monaco-editor-webpack-plugin": "^7.1.0", "prettier": "^2.8.8", - "raw-loader": "^4.0.2", "react-refresh": "^0.14.0", "rehype-mathjax": "^4.0.3", "remark-math": "^5.1.1", @@ -15024,26 +15023,6 @@ "node": ">= 0.8" } }, - "node_modules/raw-loader": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz", - "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==", - "dev": true, - "dependencies": { - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, "node_modules/rcedit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/rcedit/-/rcedit-3.1.0.tgz", diff --git a/package.json b/package.json index 5f55cbe29..cfeaa3d95 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,6 @@ "monaco-editor": "^0.35.0", "monaco-editor-webpack-plugin": "^7.1.0", "prettier": "^2.8.8", - "raw-loader": "^4.0.2", "react-refresh": "^0.14.0", "rehype-mathjax": "^4.0.3", "remark-math": "^5.1.1", diff --git a/src/Documentation/pages.ts b/src/Documentation/pages.ts index d6afd0846..950b0e953 100644 --- a/src/Documentation/pages.ts +++ b/src/Documentation/pages.ts @@ -1,69 +1,68 @@ // THIS FILE IS AUTOGENERATED -import file0 from "!!raw-loader!./doc/advanced/bitnodes.md"; -import file1 from "!!raw-loader!./doc/advanced/bladeburners.md"; -import file2 from "!!raw-loader!./doc/advanced/corporation/basic-gameplay-and-term.md"; -import file3 from "!!raw-loader!./doc/advanced/corporation/boost-material.md"; -import file4 from "!!raw-loader!./doc/advanced/corporation/demand-competition.md"; -import file5 from "!!raw-loader!./doc/advanced/corporation/division-raw-production.md"; -import file6 from "!!raw-loader!./doc/advanced/corporation/faq.md"; -import file7 from "!!raw-loader!./doc/advanced/corporation/financial-statement.md"; -import file8 from "!!raw-loader!./doc/advanced/corporation/general-advice.md"; -import file9 from "!!raw-loader!./doc/advanced/corporation/industry-supply-chain.md"; -import file10 from "!!raw-loader!./doc/advanced/corporation/miscellany.md"; -import file11 from "!!raw-loader!./doc/advanced/corporation/office.md"; -import file12 from "!!raw-loader!./doc/advanced/corporation/optimal-selling-price-market-ta2.md"; -import file13 from "!!raw-loader!./doc/advanced/corporation/product.md"; -import file14 from "!!raw-loader!./doc/advanced/corporation/quality.md"; -import file15 from "!!raw-loader!./doc/advanced/corporation/smart-supply.md"; -import file16 from "!!raw-loader!./doc/advanced/corporation/unlocks-upgrade-research.md"; -import file17 from "!!raw-loader!./doc/advanced/corporation/warehouse.md"; -import file18 from "!!raw-loader!./doc/advanced/corporation/wilson-analytics-advert.md"; -import file19 from "!!raw-loader!./doc/advanced/corporations.md"; -import file20 from "!!raw-loader!./doc/advanced/faction_list.md"; -import file21 from "!!raw-loader!./doc/advanced/gang.md"; -import file22 from "!!raw-loader!./doc/advanced/grafting.md"; -import file23 from "!!raw-loader!./doc/advanced/hacknetservers.md"; -import file24 from "!!raw-loader!./doc/advanced/intelligence.md"; -import file25 from "!!raw-loader!./doc/advanced/offlineandbonustime.md"; -import file26 from "!!raw-loader!./doc/advanced/sleeves.md"; -import file27 from "!!raw-loader!./doc/advanced/sourcefiles.md"; -import file28 from "!!raw-loader!./doc/advanced/stanek.md"; -import file29 from "!!raw-loader!./doc/basic/augmentations.md"; -import file30 from "!!raw-loader!./doc/basic/codingcontracts.md"; -import file31 from "!!raw-loader!./doc/basic/companies.md"; -import file32 from "!!raw-loader!./doc/basic/crimes.md"; -import file33 from "!!raw-loader!./doc/basic/factions.md"; -import file34 from "!!raw-loader!./doc/basic/hacking.md"; -import file35 from "!!raw-loader!./doc/basic/hacknet_nodes.md"; -import file36 from "!!raw-loader!./doc/basic/infiltration.md"; -import file37 from "!!raw-loader!./doc/basic/programs.md"; -import file38 from "!!raw-loader!./doc/basic/ram.md"; -import file39 from "!!raw-loader!./doc/basic/reputation.md"; -import file40 from "!!raw-loader!./doc/basic/scripts.md"; -import file41 from "!!raw-loader!./doc/basic/servers.md"; -import file42 from "!!raw-loader!./doc/basic/stats.md"; -import file43 from "!!raw-loader!./doc/basic/stockmarket.md"; -import file44 from "!!raw-loader!./doc/basic/terminal.md"; -import file45 from "!!raw-loader!./doc/basic/world.md"; -import file46 from "!!raw-loader!./doc/changelog-v0.md"; -import file47 from "!!raw-loader!./doc/changelog-v1.md"; -import file48 from "!!raw-loader!./doc/changelog.md"; -import file49 from "!!raw-loader!./doc/help/bitnode_order.md"; -import file50 from "!!raw-loader!./doc/help/getting_started.md"; -import file51 from "!!raw-loader!./doc/help/tools_and_resources.md"; -import file52 from "!!raw-loader!./doc/index.md"; -import file53 from "!!raw-loader!./doc/migrations/ns2.md"; -import file54 from "!!raw-loader!./doc/migrations/v1.md"; -import file55 from "!!raw-loader!./doc/migrations/v2.md"; -import file56 from "!!raw-loader!./doc/programming/game_frozen.md"; -import file57 from "!!raw-loader!./doc/programming/go_algorithms.md"; -import file58 from "!!raw-loader!./doc/programming/hackingalgorithms.md"; -import file59 from "!!raw-loader!./doc/programming/learn.md"; -import file60 from "!!raw-loader!./doc/programming/remote_api.md"; +import file0 from "./doc/advanced/bitnodes.md?raw"; +import file1 from "./doc/advanced/bladeburners.md?raw"; +import file2 from "./doc/advanced/corporation/basic-gameplay-and-term.md?raw"; +import file3 from "./doc/advanced/corporation/boost-material.md?raw"; +import file4 from "./doc/advanced/corporation/demand-competition.md?raw"; +import file5 from "./doc/advanced/corporation/division-raw-production.md?raw"; +import file6 from "./doc/advanced/corporation/faq.md?raw"; +import file7 from "./doc/advanced/corporation/financial-statement.md?raw"; +import file8 from "./doc/advanced/corporation/general-advice.md?raw"; +import file9 from "./doc/advanced/corporation/industry-supply-chain.md?raw"; +import file10 from "./doc/advanced/corporation/miscellany.md?raw"; +import file11 from "./doc/advanced/corporation/office.md?raw"; +import file12 from "./doc/advanced/corporation/optimal-selling-price-market-ta2.md?raw"; +import file13 from "./doc/advanced/corporation/product.md?raw"; +import file14 from "./doc/advanced/corporation/quality.md?raw"; +import file15 from "./doc/advanced/corporation/smart-supply.md?raw"; +import file16 from "./doc/advanced/corporation/unlocks-upgrade-research.md?raw"; +import file17 from "./doc/advanced/corporation/warehouse.md?raw"; +import file18 from "./doc/advanced/corporation/wilson-analytics-advert.md?raw"; +import file19 from "./doc/advanced/corporations.md?raw"; +import file20 from "./doc/advanced/faction_list.md?raw"; +import file21 from "./doc/advanced/gang.md?raw"; +import file22 from "./doc/advanced/grafting.md?raw"; +import file23 from "./doc/advanced/hacknetservers.md?raw"; +import file24 from "./doc/advanced/intelligence.md?raw"; +import file25 from "./doc/advanced/offlineandbonustime.md?raw"; +import file26 from "./doc/advanced/sleeves.md?raw"; +import file27 from "./doc/advanced/sourcefiles.md?raw"; +import file28 from "./doc/advanced/stanek.md?raw"; +import file29 from "./doc/basic/augmentations.md?raw"; +import file30 from "./doc/basic/codingcontracts.md?raw"; +import file31 from "./doc/basic/companies.md?raw"; +import file32 from "./doc/basic/crimes.md?raw"; +import file33 from "./doc/basic/factions.md?raw"; +import file34 from "./doc/basic/hacking.md?raw"; +import file35 from "./doc/basic/hacknet_nodes.md?raw"; +import file36 from "./doc/basic/infiltration.md?raw"; +import file37 from "./doc/basic/programs.md?raw"; +import file38 from "./doc/basic/ram.md?raw"; +import file39 from "./doc/basic/reputation.md?raw"; +import file40 from "./doc/basic/scripts.md?raw"; +import file41 from "./doc/basic/servers.md?raw"; +import file42 from "./doc/basic/stats.md?raw"; +import file43 from "./doc/basic/stockmarket.md?raw"; +import file44 from "./doc/basic/terminal.md?raw"; +import file45 from "./doc/basic/world.md?raw"; +import file46 from "./doc/changelog-v0.md?raw"; +import file47 from "./doc/changelog-v1.md?raw"; +import file48 from "./doc/changelog.md?raw"; +import file49 from "./doc/help/bitnode_order.md?raw"; +import file50 from "./doc/help/getting_started.md?raw"; +import file51 from "./doc/help/tools_and_resources.md?raw"; +import file52 from "./doc/index.md?raw"; +import file53 from "./doc/migrations/ns2.md?raw"; +import file54 from "./doc/migrations/v1.md?raw"; +import file55 from "./doc/migrations/v2.md?raw"; +import file56 from "./doc/programming/game_frozen.md?raw"; +import file57 from "./doc/programming/go_algorithms.md?raw"; +import file58 from "./doc/programming/hackingalgorithms.md?raw"; +import file59 from "./doc/programming/learn.md?raw"; +import file60 from "./doc/programming/remote_api.md?raw"; + +import type { Document } from "./root.ts"; -interface Document { - default: string; -} export const AllPages: Record = {}; AllPages["advanced/bitnodes.md"] = file0; AllPages["advanced/bladeburners.md"] = file1; diff --git a/src/Documentation/root.ts b/src/Documentation/root.ts index 464efffb9..125e5d3ca 100644 --- a/src/Documentation/root.ts +++ b/src/Documentation/root.ts @@ -1,10 +1,6 @@ -import index from "!!raw-loader!./doc/index.md"; +import Root from "./doc/index.md?raw"; import { AllPages } from "./pages"; -export type Document = typeof index; - -export const Root = { - content: index, -}; +export type Document = typeof Root; export const getPage = (title: string): Document => AllPages[title] ?? Root; diff --git a/src/RemoteFileAPI/MessageHandlers.ts b/src/RemoteFileAPI/MessageHandlers.ts index ba7932e56..f5d230bad 100644 --- a/src/RemoteFileAPI/MessageHandlers.ts +++ b/src/RemoteFileAPI/MessageHandlers.ts @@ -12,7 +12,7 @@ import { isFileData, } from "./MessageDefinitions"; -import libSource from "!!raw-loader!../ScriptEditor/NetscriptDefinitions.d.ts"; +import libSource from "../ScriptEditor/NetscriptDefinitions.d.ts?raw"; function error(errorMsg: string, { id }: RFAMessage): RFAMessage { return new RFAMessage({ error: errorMsg, id: id }); @@ -109,7 +109,7 @@ export const RFARequestHandler: Record void | R }, getDefinitionFile: function (msg: RFAMessage): RFAMessage { - return new RFAMessage({ result: libSource + "", id: msg.id }); + return new RFAMessage({ result: libSource, id: msg.id }); }, getAllServers: function (msg: RFAMessage): RFAMessage { diff --git a/src/ScriptEditor/ScriptEditor.ts b/src/ScriptEditor/ScriptEditor.ts index bad9617aa..1dd2d68a2 100644 --- a/src/ScriptEditor/ScriptEditor.ts +++ b/src/ScriptEditor/ScriptEditor.ts @@ -3,7 +3,12 @@ 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 netscriptDefinitions from "./NetscriptDefinitions.d.ts?raw"; +// We use a relative paths here to +// - bypass the exports in @types/react's package.json +// - to prevent typescript from complaining about importing a delcaration file. +import reactTypes from "../../node_modules/@types/react/index.d.ts?raw"; +import reactDomTypes from "../../node_modules/@types/react-dom/index.d.ts?raw"; import { Settings } from "../Settings/Settings"; import { NetscriptExtra } from "../NetscriptFunctions/Extra"; import * as enums from "../Enums"; @@ -57,9 +62,15 @@ export class ScriptEditor { })(); // 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"); + const source = netscriptDefinitions.replace(/export /g, ""); + for (const languageDefaults of [ + monaco.languages.typescript.javascriptDefaults, + monaco.languages.typescript.typescriptDefaults, + ]) { + languageDefaults.addExtraLib(source, "netscript.d.ts"); + languageDefaults.addExtraLib(reactTypes, "react.d.ts"); + languageDefaults.addExtraLib(reactDomTypes, "react-dom.d.ts"); + } monaco.languages.json.jsonDefaults.setModeConfiguration({ ...monaco.languages.json.jsonDefaults.modeConfiguration, //completion should be disabled because the diff --git a/src/ScriptEditor/raw-loader.d.ts b/src/ScriptEditor/raw-loader.d.ts index 895957790..8c42ee19b 100644 --- a/src/ScriptEditor/raw-loader.d.ts +++ b/src/ScriptEditor/raw-loader.d.ts @@ -1,4 +1,4 @@ -declare module "!!raw-loader!*" { - const contents: { default: string }; - export = contents; +declare module "*?raw" { + const contents: string; + export default contents; } diff --git a/src/ui/MD/MD.tsx b/src/ui/MD/MD.tsx index 6e755c577..d36f04d3d 100644 --- a/src/ui/MD/MD.tsx +++ b/src/ui/MD/MD.tsx @@ -46,7 +46,7 @@ export function MD(props: { pageFilePath: FilePath; top: number }): React.ReactE remarkPlugins={[remarkGfm, remarkMath]} rehypePlugins={[rehypeMathjax]} > - {String(pageContent)} + {pageContent} ); } diff --git a/test/jest/StockMarket.test.ts b/test/jest/StockMarket.test.ts index 991dd0eda..322b43156 100644 --- a/test/jest/StockMarket.test.ts +++ b/test/jest/StockMarket.test.ts @@ -33,10 +33,6 @@ import { } from "../../src/StockMarket/StockMarketHelpers"; import { CompanyName, OrderType, PositionType } from "../../src/Enums"; -jest.mock(`!!raw-loader!../NetscriptDefinitions.d.ts`, () => "", { - virtual: true, -}); - // jest.mock("../src/ui/React/createPopup.tsx", () => ({ // createPopup: jest.fn(), // })); diff --git a/tools/bundle-doc/index.js b/tools/bundle-doc/index.js index 230294f5f..8bada6f18 100644 --- a/tools/bundle-doc/index.js +++ b/tools/bundle-doc/index.js @@ -18,11 +18,10 @@ const processDir = (dir) => { processDir(docRoot); const autogenfile = `// THIS FILE IS AUTOGENERATED -${files.map((f, i) => `import file${i} from "!!raw-loader!./doc/${f}";`).join("\n")} +${files.map((f, i) => `import file${i} from "./doc/${f}?raw";`).join("\n")} + +import type { Document } from "./root.ts"; -interface Document { - default: string; -} export const AllPages: Record = {}; ${files.map((f, i) => `AllPages["${f}"] = file${i};`).join("\n")} `; diff --git a/webpack.config.js b/webpack.config.js index b7f0011d4..876bc4745 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -140,6 +140,7 @@ module.exports = (env, argv) => { { test: /\.(js$|jsx|ts|tsx)$/, exclude: /node_modules/, + resourceQuery: { not: /raw/ }, use: { loader: "babel-loader", options: { @@ -153,6 +154,10 @@ module.exports = (env, argv) => { test: /\.s?css$/, use: ["style-loader", "css-loader"], }, + { + resourceQuery: /raw/, + type: "asset/source", + }, ], }, optimization: {