From 3767588f37e3e80d0febe54c12ab7c8fe87db73b Mon Sep 17 00:00:00 2001 From: shitianfang <61344989+shitianfang@users.noreply.github.com> Date: Fri, 26 Sep 2025 19:42:10 +0000 Subject: [PATCH 1/7] add zero-build --- README.md | 135 ++++++++++++++++++ apps/examples/documents/templates/Invoice.tsx | 2 +- dev-workflow.js | 64 +++++++++ dev.sh | 53 +++++++ package.json | 1 + 5 files changed, 254 insertions(+), 1 deletion(-) create mode 100644 dev-workflow.js create mode 100755 dev.sh diff --git a/README.md b/README.md index 98e74ef..d9a52f1 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,9 @@ htmldocs is a local document editor and preview server to help you _create_ PDFs - 🔗 Full TypeScript support for type safety - ⚡ Dynamic data integration through props and APIs - 📊 Real-time preview server with hot reloading +- 🚀 **Zero-build development** - modify templates and see changes instantly +- 🏗️ **Monorepo architecture** with pnpm workspaces and Turbo +- 🔄 **Workspace dependencies** - automatic linking between packages ## Example @@ -60,6 +63,76 @@ npx htmldocs@latest init For further instructions or to integrate htmldocs into your existing project, refer to the [Getting Started](https://docs.htmldocs.com/getting-started) guide. +## Development Workflow + +htmldocs supports a **zero-build development experience** for rapid template iteration. You can modify template files and see changes instantly without any build step. + +### One-Click Development + +For the fastest setup, use our development script: + +```bash +# Start zero-build development (from project root) +./dev.sh + +# Or using npm/pnpm script +pnpm dev:zero-build +``` + +This script will: +- ✅ Install tsx if needed +- ✅ Build core dependencies (one-time) +- ✅ Start development server with hot reload +- ✅ Open examples at http://localhost:3000 + +### Manual Setup + +```bash +# 1. Install dependencies +pnpm install + +# 2. Build core dependencies (one-time only) +cd packages/react && pnpm build +cd ../render && pnpm build + +# 3. Install TypeScript runner +npm install -g tsx + +# 4. Start zero-build development +cd packages/htmldocs +tsx src/cli/index.ts dev --dir ../../apps/examples/documents +``` + +### What You Can Edit Without Building + +- ✅ **Template files** (`*.tsx` documents) - hot reload enabled +- ✅ **Next.js app** (`packages/htmldocs/src/app/*`) - hot reload enabled +- ✅ **CLI logic** (`packages/htmldocs/src/cli/*`) - restart to see changes +- ✅ **Styles** (CSS, Tailwind) - hot reload enabled + +### What Requires Building + +- ⚠️ **React components** (`packages/react/`) - run `pnpm build` after changes +- ⚠️ **Render engine** (`packages/render/`) - run `pnpm build` after changes + +### Development Commands + +```bash +# Start development with hot reload +tsx src/cli/index.ts dev --dir ../../apps/examples/documents + +# Build core packages when needed +pnpm build + +# Run tests +pnpm test + +# Format code +pnpm format +``` + +This workflow enables you to modify templates and see changes instantly in your browser, providing a smooth development experience similar to modern web frameworks. + ## Components htmldocs comes with a standard set of components to help you layout and style your documents. @@ -99,6 +172,68 @@ htmldocs also uses the [Paged.js library](https://pagedjs.org/) under the hood. |--------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------| | Next.js | TypeScript | Turborepo | pnpm | +## Monorepo Architecture + +This project uses a monorepo structure with pnpm workspaces and Turbo for efficient development: + +``` +├── packages/ +│ ├── htmldocs/ # Main CLI and Next.js app +│ ├── react/ # React components (@htmldocs/react) +│ ├── render/ # PDF rendering engine (@htmldocs/render) +│ ├── eslint-config/ # Shared ESLint configuration +│ └── typescript-config/ # Shared TypeScript configuration +├── apps/ +│ ├── examples/ # Example templates and documents +│ └── docs/ # Documentation site +``` + +### Package Dependencies + +- `htmldocs` → depends on `@htmldocs/render` +- `examples` → depends on `htmldocs`, `@htmldocs/react`, `@htmldocs/render` +- All packages → share `@htmldocs/eslint-config` and `@htmldocs/typescript-config` + +The monorepo uses `workspace:*` protocol for internal dependencies, enabling seamless development across packages with automatic linking. + +## Contributing + +We welcome contributions! Here's how to get started: + +### Development Environment + +1. **Clone and setup**: + ```bash + git clone https://github.com/htmldocs-js/htmldocs.git + cd htmldocs + pnpm install + ``` + +2. **Start development**: + ```bash + ./dev.sh + ``` + +3. **Make changes** to templates in `apps/examples/documents/templates/` + +4. **See changes instantly** in your browser with hot reload + +### Common Tasks + +- **Add new templates**: Create `.tsx` files in `apps/examples/documents/templates/` +- **Modify components**: Edit `packages/react/components/` (requires `pnpm build`) +- **Update CLI**: Edit `packages/htmldocs/src/cli/` (restart dev server) +- **Fix rendering**: Edit `packages/render/src/` (requires `pnpm build`) + +### Testing + +```bash +pnpm test # Run all tests +pnpm test:coverage # Run tests with coverage +pnpm lint # Check code style +pnpm format # Format code +``` + ## License MIT License diff --git a/apps/examples/documents/templates/Invoice.tsx b/apps/examples/documents/templates/Invoice.tsx index 21e2b6c..315e2d2 100644 --- a/apps/examples/documents/templates/Invoice.tsx +++ b/apps/examples/documents/templates/Invoice.tsx @@ -84,7 +84,7 @@ function Invoice({ billedTo, yourCompany, services }: InvoiceProps) { className="flex flex-row items-center justify-between" >
-
Invoice
+
🚀 开发中 Invoice

