mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-08-29 16:47:56 +00:00
Use Preact for static rendering of components
We already use preact for the copy-cat integration, so it makes sense to use it during the static pass too. This allows us to drop a dependency on react.
This commit is contained in:
@@ -5,13 +5,14 @@
|
||||
import { readFileSync } from "fs";
|
||||
import path from "path";
|
||||
|
||||
import typescript from "@rollup/plugin-typescript";
|
||||
import url from '@rollup/plugin-url';
|
||||
import terser from "@rollup/plugin-terser";
|
||||
import typescript from "@rollup/plugin-typescript";
|
||||
import url from "@rollup/plugin-url";
|
||||
|
||||
const input = "src";
|
||||
const requirejs = readFileSync("../../node_modules/requirejs/require.js");
|
||||
|
||||
/** @type import("rollup").RollupOptions */
|
||||
export default {
|
||||
input: [`${input}/index.tsx`],
|
||||
output: {
|
||||
@@ -54,7 +55,7 @@ export default {
|
||||
async transform(code, file) {
|
||||
// Allow loading files in /mount.
|
||||
const ext = path.extname(file);
|
||||
return ext != '.dfpwm' && path.dirname(file) === path.resolve(`${input}/mount`)
|
||||
return ext != ".dfpwm" && path.dirname(file) === path.resolve(`${input}/mount`)
|
||||
? `export default ${JSON.stringify(code)};\n`
|
||||
: null;
|
||||
},
|
||||
|
@@ -2,8 +2,7 @@
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
import type { FunctionComponent } from "react";
|
||||
import { createElement as h } from "react";
|
||||
import { h, type FunctionComponent, type JSX } from "preact";
|
||||
import useExport from "./WithExport";
|
||||
|
||||
const Item: FunctionComponent<{ item: string }> = ({ item }) => {
|
||||
|
@@ -2,7 +2,8 @@
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
import { createElement as h, useContext, createContext, type FunctionComponent, type ReactNode } from "react";
|
||||
import { h, createContext, type FunctionComponent, type VNode } from "preact";
|
||||
import { useContext } from "preact/hooks";
|
||||
|
||||
export type DataExport = {
|
||||
readonly itemNames: Record<string, string>,
|
||||
@@ -23,5 +24,5 @@ const DataExport = createContext<DataExport>({
|
||||
export const useExport = () => useContext(DataExport);
|
||||
export default useExport;
|
||||
|
||||
export const WithExport: FunctionComponent<{ data: DataExport, children: ReactNode }> =
|
||||
({ data, children }) => <DataExport.Provider value={data}> {children}</DataExport.Provider >;
|
||||
export const WithExport: FunctionComponent<{ data: DataExport, children: VNode }> =
|
||||
({ data, children }) => <DataExport.Provider value={data}> {children}</DataExport.Provider>;
|
||||
|
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
import type { FunctionComponent } from "react";
|
||||
import { type FunctionComponent } from "preact";
|
||||
|
||||
/**
|
||||
* Wrap a component and ensure that no children are passed to it.
|
||||
@@ -20,7 +20,7 @@ export const noChildren = function <T>(component: FunctionComponent<T>): Functio
|
||||
|
||||
const name = component.displayName ?? component.name;
|
||||
const wrapped: FunctionComponent<T> = props => {
|
||||
if ((props as any).children) throw Error("Unexpected children in " + name);
|
||||
if (props.children) throw Error("Unexpected children in " + name);
|
||||
|
||||
return component(props);
|
||||
};
|
||||
|
@@ -2,18 +2,18 @@
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
import { render, h, Component, Computer, type PeripheralKind } from "copycat/embed";
|
||||
import type { ComponentChild } from "preact";
|
||||
import { Component, Computer, h, render, type PeripheralKind } from "copycat/embed";
|
||||
import type { ComponentChild, FunctionalComponent } from "preact";
|
||||
|
||||
import settingsFile from "./mount/.settings";
|
||||
import startupFile from "./mount/startup.lua";
|
||||
import exprTemplate from "./mount/expr_template.lua";
|
||||
import exampleAudioUrl from "./mount/example.dfpwm";
|
||||
import exampleAudioLicense from "./mount/example.dfpwm.license";
|
||||
import exampleNfp from "./mount/example.nfp";
|
||||
import exampleNft from "./mount/example.nft";
|
||||
import exampleAudioLicense from "./mount/example.dfpwm.license";
|
||||
import exampleAudioUrl from "./mount/example.dfpwm";
|
||||
import exprTemplate from "./mount/expr_template.lua";
|
||||
import startupFile from "./mount/startup.lua";
|
||||
|
||||
const defaultFiles: { [filename: string]: string } = {
|
||||
const defaultFiles: Record<string, string> = {
|
||||
".settings": settingsFile,
|
||||
"startup.lua": startupFile,
|
||||
|
||||
@@ -36,13 +36,13 @@ const download = async (url: string): Promise<Uint8Array> => {
|
||||
|
||||
let dfpwmAudio: Promise<Uint8Array> | null = null;
|
||||
|
||||
const Click = (options: { run: () => void }) =>
|
||||
<button type="button" class="example-run" onClick={options.run}>Run ᐅ</button>
|
||||
const Click: FunctionalComponent<{ run: () => void }> = ({ run }) =>
|
||||
<button type="button" class="example-run" onClick={run}>Run ᐅ</button>
|
||||
|
||||
type WindowProps = {};
|
||||
|
||||
type Example = {
|
||||
files: { [file: string]: string | Uint8Array },
|
||||
files: Record<string, string | Uint8Array>,
|
||||
peripheral: PeripheralKind | null,
|
||||
}
|
||||
|
||||
@@ -105,8 +105,8 @@ class Window extends Component<WindowProps, WindowState> {
|
||||
</div>
|
||||
<div class="computer-container">
|
||||
<Computer key={exampleIdx} files={{
|
||||
...defaultFiles, ...example!.files,
|
||||
}} peripherals={{ back: example!.peripheral }} />
|
||||
...defaultFiles, ...example.files,
|
||||
}} peripherals={{ back: example.peripheral }} />
|
||||
</div>
|
||||
</div>
|
||||
</div> : <div class="example-window example-window-hidden" />;
|
||||
@@ -120,7 +120,7 @@ class Window extends Component<WindowProps, WindowState> {
|
||||
this.top = 20;
|
||||
}
|
||||
|
||||
const files: { [file: string]: string | Uint8Array } = { "example.lua": example };
|
||||
const files: Record<string, string | Uint8Array> = { "example.lua": example };
|
||||
if (mount !== null) {
|
||||
for (const toMount of mount.split(",")) {
|
||||
const [name, path] = toMount.split(":", 2);
|
||||
|
@@ -10,20 +10,20 @@
|
||||
*
|
||||
* Yes, this would be so much nicer with next.js.
|
||||
*/
|
||||
import * as fs from "fs/promises";
|
||||
import fs from "fs/promises";
|
||||
import { glob } from "glob";
|
||||
import * as path from "path";
|
||||
import { createElement as h } from 'react';
|
||||
import runtime from 'react/jsx-runtime';
|
||||
import { renderToStaticMarkup } from "react-dom/server";
|
||||
import rehypeHighlight from "rehype-highlight";
|
||||
import rehypeParse from 'rehype-parse';
|
||||
import rehypeReact, { type Options as ReactOptions } from 'rehype-react';
|
||||
import { unified } from 'unified';
|
||||
import path from "path";
|
||||
import { h, type JSX } from "preact";
|
||||
import renderToStaticMarkup from "preact-render-to-string";
|
||||
import * as runtime from "preact/jsx-runtime";
|
||||
import rehypeHighlight, { type Options as HighlightOptions } from "rehype-highlight";
|
||||
import rehypeParse from "rehype-parse";
|
||||
import rehypeReact, { type Options as ReactOptions } from "rehype-react";
|
||||
import { unified, type Plugin } from "unified";
|
||||
// Our components
|
||||
import Recipe from "./components/Recipe";
|
||||
import { noChildren } from "./components/support";
|
||||
import { type DataExport, WithExport } from "./components/WithExport";
|
||||
import { WithExport, type DataExport } from "./components/WithExport";
|
||||
|
||||
(async () => {
|
||||
const base = "build/illuaminate";
|
||||
@@ -31,19 +31,19 @@ import { type DataExport, WithExport } from "./components/WithExport";
|
||||
const reactOptions: ReactOptions = {
|
||||
...(runtime as ReactOptions),
|
||||
components: {
|
||||
['mc-recipe']: noChildren(Recipe),
|
||||
['mcrecipe']: noChildren(Recipe),
|
||||
["mc-recipe"]: noChildren(Recipe),
|
||||
["mcrecipe"]: noChildren(Recipe),
|
||||
// Wrap example snippets in a <div class="lua-example">...</div>, so we can inject a
|
||||
// Run button into them.
|
||||
['pre']: (args: JSX.IntrinsicElements["pre"] & { "data-lua-kind"?: undefined }) => {
|
||||
["pre"]: (args: JSX.IntrinsicElements["pre"] & { "data-lua-kind"?: undefined }) => {
|
||||
const element = <pre {...args} />;
|
||||
return args["data-lua-kind"] ? <div className="lua-example">{element}</div> : element
|
||||
}
|
||||
} as any
|
||||
}
|
||||
};
|
||||
const processor = unified()
|
||||
.use(rehypeParse, { emitParseErrors: true })
|
||||
.use(rehypeHighlight, { prefix: "" })
|
||||
.use(rehypeHighlight as unknown as Plugin<[HighlightOptions], import("hast").Root>, { prefix: "" })
|
||||
.use(rehypeReact, reactOptions);
|
||||
|
||||
const dataExport = JSON.parse(await fs.readFile("src/export/index.json", "utf-8")) as DataExport;
|
||||
|
Reference in New Issue
Block a user