@punkestu/react-html 0.1.0 ā 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 +72 -15
- package/dist/cli/docs-content.d.ts +8 -0
- package/dist/cli/docs-content.d.ts.map +1 -0
- package/dist/cli/docs-content.js +328 -0
- package/dist/cli/docs-content.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +135 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/tui-docs.d.ts +5 -0
- package/dist/cli/tui-docs.d.ts.map +1 -0
- package/dist/cli/tui-docs.js +191 -0
- package/dist/cli/tui-docs.js.map +1 -0
- package/dist/client/hydrate.d.ts +4 -0
- package/dist/client/hydrate.d.ts.map +1 -0
- package/dist/client/hydrate.js +80 -0
- package/dist/client/hydrate.js.map +1 -0
- package/dist/core/bundler.d.ts +9 -0
- package/dist/core/bundler.d.ts.map +1 -0
- package/dist/core/bundler.js +245 -0
- package/dist/core/bundler.js.map +1 -0
- package/dist/core/formatter.d.ts +6 -0
- package/dist/core/formatter.d.ts.map +1 -0
- package/dist/core/formatter.js +74 -0
- package/dist/core/formatter.js.map +1 -0
- package/dist/core/island-client.d.ts +9 -0
- package/dist/core/island-client.d.ts.map +1 -0
- package/dist/core/island-client.js +8 -0
- package/dist/core/island-client.js.map +1 -0
- package/dist/core/island-discovery.d.ts +19 -0
- package/dist/core/island-discovery.d.ts.map +1 -0
- package/dist/core/island-discovery.js +92 -0
- package/dist/core/island-discovery.js.map +1 -0
- package/dist/core/island-registry.d.ts +15 -0
- package/dist/core/island-registry.d.ts.map +1 -0
- package/dist/core/island-registry.js +17 -0
- package/dist/core/island-registry.js.map +1 -0
- package/dist/core/island.d.ts +32 -0
- package/dist/core/island.d.ts.map +1 -0
- package/dist/core/island.js +47 -0
- package/dist/core/island.js.map +1 -0
- package/dist/core/loader.d.ts +11 -0
- package/dist/core/loader.d.ts.map +1 -0
- package/dist/core/loader.js +87 -0
- package/dist/core/loader.js.map +1 -0
- package/dist/core/renderer.d.ts +20 -0
- package/dist/core/renderer.d.ts.map +1 -0
- package/dist/core/renderer.js +53 -0
- package/dist/core/renderer.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +110 -0
- package/dist/index.js.map +1 -0
- package/dist/server/dev-server.d.ts +8 -0
- package/dist/server/dev-server.d.ts.map +1 -0
- package/dist/server/dev-server.js +112 -0
- package/dist/server/dev-server.js.map +1 -0
- package/dist/server/engine.d.ts +50 -0
- package/dist/server/engine.d.ts.map +1 -0
- package/dist/server/engine.js +225 -0
- package/dist/server/engine.js.map +1 -0
- package/{src/server/index.ts ā dist/server/index.d.ts} +1 -1
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +3 -0
- package/dist/server/index.js.map +1 -0
- package/package.json +5 -1
- package/.react-html/cache/page-fefe905ae5d2.mjs +0 -9
- package/DOCS.md +0 -317
- package/example/public/styles.css +0 -184
- package/example/src/components/Card.tsx +0 -17
- package/example/src/components/Counter.island.tsx +0 -35
- package/example/src/components/Footer.tsx +0 -13
- package/example/src/components/Header.tsx +0 -20
- package/example/src/components/Layout.tsx +0 -39
- package/example/src/components/Tabs.island.tsx +0 -59
- package/example/src/pages/index.tsx +0 -49
- package/example/src/pages/pure.tsx +0 -56
- package/src/cli/docs-content.ts +0 -268
- package/src/cli/index.ts +0 -113
- package/src/cli/tui-docs.ts +0 -214
- package/src/client/hydrate.ts +0 -84
- package/src/core/bundler.ts +0 -122
- package/src/core/formatter.ts +0 -92
- package/src/core/island-client.ts +0 -23
- package/src/core/island-registry.ts +0 -35
- package/src/core/island.tsx +0 -110
- package/src/core/loader.ts +0 -89
- package/src/core/renderer.ts +0 -80
- package/src/index.ts +0 -138
- package/src/server/dev-server.ts +0 -125
- package/src/server/engine.ts +0 -270
- package/tests/engine.test.mjs +0 -288
- package/tsconfig.json +0 -21
package/README.md
CHANGED
|
@@ -33,9 +33,12 @@ npm link
|
|
|
33
33
|
### CLI Usage
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
|
-
# Build static site to dist/
|
|
36
|
+
# Build static site to dist/ (with code splitting, islands are ~800 B each)
|
|
37
37
|
react-html build
|
|
38
38
|
|
|
39
|
+
# Ultra-light Preact mode (drops total framework chunk to ~24 KB!)
|
|
40
|
+
react-html build --preact
|
|
41
|
+
|
|
39
42
|
# Build with custom pages or output directory
|
|
40
43
|
react-html build --pages src/pages --out dist
|
|
41
44
|
|
|
@@ -114,20 +117,15 @@ export default function AboutPage() {
|
|
|
114
117
|
|
|
115
118
|
---
|
|
116
119
|
|
|
117
|
-
### 2. Reactive Components (
|
|
120
|
+
### 2. Reactive Components (Island Auto-Discovery)
|
|
118
121
|
|
|
119
|
-
When a component needs client-side state and interactivity,
|
|
122
|
+
When a component needs client-side state and interactivity, simply name the file `*.island.tsx` (or place it inside an `islands/` directory) and **export default** your pure React component. Zero wrapping required!
|
|
120
123
|
|
|
121
124
|
```tsx
|
|
122
|
-
// src/components/Counter.island.tsx
|
|
125
|
+
// src/components/Counter.island.tsx (or src/islands/Counter.tsx)
|
|
123
126
|
import React, { useState } from 'react';
|
|
124
|
-
import { island } from 'react-html';
|
|
125
|
-
|
|
126
|
-
export interface CounterProps {
|
|
127
|
-
initial?: number;
|
|
128
|
-
}
|
|
129
127
|
|
|
130
|
-
function
|
|
128
|
+
export default function Counter({ initial = 0 }: { initial?: number }) {
|
|
131
129
|
const [count, setCount] = useState(initial);
|
|
132
130
|
|
|
133
131
|
return (
|
|
@@ -138,10 +136,6 @@ function CounterComponent({ initial = 0 }: CounterProps) {
|
|
|
138
136
|
</div>
|
|
139
137
|
);
|
|
140
138
|
}
|
|
141
|
-
|
|
142
|
-
// Export the island with its unique name and source path
|
|
143
|
-
export const Counter = island(CounterComponent, import.meta.url, 'Counter');
|
|
144
|
-
export default Counter;
|
|
145
139
|
```
|
|
146
140
|
|
|
147
141
|
Now import and use it in any page just like a normal React component:
|
|
@@ -150,7 +144,7 @@ Now import and use it in any page just like a normal React component:
|
|
|
150
144
|
// src/pages/index.tsx
|
|
151
145
|
import React from 'react';
|
|
152
146
|
import { Layout } from '../components/Layout.js';
|
|
153
|
-
import
|
|
147
|
+
import Counter from '../components/Counter.island.js';
|
|
154
148
|
|
|
155
149
|
export default function HomePage() {
|
|
156
150
|
return (
|
|
@@ -163,6 +157,8 @@ export default function HomePage() {
|
|
|
163
157
|
}
|
|
164
158
|
```
|
|
165
159
|
|
|
160
|
+
> š” **Manual Island Wrapping (Optional)**: If you prefer explicit wrapping or have dynamic component references, `island(Component, import.meta.url, 'Name')` and `<Island component={...} />` are also supported for full backward compatibility.
|
|
161
|
+
|
|
166
162
|
**What the engine does:**
|
|
167
163
|
1. Renders the initial static markup during SSR for instant paint.
|
|
168
164
|
2. Compiles a dedicated micro-bundle `dist/assets/islands/Counter.js`.
|
|
@@ -171,6 +167,53 @@ export default function HomePage() {
|
|
|
171
167
|
|
|
172
168
|
---
|
|
173
169
|
|
|
170
|
+
### 3. Pure Vanilla DOM Islands (Zero-React Client Compilation)
|
|
171
|
+
|
|
172
|
+
Want client-side interactivity but **zero React or VDOM runtime on the client**?
|
|
173
|
+
|
|
174
|
+
You can write standard React JSX on the server for DRY markup, and export a native `client(element, props)` controller function in the same island file:
|
|
175
|
+
|
|
176
|
+
```tsx
|
|
177
|
+
// src/components/VanillaCounter.island.tsx
|
|
178
|
+
import React from 'react';
|
|
179
|
+
|
|
180
|
+
// 1. Server: Pure modular HTML via standard React JSX
|
|
181
|
+
export default function VanillaCounter({ initialCount = 0, step = 1 }: { initialCount?: number; step?: number }) {
|
|
182
|
+
return (
|
|
183
|
+
<div className="counter-box">
|
|
184
|
+
<span className="counter-value">{initialCount}</span>
|
|
185
|
+
<button data-action="dec">- {step}</button>
|
|
186
|
+
<button data-action="inc">+ {step}</button>
|
|
187
|
+
</div>
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// 2. Client: Pure native DOM controller (Zero React/VDOM runtime!)
|
|
192
|
+
export function client(el: HTMLElement, props: { initialCount?: number; step?: number }) {
|
|
193
|
+
let count = props.initialCount || 0;
|
|
194
|
+
const step = props.step || 1;
|
|
195
|
+
const display = el.querySelector('.counter-value');
|
|
196
|
+
|
|
197
|
+
el.querySelector('[data-action="dec"]')?.addEventListener('click', () => {
|
|
198
|
+
count -= step;
|
|
199
|
+
if (display) display.textContent = String(count);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
el.querySelector('[data-action="inc"]')?.addEventListener('click', () => {
|
|
203
|
+
count += step;
|
|
204
|
+
if (display) display.textContent = String(count);
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
**Why this is huge:**
|
|
210
|
+
- **0 KB React, 0 KB ReactDOM, 0 KB Preact**: The engine completely stubs React in the client bundle.
|
|
211
|
+
- **Zero Chunk Imports**: Outputs a single, self-contained standalone `.js` file (~1 KB uncompressed, ~450 bytes gzipped).
|
|
212
|
+
- **Zero Hydration Overhead**: Bypasses VDOM reconciliation and binds native event listeners directly to existing DOM nodes.
|
|
213
|
+
- **Mix & Match**: You can use Pure Vanilla DOM islands and standard React/Preact islands in the very same project without conflict!
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
174
217
|
## š ļø Hydration Directives
|
|
175
218
|
|
|
176
219
|
`react-html` supports client loading directives to maximize performance:
|
|
@@ -183,6 +226,20 @@ export default function HomePage() {
|
|
|
183
226
|
|
|
184
227
|
---
|
|
185
228
|
|
|
229
|
+
## ā” Tiny Island Bundles & Preact Ultra-Light Mode
|
|
230
|
+
|
|
231
|
+
`react-html` uses ESM multi-entry code splitting and comment stripping to keep island bundles tiny:
|
|
232
|
+
|
|
233
|
+
- **Code Splitting by Default**: Component logic is separated from runtime code. `Counter.js` and `Tabs.js` weigh only **~800 bytes to 1 KB** each, importing a shared vendor chunk that the browser caches across all pages.
|
|
234
|
+
- **Ultra-Light Preact Mode (`--preact`)**: Want microscopic client bundles? Pass `--preact` to alias client hydration to `preact/compat`. You still write standard React JSX, but the shared runtime shrinks by **90%** down to **~24 KB uncompressed (~8 KB gzipped)**!
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
# Build with Preact ultra-light runtime
|
|
238
|
+
react-html build --preact
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
186
243
|
## š» Programmatic API
|
|
187
244
|
|
|
188
245
|
You can also run `react-html` programmatically from your Node.js scripts:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docs-content.d.ts","sourceRoot":"","sources":["../../src/cli/docs-content.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,eAAO,MAAM,YAAY,EAAE,UAAU,EAsUpC,CAAC"}
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
export const DOC_SECTIONS = [
|
|
2
|
+
{
|
|
3
|
+
id: 'intro',
|
|
4
|
+
title: '1. Overview & Philosophy',
|
|
5
|
+
summary: 'Core concepts: pure HTML output, zero-JS by default, and modular JSX.',
|
|
6
|
+
content: [
|
|
7
|
+
'# 1. Overview & Philosophy',
|
|
8
|
+
'',
|
|
9
|
+
'react-html bridges the gap between modern component-based developer experience',
|
|
10
|
+
'and lightweight, blazing-fast static websites.',
|
|
11
|
+
'',
|
|
12
|
+
'* ZERO JAVASCRIPT BY DEFAULT:',
|
|
13
|
+
' Standard components (layouts, navigation, typography, cards, footers) render into',
|
|
14
|
+
' 100% clean, semantic HTML5. No React runtime, no data-reactroot attributes,',
|
|
15
|
+
' and 0 KB JavaScript sent to the browser.',
|
|
16
|
+
'',
|
|
17
|
+
'* MODULAR & DRY (DON\'T REPEAT YOURSELF):',
|
|
18
|
+
' Eliminate copy-pasting HTML boilerplate. Compose pages with reusable React',
|
|
19
|
+
' components (<Layout>, <Header>, <Card>, <Footer>) with typed props.',
|
|
20
|
+
'',
|
|
21
|
+
'* SELECTIVE REACTIVITY (ISLANDS ARCHITECTURE):',
|
|
22
|
+
' Only components that explicitly require client-side interactivity are bundled',
|
|
23
|
+
' into isolated, tiny JavaScript files. Everything around them remains pure HTML.'
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
id: 'quickstart',
|
|
28
|
+
title: '2. Getting Started & Setup',
|
|
29
|
+
summary: 'Installation, Node.js environment, and initial directory structure.',
|
|
30
|
+
content: [
|
|
31
|
+
'# 2. Getting Started & Setup',
|
|
32
|
+
'',
|
|
33
|
+
'* PREREQUISITES:',
|
|
34
|
+
' - Node.js v20.0.0 or higher (runs natively on standard Node.js & npm)',
|
|
35
|
+
'',
|
|
36
|
+
'* INSTALLATION:',
|
|
37
|
+
' $ npm install react-html',
|
|
38
|
+
'',
|
|
39
|
+
'* RECOMMENDED PROJECT STRUCTURE:',
|
|
40
|
+
' my-project/',
|
|
41
|
+
' āāā package.json',
|
|
42
|
+
' āāā public/ # Static assets (CSS, images, icons)',
|
|
43
|
+
' ā āāā styles.css',
|
|
44
|
+
' āāā src/',
|
|
45
|
+
' āāā components/ # Reusable UI components',
|
|
46
|
+
' ā āāā Layout.tsx # Master HTML shell',
|
|
47
|
+
' ā āāā Header.tsx # Navigation bar',
|
|
48
|
+
' ā āāā Counter.island.tsx # Interactive island component',
|
|
49
|
+
' āāā pages/ # Multi-page entries',
|
|
50
|
+
' āāā index.tsx # -> dist/index.html',
|
|
51
|
+
' āāā about.tsx # -> dist/about.html',
|
|
52
|
+
' āāā blog/',
|
|
53
|
+
' āāā first.tsx # -> dist/blog/first.html'
|
|
54
|
+
]
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: 'modular-html',
|
|
58
|
+
title: '3. Modular HTML with React',
|
|
59
|
+
summary: 'Creating reusable layouts, header partials, and nested components.',
|
|
60
|
+
content: [
|
|
61
|
+
'# 3. Modular HTML with React',
|
|
62
|
+
'',
|
|
63
|
+
'Stop repeating HTML boilerplate. Create a single Layout component:',
|
|
64
|
+
'',
|
|
65
|
+
'// src/components/Layout.tsx',
|
|
66
|
+
'import React, { ReactNode } from "react";',
|
|
67
|
+
'import { Header } from "./Header.js";',
|
|
68
|
+
'import { Footer } from "./Footer.js";',
|
|
69
|
+
'',
|
|
70
|
+
'export function Layout({ title, children }: { title: string; children: ReactNode }) {',
|
|
71
|
+
' return (',
|
|
72
|
+
' <html lang="en">',
|
|
73
|
+
' <head>',
|
|
74
|
+
' <meta charSet="UTF-8" />',
|
|
75
|
+
' <meta name="viewport" content="width=device-width, initial-scale=1.0" />',
|
|
76
|
+
' <title>{title}</title>',
|
|
77
|
+
' <link rel="stylesheet" href="/styles.css" />',
|
|
78
|
+
' </head>',
|
|
79
|
+
' <body>',
|
|
80
|
+
' <Header />',
|
|
81
|
+
' <main>{children}</main>',
|
|
82
|
+
' <Footer />',
|
|
83
|
+
' </body>',
|
|
84
|
+
' </html>',
|
|
85
|
+
' );',
|
|
86
|
+
'}',
|
|
87
|
+
'',
|
|
88
|
+
'Every page simply wraps its content in <Layout>: no copy-pasting required!'
|
|
89
|
+
]
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
id: 'islands',
|
|
93
|
+
title: '4. Reactive Islands Architecture (Auto-Discovery)',
|
|
94
|
+
summary: 'Zero-boilerplate islands: export default pure React components from *.island.tsx.',
|
|
95
|
+
content: [
|
|
96
|
+
'# 4. Reactive Islands Architecture (Auto-Discovery)',
|
|
97
|
+
'',
|
|
98
|
+
'When you need client-side state (useState, useEffect, event listeners):',
|
|
99
|
+
'',
|
|
100
|
+
'1. Simply name your file *.island.tsx (or place in islands/) and export default:',
|
|
101
|
+
'// src/components/Counter.island.tsx',
|
|
102
|
+
'import React, { useState } from "react";',
|
|
103
|
+
'',
|
|
104
|
+
'export default function Counter({ initial = 0 }) {',
|
|
105
|
+
' const [count, setCount] = useState(initial);',
|
|
106
|
+
' return (',
|
|
107
|
+
' <button onClick={() => setCount(c => c + 1)}>Count: {count}</button>',
|
|
108
|
+
' );',
|
|
109
|
+
'}',
|
|
110
|
+
'',
|
|
111
|
+
'No island() wrapping required! The engine auto-discovers and wraps it for SSR.',
|
|
112
|
+
'',
|
|
113
|
+
'2. Use it in any page just like a normal React component:',
|
|
114
|
+
'// src/pages/index.tsx',
|
|
115
|
+
'import Counter from "../components/Counter.island.js";',
|
|
116
|
+
'<Counter initial={10} />',
|
|
117
|
+
'',
|
|
118
|
+
'* HOW THE ENGINE COMPILES IT:',
|
|
119
|
+
' - Initial HTML is pre-rendered for instant paint and SEO.',
|
|
120
|
+
' - esbuild bundles ONLY Counter into dist/assets/islands/Counter.js.',
|
|
121
|
+
' - Only pages containing <Counter> will have the <script> tag injected.'
|
|
122
|
+
]
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
id: 'vanilla-islands',
|
|
126
|
+
title: '5. Pure Vanilla DOM Islands (Zero-React Client)',
|
|
127
|
+
summary: 'Compile islands to pure native DOM JavaScript with zero React/VDOM runtime.',
|
|
128
|
+
content: [
|
|
129
|
+
'# 5. Pure Vanilla DOM Islands (Zero-React Client)',
|
|
130
|
+
'',
|
|
131
|
+
'Author layouts and components with React JSX on the server, but compile to',
|
|
132
|
+
'pure native DOM JavaScript on the client with ZERO React or VDOM overhead!',
|
|
133
|
+
'',
|
|
134
|
+
'* HOW TO WRITE A VANILLA ISLAND:',
|
|
135
|
+
' In your *.island.tsx file, export both:',
|
|
136
|
+
' 1. `export default function`: React JSX markup rendered on the server.',
|
|
137
|
+
' 2. `export function client(el, props)`: Pure native DOM controller on the client.',
|
|
138
|
+
'',
|
|
139
|
+
' // src/components/VanillaCounter.island.tsx',
|
|
140
|
+
' import React from "react";',
|
|
141
|
+
'',
|
|
142
|
+
' export default function VanillaCounter({ initialCount = 0, step = 1 }) {',
|
|
143
|
+
' return (',
|
|
144
|
+
' <div className="counter-box">',
|
|
145
|
+
' <span className="counter-value">{initialCount}</span>',
|
|
146
|
+
' <button data-action="dec">- {step}</button>',
|
|
147
|
+
' <button data-action="inc">+ {step}</button>',
|
|
148
|
+
' </div>',
|
|
149
|
+
' );',
|
|
150
|
+
' }',
|
|
151
|
+
'',
|
|
152
|
+
' export function client(el: HTMLElement, props: { initialCount?: number; step?: number }) {',
|
|
153
|
+
' let count = props.initialCount || 0;',
|
|
154
|
+
' const step = props.step || 1;',
|
|
155
|
+
' const display = el.querySelector(".counter-value");',
|
|
156
|
+
' el.querySelector(\'[data-action="inc"]\')?.addEventListener("click", () => {',
|
|
157
|
+
' count += step;',
|
|
158
|
+
' if (display) display.textContent = String(count);',
|
|
159
|
+
' });',
|
|
160
|
+
' }',
|
|
161
|
+
'',
|
|
162
|
+
'* THE COMPILED OUTPUT:',
|
|
163
|
+
' - 0 KB React, 0 KB ReactDOM, 0 KB Preact (React is completely stubbed).',
|
|
164
|
+
' - Self-contained standalone bundle (~1 KB uncompressed, ~450 B gzipped).',
|
|
165
|
+
' - Zero framework chunk dependencies (no imports).',
|
|
166
|
+
' - Full support for client="load", client="idle", and client="visible".'
|
|
167
|
+
]
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
id: 'directives',
|
|
171
|
+
title: '6. Hydration Directives (Performance)',
|
|
172
|
+
summary: 'Controlling client hydration timing with load, idle, and visible.',
|
|
173
|
+
content: [
|
|
174
|
+
'# 6. Hydration Directives (Performance)',
|
|
175
|
+
'',
|
|
176
|
+
'Control when JavaScript executes on the user\'s device with the `client` prop:',
|
|
177
|
+
'',
|
|
178
|
+
'* client="load" (Default):',
|
|
179
|
+
' <Counter client="load" />',
|
|
180
|
+
' Hydrates as soon as DOMContentLoaded fires. Use for critical UI above the fold.',
|
|
181
|
+
'',
|
|
182
|
+
'* client="idle":',
|
|
183
|
+
' <Counter client="idle" />',
|
|
184
|
+
' Hydrates during browser idle time via requestIdleCallback. Perfect for widgets',
|
|
185
|
+
' or floating elements that do not block immediate interaction.',
|
|
186
|
+
'',
|
|
187
|
+
'* client="visible":',
|
|
188
|
+
' <Counter client="visible" />',
|
|
189
|
+
' Hydrates only when scrolled into the viewport using IntersectionObserver.',
|
|
190
|
+
' Ideal for carousels, comment sections, or widgets further down the page.'
|
|
191
|
+
]
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
id: 'optimization',
|
|
195
|
+
title: '7. Island Size Optimization (Code Splitting & Preact)',
|
|
196
|
+
summary: 'Multi-entry code splitting (~800 B islands) and optional Preact ultra-light mode (~24 KB).',
|
|
197
|
+
content: [
|
|
198
|
+
'# 7. Island Size Optimization',
|
|
199
|
+
'',
|
|
200
|
+
'* MULTI-ENTRY CODE SPLITTING (DEFAULT):',
|
|
201
|
+
' - react-html automatically splits shared dependencies (React, ReactDOM) into',
|
|
202
|
+
' a shared chunk (chunks/chunk-[hash].js).',
|
|
203
|
+
' - Individual island files (Counter.js, Tabs.js) drop to ~800 bytes to 1 KB each!',
|
|
204
|
+
' - The browser downloads the framework chunk once and caches it across all pages.',
|
|
205
|
+
'',
|
|
206
|
+
'* PREACT ULTRA-LIGHT MODE (--preact):',
|
|
207
|
+
' - Pass `--preact` to drop the entire framework chunk to ~24 KB uncompressed (~8 KB gzipped):',
|
|
208
|
+
' $ react-html build --preact',
|
|
209
|
+
' - Automatically aliases react and react-dom to preact/compat for hydration.',
|
|
210
|
+
' - Zero component changes needed: write standard React JSX and hooks!'
|
|
211
|
+
]
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
id: 'cli',
|
|
215
|
+
title: '8. CLI Commands & Options',
|
|
216
|
+
summary: 'Full guide for build, dev, and docs commands.',
|
|
217
|
+
content: [
|
|
218
|
+
'# 8. CLI Commands & Options',
|
|
219
|
+
'',
|
|
220
|
+
'* BUILD PRODUCTION STATIC SITE:',
|
|
221
|
+
' $ react-html build [options]',
|
|
222
|
+
' Flags:',
|
|
223
|
+
' --pages <dir> Directory containing pages (default: src/pages or pages)',
|
|
224
|
+
' --out <dir> Output directory (default: dist)',
|
|
225
|
+
' --root <dir> Root directory of the project (default: cwd)',
|
|
226
|
+
' --client-runtime <type> Island hydration runtime (react | preact, default: react)',
|
|
227
|
+
' --preact Shortcut for --client-runtime preact (ultra-light ~24 KB)',
|
|
228
|
+
' --no-minify Disable JS minification for debugging',
|
|
229
|
+
'',
|
|
230
|
+
'* START DEV SERVER (LIVE PREVIEW & WATCH):',
|
|
231
|
+
' $ react-html dev [options]',
|
|
232
|
+
' Flags:',
|
|
233
|
+
' --port <number> Port to listen on (default: 3000)',
|
|
234
|
+
' --host <string> Host to bind to (default: localhost)',
|
|
235
|
+
'',
|
|
236
|
+
'* TERMINAL UI DOCUMENTATION (TUI):',
|
|
237
|
+
' $ react-html docs # Interactive TUI navigator',
|
|
238
|
+
' $ react-html docs --all # Print entire manual to stdout',
|
|
239
|
+
' $ react-html docs <section-id> # Print specific section'
|
|
240
|
+
]
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
id: 'api',
|
|
244
|
+
title: '9. Programmatic API Reference',
|
|
245
|
+
summary: 'Using build(), renderPageToHtml(), and createDevServer() in Node.js.',
|
|
246
|
+
content: [
|
|
247
|
+
'# 9. Programmatic API Reference',
|
|
248
|
+
'',
|
|
249
|
+
'import { build, renderPageToHtml, island, Island } from "react-html";',
|
|
250
|
+
'',
|
|
251
|
+
'* build(config):',
|
|
252
|
+
' const result = await build({',
|
|
253
|
+
' root: process.cwd(),',
|
|
254
|
+
' pagesDir: "src/pages",',
|
|
255
|
+
' outDir: "dist",',
|
|
256
|
+
' minify: true,',
|
|
257
|
+
' clientRuntime: "preact" // optional ultra-light mode',
|
|
258
|
+
' });',
|
|
259
|
+
' // Returns: { pages: [...], islands: [...], outDir: string }',
|
|
260
|
+
'',
|
|
261
|
+
'* renderPageToHtml({ pagePath, Component, props, metadata }):',
|
|
262
|
+
' const { html, islands } = renderPageToHtml({',
|
|
263
|
+
' pagePath: "/path/to/page.tsx",',
|
|
264
|
+
' Component: MyPage,',
|
|
265
|
+
' metadata: { title: "Custom Title" }',
|
|
266
|
+
' });',
|
|
267
|
+
' // Returns pure HTML string and list of detected islands.'
|
|
268
|
+
]
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
id: 'server',
|
|
272
|
+
title: '10. Server App Integration (Express, Fastify, Node HTTP)',
|
|
273
|
+
summary: 'Using createEngine() for production static hosting and development live rebuilds.',
|
|
274
|
+
content: [
|
|
275
|
+
'# 10. Server App Integration (Express, Fastify, Node HTTP)',
|
|
276
|
+
'',
|
|
277
|
+
'You can import and use react-html directly inside your backend server application:',
|
|
278
|
+
'',
|
|
279
|
+
'import express from "express";',
|
|
280
|
+
'import { createEngine } from "react-html";',
|
|
281
|
+
'// or: import { createEngine } from "react-html/server";',
|
|
282
|
+
'',
|
|
283
|
+
'const app = express();',
|
|
284
|
+
'const engine = createEngine({',
|
|
285
|
+
' pagesDir: "src/pages",',
|
|
286
|
+
' distDir: "dist",',
|
|
287
|
+
' // Automatically checks process.env.NODE_ENV === "production"',
|
|
288
|
+
'});',
|
|
289
|
+
'',
|
|
290
|
+
'* 1. CONNECT / EXPRESS MIDDLEWARE:',
|
|
291
|
+
' app.use(engine.middleware);',
|
|
292
|
+
' // In production: finds and streams pre-built static HTML from dist/.',
|
|
293
|
+
' // In development: dynamically rebuilds TSX on the fly and returns fresh HTML.',
|
|
294
|
+
'',
|
|
295
|
+
'* 2. PROGRAMMATIC ROUTE RENDERING:',
|
|
296
|
+
' app.get("/custom", async (req, res) => {',
|
|
297
|
+
' const html = await engine.render("index", { user: req.user });',
|
|
298
|
+
' res.setHeader("Content-Type", "text/html; charset=utf-8");',
|
|
299
|
+
' res.send(html);',
|
|
300
|
+
' });',
|
|
301
|
+
'',
|
|
302
|
+
'* 3. NATIVE NODE HTTP SERVER:',
|
|
303
|
+
' import http from "node:http";',
|
|
304
|
+
' const server = http.createServer(engine.handle);',
|
|
305
|
+
' server.listen(3000);'
|
|
306
|
+
]
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
id: 'troubleshooting',
|
|
310
|
+
title: '11. Best Practices & Troubleshooting',
|
|
311
|
+
summary: 'Avoiding hydration mismatch, React error #418, and styling rules.',
|
|
312
|
+
content: [
|
|
313
|
+
'# 11. Best Practices & Troubleshooting',
|
|
314
|
+
'',
|
|
315
|
+
'* PREVENTING HYDRATION MISMATCH (React Error #418):',
|
|
316
|
+
' - Ensure server and initial client props match.',
|
|
317
|
+
' - Do not use client-only objects (window.innerWidth, localStorage) in initial render.',
|
|
318
|
+
' Instead, read them inside useEffect() or an event handler.',
|
|
319
|
+
' - react-html automatically protects island markup during formatting and uses',
|
|
320
|
+
' renderToString for interactive inner trees to guarantee matching text nodes.',
|
|
321
|
+
'',
|
|
322
|
+
'* ISOLATE STATEFUL LOGIC:',
|
|
323
|
+
' Keep non-interactive parts (headers, card shells, footers) pure React components.',
|
|
324
|
+
' Only place state hooks (useState, useReducer) inside *.island.tsx files.'
|
|
325
|
+
]
|
|
326
|
+
}
|
|
327
|
+
];
|
|
328
|
+
//# sourceMappingURL=docs-content.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docs-content.js","sourceRoot":"","sources":["../../src/cli/docs-content.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAWA,wBAAsB,MAAM,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CAsHlF"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { build } from '../index.js';
|
|
4
|
+
import { createDevServer } from '../server/dev-server.js';
|
|
5
|
+
import { launchDocsTui } from './tui-docs.js';
|
|
6
|
+
function formatBytes(bytes) {
|
|
7
|
+
if (bytes < 1024)
|
|
8
|
+
return `${bytes} B`;
|
|
9
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
10
|
+
}
|
|
11
|
+
export async function runCli(args = process.argv.slice(2)) {
|
|
12
|
+
const command = args[0] || 'help';
|
|
13
|
+
function getArgValue(flag) {
|
|
14
|
+
const idx = args.indexOf(flag);
|
|
15
|
+
return idx !== -1 && args[idx + 1] ? args[idx + 1] : undefined;
|
|
16
|
+
}
|
|
17
|
+
const hasFlag = (flag) => args.includes(flag);
|
|
18
|
+
if (hasFlag('--help') || hasFlag('-h') || command === 'help') {
|
|
19
|
+
console.log(`
|
|
20
|
+
react-html - Engine to convert React to pure HTML with reactive islands
|
|
21
|
+
|
|
22
|
+
Usage:
|
|
23
|
+
react-html <command> [options]
|
|
24
|
+
|
|
25
|
+
Commands:
|
|
26
|
+
build Compile pages into pure HTML & bundle reactive islands
|
|
27
|
+
dev Start live preview development server with auto-rebuild
|
|
28
|
+
docs Browse interactive documentation in Terminal UI (TUI)
|
|
29
|
+
help Show this help message
|
|
30
|
+
|
|
31
|
+
Options:
|
|
32
|
+
--pages <dir> Pages directory (default: src/pages or pages)
|
|
33
|
+
--out <dir> Output directory (default: dist)
|
|
34
|
+
--port <number> Dev server port (default: 3000)
|
|
35
|
+
--host <string> Dev server host (default: localhost)
|
|
36
|
+
--client-runtime <type> Island hydration runtime ('react' | 'preact', default: 'react')
|
|
37
|
+
--preact Shortcut for '--client-runtime preact' (ultra-light ~4 KB runtime)
|
|
38
|
+
--no-minify Disable minification for island bundles
|
|
39
|
+
--root <path> Project root directory (default: cwd)
|
|
40
|
+
|
|
41
|
+
Docs Options:
|
|
42
|
+
react-html docs Launch interactive Terminal UI
|
|
43
|
+
react-html docs --all Print complete manual to terminal
|
|
44
|
+
react-html docs <section> Print a specific section (e.g. islands, api, cli)
|
|
45
|
+
`);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (hasFlag('--version') || hasFlag('-v')) {
|
|
49
|
+
console.log(`react-html v0.1.1`);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const root = getArgValue('--root') || process.cwd();
|
|
53
|
+
const pagesDir = getArgValue('--pages');
|
|
54
|
+
const outDir = getArgValue('--out') || 'dist';
|
|
55
|
+
const minify = !hasFlag('--no-minify');
|
|
56
|
+
const clientRuntime = (hasFlag('--preact') || getArgValue('--client-runtime') === 'preact')
|
|
57
|
+
? 'preact'
|
|
58
|
+
: 'react';
|
|
59
|
+
if (command === 'build') {
|
|
60
|
+
console.log(`\nš [react-html] Building static site (${clientRuntime === 'preact' ? 'ā” Preact Ultra-Light' : 'React 19'})...`);
|
|
61
|
+
const startTime = Date.now();
|
|
62
|
+
try {
|
|
63
|
+
const result = await build({
|
|
64
|
+
root,
|
|
65
|
+
pagesDir,
|
|
66
|
+
outDir,
|
|
67
|
+
minify,
|
|
68
|
+
clientRuntime
|
|
69
|
+
});
|
|
70
|
+
console.log(`ā
[react-html] Build successful in ${Date.now() - startTime}ms`);
|
|
71
|
+
console.log(`š Pages compiled (${result.pages.length}):`);
|
|
72
|
+
result.pages.forEach(p => {
|
|
73
|
+
console.log(` - ${path.relative(root, p.output)}`);
|
|
74
|
+
});
|
|
75
|
+
if (result.islands.length > 0) {
|
|
76
|
+
console.log(`šļø Reactive islands bundled (${result.islands.length}):`);
|
|
77
|
+
for (const isl of result.islands) {
|
|
78
|
+
let sizeStr = '';
|
|
79
|
+
try {
|
|
80
|
+
const st = await fs.stat(isl);
|
|
81
|
+
sizeStr = ` (${formatBytes(st.size)})`;
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
// ignore
|
|
85
|
+
}
|
|
86
|
+
const isChunk = isl.includes('/chunks/') || isl.includes('\\chunks\\');
|
|
87
|
+
const chunkLabel = isChunk ? ' [shared chunk]' : '';
|
|
88
|
+
console.log(` - ${path.relative(root, isl)}${sizeStr}${chunkLabel}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
console.log(`⨠Pure 100% HTML generated (0 KB JavaScript overhead)`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
console.error(`ā [react-html] Build failed:`, err?.message || err);
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
else if (command === 'dev') {
|
|
101
|
+
const port = parseInt(getArgValue('--port') || '3000', 10);
|
|
102
|
+
const host = getArgValue('--host') || 'localhost';
|
|
103
|
+
try {
|
|
104
|
+
await createDevServer({
|
|
105
|
+
root,
|
|
106
|
+
pagesDir,
|
|
107
|
+
outDir,
|
|
108
|
+
port,
|
|
109
|
+
host
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
console.error(`ā [react-html] Dev server failed:`, err?.message || err);
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
else if (command === 'docs') {
|
|
118
|
+
try {
|
|
119
|
+
await launchDocsTui(args[1]);
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
console.error(`ā [react-html] Docs error:`, err?.message || err);
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
console.error(`Unknown command "${command}". Run "react-html --help" for available commands.`);
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// Direct invocation check
|
|
132
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
133
|
+
runCli();
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,SAAS,WAAW,CAAC,KAAa;IAChC,IAAI,KAAK,GAAG,IAAI;QAAE,OAAO,GAAG,KAAK,IAAI,CAAC;IACtC,OAAO,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;AAC3C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,OAAiB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACjE,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC;IAElC,SAAS,WAAW,CAAC,IAAY;QAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,OAAO,GAAG,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACjE,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAEtD,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QAC7D,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;CA0Bf,CAAC,CAAC;QACC,OAAO;IACT,CAAC;IAED,IAAI,OAAO,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QACjC,OAAO;IACT,CAAC;IAED,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACpD,MAAM,QAAQ,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC;IAC9C,MAAM,MAAM,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IACvC,MAAM,aAAa,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,WAAW,CAAC,kBAAkB,CAAC,KAAK,QAAQ,CAAC;QACzF,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,OAAO,CAAC;IAEZ,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,2CAA2C,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,UAAU,MAAM,CAAC,CAAC;QAC/H,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC;gBACzB,IAAI;gBACJ,QAAQ;gBACR,MAAM;gBACN,MAAM;gBACN,aAAa;aACd,CAAC,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,sCAAsC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,IAAI,CAAC,CAAC;YAC9E,OAAO,CAAC,GAAG,CAAC,sBAAsB,MAAM,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;YAC3D,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;gBACvB,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACvD,CAAC,CAAC,CAAC;YAEH,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9B,OAAO,CAAC,GAAG,CAAC,kCAAkC,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;gBACzE,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;oBACjC,IAAI,OAAO,GAAG,EAAE,CAAC;oBACjB,IAAI,CAAC;wBACH,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;wBAC9B,OAAO,GAAG,KAAK,WAAW,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC;oBACzC,CAAC;oBAAC,MAAM,CAAC;wBACP,SAAS;oBACX,CAAC;oBACD,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;oBACvE,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC;oBACpD,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,GAAG,OAAO,GAAG,UAAU,EAAE,CAAC,CAAC;gBACzE,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAC;YACvE,CAAC;QACH,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,GAAG,EAAE,OAAO,IAAI,GAAG,CAAC,CAAC;YACnE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;SAAM,IAAI,OAAO,KAAK,KAAK,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,QAAQ,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;QAC3D,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,IAAI,WAAW,CAAC;QAClD,IAAI,CAAC;YACH,MAAM,eAAe,CAAC;gBACpB,IAAI;gBACJ,QAAQ;gBACR,MAAM;gBACN,IAAI;gBACJ,IAAI;aACL,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,GAAG,EAAE,OAAO,IAAI,GAAG,CAAC,CAAC;YACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;SAAM,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,GAAG,EAAE,OAAO,IAAI,GAAG,CAAC,CAAC;YACjE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,oBAAoB,OAAO,oDAAoD,CAAC,CAAC;QAC/F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,0BAA0B;AAC1B,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,UAAU,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IACpD,MAAM,EAAE,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { DocSection } from './docs-content.js';
|
|
2
|
+
export declare function printSectionDirect(section: DocSection): void;
|
|
3
|
+
export declare function printAllDocs(): void;
|
|
4
|
+
export declare function launchDocsTui(initialArg?: string): Promise<void>;
|
|
5
|
+
//# sourceMappingURL=tui-docs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui-docs.d.ts","sourceRoot":"","sources":["../../src/cli/tui-docs.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAgC7D,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,CAM5D;AAED,wBAAgB,YAAY,IAAI,IAAI,CAQnC;AAED,wBAAsB,aAAa,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiKtE"}
|