mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-04-17 06:48:42 +02:00
CODEBASE: Generate display data for math notation at built time and remove runtime mathjax dependency (#2447)
This commit is contained in:
@@ -28,6 +28,7 @@ export const CONSTANTS = {
|
||||
|
||||
// Faction and Company favor-related things
|
||||
BaseFavorToDonate: 150,
|
||||
// If we change this constant, we must update the "RepDonation" value in src/Documentation/data/MathNotation.json
|
||||
DonateMoneyToRepDivisor: 1e6,
|
||||
|
||||
// NeuroFlux Governor Augmentation cost multiplier
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// React Component for displaying an Division's overview information
|
||||
// (top-left panel in the Division UI)
|
||||
import React, { useState } from "react";
|
||||
import { MathJax } from "better-react-mathjax";
|
||||
|
||||
import { IndustryType } from "@enums";
|
||||
import { hireAdVert } from "../Actions";
|
||||
@@ -23,6 +22,8 @@ import Paper from "@mui/material/Paper";
|
||||
import IconButton from "@mui/material/IconButton";
|
||||
import HelpIcon from "@mui/icons-material/Help";
|
||||
import Box from "@mui/material/Box";
|
||||
import MathNotation from "../../Documentation/data/MathNotation.json";
|
||||
import { MathNotationOutput } from "../../Documentation/ui/MathNotationOutput";
|
||||
|
||||
function MakeProductButton(): React.ReactElement {
|
||||
const corp = useCorporation();
|
||||
@@ -132,8 +133,11 @@ export function DivisionOverview(props: DivisionOverviewProps): React.ReactEleme
|
||||
<>
|
||||
<Typography>Multiplier for this industry's sales due to its awareness and popularity.</Typography>
|
||||
<br />
|
||||
<MathJax>{`\\(\\text{${division.industry} Industry: }\\alpha = ${division.advertisingFactor}\\)`}</MathJax>
|
||||
<MathJax>{`\\(\\text{multiplier} = \\left((\\text{awareness}+1)^{\\alpha} \\times (\\text{popularity}+1)^{\\alpha} \\times \\frac{\\text{popularity}+0.001}{\\text{awareness}}\\right)^{0.85}\\)`}</MathJax>
|
||||
<Typography>
|
||||
{division.industry} Industry: 𝞪 = {division.advertisingFactor}
|
||||
</Typography>
|
||||
<br />
|
||||
<MathNotationOutput notation={MathNotation.CorpAdvertFactor} />
|
||||
<br />
|
||||
<StatsTable
|
||||
rows={[
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import { Division } from "../Division";
|
||||
import { MathJax } from "better-react-mathjax";
|
||||
import { getRecordEntries } from "../../Types/Record";
|
||||
import Typography from "@mui/material/Typography";
|
||||
|
||||
interface IProps {
|
||||
division: Division;
|
||||
@@ -10,13 +10,19 @@ interface IProps {
|
||||
export function IndustryProductEquation(props: IProps): React.ReactElement {
|
||||
const reqs = [];
|
||||
for (const [reqMat, reqAmt] of getRecordEntries(props.division.requiredMaterials)) {
|
||||
if (!reqAmt) continue;
|
||||
reqs.push(String.raw`${reqAmt}\;\textit{${reqMat}}`);
|
||||
if (!reqAmt) {
|
||||
continue;
|
||||
}
|
||||
reqs.push(`${reqAmt} ${reqMat}`);
|
||||
}
|
||||
const prod = props.division.producedMaterials.map((p) => `1\\;\\textit{${p}}`);
|
||||
const prod = props.division.producedMaterials.map((materialName) => `1 ${materialName}`);
|
||||
if (props.division.makesProducts) {
|
||||
prod.push("\\textit{Products}");
|
||||
prod.push("Products");
|
||||
}
|
||||
|
||||
return <MathJax>{"\\(" + reqs.join("+") + `\\Rightarrow ` + prod.join("+") + "\\)"}</MathJax>;
|
||||
return (
|
||||
<Typography component="span">
|
||||
{reqs.join(" + ")} ⟹ {prod.join(" + ")}
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// React Component for displaying Corporation Overview info
|
||||
import React, { useState } from "react";
|
||||
import { MathJax } from "better-react-mathjax";
|
||||
import { LevelableUpgrade } from "./LevelableUpgrade";
|
||||
import { Unlock } from "./Unlock";
|
||||
import { BribeFactionModal } from "./modals/BribeFactionModal";
|
||||
@@ -36,6 +35,8 @@ import { ButtonWithTooltip } from "../../ui/Components/ButtonWithTooltip";
|
||||
import { CreateCorporationModal } from "./modals/CreateCorporationModal";
|
||||
import InfoIcon from "@mui/icons-material/Info";
|
||||
import { CorruptibleText } from "../../ui/React/CorruptibleText";
|
||||
import MathNotation from "../../Documentation/data/MathNotation.json";
|
||||
import { MathNotationOutput } from "../../Documentation/ui/MathNotationOutput";
|
||||
|
||||
interface IProps {
|
||||
rerender: () => void;
|
||||
@@ -390,9 +391,9 @@ function DividendsStats({ profit }: IDividendsStatsProps): React.ReactElement {
|
||||
"TributeModifier". Formulas:
|
||||
<br />
|
||||
<br />
|
||||
<MathJax>{`\\(TotalDividends = DividendRate\\ast(Revenue - Expenses)\\ast 10\\)`}</MathJax>
|
||||
<MathNotationOutput notation={MathNotation.CorpTotalDividends} />
|
||||
<br />
|
||||
<MathJax>{`\\(Dividend = \\left(OwnedShares\\ast\\frac{TotalDividends}{TotalShares}\\right)^{1 - TributeModifier}\\)`}</MathJax>
|
||||
<MathNotationOutput notation={MathNotation.CorpDividend} />
|
||||
</>
|
||||
}
|
||||
>
|
||||
|
||||
10
src/Documentation/data/MathNotation.json
Normal file
10
src/Documentation/data/MathNotation.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"RepDonation": "reputation = \\frac{\\text{donation amount} \\cdot \\text{reputation multiplier}}{10^{6}}",
|
||||
"CoreCost": "\\large{cost = 10^9 \\cdot 7.5 ^{\\text{cores}}}",
|
||||
"HomeRAMCost": "\\large{cost = ram \\cdot 3.2 \\cdot 10^4 \\cdot 1.58^{log_2{(ram)}}} \\cdot HomeRamCostMult",
|
||||
"FavorBonus": "\\huge{\\Delta r = \\Delta r \\times \\frac{100+favor}{100}}",
|
||||
"RepToFavor": "\\huge{favor=\\log_{1.02}\\left(1+\\frac{r}{25000}\\right)}",
|
||||
"CorpTotalDividends": "TotalDividends = DividendRate\\ast(Revenue - Expenses)\\ast 10",
|
||||
"CorpDividend": "Dividend = \\left(OwnedShares\\ast\\frac{TotalDividends}{TotalShares}\\right)^{1 - TributeModifier}",
|
||||
"CorpAdvertFactor": "\\text{multiplier} = \\left((\\text{awareness}+1)^{\\alpha} \\times (\\text{popularity}+1)^{\\alpha} \\times \\frac{\\text{popularity}+0.001}{\\text{awareness}}\\right)^{0.85}"
|
||||
}
|
||||
1
src/Documentation/data/MathNotationOutput.json
Normal file
1
src/Documentation/data/MathNotationOutput.json
Normal file
File diff suppressed because one or more lines are too long
@@ -1,5 +1,6 @@
|
||||
import { AllPages } from "./pages";
|
||||
import { EventEmitter } from "../utils/EventEmitter";
|
||||
import MathNotationOutput from "./data/MathNotationOutput.json";
|
||||
|
||||
export const resolvePage = (title: string): { pageName: string | null; pageContent: string } => {
|
||||
const lang = new Intl.Locale(navigator.language).language;
|
||||
@@ -35,3 +36,13 @@ export const DocumentationPopUpEvents = new EventEmitter<[string | undefined]>()
|
||||
export function openDocumentationPopUp(path: string): void {
|
||||
DocumentationPopUpEvents.emit(path);
|
||||
}
|
||||
|
||||
export function convertMathNotation(value: string): string {
|
||||
// MathNotationOutput is imported as json data, so we need to typecast here to access the value via string index
|
||||
// easier without fighting with the TS compiler.
|
||||
const output = (MathNotationOutput as Record<string, string>)[value];
|
||||
if (output == null) {
|
||||
throw new Error(`Unknown math notation: ${value}`);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
9
src/Documentation/ui/MathNotationOutput.tsx
Normal file
9
src/Documentation/ui/MathNotationOutput.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import React from "react";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import { convertMathNotation } from "../root";
|
||||
|
||||
export function MathNotationOutput({ notation }: { notation: string }): JSX.Element {
|
||||
// It's fine to use dangerouslySetInnerHTML here. We control the data in both MathNotation.json and
|
||||
// MathNotationOutput.json. They are not user-provided data.
|
||||
return <Typography dangerouslySetInnerHTML={{ __html: convertMathNotation(notation) }} />;
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { Faction } from "../Faction";
|
||||
import { Player } from "@player";
|
||||
import { canDonate, donate, repFromDonation } from "../formulas/donation";
|
||||
@@ -10,12 +9,13 @@ import { Money } from "../../ui/React/Money";
|
||||
import { Reputation } from "../../ui/React/Reputation";
|
||||
|
||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
||||
import { MathJax } from "better-react-mathjax";
|
||||
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Paper from "@mui/material/Paper";
|
||||
import Button from "@mui/material/Button";
|
||||
import { NumberInput } from "../../ui/React/NumberInput";
|
||||
import MathNotation from "../../Documentation/data/MathNotation.json";
|
||||
import { MathNotationOutput } from "../../Documentation/ui/MathNotationOutput";
|
||||
|
||||
type DonateOptionProps = {
|
||||
faction: Faction;
|
||||
@@ -27,7 +27,6 @@ type DonateOptionProps = {
|
||||
/** React component for a donate option on the Faction UI */
|
||||
export function DonateOption({ faction, favorToDonate, disabled, rerender }: DonateOptionProps): React.ReactElement {
|
||||
const [donateAmt, setDonateAmt] = useState<number>(NaN);
|
||||
const digits = (CONSTANTS.DonateMoneyToRepDivisor + "").length - 1;
|
||||
|
||||
function onDonate(): void {
|
||||
const repGain = donate(donateAmt, faction);
|
||||
@@ -76,9 +75,7 @@ export function DonateOption({ faction, favorToDonate, disabled, rerender }: Don
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<Typography>
|
||||
<MathJax>{`\\(reputation = \\frac{\\text{donation amount} \\cdot \\text{reputation multiplier}}{10^{${digits}}}\\)`}</MathJax>
|
||||
</Typography>
|
||||
<MathNotationOutput notation={MathNotation.RepDonation} />
|
||||
</>
|
||||
)}
|
||||
</Paper>
|
||||
|
||||
@@ -6,7 +6,8 @@ import Typography from "@mui/material/Typography";
|
||||
import { Player } from "@player";
|
||||
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { MathJax } from "better-react-mathjax";
|
||||
import MathNotation from "../../Documentation/data/MathNotation.json";
|
||||
import { MathNotationOutput } from "../../Documentation/ui/MathNotationOutput";
|
||||
|
||||
interface IProps {
|
||||
rerender: () => void;
|
||||
@@ -32,7 +33,7 @@ export function CoresButton(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
return (
|
||||
<Tooltip title={<MathJax>{`\\(\\large{cost = 10^9 \\cdot 7.5 ^{\\text{cores}}}\\)`}</MathJax>}>
|
||||
<Tooltip title={<MathNotationOutput notation={MathNotation.CoreCost} />}>
|
||||
<span>
|
||||
<br />
|
||||
<Typography>
|
||||
|
||||
@@ -9,9 +9,10 @@ import { purchaseRamForHomeComputer } from "../../Server/ServerPurchases";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { formatRam } from "../../ui/formatNumber";
|
||||
|
||||
import { MathJax } from "better-react-mathjax";
|
||||
import { currentNodeMults } from "../../BitNode/BitNodeMultipliers";
|
||||
import { ServerConstants } from "../../Server/data/Constants";
|
||||
import MathNotation from "../../Documentation/data/MathNotation.json";
|
||||
import { MathNotationOutput } from "../../Documentation/ui/MathNotationOutput";
|
||||
|
||||
interface IProps {
|
||||
rerender: () => void;
|
||||
@@ -30,12 +31,13 @@ export function RamButton(props: IProps): React.ReactElement {
|
||||
props.rerender();
|
||||
}
|
||||
|
||||
const bnMult = currentNodeMults.HomeComputerRamCost === 1 ? "" : `\\cdot ${currentNodeMults.HomeComputerRamCost}`;
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
title={
|
||||
<MathJax>{`\\(\\large{cost = ram \\cdot 3.2 \\cdot 10^4 \\cdot 1.58^{log_2{(ram)}}} ${bnMult}\\)`}</MathJax>
|
||||
<>
|
||||
<Typography>HomeRamCostMult = {currentNodeMults.HomeComputerRamCost}</Typography>
|
||||
<MathNotationOutput notation={MathNotation.HomeRAMCost} />
|
||||
</>
|
||||
}
|
||||
>
|
||||
<span>
|
||||
|
||||
6
src/ThirdParty/RehypePlugin.d.mts
vendored
Normal file
6
src/ThirdParty/RehypePlugin.d.mts
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
// Minimal type information
|
||||
export declare function createPlugin(
|
||||
createRenderer: () => {
|
||||
render: (value: string, { display }: { display: boolean }) => any[];
|
||||
},
|
||||
): () => (tree: any, file: any) => void;
|
||||
343
src/ThirdParty/RehypePlugin.mjs
vendored
Normal file
343
src/ThirdParty/RehypePlugin.mjs
vendored
Normal file
@@ -0,0 +1,343 @@
|
||||
/**
|
||||
* We need to use a custom rehype plugin similar to rehype-mathjax. Specifically, we need to implement a function
|
||||
* similar to "createPlugin" in that library. That library depends on mathjax, which is what we want to get rid of at
|
||||
* runtime, so we copy only "create-plugin.js" from that library.
|
||||
*
|
||||
* The source code is retrieved from https://raw.githubusercontent.com/remarkjs/remark-math/76c14978ff6805011b8c56727c54104a511b9055/packages/rehype-mathjax/lib/create-plugin.js
|
||||
* The license is retrieved from https://raw.githubusercontent.com/remarkjs/remark-math/76c14978ff6805011b8c56727c54104a511b9055/license
|
||||
*/
|
||||
|
||||
/**
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) Junyoung Choi <fluke8259@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @import {ElementContent, Element, Root} from 'hast'
|
||||
* @import {VFile} from 'vfile'
|
||||
*/
|
||||
|
||||
/**
|
||||
* @callback CreateRenderer
|
||||
* Create a renderer.
|
||||
* @param {Readonly<Options>} options
|
||||
* Configuration.
|
||||
* @returns {Renderer}
|
||||
* Rendeder.
|
||||
*
|
||||
* @callback FormatError
|
||||
* Format an error.
|
||||
* @param {any} jax
|
||||
* MathJax object.
|
||||
* @param {any} error
|
||||
* Error.
|
||||
* @returns {string}
|
||||
* Formatted error.
|
||||
*
|
||||
* @typedef InputTexOptions
|
||||
* Configuration for input tex math.
|
||||
* <http://docs.mathjax.org/en/latest/options/input/tex.html#the-configuration-block>
|
||||
* @property {string | null | undefined} [baseURL]
|
||||
* URL for use with links to tags, when there is a `<base>` tag in effect
|
||||
* (optional).
|
||||
* @property {RegExp | null | undefined} [digits]
|
||||
* Pattern for recognizing numbers (optional).
|
||||
* @property {ReadonlyArray<MathNotation> | null | undefined} [displayMath]
|
||||
* Start/end delimiter pairs for display math (optional).
|
||||
* @property {FormatError | null | undefined} [formatError]
|
||||
* Function called when TeX syntax errors occur (optional).
|
||||
* @property {ReadonlyArray<MathNotation> | null | undefined} [inlineMath]
|
||||
* Start/end delimiter pairs for in-line math (optional).
|
||||
* @property {number | null | undefined} [maxBuffer]
|
||||
* Max size for the internal TeX string (5K) (optional).
|
||||
* @property {number | null | undefined} [maxMacros]
|
||||
* Max number of macro substitutions per expression (optional).
|
||||
* @property {ReadonlyArray<string> | null | undefined} [packages]
|
||||
* Extensions to use (optional).
|
||||
* @property {boolean | null | undefined} [processEnvironments]
|
||||
* Process `\begin{xxx}...\end{xxx}` outside math mode (optional).
|
||||
* @property {boolean | null | undefined} [processEscapes]
|
||||
* Use `\$` to produce a literal dollar sign (optional).
|
||||
* @property {boolean | null | undefined} [processRefs]
|
||||
* Process `\ref{...}` outside of math mode (optional).
|
||||
* @property {string | null | undefined} [tagIndent]
|
||||
* Amount to indent tags (optional).
|
||||
* @property {'left' | 'right' | null | undefined} [tagSide]
|
||||
* Side for `\tag` macros (optional).
|
||||
* @property {'all' | 'ams' | 'none' | null | undefined} [tags]
|
||||
* Optional.
|
||||
* @property {boolean | null | undefined} [useLabelIds]
|
||||
* Use label name rather than tag for ids (optional).
|
||||
*
|
||||
* @typedef {[open: string, close: string]} MathNotation
|
||||
* Markers to use for math.
|
||||
* See: <http://docs.mathjax.org/en/latest/options/input/tex.html#the-configuration-block>
|
||||
*
|
||||
* @typedef Options
|
||||
* Configuration.
|
||||
*
|
||||
* ###### Notes
|
||||
*
|
||||
* When using `rehype-mathjax/browser`, only `options.tex.displayMath` and
|
||||
* `options.tex.inlineMath` are used.
|
||||
* That plugin will use the first delimiter pair in those fields to wrap
|
||||
* math.
|
||||
* Then you need to load MathJax yourself on the client and start it with the
|
||||
* same markers.
|
||||
* You can pass other options on the client.
|
||||
*
|
||||
* When using `rehype-mathjax/chtml`, `options.chtml.fontURL` is required.
|
||||
* For example:
|
||||
*
|
||||
* ```js
|
||||
* // …
|
||||
* .use(rehypeMathjaxChtml, {
|
||||
* chtml: {
|
||||
* fontURL: 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/output/chtml/fonts/woff-v2'
|
||||
* }
|
||||
* })
|
||||
* // …
|
||||
* ```
|
||||
* @property {Readonly<OutputChtmlOptions> | null | undefined} [chtml]
|
||||
* Configuration for the output, when CHTML (optional).
|
||||
* @property {Readonly<OutputSvgOptions> | null | undefined} [svg]
|
||||
* Configuration for the output, when SVG (optional).
|
||||
* @property {Readonly<InputTexOptions> | null | undefined} [tex]
|
||||
* Configuration for the input TeX (optional).
|
||||
*
|
||||
* @typedef OutputChtmlOptions
|
||||
* Configuration for output CHTML.
|
||||
* <http://docs.mathjax.org/en/latest/options/output/chtml.html#the-configuration-block>
|
||||
* @property {boolean | null | undefined} [adaptiveCSS]
|
||||
* `true` means only produce CSS that is used in the processed equations (optional).
|
||||
* @property {'center' | 'left' | 'right' | null | undefined} [displayAlign]
|
||||
* Default for indentalign when set to `'auto'` (optional).
|
||||
* @property {string | null | undefined} [displayIndent]
|
||||
* Default for indentshift when set to `'auto'` (optional).
|
||||
* @property {number | null | undefined} [exFactor]
|
||||
* Default size of ex in em units (optional).
|
||||
* @property {string} fontURL
|
||||
* The URL where the fonts are found (**required**).
|
||||
* @property {boolean | null | undefined} [matchFontHeight]
|
||||
* `true` to match ex-height of surrounding font (optional).
|
||||
* @property {boolean | null | undefined} [mathmlSpacing]
|
||||
* `true` for MathML spacing rules, false for TeX rules (optional).
|
||||
* @property {boolean | null | undefined} [merrorInheritFont]
|
||||
* `true` to make merror text use surrounding font (optional).
|
||||
* @property {number | null | undefined} [minScale]
|
||||
* Smallest scaling factor to use (optional).
|
||||
* @property {boolean | null | undefined} [mtextInheritFont]
|
||||
* `true` to make mtext elements use surrounding font (optional).
|
||||
* @property {number | null | undefined} [scale]
|
||||
* Global scaling factor for all expressions (optional).
|
||||
* @property {Readonly<Record<string, boolean>> | null | undefined} [skipAttributes]
|
||||
* RFDa and other attributes NOT to copy to the output (optional).
|
||||
*
|
||||
* @typedef OutputSvgOptions
|
||||
* Configuration for output SVG.
|
||||
* <http://docs.mathjax.org/en/latest/options/output/svg.html#the-configuration-block>
|
||||
* @property {'center' | 'left' | 'right' | null | undefined} [displayAlign]
|
||||
* Default for indentalign when set to `'auto'` (optional).
|
||||
* @property {string | null | undefined} [displayIndent]
|
||||
* Default for indentshift when set to `'auto'` (optional).
|
||||
* @property {number | null | undefined} [exFactor]
|
||||
* Default size of ex in em units (optional).
|
||||
* @property {'global' | 'local' | 'none' | null | undefined} [fontCache]
|
||||
* Or `'global'` or `'none'` (optional).
|
||||
* @property {boolean | null | undefined} [internalSpeechTitles]
|
||||
* Insert `<title>` tags with speech content (optional).
|
||||
* @property {string | null | undefined} [localID]
|
||||
* ID to use for local font cache, for single equation processing (optional).
|
||||
* @property {boolean | null | undefined} [mathmlSpacing]
|
||||
* `true` for MathML spacing rules, `false` for TeX rules (optional).
|
||||
* @property {boolean | null | undefined} [merrorInheritFont]
|
||||
* `true` to make merror text use surrounding font (optional).
|
||||
* @property {number | null | undefined} [minScale]
|
||||
* Smallest scaling factor to use (optional).
|
||||
* @property {boolean | null | undefined} [mtextInheritFont]
|
||||
* `true` to make mtext elements use surrounding font (optional).
|
||||
* @property {number | null | undefined} [scale]
|
||||
* Global scaling factor for all expressions (optional).
|
||||
* @property {Readonly<Record<string, boolean>> | null | undefined} [skipAttributes]
|
||||
* RFDa and other attributes *not* to copy to the output (optional).
|
||||
* @property {number | null | undefined} [titleID]
|
||||
* Initial ID number to use for `aria-labeledby` titles (optional).
|
||||
*
|
||||
* @callback Render
|
||||
* Render a math node.
|
||||
* @param {string} value
|
||||
* Math value.
|
||||
* @param {Readonly<RenderOptions>} options
|
||||
* Configuration.
|
||||
* @returns {Array<ElementContent>}
|
||||
* Content.
|
||||
*
|
||||
* @typedef RenderOptions
|
||||
* Configuration.
|
||||
* @property {boolean} display
|
||||
* Whether to render display math.
|
||||
*
|
||||
* @typedef Renderer
|
||||
* Renderer.
|
||||
* @property {(() => undefined) | undefined} [register]
|
||||
* Called before transform.
|
||||
* @property {(() => undefined) | undefined} [unregister]
|
||||
* Called after transform.
|
||||
* @property {Render} render
|
||||
* Render a math node.
|
||||
* @property {StyleSheet | undefined} [styleSheet]
|
||||
* Render a style sheet (optional).
|
||||
*
|
||||
* @callback StyleSheet
|
||||
* Render a style sheet.
|
||||
* @returns {Element}
|
||||
* Style sheet.
|
||||
*/
|
||||
|
||||
import { toText } from "hast-util-to-text";
|
||||
import { SKIP, visitParents } from "unist-util-visit-parents";
|
||||
|
||||
/** @type {Readonly<Options>} */
|
||||
const emptyOptions = {};
|
||||
/** @type {ReadonlyArray<unknown>} */
|
||||
const emptyClasses = [];
|
||||
|
||||
/**
|
||||
* Create a plugin.
|
||||
*
|
||||
* @param {CreateRenderer} createRenderer
|
||||
* Create a renderer.
|
||||
* @returns
|
||||
* Plugin.
|
||||
*/
|
||||
export function createPlugin(createRenderer) {
|
||||
/**
|
||||
* Plugin.
|
||||
*
|
||||
* @param {Readonly<Options> | null | undefined} [options]
|
||||
* Configuration (optional).
|
||||
* @returns
|
||||
* Transform.
|
||||
*/
|
||||
return function (options) {
|
||||
/**
|
||||
* Transform.
|
||||
*
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @param {VFile} file
|
||||
* File.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
return function (tree, file) {
|
||||
const renderer = createRenderer(options || emptyOptions);
|
||||
let found = false;
|
||||
/** @type {Element | Root} */
|
||||
let context = tree;
|
||||
|
||||
visitParents(tree, "element", function (element, parents) {
|
||||
const classes = Array.isArray(element.properties.className) ? element.properties.className : emptyClasses;
|
||||
// This class can be generated from markdown with ` ```math `.
|
||||
const languageMath = classes.includes("language-math");
|
||||
// This class is used by `remark-math` for flow math (block, `$$\nmath\n$$`).
|
||||
const mathDisplay = classes.includes("math-display");
|
||||
// This class is used by `remark-math` for text math (inline, `$math$`).
|
||||
const mathInline = classes.includes("math-inline");
|
||||
let display = mathDisplay;
|
||||
|
||||
// Find `<head>`.
|
||||
if (element.tagName === "head") {
|
||||
context = element;
|
||||
}
|
||||
|
||||
// Any class is fine.
|
||||
if (!languageMath && !mathDisplay && !mathInline) {
|
||||
return;
|
||||
}
|
||||
|
||||
let parent = parents[parents.length - 1];
|
||||
let scope = element;
|
||||
|
||||
// If this was generated with ` ```math `, replace the `<pre>` and use
|
||||
// display.
|
||||
if (
|
||||
element.tagName === "code" &&
|
||||
languageMath &&
|
||||
parent &&
|
||||
parent.type === "element" &&
|
||||
parent.tagName === "pre"
|
||||
) {
|
||||
scope = parent;
|
||||
parent = parents[parents.length - 2];
|
||||
display = true;
|
||||
}
|
||||
|
||||
/* c8 ignore next -- verbose to test. */
|
||||
if (!parent) return;
|
||||
|
||||
if (!found && renderer.register) renderer.register();
|
||||
found = true;
|
||||
|
||||
const text = toText(scope, { whitespace: "pre" });
|
||||
/** @type {Array<ElementContent> | undefined} */
|
||||
let result;
|
||||
|
||||
try {
|
||||
result = renderer.render(text, { display });
|
||||
} catch (error) {
|
||||
const cause = /** @type {Error} */ (error);
|
||||
|
||||
file.message("Could not render math with mathjax", {
|
||||
ancestors: [...parents, element],
|
||||
cause,
|
||||
place: element.position,
|
||||
ruleId: "mathjax-error",
|
||||
source: "rehype-mathjax",
|
||||
});
|
||||
|
||||
result = [
|
||||
{
|
||||
type: "element",
|
||||
tagName: "span",
|
||||
properties: {
|
||||
className: ["mathjax-error"],
|
||||
style: "color:#cc0000",
|
||||
title: String(cause),
|
||||
},
|
||||
children: [{ type: "text", value: text }],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
const index = parent.children.indexOf(scope);
|
||||
parent.children.splice(index, 1, ...result);
|
||||
return SKIP;
|
||||
});
|
||||
|
||||
if (found) {
|
||||
if (renderer.styleSheet) context.children.push(renderer.styleSheet());
|
||||
if (renderer.unregister) renderer.unregister();
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -69,7 +69,6 @@ import { BypassWrapper } from "./React/BypassWrapper";
|
||||
|
||||
import { Apr1 } from "./Apr1";
|
||||
import { V2Modal } from "../utils/V2Modal";
|
||||
import { MathJaxContext } from "better-react-mathjax";
|
||||
import { useRerender } from "./React/hooks";
|
||||
import { HistoryProvider } from "./React/Documentation";
|
||||
import { GoRoot } from "../Go/ui/GoRoot";
|
||||
@@ -505,7 +504,7 @@ export function GameRoot(): React.ReactElement {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<MathJaxContext version={3} src={__webpack_public_path__ + "mathjax/tex-chtml.js"}>
|
||||
<>
|
||||
<ErrorBoundary key={errorBoundaryKey} softReset={softReset}>
|
||||
<BypassWrapper content={bypassGame ? mainPage : null}>
|
||||
<HistoryProvider>
|
||||
@@ -547,6 +546,6 @@ export function GameRoot(): React.ReactElement {
|
||||
</BypassWrapper>
|
||||
</ErrorBoundary>
|
||||
<V2Modal />
|
||||
</MathJaxContext>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,11 +6,31 @@ import { h1, h2, h3, h4, h5, h6, li, Td, Th, table, tr, Blockquote, p } from "./
|
||||
import { code, Pre } from "./code";
|
||||
import { A } from "./a";
|
||||
import remarkMath from "remark-math";
|
||||
import rehypeMathjax from "rehype-mathjax/svg";
|
||||
import rehypeRaw from "rehype-raw";
|
||||
import { FilePath } from "../../Paths/FilePath";
|
||||
import { getPage } from "../../Documentation/root";
|
||||
import { convertMathNotation, getPage } from "../../Documentation/root";
|
||||
import { DocImages } from "../../Documentation/pages";
|
||||
import { createPlugin } from "../../ThirdParty/RehypePlugin.mjs";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
import { fromDom } from "hast-util-from-dom";
|
||||
|
||||
const rehypePlugin = createPlugin(function () {
|
||||
return {
|
||||
render(value: string, { display }: { display: boolean }) {
|
||||
const mml = convertMathNotation(value);
|
||||
const element = document.createElement(display ? "div" : "span");
|
||||
if (display) {
|
||||
element.style.textAlign = "center";
|
||||
}
|
||||
element.style.fontFamily = Settings.styles.fontFamily;
|
||||
// Check the comment in src/Themes/ui/StyleEditorModal.tsx to see why we need to convert the font size.
|
||||
element.style.fontSize = `${Settings.styles.fontSize * (16 / 14)}px`;
|
||||
element.style.color = Settings.theme.primary;
|
||||
element.innerHTML = mml;
|
||||
return [fromDom(element)];
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export function MD({ pageFilePath }: { pageFilePath: FilePath }): React.ReactElement {
|
||||
const pageContent = getPage(pageFilePath);
|
||||
@@ -38,8 +58,9 @@ export function MD({ pageFilePath }: { pageFilePath: FilePath }): React.ReactEle
|
||||
a: A,
|
||||
}}
|
||||
remarkPlugins={[remarkGfm, remarkMath]}
|
||||
// Use rehypeRaw to support HTML content in NS API docs.
|
||||
rehypePlugins={[rehypeMathjax, rehypeRaw]}
|
||||
// Use a custom rehype plugin to render LaTeX notation in md files. Use rehypeRaw to support HTML content in NS
|
||||
// API docs.
|
||||
rehypePlugins={[rehypePlugin, rehypeRaw]}
|
||||
transformImageUri={(__src, alt) => {
|
||||
return DocImages[alt];
|
||||
}}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import React from "react";
|
||||
import { MathJax } from "better-react-mathjax";
|
||||
|
||||
import InfoIcon from "@mui/icons-material/Info";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import Typography from "@mui/material/Typography";
|
||||
|
||||
import { Favor } from "../../ui/React/Favor";
|
||||
import MathNotation from "../../Documentation/data/MathNotation.json";
|
||||
import { MathNotationOutput } from "../../Documentation/ui/MathNotationOutput";
|
||||
|
||||
export function FavorInfo({ favor, boldLabel }: { favor: number; boldLabel?: boolean }): React.ReactElement {
|
||||
return (
|
||||
@@ -17,8 +17,8 @@ export function FavorInfo({ favor, boldLabel }: { favor: number; boldLabel?: boo
|
||||
favor is gained whenever you install an Augmentation. The amount of favor you gain depends on the total
|
||||
amount of reputation you earned with this faction across all resets.
|
||||
</Typography>
|
||||
<MathJax>{"\\(\\huge{r = reputation}\\)"}</MathJax>
|
||||
<MathJax>{"\\(\\huge{\\Delta r = \\Delta r \\times \\frac{100+favor}{100}}\\)"}</MathJax>
|
||||
<Typography style={{ fontSize: "2rem" }}>r = Reputation gain</Typography>
|
||||
<MathNotationOutput notation={MathNotation.FavorBonus} />
|
||||
</>
|
||||
}
|
||||
>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import React from "react";
|
||||
import { MathJax } from "better-react-mathjax";
|
||||
|
||||
import InfoIcon from "@mui/icons-material/Info";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
@@ -8,6 +7,8 @@ import Typography from "@mui/material/Typography";
|
||||
import { addRepToFavor } from "../../Faction/formulas/favor";
|
||||
import { Favor } from "../../ui/React/Favor";
|
||||
import { Reputation } from "./Reputation";
|
||||
import MathNotation from "../../Documentation/data/MathNotation.json";
|
||||
import { MathNotationOutput } from "../../Documentation/ui/MathNotationOutput";
|
||||
|
||||
export function ReputationInfo({
|
||||
favor,
|
||||
@@ -26,8 +27,8 @@ export function ReputationInfo({
|
||||
You will have <Favor favor={addRepToFavor(favor, playerReputation)} /> faction favor after installing an
|
||||
Augmentation.
|
||||
</Typography>
|
||||
<MathJax>{"\\(\\huge{r = \\text{total faction reputation}}\\)"}</MathJax>
|
||||
<MathJax>{"\\(\\huge{favor=\\log_{1.02}\\left(1+\\frac{r}{25000}\\right)}\\)"}</MathJax>
|
||||
<Typography style={{ fontSize: "2rem" }}>r = Total faction reputation</Typography>
|
||||
<MathNotationOutput notation={MathNotation.RepToFavor} />
|
||||
</>
|
||||
}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user