#AB2324-01

diff --git a/dev-workflow.js b/dev-workflow.js new file mode 100644 index 0000000..c5d9f9a --- /dev/null +++ b/dev-workflow.js @@ -0,0 +1,64 @@ +#!/usr/bin/env node + +/** + * HTMLDocs 零构建开发工作流程 + * + * 直接运行 TypeScript 源码,无需预先构建 + * 使用方法: + * node dev-workflow.js dev + * node dev-workflow.js dev --dir ./my-templates + */ + +import { spawn } from 'child_process'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +// CLI 源码路径 +const cliSourcePath = path.join(__dirname, 'packages/htmldocs/src/cli/index.ts'); + +// 检查是否安装了 tsx +let useNodeLoader = true; +try { + const { execSync } = await import('child_process'); + execSync('tsx --version', { stdio: 'ignore' }); + useNodeLoader = false; +} catch (e) { + // tsx 未安装,使用 Node.js --loader +} + +// 构建参数 +const args = useNodeLoader + ? [ + '--loader', '@esbuild-kit/esm-loader', + cliSourcePath, + ...process.argv.slice(2) + ] + : [ + cliSourcePath, + ...process.argv.slice(2) + ]; + +const command = useNodeLoader ? 'node' : 'tsx'; + +// 设置开发环境变量 +const env = { + ...process.env, + NODE_ENV: 'development' +}; + +console.log('🚀 Starting HTMLDocs CLI in development mode...'); +console.log('📁 Running source:', cliSourcePath); +console.log('🔧 Command:', command, args.join(' ')); + +const child = spawn(command, args, { + stdio: 'inherit', + env, + cwd: path.join(__dirname, 'packages/htmldocs') +}); + +child.on('exit', (code) => { + process.exit(code || 0); +}); \ No newline at end of file diff --git a/dev.sh b/dev.sh new file mode 100755 index 0000000..bb43d97 --- /dev/null +++ b/dev.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +# HTMLDocs 零构建开发工作流程 +# 直接从源码运行,无需预先构建 + +set -e # 遇到错误时退出 + +echo "🚀 HTMLDocs 零构建开发模式" +echo "================================" +echo + +# 确保在正确的目录 +if [[ ! -f "pnpm-workspace.yaml" ]]; then + echo "❌ 请在项目根目录运行此脚本" + exit 1 +fi + +# 确保安装了 tsx +if ! command -v tsx &> /dev/null; then + echo "📦 安装 tsx (TypeScript 运行器)..." + npm install -g tsx + echo +fi + +# 构建依赖的包(仅一次性需要) +echo "🔧 检查并构建依赖包..." +cd packages/react +if [[ ! -d dist ]]; then + echo " 📦 构建 @htmldocs/react..." + pnpm build +fi + +cd ../render +if [[ ! -d dist ]]; then + echo " 📦 构建 @htmldocs/render..." + pnpm build +fi + +cd ../htmldocs +echo + +echo "🌟 启动零构建开发服务器..." +echo " 📁 模板目录: ../../apps/examples/documents" +echo " 🌐 预览地址: http://localhost:3000 (或下一个可用端口)" +echo " 🔥 热重载: 模板文件修改后自动刷新" +echo " 📝 编辑文件: apps/examples/documents/templates/*.tsx" +echo +echo "按 Ctrl+C 停止服务器" +echo "================================" +echo + +# 直接运行 TypeScript 源码 +tsx src/cli/index.ts dev --dir ../../apps/examples/documents \ No newline at end of file diff --git a/package.json b/package.json index 34074e1..3729278 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "scripts": { "build": "turbo run build --filter=./packages/* --filter=!htmldocs-starter", "dev": "turbo dev", + "dev:zero-build": "./dev.sh", "lint": "turbo lint", "format": "prettier --write \"**/*.{ts,tsx,md}\"", "version": "changeset version && pnpm install --no-frozen-lockfile", From 974b3836725d6e86454eb1d86f5c79eed459b297 Mon Sep 17 00:00:00 2001 From: shitianfang <61344989+shitianfang@users.noreply.github.com> Date: Fri, 26 Sep 2025 20:12:54 +0000 Subject: [PATCH 2/7] Initial commit From b20bb71bc7540064420f73f987ac0e7b929bf081 Mon Sep 17 00:00:00 2001 From: shitianfang <61344989+shitianfang@users.noreply.github.com> Date: Fri, 26 Sep 2025 21:18:53 +0000 Subject: [PATCH 3/7] fixed dev dir --- dev.sh | 62 +++++++++++++++++++---- packages/htmldocs/src/cli/commands/dev.ts | 18 +++++++ 2 files changed, 70 insertions(+), 10 deletions(-) diff --git a/dev.sh b/dev.sh index bb43d97..84eee93 100755 --- a/dev.sh +++ b/dev.sh @@ -5,16 +5,37 @@ set -e # 遇到错误时退出 +# 获取脚本所在的绝对路径 +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$SCRIPT_DIR" + echo "🚀 HTMLDocs 零构建开发模式" echo "================================" +echo "📁 项目根目录: $PROJECT_ROOT" echo # 确保在正确的目录 -if [[ ! -f "pnpm-workspace.yaml" ]]; then - echo "❌ 请在项目根目录运行此脚本" +if [[ ! -f "$PROJECT_ROOT/pnpm-workspace.yaml" ]]; then + echo "❌ 未找到 pnpm-workspace.yaml,请确保在项目根目录运行此脚本" exit 1 fi +# 定义关键路径 +PACKAGES_DIR="$PROJECT_ROOT/packages" +REACT_PKG_DIR="$PACKAGES_DIR/react" +RENDER_PKG_DIR="$PACKAGES_DIR/render" +HTMLDOCS_PKG_DIR="$PACKAGES_DIR/htmldocs" +EXAMPLES_DIR="$PROJECT_ROOT/apps/examples" +DOCUMENTS_DIR="$EXAMPLES_DIR/documents" + +# 验证关键目录存在 +for dir in "$PACKAGES_DIR" "$REACT_PKG_DIR" "$RENDER_PKG_DIR" "$HTMLDOCS_PKG_DIR" "$EXAMPLES_DIR" "$DOCUMENTS_DIR"; do + if [[ ! -d "$dir" ]]; then + echo "❌ 目录不存在: $dir" + exit 1 + fi +done + # 确保安装了 tsx if ! command -v tsx &> /dev/null; then echo "📦 安装 tsx (TypeScript 运行器)..." @@ -22,32 +43,53 @@ if ! command -v tsx &> /dev/null; then echo fi +# 保存当前目录,用于后续恢复 +ORIGINAL_DIR="$(pwd)" + +# 错误处理函数 +cleanup() { + echo "🧹 清理并返回原始目录..." + cd "$ORIGINAL_DIR" +} + +# 设置退出时的清理 +trap cleanup EXIT + # 构建依赖的包(仅一次性需要) echo "🔧 检查并构建依赖包..." -cd packages/react + +# 构建 React 包 +cd "$REACT_PKG_DIR" if [[ ! -d dist ]]; then echo " 📦 构建 @htmldocs/react..." pnpm build +else + echo " ✅ @htmldocs/react 已构建" fi -cd ../render +# 构建 Render 包 +cd "$RENDER_PKG_DIR" if [[ ! -d dist ]]; then - echo " 📦 构建 @htmldocs/render..." + echo " 📦 构建 @htmldocs/render..." pnpm build +else + echo " ✅ @htmldocs/render 已构建" fi -cd ../htmldocs echo echo "🌟 启动零构建开发服务器..." -echo " 📁 模板目录: ../../apps/examples/documents" +echo " 📁 模板目录: $DOCUMENTS_DIR" echo " 🌐 预览地址: http://localhost:3000 (或下一个可用端口)" echo " 🔥 热重载: 模板文件修改后自动刷新" -echo " 📝 编辑文件: apps/examples/documents/templates/*.tsx" +echo " 📝 编辑文件: $DOCUMENTS_DIR/templates/*.tsx" echo echo "按 Ctrl+C 停止服务器" echo "================================" echo -# 直接运行 TypeScript 源码 -tsx src/cli/index.ts dev --dir ../../apps/examples/documents \ No newline at end of file +# 切换到 htmldocs 包目录以确保路径解析正确 +cd "$HTMLDOCS_PKG_DIR" + +# 直接运行 TypeScript 源码,指向正确的文档目录 +tsx src/cli/index.ts dev --dir "$DOCUMENTS_DIR" \ No newline at end of file diff --git a/packages/htmldocs/src/cli/commands/dev.ts b/packages/htmldocs/src/cli/commands/dev.ts index 1534aeb..b50d066 100644 --- a/packages/htmldocs/src/cli/commands/dev.ts +++ b/packages/htmldocs/src/cli/commands/dev.ts @@ -1,5 +1,7 @@ import fs from 'node:fs'; +import path from 'node:path'; import { startDevServer, setupHotreloading } from '../utils'; +import { getEnvVariablesForPreviewApp } from '../utils/preview/get-env-variables-for-preview-app'; import logger from '~/lib/logger'; interface Args { @@ -8,12 +10,28 @@ interface Args { } export const dev = async ({ dir: documentsDirRelativePath, port }: Args) => { + + console.log("路径地址:", documentsDirRelativePath); + try { if (!fs.existsSync(documentsDirRelativePath)) { logger.error(`Missing ${documentsDirRelativePath} folder`); throw new Error(`Missing ${documentsDirRelativePath} folder`); } + // 动态更新环境变量以使用正确的文档目录路径 + const documentsDir = path.resolve(documentsDirRelativePath); + const envVars = getEnvVariablesForPreviewApp( + path.relative(process.cwd(), documentsDir), + process.env.NEXT_PUBLIC_CLI_PACKAGE_LOCATION!, + process.cwd() + ); + + // 更新环境变量 + Object.assign(process.env, envVars); + + logger.debug(`Documents directory absolute path: ${envVars.DOCUMENTS_DIR_ABSOLUTE_PATH}`); + logger.debug(`Starting dev server for ${documentsDirRelativePath} on port ${port}`); const devServer = await startDevServer( documentsDirRelativePath, From b20d80f8f0ffd08e599e172c532afa5bb29359f8 Mon Sep 17 00:00:00 2001 From: shitianfang <61344989+shitianfang@users.noreply.github.com> Date: Fri, 26 Sep 2025 21:46:06 +0000 Subject: [PATCH 4/7] add single page --- apps/examples/documents/templates/Index.tsx | 88 ++++++++++++++++++ package.json | 2 +- .../htmldocs/src/app/components/shell.tsx | 2 +- packages/htmldocs/src/app/page.tsx | 70 +++++++++++---- .../src/app/preview/[...slug]/preview.tsx | 90 ++++++++++++++----- packages/htmldocs/src/cli/commands/dev.ts | 7 +- .../hot-reloading/setup-hot-reloading.ts | 36 +++++++- 7 files changed, 248 insertions(+), 47 deletions(-) create mode 100644 apps/examples/documents/templates/Index.tsx diff --git a/apps/examples/documents/templates/Index.tsx b/apps/examples/documents/templates/Index.tsx new file mode 100644 index 0000000..bf6cd9d --- /dev/null +++ b/apps/examples/documents/templates/Index.tsx @@ -0,0 +1,88 @@ +import { Document, Head, Page, Footer } from '@htmldocs/react'; +import * as React from 'react'; + +export default function Index() { + return ( + + + My Document + + + + +
+
+

