From ac65b75c7384fc38391c728594b76f8b13cb7d8f Mon Sep 17 00:00:00 2001 From: ZhangAo Date: Thu, 8 Oct 2026 11:34:12 +0800 Subject: [PATCH] chore: sync --- code/g3soft-libs/CODEBUDDY.md | 113 +++++++++++++++++++++++++ code/g3soft-libs/README.md | 10 +-- code/g3soft-libs/docs/content/index.md | 6 +- code/g3soft-libs/docs/nuxt.config.ts | 9 +- code/g3soft-libs/docs/package.json | 2 +- code/g3soft-libs/docs/scripts/dev.mjs | 49 +++++++++++ 6 files changed, 179 insertions(+), 10 deletions(-) create mode 100644 code/g3soft-libs/CODEBUDDY.md create mode 100644 code/g3soft-libs/docs/scripts/dev.mjs diff --git a/code/g3soft-libs/CODEBUDDY.md b/code/g3soft-libs/CODEBUDDY.md new file mode 100644 index 00000000..4247b091 --- /dev/null +++ b/code/g3soft-libs/CODEBUDDY.md @@ -0,0 +1,113 @@ +# CODEBUDDY.md + +This file provides guidance to CodeBuddy Code when working with code in this repository. + +## Overview + +G3Soft frontend infrastructure — a pnpm monorepo holding a self-built **Vue 3 component library** plus a **Docus documentation site**. + +- `packages/ui` (`@g3soft/ui`) — component library, published to a private npm registry. One directory per component under `src//`. +- `packages/tokens` (`@g3soft/tokens`) — design tokens as plain CSS (`--g3-*` variables), shared by the library and the docs site. +- `docs` (`@g3soft/docs`) — Docus/Nuxt docs site. `private: true`, never published. +- `scripts/gen-api.mjs` — generates component API data from source. + +Requires Node >= 20.19 and pnpm 11 (see `packageManager` in root `package.json`). + +## Commands + +```bash +pnpm install + +pnpm dev # start docs site (http://localhost:3000); live-reloads packages/ui via alias +pnpm build # build all packages under packages/** (component lib -> dist) +pnpm build:docs # build docs static site -> docs/.output/public +pnpm preview:docs # preview the built docs site + +pnpm gen:api # regenerate docs/data/api/*.json from component source (REQUIRED after changing props/events/slots) +``` + +Deploying docs to a subpath: + +```bash +NUXT_APP_BASE_URL=/docs/ pnpm build:docs +``` + +Releasing the component library (changesets): + +```bash +pnpm changeset # record the change +pnpm version # bump versions + generate CHANGELOG +pnpm release # build + publish to the private registry +``` + +`packages/ui` runs `publint` via `prepublishOnly` to validate package structure (`exports`/`files` consistency). + +**Testing:** there is no test runner configured in this repo (no vitest/jest, no test files). Do not assume `pnpm test` exists. + +### Running a single component's checks + +There is no per-component test/lint script. The closest equivalent is `pnpm --filter @g3soft/ui build` (runs `vite build`, which type-checks declarations via `vite-plugin-dts`), and `pnpm gen:api` to verify the docgen extraction still parses a component. + +## Architecture + +### Two independent pipelines + +The docs site and the component library are deliberately decoupled: + +| | Docs site | Component package | +|---|---|---| +| Published | No (`private: true`) | Yes (private npm registry) | +| Versioning | None | changesets (`ignore: ["@g3soft/docs"]`) | +| Build | `pnpm build:docs` | `pnpm build` | +| Output | `docs/.output/public` (static) | `packages/ui/dist` (ESM + d.ts) | +| Dep boundary | Docus/Nuxt/Tailwind live only in the `docs` package | only `vue` (peer) + `@g3soft/tokens` | + +Nuxt-related deps appear **only** in `docs/package.json`; the library's dependency tree has none of it. changesets' `ignore` keeps the docs site out of version tags. + +### Component library build (`packages/ui`) + +`vite.config.ts` builds ESM + type declarations. Critical points: +- `vue` is marked `external` — never bundle Vue, or consumers get duplicate instances. +- `preserveModules` keeps the `src` structure so consumers can tree-shake. +- `vite-plugin-dts` with `rollupTypes` emits a single `dist/index.d.ts`, matched by `exports.types`. +- `src/index.ts` is the public entry: it re-exports every component plus its types, and exports the optional `G3UI` install plugin for whole-library registration. + +### Docs site (`docs`) + +- `extends: ['docus']` — all navigation/search/theme comes from the Docus Nuxt Layer. +- `vite.resolve.alias` points `@g3soft/ui` and `@g3soft/tokens` **directly at `packages/*/src`**, so the docs site can develop against the library without building it. Editing `packages/ui` hot-reloads the docs immediately. +- `site.url` is required (sitemap, llms.txt, OG images) — missing it breaks prerender with a 500. +- Deploy base path comes from `NUXT_APP_BASE_URL` (Nuxt's env override for `app.baseURL`), never hardcoded. +- `docs/app/components/content/` holds components usable directly inside Markdown: `Demo.vue` (renders a runnable example + source) and `ApiTable.vue` (renders the generated API tables). + +### API generation pipeline + +`scripts/gen-api.mjs` uses `vue-docgen-api` to parse every `.vue` under `packages/ui/src`, extracts props/events/slots and their JSDoc comments, and writes `docs/data/api/.json`. `ApiTable.vue` reads those JSON files by component name. + +Consequence: **API tables are generated from source and must never be hand-written.** The component directory name is the doc key (`src/button/Button.vue` → `button`). After any change to a component's props/events/slots, run `pnpm gen:api`. + +### Design tokens (`packages/tokens`) + +- `src/index.css` imports `tokens.css` (light/default) and `dark.css`. Consumed as `import '@g3soft/tokens'`. +- Dark theme activates via `html[data-g3-theme='dark']` (`document.documentElement.dataset.g3Theme = 'dark'`). +- Re-theming/customer customization = overriding same-named `--g3-*` variables, no component changes. + +### Windows: dev-server port selection + +`docs/package.json` runs `node scripts/dev.mjs` for `dev` (not `nuxt dev` directly). On Windows, Node sets `SO_REUSEADDR`, so **two processes can bind the same `host:port`**. Nuxt's built-in "is the port free?" check works by *trying to bind* a probe socket — which therefore succeeds even when another service already listens on 3000, so `pnpm dev` silently lands on 3000 (no 3000→3001 fallback). `scripts/dev.mjs` sidesteps this by testing the port with a real TCP *connection* (`connect` to `127.0.0.1`/`::1`) and walking upward from `DOCS_PORT`/`PORT`/3000 until it finds a free one, then passing `--port`. `devServer.host: ''` (empty string — deliberately not `'0.0.0.0'`) makes listhen listen on all interfaces *and* print a usable `Local: http://localhost:/` plus the LAN `Network:` URL; with `'0.0.0.0'` the Local line would be an unopenable `http://0.0.0.0:/`. + +## Conventions (must follow) + +- **No `scoped` in component `