mini-tsx 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +87 -0
- package/create-mini-tsx/index.js +79 -0
- package/create-mini-tsx/package.json +16 -0
- package/package.json +15 -0
- package/src/index.ts +22 -0
- package/tsconfig.json +16 -0
package/README.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Mini TSX
|
|
2
|
+
|
|
3
|
+
A tiny, zero-dependency TSX-to-HTML compiler library.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Zero dependencies** (uses native Node.js modules).
|
|
8
|
+
- **Lightweight** (~1KB).
|
|
9
|
+
- **Standard JSX** support (TypeScript).
|
|
10
|
+
- **Automatic HTML generation** with hashing.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install mini-tsx
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## CLI (Scaffolding)
|
|
19
|
+
|
|
20
|
+
Initialize a new project with default `tsconfig.json` and `src/index.tsx`:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npx mini-tsx
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Setup (Manual)
|
|
27
|
+
|
|
28
|
+
1. **Configure `tsconfig.json`**:
|
|
29
|
+
|
|
30
|
+
Ensure your `tsconfig.json` has the following compiler options to enable JSX:
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"compilerOptions": {
|
|
35
|
+
"jsx": "react",
|
|
36
|
+
"jsxFactory": "jsx",
|
|
37
|
+
"module": "ESNext",
|
|
38
|
+
"moduleResolution": "node"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
2. **Add `type: "module"` to `package.json`**:
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"type": "module"
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Usage
|
|
52
|
+
|
|
53
|
+
Create a `.tsx` file (e.g., `src/index.tsx`):
|
|
54
|
+
|
|
55
|
+
```tsx
|
|
56
|
+
import { jsx, render } from "mini-tsx";
|
|
57
|
+
|
|
58
|
+
const Button = ({ color, children }: { color: string; children: any }) => (
|
|
59
|
+
<button style={`color: ${color}`}>
|
|
60
|
+
{children}
|
|
61
|
+
</button>
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
const App = () => (
|
|
65
|
+
<div>
|
|
66
|
+
<h1>Hello World</h1>
|
|
67
|
+
<Button color="blue">Click me</Button>
|
|
68
|
+
</div>
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
// Renders to dist/index.<hash>.html by default
|
|
72
|
+
render(App());
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Build & Run
|
|
76
|
+
|
|
77
|
+
Compile your TypeScript code and run it with Node.js:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# Compile
|
|
81
|
+
npx tsc
|
|
82
|
+
|
|
83
|
+
# Run (generates HTML)
|
|
84
|
+
node dist/index.js
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
The output HTML file will be generated in the `dist/` folder.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { writeFileSync, existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { execSync } from "node:child_process";
|
|
6
|
+
|
|
7
|
+
const cwd = process.cwd();
|
|
8
|
+
|
|
9
|
+
// 1. Initialize package.json if missing
|
|
10
|
+
if (!existsSync(join(cwd, "package.json"))) {
|
|
11
|
+
console.log("Initializing package.json...");
|
|
12
|
+
execSync("npm init -y", { stdio: "inherit" });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// 2. Install mini-tsx
|
|
16
|
+
console.log("Installing mini-tsx...");
|
|
17
|
+
try {
|
|
18
|
+
execSync("npm install mini-tsx", { stdio: "inherit" });
|
|
19
|
+
} catch (e) {
|
|
20
|
+
console.log("Skipping install (might be local test)");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// 3. Setup tsconfig.json
|
|
24
|
+
const tsconfigPath = join(cwd, "tsconfig.json");
|
|
25
|
+
const requiredOptions = {
|
|
26
|
+
"jsx": "react",
|
|
27
|
+
"jsxFactory": "jsx",
|
|
28
|
+
"module": "ESNext",
|
|
29
|
+
"moduleResolution": "node",
|
|
30
|
+
"strict": true,
|
|
31
|
+
"esModuleInterop": true,
|
|
32
|
+
"outDir": "dist"
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
let tsconfig = {
|
|
36
|
+
"compilerOptions": { ...requiredOptions },
|
|
37
|
+
"include": ["src/**/*"]
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
if (existsSync(tsconfigPath)) {
|
|
41
|
+
try {
|
|
42
|
+
const existing = JSON.parse(readFileSync(tsconfigPath, "utf-8"));
|
|
43
|
+
tsconfig = existing;
|
|
44
|
+
tsconfig.compilerOptions = tsconfig.compilerOptions || {};
|
|
45
|
+
Object.assign(tsconfig.compilerOptions, requiredOptions);
|
|
46
|
+
console.log("Updated tsconfig.json");
|
|
47
|
+
} catch (e) {
|
|
48
|
+
console.log("Error reading tsconfig.json, overwriting...");
|
|
49
|
+
}
|
|
50
|
+
} else {
|
|
51
|
+
console.log("Created tsconfig.json");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
writeFileSync(tsconfigPath, JSON.stringify(tsconfig, null, 2));
|
|
55
|
+
|
|
56
|
+
// 4. Create src/index.tsx
|
|
57
|
+
const srcDir = join(cwd, "src");
|
|
58
|
+
if (!existsSync(srcDir)) mkdirSync(srcDir);
|
|
59
|
+
|
|
60
|
+
const indexTsxPath = join(srcDir, "index.tsx");
|
|
61
|
+
if (!existsSync(indexTsxPath)) {
|
|
62
|
+
const indexTsx = `import { jsx, render } from "mini-tsx";
|
|
63
|
+
|
|
64
|
+
const App = () => (
|
|
65
|
+
<div>
|
|
66
|
+
<h1>Hello World</h1>
|
|
67
|
+
<p>Welcome to your new Mini TSX project!</p>
|
|
68
|
+
</div>
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
render(App());
|
|
72
|
+
`;
|
|
73
|
+
writeFileSync(indexTsxPath, indexTsx);
|
|
74
|
+
console.log("Created src/index.tsx");
|
|
75
|
+
} else {
|
|
76
|
+
console.log("src/index.tsx already exists");
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
console.log("\nDone! Run 'npx tsc && node dist/index.js' to build and run.");
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-mini-tsx",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"create-mini-tsx": "index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [],
|
|
14
|
+
"author": "",
|
|
15
|
+
"license": "ISC"
|
|
16
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mini-tsx",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc"
|
|
9
|
+
},
|
|
10
|
+
"devDependencies": {
|
|
11
|
+
"@types/node": "^25.2.3",
|
|
12
|
+
"ts-node": "^10.9.1",
|
|
13
|
+
"typescript": "^5.2.2"
|
|
14
|
+
}
|
|
15
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { basename, extname, dirname, join } from "node:path";
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
|
|
5
|
+
declare global { namespace JSX { interface ElementChildrenAttribute { children: {} } interface IntrinsicElements { [k: string]: any } } }
|
|
6
|
+
|
|
7
|
+
export const jsx = (t: any, p: any, ...c: any[]) => {
|
|
8
|
+
if (typeof t == "function") return t({ ...p, children: c });
|
|
9
|
+
let s = ""; for (let k in (p ||= {})) s += ` ${k}="${p[k]}"`;
|
|
10
|
+
return `<${t}${s}>${c.flat().join("")}</${t}>`;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const render = (b: string, f?: string) => {
|
|
14
|
+
const h = `<!DOCTYPE html><meta charset="utf-8"><meta name="viewport" content="width=device-width">${b}`;
|
|
15
|
+
if (!f) {
|
|
16
|
+
const hash = createHash("md5").update(h).digest("hex").slice(0, 8);
|
|
17
|
+
f = join("dist", basename(process.argv[1], extname(process.argv[1])) + "." + hash + ".html");
|
|
18
|
+
}
|
|
19
|
+
mkdirSync(dirname(f), { recursive: true });
|
|
20
|
+
writeFileSync(f, h);
|
|
21
|
+
console.log(`Rendered: ${f}`);
|
|
22
|
+
};
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"jsx": "react",
|
|
6
|
+
"jsxFactory": "jsx",
|
|
7
|
+
"strict": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"moduleResolution": "node",
|
|
10
|
+
"outDir": "dist",
|
|
11
|
+
"declaration": true
|
|
12
|
+
},
|
|
13
|
+
"include": [
|
|
14
|
+
"src/**/*"
|
|
15
|
+
]
|
|
16
|
+
}
|