Welcome to HTMLDocs 666 98623

+

Single File Mode

+
+ +
+

+ This is your Index.tsx file. Edit this file to see changes in real-time! +

+ +
+

📝 Note: This application now only monitors changes to this Index.tsx file. + All other UI elements have been simplified for a clean, focused experience.

+
+ +

Features:

+
    +
  • ✅ Single file monitoring
  • +
  • ✅ Clean, minimal UI
  • +
  • ✅ Hot reload for Index.tsx only
  • +
  • ✅ Direct rendering without navigation
  • +
+ +

+ Try editing this file to see the hot reload in action! The changes will appear + instantly without any need to refresh the page. +

+
+
+
+
+ ); +} \ No newline at end of file diff --git a/package.json b/package.json index 3729278..8b5cfe6 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "scripts": { "build": "turbo run build --filter=./packages/* --filter=!htmldocs-starter", "dev": "turbo dev", - "dev:zero-build": "./dev.sh", + "div": "./dev.sh", "lint": "turbo lint", "format": "prettier --write \"**/*.{ts,tsx,md}\"", "version": "changeset version && pnpm install --no-frozen-lockfile", diff --git a/packages/htmldocs/src/app/components/shell.tsx b/packages/htmldocs/src/app/components/shell.tsx index bad1a83..12adf3a 100644 --- a/packages/htmldocs/src/app/components/shell.tsx +++ b/packages/htmldocs/src/app/components/shell.tsx @@ -35,7 +35,7 @@ export const Shell = ({
- + 123