@yKicchan
GenerateDirectoryListingAction
index.html
- name: Generate directory listing uses: yKicchan/generate-directory-listing-action@v1 with: target: dist
実際の利用時にはコミットハッシュを指定しよう
目的のページまでの繋ぎとして利用するのに便利
renderToString
HTML
string
fs.writeFile
import { renderToString } from "preact-render-to-string"; import { App, type AppProps } from "path/to/app"; export const renderHTML = (props: AppProps) => `<!DOCTYPE html>${renderToString(HTML(props))}`; const HTML = (props: AppProps) => ( <html> <head><!-- 中略 --></head> <body> <App {...props} /> </body> </html> );
import fs from "node:fs"; import { renderHTML } from "./html"; const html = renderHTML({ /* props */ }); fs.writeFileSync("index.html", html, "utf-8");
実際の実装: → generator.ts html/index.tsx
export const renderHTML = async (props: AppProps) => { const htmlComponent = await HTML(props); return `<!DOCTYPE html>${renderToString(htmlComponent)}`; } const HTML = async (props: AppProps) => { const appComponent = await App(props); return ( <html> <head><!-- 中略 --></head> <body>{appComponent}</body> </html> ); }
改良余地として、グローバルにしか読んでいない(コンポーネントごとにCSSを読んでいない)ところや未使用クラスの削除には対応できていない シンプルな View を提供しているのでグローバルCSSで事足りておりわざわざ時間を使わなかったという戦略的撤退でもある
import cssnano from "cssnano"; import postcss from "postcss"; import flexbugsFixes from "postcss-flexbugs-fixes"; import presetEnv from "postcss-preset-env"; import mycss from "path/to/css.pcss"; export async function CSS() { const css = await applyPostcssPlugins(mycss); return <style>{css}</style>; } async function applyPostcssPlugins(css: string) { const result = await postcss([ presetEnv(), flexbugsFixes(), cssnano() ]).process(css, { from: undefined }); return result.css; }
import { build } from "esbuild"; build({ // 中略 loader: { ".tsx": "tsx", ".ts": "ts", ".css": "text", ".pcss": "text", }, })
実際の実装: → css/index.tsx esbuild.config.mjs
vitest
jest
@testing-library/preact
happy-dom
getByRole
import { generate } from "./generator"; const setup = (dir: Path) => generate(dir); it("ファイルがなかったとき、何もしない", async () => { const dir = { fullpath: () => "unknown" } as Path; await setup(dir); expect(mockWriteFile).not.toHaveBeenCalled(); }); it("ディレクトリ内にファイル(またはディレクトリ)が1つ以上あるとき index.html を生成する", async () => { const dir = { fullpath: () => "sandbox" } as Path; await setup(dir); expect(mockWriteFile).toHaveBeenCalledWith("sandbox/index.html", "html", "utf-8"); });
@actions/core