Init
This commit is contained in:
commit
84a1d08651
29
.eslintrc.js
Normal file
29
.eslintrc.js
Normal file
@ -0,0 +1,29 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
es6: true,
|
||||
node: true,
|
||||
},
|
||||
extends: ['prettier'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
ecmaVersion: 2018,
|
||||
sourceType: 'module',
|
||||
project: './tsconfig.json',
|
||||
},
|
||||
plugins: [
|
||||
'@typescript-eslint/eslint-plugin',
|
||||
'prettier',
|
||||
],
|
||||
rules: {
|
||||
camelcase: 'error',
|
||||
'@typescript-eslint/return-await': 'off',
|
||||
'@typescript-eslint/camelcase': 'off',
|
||||
'no-param-reassign': ['error', { props: false }],
|
||||
'no-underscore-dangle': ['error', { allow: ['_id'] }],
|
||||
},
|
||||
reportUnusedDisableDirectives: true,
|
||||
};
|
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
.out/
|
||||
.tmp/
|
||||
node_modules/
|
||||
.idea/
|
||||
.vscode/
|
38
package.json
Normal file
38
package.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "ssg",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"compile": "esbuild ssg/build.tsx --bundle --outfile=.tmp/ssg/build.js --jsx-import-source=@kitajs/html --minify --sourcemap --platform=node --external:esbuild",
|
||||
"buld": "npm run compile && node .tmp/ssg/build.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@kitajs/html": "^4.2.7",
|
||||
"@kitajs/ts-html-plugin": "^4.1.1",
|
||||
"@types/node": "^22.14.0",
|
||||
"esbuild": "^0.25.2",
|
||||
"esbuild-sass-plugin": "^3.3.1",
|
||||
"glob": "^11.0.1",
|
||||
"prettier": "^3.5.3",
|
||||
"typescript": "^5.8.3",
|
||||
"eslint": "8.56.0",
|
||||
"eslint-config-prettier": "9.1.0",
|
||||
"eslint-plugin-import": "2.29.1",
|
||||
"eslint-plugin-prettier": "5.1.3",
|
||||
"@typescript-eslint/typescript-estree": "8.22.0",
|
||||
"@typescript-eslint/eslint-plugin": "7.0.2",
|
||||
"@typescript-eslint/parser": "7.0.2"
|
||||
},
|
||||
"prettier": {
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "all",
|
||||
"arrowParens": "always",
|
||||
"printWidth": 80
|
||||
}
|
||||
}
|
3375
pnpm-lock.yaml
Normal file
3375
pnpm-lock.yaml
Normal file
File diff suppressed because it is too large
Load Diff
3
src/components/body/body.module.scss
Normal file
3
src/components/body/body.module.scss
Normal file
@ -0,0 +1,3 @@
|
||||
.body {
|
||||
color: blue;
|
||||
}
|
5
src/components/body/body.tsx
Normal file
5
src/components/body/body.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
import styles from './body.module.scss';
|
||||
|
||||
export default function Body(props: { children: any }) {
|
||||
return <p className={styles.body}>{props.children}</p>;
|
||||
}
|
3
src/components/heading/heading.module.scss
Normal file
3
src/components/heading/heading.module.scss
Normal file
@ -0,0 +1,3 @@
|
||||
.heading {
|
||||
color: red;
|
||||
}
|
5
src/components/heading/heading.tsx
Normal file
5
src/components/heading/heading.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
import styles from './heading.module.scss';
|
||||
|
||||
export default function Heading(props: { children: any }) {
|
||||
return <h1 className={styles.heading}>{props.children}</h1>;
|
||||
}
|
3
src/pages/404.tsx
Normal file
3
src/pages/404.tsx
Normal file
@ -0,0 +1,3 @@
|
||||
export default function NotFound() {
|
||||
return <div>Not Found</div>;
|
||||
}
|
11
src/pages/index.tsx
Normal file
11
src/pages/index.tsx
Normal file
@ -0,0 +1,11 @@
|
||||
import Heading from '../components/heading/heading';
|
||||
import Body from '../components/body/body';
|
||||
|
||||
export default function Index() {
|
||||
return (
|
||||
<div>
|
||||
<Heading>foo</Heading>
|
||||
<Body>Hello World!</Body>
|
||||
</div>
|
||||
);
|
||||
}
|
51
ssg/build.tsx
Normal file
51
ssg/build.tsx
Normal file
@ -0,0 +1,51 @@
|
||||
import { glob } from 'glob';
|
||||
import { build } from 'esbuild';
|
||||
import { mkdirSync, writeFileSync, rmSync } from 'node:fs';
|
||||
import { sassPlugin } from 'esbuild-sass-plugin';
|
||||
import Root from './root';
|
||||
import { getPaths, getStylePath, outDir } from './utils';
|
||||
|
||||
mkdirSync(outDir, { recursive: true });
|
||||
|
||||
void (async () => {
|
||||
const pages = await glob('src/pages/**/*.tsx');
|
||||
|
||||
await Promise.all(
|
||||
pages.map(async (page) => {
|
||||
const { pagePath, tmpJsPath, outputHtmlPath } = getPaths(page);
|
||||
|
||||
await build({
|
||||
entryPoints: [pagePath],
|
||||
bundle: true,
|
||||
outfile: tmpJsPath,
|
||||
jsxImportSource: '@kitajs/html',
|
||||
minify: true,
|
||||
platform: 'node',
|
||||
external: ['esbuild'],
|
||||
plugins: [
|
||||
sassPlugin({
|
||||
filter: /\.module\.scss$/,
|
||||
type: 'local-css',
|
||||
}),
|
||||
sassPlugin({
|
||||
filter: /\.scss$/,
|
||||
type: 'css',
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
const { default: Page } = await import(tmpJsPath);
|
||||
const html = Page.default();
|
||||
let stylePaths: string[] = getStylePath(tmpJsPath, outputHtmlPath);
|
||||
|
||||
writeFileSync(
|
||||
outputHtmlPath,
|
||||
<Root title="My App" stylePaths={stylePaths} scriptPaths={[]}>
|
||||
{html}
|
||||
</Root>,
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
rmSync('.tmp', { recursive: true });
|
||||
})();
|
25
ssg/root.tsx
Normal file
25
ssg/root.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
interface Props {
|
||||
children: HTMLElement;
|
||||
title: string;
|
||||
scriptPaths: string[];
|
||||
stylePaths: string[];
|
||||
}
|
||||
|
||||
export default function Root(props: Props) {
|
||||
const { children, title, scriptPaths, stylePaths } = props;
|
||||
|
||||
return (
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>{title}</title>
|
||||
{stylePaths.map((path) => (
|
||||
<link rel="stylesheet" href={path} />
|
||||
))}
|
||||
{scriptPaths.map((path) => (
|
||||
<script src={path} />
|
||||
))}
|
||||
</head>
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
31
ssg/utils.ts
Normal file
31
ssg/utils.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { cpSync, existsSync } from 'node:fs';
|
||||
import { resolve } from 'path';
|
||||
|
||||
export const outDir = resolve('.out');
|
||||
|
||||
export const getStylePath = (tmpJsPath: string, outputHtmlPath: string) => {
|
||||
let stylePaths: string[] = [];
|
||||
|
||||
if (existsSync(tmpJsPath.replace('.js', '.css'))) {
|
||||
cpSync(
|
||||
tmpJsPath.replace('.js', '.css'),
|
||||
outputHtmlPath.replace('.html', '.css'),
|
||||
);
|
||||
|
||||
stylePaths.push(
|
||||
outputHtmlPath.replace('.html', '.css').replace(outDir, '.'),
|
||||
);
|
||||
}
|
||||
|
||||
return stylePaths;
|
||||
};
|
||||
|
||||
export const getPaths = (rawPath: string) => {
|
||||
const pagePath = resolve(rawPath);
|
||||
const tmpJsPath = pagePath.replace('src', '.tmp').replace('.tsx', '.js');
|
||||
const outputHtmlPath = pagePath
|
||||
.replace('src/pages', '.out')
|
||||
.replace('.tsx', '.html');
|
||||
|
||||
return { pagePath, tmpJsPath, outputHtmlPath };
|
||||
};
|
23
tsconfig.json
Normal file
23
tsconfig.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"lib": ["dom", "dom.iterable", "es2021"],
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "@kitajs/html",
|
||||
"plugins": [{ "name": "@kitajs/ts-html-plugin" }],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"incremental": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"outDir": "./out",
|
||||
},
|
||||
"include": ["**/*.tsx", "**/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
Loading…
Reference in New Issue
Block a user