Skip to content

Commit

Permalink
DOC: WIP: Convert markdown to rehype's hast at build time.
Browse files Browse the repository at this point in the history
This is a demo of parsing markdown all the way to hast JSON,
and then tricking react-markdown into using that pre-parsed
hast directt, rather than parsing markdown at runtime.
  • Loading branch information
tomprince committed Jul 17, 2024
1 parent abe7a43 commit ef9471d
Show file tree
Hide file tree
Showing 7 changed files with 446 additions and 201 deletions.
445 changes: 325 additions & 120 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"clsx": "^1.2.1",
"date-fns": "^2.30.0",
"escodegen": "^2.1.0",
"html-loader": "^5.0.0",
"js-sha256": "^0.9.0",
"jszip": "^3.10.1",
"material-ui-color": "^1.2.0",
Expand All @@ -45,9 +46,14 @@
"react-markdown": "^8.0.7",
"react-resizable": "^3.0.5",
"react-syntax-highlighter": "^15.5.0",
"rehype-stringify": "^9.0.4",
"remark": "^14.0.3",
"remark-gfm": "^3.0.1",
"remark-loader": "^6.0.0",
"remark-rehype": "^10.1.0",
"sprintf-js": "^1.1.3",
"tss-react": "^4.9.10"
"tss-react": "^4.9.10",
"unified": "^10.1.2"
},
"description": "A cyberpunk-themed incremental game",
"devDependencies": {
Expand Down
122 changes: 61 additions & 61 deletions src/Documentation/pages.ts
Original file line number Diff line number Diff line change
@@ -1,65 +1,65 @@
// THIS FILE IS AUTOGENERATED
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 file0 from "./doc/advanced/bitnodes.md";
import file1 from "./doc/advanced/bladeburners.md";
import file2 from "./doc/advanced/corporation/basic-gameplay-and-term.md";
import file3 from "./doc/advanced/corporation/boost-material.md";
import file4 from "./doc/advanced/corporation/demand-competition.md";
import file5 from "./doc/advanced/corporation/division-raw-production.md";
import file6 from "./doc/advanced/corporation/faq.md";
import file7 from "./doc/advanced/corporation/financial-statement.md";
import file8 from "./doc/advanced/corporation/general-advice.md";
import file9 from "./doc/advanced/corporation/industry-supply-chain.md";
import file10 from "./doc/advanced/corporation/miscellany.md";
import file11 from "./doc/advanced/corporation/office.md";
import file12 from "./doc/advanced/corporation/optimal-selling-price-market-ta2.md";
import file13 from "./doc/advanced/corporation/product.md";
import file14 from "./doc/advanced/corporation/quality.md";
import file15 from "./doc/advanced/corporation/smart-supply.md";
import file16 from "./doc/advanced/corporation/unlocks-upgrade-research.md";
import file17 from "./doc/advanced/corporation/warehouse.md";
import file18 from "./doc/advanced/corporation/wilson-analytics-advert.md";
import file19 from "./doc/advanced/corporations.md";
import file20 from "./doc/advanced/faction_list.md";
import file21 from "./doc/advanced/gang.md";
import file22 from "./doc/advanced/grafting.md";
import file23 from "./doc/advanced/hacknetservers.md";
import file24 from "./doc/advanced/intelligence.md";
import file25 from "./doc/advanced/offlineandbonustime.md";
import file26 from "./doc/advanced/sleeves.md";
import file27 from "./doc/advanced/sourcefiles.md";
import file28 from "./doc/advanced/stanek.md";
import file29 from "./doc/basic/augmentations.md";
import file30 from "./doc/basic/codingcontracts.md";
import file31 from "./doc/basic/companies.md";
import file32 from "./doc/basic/crimes.md";
import file33 from "./doc/basic/factions.md";
import file34 from "./doc/basic/hacking.md";
import file35 from "./doc/basic/hacknet_nodes.md";
import file36 from "./doc/basic/infiltration.md";
import file37 from "./doc/basic/programs.md";
import file38 from "./doc/basic/ram.md";
import file39 from "./doc/basic/reputation.md";
import file40 from "./doc/basic/scripts.md";
import file41 from "./doc/basic/servers.md";
import file42 from "./doc/basic/stats.md";
import file43 from "./doc/basic/stockmarket.md";
import file44 from "./doc/basic/terminal.md";
import file45 from "./doc/basic/world.md";
import file46 from "./doc/changelog-v0.md";
import file47 from "./doc/changelog-v1.md";
import file48 from "./doc/changelog.md";
import file49 from "./doc/help/bitnode_order.md";
import file50 from "./doc/help/getting_started.md";
import file51 from "./doc/help/tools_and_resources.md";
import file52 from "./doc/index.md";
import file53 from "./doc/migrations/ns2.md";
import file54 from "./doc/migrations/v1.md";
import file55 from "./doc/migrations/v2.md";
import file56 from "./doc/programming/game_frozen.md";
import file57 from "./doc/programming/go_algorithms.md";
import file58 from "./doc/programming/hackingalgorithms.md";
import file59 from "./doc/programming/learn.md";
import file60 from "./doc/programming/remote_api.md";

import type { Document } from "./root.ts";

Expand Down
5 changes: 5 additions & 0 deletions src/ScriptEditor/raw-loader.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,8 @@ declare module "*?raw" {
const contents: string;
export default contents;
}

declare module "*.md" {
const jsonHast: any;
export default jsonHast;
}
8 changes: 5 additions & 3 deletions src/ui/MD/MD.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,12 @@ export function MD(props: { pageFilePath: FilePath; top: number }): React.ReactE
blockquote: Blockquote,
a: A,
}}
remarkPlugins={[remarkGfm, remarkMath]}
rehypePlugins={[rehypeMathjax]}
// We generated JSON-ified hast during the webpack build.
// This adds a rehype plugin that ignores its input and returns
// the pre-generated hast instead.
rehypePlugins={[() => () => pageContent]}
>
{pageContent}
{""}
</ReactMarkdown>
);
}
2 changes: 1 addition & 1 deletion tools/bundle-doc/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const processDir = (dir) => {
processDir(docRoot);

const autogenfile = `// THIS FILE IS AUTOGENERATED
${files.map((f, i) => `import file${i} from "./doc/${f}?raw";`).join("\n")}
${files.map((f, i) => `import file${i} from "./doc/${f}";`).join("\n")}
import type { Document } from "./root.ts";
Expand Down
57 changes: 42 additions & 15 deletions webpack.config.js → webpack.config.mjs
Original file line number Diff line number Diff line change
@@ -1,12 +1,28 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const path = require("path");
const webpack = require("webpack");
const MonacoWebpackPlugin = require("monaco-editor-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
const ReactRefreshWebpackPlugin = require("@pmmmwh/react-refresh-webpack-plugin");
import path from "path";
import webpack from "webpack";
import MonacoWebpackPlugin from "monaco-editor-webpack-plugin";
import HtmlWebpackPlugin from "html-webpack-plugin";
import ForkTsCheckerWebpackPlugin from "fork-ts-checker-webpack-plugin";
import ReactRefreshWebpackPlugin from "@pmmmwh/react-refresh-webpack-plugin";
import { execSync } from "child_process";
import { exit } from "process";

module.exports = (env, argv) => {
/** @type {import("unified").Pluggable[]} */
const remarkPlugins = [
(await import("remark-gfm")).default,
(await import("remark-math")).default,
[(await import("remark-rehype")).default, { allowDangerousHtml: true }],
(await import("rehype-mathjax")).default,
/** Turn the generated hast into JSON for converting to react at runtime. */
function rehypeToJson() {
this.Compiler = function compiler(tree) {
return JSON.stringify(tree);
};
},
];

/** @type {(env: any, argv: any) => import("webpack").Configuration} */
export default (env, argv) => {
const isDevServer = (env || {}).devServer === true;
const runInContainer = (env || {}).runInContainer === true;
const isDevelopment = argv.mode === "development";
Expand All @@ -33,7 +49,7 @@ module.exports = (env, argv) => {
stats: statsConfig,
},
static: {
directory: path.join(__dirname, "dist"),
directory: path.join(import.meta.dirname, "dist"),
publicPath: "/dist",
},
};
Expand All @@ -50,7 +66,7 @@ module.exports = (env, argv) => {

// Get the current commit hash to inject into the app
// https://stackoverflow.com/a/38401256
const commitHash = require("child_process").execSync("git rev-parse --short HEAD").toString().trim();
const commitHash = execSync("git rev-parse --short HEAD").toString().trim();

const htmlConfig = {
title: "Bitburner",
Expand Down Expand Up @@ -131,7 +147,7 @@ module.exports = (env, argv) => {
target: "web",
entry: entry,
output: {
path: path.resolve(__dirname, outputDirectory),
path: path.resolve(import.meta.dirname, outputDirectory),
filename: "[name].bundle.js",
assetModuleFilename: "assets/[hash][ext][query]",
},
Expand All @@ -144,7 +160,7 @@ module.exports = (env, argv) => {
use: {
loader: "babel-loader",
options: {
plugins: [enableReactRefresh && require.resolve("react-refresh/babel")].filter(Boolean),
// plugins: [enableReactRefresh && "react-refresh/babel"],
cacheDirectory: true,
},
},
Expand All @@ -158,6 +174,17 @@ module.exports = (env, argv) => {
resourceQuery: /raw/,
type: "asset/source",
},
{
test: /\.md$/,
type: "json",

loader: "remark-loader",
options: {
remarkOptions: {
plugins: remarkPlugins,
},
},
},
],
},
optimization: {
Expand Down Expand Up @@ -185,9 +212,9 @@ module.exports = (env, argv) => {
resolve: {
extensions: [".tsx", ".ts", ".js", ".jsx"],
alias: {
"@player": path.resolve(__dirname, "src/Player"),
"@enums": path.resolve(__dirname, "src/Enums"),
"@nsdefs": path.resolve(__dirname, "src/ScriptEditor/NetscriptDefinitions.d.ts"),
"@player": path.resolve(import.meta.dirname, "src/Player"),
"@enums": path.resolve(import.meta.dirname, "src/Enums"),
"@nsdefs": path.resolve(import.meta.dirname, "src/ScriptEditor/NetscriptDefinitions.d.ts"),
},
fallback: { crypto: false },
},
Expand Down

0 comments on commit ef9471d

Please sign in to comment.