Commit Graph

51 Commits

Author SHA1 Message Date
袁章洪 6eac1cb656 fix(api-reference): cast markdown-it-container plugin type for astro check
@types/markdown-it-container targets a different @types/markdown-it build, so
its plugin signature doesn't unify with our MarkdownIt instance — astro check
(tsc) failed. Cast it to the expected use() parameter type.
2026-09-14 16:37:21 +08:00
袁章洪 22a9257279 feat(api): path-based endpoint URLs (/docs/api/<op>)
Make /docs/api/<operationId> the canonical shareable URL for an endpoint
(previously only /docs/api?op=<id> worked). The React app now reads the op from
the pathname (query ?op= kept as a fallback for old links) and pushes path URLs
on navigation. Add prerendered [op].astro routes (en + zh-CN/zh-HK) so direct
load, refresh, and sharing of /docs/api/<op> resolve — rendering the same
interactive reference, with the endpoint summary in the page title.
2026-09-14 15:45:40 +08:00
袁章洪 88fe062d22 docs(api): render :::admonitions as docs-style callout boxes
Region warnings, tips, etc. were rendering as plain blockquotes in the
reference. Convert them back to ::: container syntax in the descriptions and
add a markdown-it-container plugin that emits the same DOM as the docs
remark-callout (.callout.callout-<type> + .callout-title), with the docs
callout.css copied into the package. Now :::warning/:::tip render as the same
colored boxes as docs; the .md keeps readable ::: blocks for AI consumers.
2026-09-14 11:44:08 +08:00
袁章洪 dd5fba5292 docs(api): style QuotePermission card to match docs
The reference's QuotePermission was rendering unstyled (plain text, no green
box / shield icon / badge pill) because its class names had no CSS and it only
supported 'command' (level-only watchlist ops rendered nothing). Port it 1:1
from the docs MDX component: shield icon, data-level color theming, market tag,
description, footer link + note; resolve command/level/market. Copy the docs
QuotePermission.css into the package and load it via api-reference.css.
2026-09-14 11:35:36 +08:00
袁章洪 ba609b634a docs(api): 3-level sidebar mirroring docs (section > subsection > endpoint)
Add x-subgroup (docs subsection) to every op and x-subgroups (ordered
subsection labels, trilingual) to each tag, so the reference sidebar nests
like the docs menu: e.g. 行情 > 个股行情/期权/数据分析/自选股, 交易 >
订单/网格交易/成交/资产. Screener stays flat (no docs subsections).

- Loader: SubGroup type; parseSpec partitions each tag's endpoints into
  ordered subgroups (by op x-subgroup, ordered per tag x-subgroups) plus
  leftover flat endpoints.
- ApiReference: nested collapsible subgroup level in the sidebar.
- openapi-markdown: render ## section > ### subsection > #### endpoint;
  fix endpointList / endpointMarkdownById to include subgroup endpoints
  (they previously only walked flat endpoints, 404-ing per-endpoint .md).
2026-09-14 11:30:19 +08:00
袁章洪 c6a6abaf0b docs(api): carry special docs markers (quote permission, region warnings) into reference
Audited all 116 backing-page ops for special markers. Fixes:
- QuotePermission: render x-quote-command/level/market as a callout in BOTH
  the CSR page and the AI markdown (openapi-markdown resolves
  quote-permissions.yaml). Convert the 4 watchlist ops' leaked
  '<QuotePermission level="basic" />' raw tags to x-quote-level: basic.
- Convert 2 topics ops' leaked '<TipContainer>' tags to blockquotes.
- Restore 3 admonitions dropped by the description cut / descOverride:
  dca_toggle (US-account region warning), grid_trigger_history (uses
  grid_order_id not order_id), ai_conversation (how to find an Agent UID).
- Loader: add x-quote-level / x-quote-market. CSR: pass level+market to
  <QuotePermission>, render when any of command/level/market is set.
2026-09-14 10:34:23 +08:00
袁章洪 fa27c69ec1 docs(api): fix AI-consumption issues from review
- Correct 5 endpoints' request params to true HTTP wire names (Rust does
  client-side transforms): screener/search body (filters/returns/page/size),
  broker-holding (add type), broker-holding/daily (parti_number),
  ahpremium/klines (line_type/line_num), finance_calendar (date/date_end/
  types[]/markets[]); fix finance_calendar response type wire name.
- Make POST examples executable: include full body (not just required) with
  type-aware placeholders (arrays/ints/objects), so top_movers etc. no longer
  emit an empty POST.
- Disambiguate duplicate summaries: short_positions/short_trades hk vs us now
  carry market-specific titles.
- Strip embedded leading headings from descriptions (removes duplicate H1).
- Renderer: drop page-body heading that repeats the page title (fixes the
  doubled '## Error Codes' in the aggregated api.md).
2026-09-14 10:16:01 +08:00
袁章洪 60745f7c32 feat(api-reference): AI-readable markdown — /docs/api.md, /docs/api/<op>.md (3 locales) from openapi.yaml; wire into llms.txt/llms-full.txt 2026-09-11 16:24:17 +08:00
袁章洪 bac1f434b7 style(api-reference): pin DocFooter to the bottom on short pages (flex-fill docs-inner) 2026-09-11 16:08:22 +08:00
袁章洪 e25bab222e feat(api-reference): copy button on x-page markdown code blocks 2026-09-11 11:35:18 +08:00
袁章洪 f66865bf80 style(api-reference): syntax-highlight x-page code blocks (github-light), guard against double H1 title 2026-09-11 10:50:36 +08:00
袁章洪 8674bb47ba style(api-reference): style x-page markdown code blocks as light code cards (match CodeTabs/Response JSON card) 2026-09-11 10:18:24 +08:00
袁章洪 44765e5a9c style(api-reference): render x-pages with a title h1 and native docs-content typography (match endpoint page style) 2026-09-11 10:06:17 +08:00
袁章洪 3737b53a56 style(api-reference): align page-item icons to the method-badge column width so all sidebar text lines up 2026-09-10 19:28:09 +08:00
袁章洪 aa3bba9fd2 feat(api-reference): 7-language API-Key signing helpers as CodeTabs on Authentication page (cURL/Python/Node/Java/Rust/C++/Go) 2026-09-10 17:04:25 +08:00
袁章洪 87d2d7ecb9 feat(api-reference): request examples default to OAuth Bearer; add per-language API-Key signing helpers to Authentication page; link endpoints to it 2026-09-10 16:58:14 +08:00
袁章洪 eb29bd5616 fix(api-reference): unique row keys + dedupe response fields — fixes stale rows leaking across endpoints on CSR navigation 2026-09-10 16:49:33 +08:00
袁章洪 2c3fd1afa2 style(api-reference): remove inline-code background on field-name cells in param/response tables (match docs) 2026-09-10 16:14:04 +08:00
袁章洪 87e00ea247 style(api-reference): fixed-width, subtler sidebar method badges so items align and match the docs sidebar 2026-09-10 16:11:30 +08:00
袁章洪 546d1a7ee2 feat(api-reference): split params into Path/Query/Request Body with real HTTP wire field names; drop 'SDK method parameters' note; regenerate DCA (wire request) 2026-09-10 15:53:38 +08:00
袁章洪 71e2f4ee98 feat(api-reference): add docs breadcrumb + slim DocFooter (in .docs-inner), suppress big marketing footer — full docs parity 2026-09-10 15:31:40 +08:00
袁章洪 b4ae113c18 refactor(api-reference): render endpoint pages with the docs DOM structure (docs-layout/sidebar/docs-body/docs-inner/docs-main/article.docs-content/docs-toc) so HTML + styling match docs exactly 2026-09-10 15:24:29 +08:00
袁章洪 85c9c8c2cd feat(api-reference): rebuild sidebar to match docs structure/style (bare page group, dividers, collapsible tag sections with caret, rounded brand highlight) 2026-09-10 15:11:34 +08:00
袁章洪 381b844fb2 fix(api-reference): center docs-model layout (margin auto like docs .docs-inner) 2026-09-10 14:57:52 +08:00
袁章洪 be3cea2bff feat(api-reference): reuse docs CliCommand card for parity; widen docs-model layout to 80rem/14rem to match docs 2026-09-10 13:56:10 +08:00
袁章洪 73490b7e31 fix(api-reference): correct auth (App Key/Secret/Access Token + HMAC signature) in raw-HTTP examples, add Authentication page, fix code highlighter corrupting URLs 2026-09-10 13:47:46 +08:00
袁章洪 a3fe260b07 fix(api-reference): cap docs-model endpoint layout width (content + TOC) so it is not full-bleed 2026-09-10 13:39:57 +08:00
袁章洪 8990e4f8a5 feat(api-reference): full docs-mirror endpoint pages (Request/Parameters/Request Example tabs, Response Properties, Response JSON, Error Code, On-this-page TOC, light code); regenerate DCA 2026-09-10 12:04:58 +08:00
袁章洪 c6eb762787 feat(api-reference): single-column docs-style endpoint detail with parameter tables 2026-09-10 11:46:10 +08:00
袁章洪 494ff0a594 feat(api-reference): docs-mirror endpoint detail (Parameters table, CLI block, raw-HTTP request); regenerate DCA 2026-09-10 11:29:41 +08:00
袁章洪 2d6f28b359 test(api-reference): add openapi.yaml invariants; add tag taxonomy + zh-HK summaries 2026-09-10 10:48:39 +08:00
袁章洪 46d4c2f457 feat(api-reference): wire zh-HK locale, websocket detail, full description render 2026-09-10 10:45:44 +08:00
袁章洪 60b798bb8f feat(api-reference): add pickLocale + zh-HK fields and websocket parsing to loader 2026-09-10 10:43:57 +08:00
twosugar 2843b64766 fix: 补 @types/markdown-it 依赖 2026-08-28 17:26:28 +08:00
twosugar 43a386ca92 chore(lint): 引入 oxlint 并清理未使用代码
新增 oxlint@1.80.0 + .oxlintrc.json + lint/lint:fix 脚本;清空所有
no-unused-vars 告警(未用 React/导入/变量/参数),删除无引用的 ui/Skill。
oxlint exit 0。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-28 16:14:18 +08:00
twosugar 2cdddf342f fix(build): bidirectional copy-routes, css minify, sitemap filter & CI dist path
copy-routes now emits both foo.html and foo/index.html so the unchanged nginx serves docs/sdk (.html) and the catch-all (/index.html). Fix an invalid empty selector in api-reference.css that broke lightningcss minify. Exclude migration URLs from the sitemap. Point the release/canary deploy at dist/ instead of the removed docs/.vitepress/dist (was uploading an empty dir → no md/html on OSS).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-28 15:04:41 +08:00
twosugar ebc9ed3628 feat(migrate): align shell/docs with legacy, add mobile responsive & login redirect
Header is now position:fixed (like legacy) so it stays pinned during overscroll; #main-content reserves its 60px. Rebuild the mobile top nav (icon hamburger, accordion Features, overlay panel) and the docs local-nav (reveal-on-scroll bar + On this page TOC). Fixed-header/mobile fixes: 60px logo→menu gap, mobile tail alignment, footer 2-col + centered bottom bar, breadcrumb/doc-footer alignment, symmetric mobile padding. MCP page excluded from the docs sidebar (sidebar:false). Migrate the login redirect logic from the legacy AppNav: createLoginRedirectPath (/login?redirect_to=<sso?redirect_to=current>&logout=1&with-us=1), login state via window.longportInternal, and the logged-in Dashboard + avatar dropdown; UserAvatar now renders the full login block.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-28 13:40:03 +08:00
twosugar b38e88f63c feat(migrate): replicate homepage & skill pages 1:1 with legacy
Port the legacy VitePress homepage (10 sections: hero, channels, features, CLI spotlight, AI Skill, MCP, API capabilities, SDK, get-started, CTA) and the Skill page (hero, demo, catalog, capability, cases, get-started) as hydrated React islands, matching legacy markup/CSS and interactions. Add a shared CopyButton with copied feedback across the homepage code blocks. Remove 14 orphaned homepage sections and the old SkillCatalog; wire the home/skill islands via the [...slug] routes and the mdx-component map.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-28 13:39:19 +08:00
twosugar 7a3daba71c feat(migrate): sync upstream main into Astro and align footer with legacy
Content (from origin/main, 3 locales):
- add grid trading, multi-leg, CLI ai/serve, and style-guide pages (58 files)
- rename Longbridge AI -> LongbridgeAI; add multi-leg fields, remove
  contract_size, add US paper-account notes (39 files)
- sync grid trading endpoints into openapi.yaml

Components:
- footer: add AI Integrations column (MCP / ChatGPT App / Claude Connector);
  restore legacy tagline, status pill, padding, grid, heading + link styles;
  hug footer to content (drop mt-16)
- sdk-links: support grid module (GridContext, hideGo)
- raw markdown: serve EN source prefixless at /docs/<path>.md (legacy parity)

Polish:
- CliCommand terminal card with per-command doc deep-links
- resolve relative-slug URLs in sidebar / prev-next / breadcrumb
- hydrate pricing billing toggle + eyebrow badge; thin scrollbars
- global body base + site-wide antialiasing

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-27 15:56:05 +08:00
twosugar b90cbb4eb4 feat(docs): align doc detail page with legacy (footer, callout, meta, anchors, TOC, sidebar)
- Docs pages render a slim link-row footer (DocFooter) instead of the big
  marketing footer; BaseLayout gains a hideFooter prop
- Callout blocks restyled to the legacy TipContainer look (1px border, radius,
  per-type icon, accent-coloured title + body)
- Doc meta row (Markdown / Edit / Last Updated) via DocMeta; real per-page
  dates from origin/main git history (src/lib/last-updated.ts)
- Body copy: antialiased smoothing + faint rgba(0,0,0,.06) underline colour to
  match legacy .vp-doc
- Heading anchors moved to the left gutter; scroll-margin-top offsets the 61px
  sticky header on TOC/anchor jumps
- TOC pinned at its at-rest offset so it no longer jumps up on scroll
- Breadcrumb: bold current-page crumb
- Sidebar: childless category folders (e.g. cli/ipo) render as clickable bold
  headers instead of dead muted leaves

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-25 19:45:38 +08:00
twosugar fd6b5a6996 fix(migrate): restore root "Overview" sidebar entry (docs/{locale}/index.mdx)
Follow-up to the sidebar refactor. The legacy sidebar shows a top-level
"Overview" (/docs) as the first, active item — it's docs/{locale}/docs/
index.mdx (title Overview / 平台介绍 / 平台介紹, sidebar_position -999,
book_open icon). buildItems() skipped EVERY index.mdx, so that page never
appeared in the tree and /docs had no active sidebar item.

buildItems() gains an `includeIndex` param (default false). buildSidebar's
root call passes true so the root index.mdx is emitted as a top-level leaf
(link /docs, /zh-CN/docs, /zh-HK/docs via urlFromAbsPath; -999 sorts it
first). Nested index.mdx files still skip — they're absorbed as directory
links via _category_.json, unchanged.

Applies to both scopes: docs/{locale}/docs/index.mdx and the cli sidebar's
docs/{locale}/docs/cli/index.mdx (both exist in all three locales).

Verified: /docs now shows "Overview" with book-open icon + teal active
pill at the top of the first group, matching the legacy reference.
navigation.test.ts 3/3 pass (non-empty, zh-CN count == en count, position
ascending all still hold — the new node's -999 sorts first).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-24 11:14:51 +08:00
twosugar f5793031f0 fix(migrate): pre-cutover polish — title fallback, SDK hero SVG, locale SSR binding
Gate-4 flagged three A-class residuals blocking cutover:

- **A5/A21** — Homepage tab title `(untitled)` on / and /zh-CN/.
  index.mdx frontmatter uses `titleTemplate` (not `title`); the 3
  [...slug].astro dispatchers were hard-fallback to '(untitled)'.
  Now cascade: title → titleTemplate → 'Longbridge Developers'.
  content.config.ts schema gains a `titleTemplate` z.string().optional().

- **A19** — /sdk hero SVG rendered as literal text `/assets/sdk.svg`.
  Stage-1 T11 SDK.tsx placeholder shipped a text stub instead of
  <img>. Ported the layout from legacy SDK.vue (max-w-4xl 2-col hero
  with h-244 svg on the right). Asset copied to
  public/assets/sdk.svg (matches legacy `docs/public/assets/sdk.svg`
  path convention).

- **B8** (new) — /zh-CN/ hero rendered English strings ("Powering",
  "Get Started") despite Chinese nav. Root: mdx `<NewHomePage />`
  tag has no way to thread route locale through <Content components>.
  Solved via `buildMdxComponents(locale)` factory that binds locale
  at SSR time to any component with a `locale?` prop
  (SkillCatalog / NewHomePage / McpTools / Pricing / QuotePermission
  / TryIt). Three [...slug].astro files now call
  `buildMdxComponents('en'|'zh-CN'|'zh-HK')` per locale.

  NewHomePage also grows a client-side detectLocale() fallback via
  document.documentElement.lang for edge cases where propsLocale is
  absent (defensive; the factory ensures it's always passed).

Verified:
- astro check: 0 errors (138 files)
- / SSR: "Powering" / "Get Started" (en)
- /zh-CN/ SSR: "接入" / "快速开始" (Simplified)
- /zh-HK/ SSR: "接入" / "快速開始" (Traditional)
- /sdk SSR: <img class="h-[244px]" src="/assets/sdk.svg" alt="">
- /assets/sdk.svg → 200

Gate-4 A-class findings all closed; cutover unblocked pending §S12
(nginx) + §S13 (canary).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-19 11:59:11 +08:00
twosugar 3679945744 feat(migrate): port inspira animation components to React workspace
Sprint 2 §S9. Ports 18 vue animation components (1462 lines) from
`docs/.vitepress/theme/components/inspira/` to React inside a new
`packages/inspira` workspace published as `@longbridge/openapi-inspira`.
Adds `motion` (v13.x — API-compatible with the ^11 the plan
suggested; `motion-v` in vue → `motion/react` in React).

Files created (18 components + barrel):
- packages/inspira/package.json — bun workspace, motion dep
- packages/inspira/tsconfig.json
- packages/inspira/src/index.ts — barrel
- packages/inspira/src/AnimatedBeam.tsx (from 190-line vue)
- packages/inspira/src/BentoGrid.tsx (18)
- packages/inspira/src/BentoGridItem.tsx (32)
- packages/inspira/src/BlurReveal.tsx (54)
- packages/inspira/src/BorderBeam.tsx (61)
- packages/inspira/src/BoxReveal.tsx (47)
- packages/inspira/src/ColourfulText.tsx (73)
- packages/inspira/src/FlickeringGrid.tsx (256)
- packages/inspira/src/GlowBorder.tsx (59)
- packages/inspira/src/GlowingEffect.tsx (94)
- packages/inspira/src/InteractiveGridPattern.tsx (70)
- packages/inspira/src/InteractiveHoverButton.tsx (64)
- packages/inspira/src/Marquee.tsx (73)
- packages/inspira/src/Meteors.tsx (57)
- packages/inspira/src/MorphingText.tsx (100)
- packages/inspira/src/NumberTicker.tsx (75)
- packages/inspira/src/ShimmerButton.tsx (75)
- packages/inspira/src/TextHighlight.tsx (64)

Migration decisions:
- `motion/react` in place of `motion-v` — same underlying framer-motion
- CSS keyframes from Vue `<style scoped>` re-emitted as `<style>` JSX
  tags with `inspira-` prefix to prevent collisions
- `propsRef` pattern in FlickeringGrid + MorphingText to avoid stale
  closures in RAF loops
- `useElementVisibility` + `useTransition` (@vueuse/core) replaced with
  native `IntersectionObserver` + `requestAnimationFrame`
- Fixed 2 type errors uncovered by check: duplicate borderRadius in
  GlowBorder inline styles; canvas/ctx narrowing through nested
  closures in FlickeringGrid

Modified:
- root package.json — @longbridge/openapi-inspira workspace dep +
  motion dep

Verified:
- astro check: 0 errors (132 files)
- 8 canonical URLs return 200

Deferred: rewiring homepage sections to use inspira components lands
alongside §S10 composite polish; §S9 scope is producing the package.

Closes Sprint 2 §S9.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-19 10:12:38 +08:00
twosugar 01efaccf80 feat(migrate): port NewHomePage (15 sections + ArchCanvas) to React workspace
Sprint 2 §S8. Ports legacy `docs/.vitepress/theme/components/NewHomePage/`
(16 vue files, 9122 lines) to React inside a new `packages/homepage`
workspace published as `@longbridge/openapi-homepage`. Chunked-read
protocol across four subagent batches (§S8, §S8-b, §S8-c, §S8-d) since
individual vue files were too large for a single subagent context (up
to 930 lines each; index.vue at 2912 lines was skipped in favour of a
purpose-built React aggregator).

Sections ported (15):
- HeroSection (352 lines vue)
- CoreFeaturesSection (290)
- CapSection (236)
- ArchSection (231; wires SdkMarquee with SDK data lifted from vue)
- ArchCanvas (498; pure CSS flexbox arch diagram — no @xyflow/react
  needed after all)
- MarketCoverage (177)
- PlatformStats (458)
- ProductOpenAPI (668)
- ProductCLI (730)
- ProductMCP (792)
- ProductSkill (930)
- SdkMarquee (401)
- GetStarted (278)
- StyleToggle (36; kept as controlled widget, not page section)
- HomepageFooter (133; distinct from site-wide shell/Footer)

Files created:
- packages/homepage/package.json — bun workspace; @longbridge/openapi-utils dep
- packages/homepage/tsconfig.json
- packages/homepage/src/index.ts — barrel
- packages/homepage/src/NewHomePage.tsx — aggregator, imports all 15
  sections in the same order as legacy index.vue
- packages/homepage/src/ArchCanvas.tsx
- packages/homepage/src/homepage.css — page-level styles
- packages/homepage/src/sections/*.tsx — 15 section files

Files modified:
- src/mdx-components.tsx — swap import from placeholder to
  `@longbridge/openapi-homepage`
- root package.json — workspace dep

Files deleted:
- src/components/mdx/placeholders/NewHomePage.tsx

Verified:
- astro check: 0 errors (113 files)
- 7 canonical URLs return 200
- data-lbus-component tags visible in /: hero-section, core-features,
  cap-section, arch-section, market-coverage, platform-stats,
  product-openapi, product-cli, product-mcp, product-skill, sdk-marquee,
  arch-canvas, get-started, homepage-footer, new-home-page

Deferrals:
- SdkMarquee is wired through ArchSection with the SDK_LIST hoisted
  out; if legacy shows SdkMarquee elsewhere on the page, that mount
  point will surface in the gate visual diff and can be adjusted
- Animations (parallax, typewriter, particles, gradient shifts) match
  legacy behavioral shape; pixel-perfect timing may need a second pass
  in §S11 gate

Closes Sprint 2 §S8 (gate finding A1 / A5 / A6 / A7 / A21).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-19 09:58:03 +08:00
twosugar d83d52b73d feat(migrate): port TryIt (interactive API caller) to React workspace
Sprint 2 §S7. Ports legacy TryIt (9 vue files under
`docs/.vitepress/theme/components/TryIt/` + `theme/utils/{http-client,
websocket-client}.ts`) to React inside a new `packages/tryit` workspace
published as `@longbridge/openapi-tryit`. Uses react-hook-form for
form generation from openapi schema; fires real API requests against
`openapi.longportapp.com`.

Files created:
- packages/tryit/package.json — bun workspace, deps: react-hook-form,
  @longbridge/openapi-utils, @longbridge/openapi-api-reference
- packages/tryit/tsconfig.json
- packages/tryit/src/index.ts — barrel
- packages/tryit/src/TryIt.tsx — orchestrator: button mode → panel mode,
  data-lbus-component="tryit" preserved
- packages/tryit/src/AuthorizationForm.tsx — cookie/localStorage-backed
  appKey / appSecret / accessToken inputs
- packages/tryit/src/ParametersForm.tsx — walks op parameters + request
  body via SchemaRenderer
- packages/tryit/src/PlayButton.tsx — assembles request, dispatches via
  clients
- packages/tryit/src/ResponseView.tsx — pretty-prints JSON response
- packages/tryit/src/tryit.css — form + response viewer styles
- packages/tryit/src/clients/http-client.ts — verbatim port of legacy
- packages/tryit/src/clients/websocket-client.ts — verbatim port of legacy
- packages/tryit/src/utils/app-id.ts — id derivation
- packages/tryit/src/utils/request.ts — request assembly helper
- packages/tryit/src/hooks/useTryItMode.ts — `?mode=try-it` URL toggle
- packages/tryit/src/hooks/useAuthorization.ts — cookie sync
- packages/tryit/src/hooks/useResponse.ts — response state

Modified:
- src/mdx-components.tsx — swap import from placeholder to
  `@longbridge/openapi-tryit`
- root package.json — workspace dep

Deleted:
- src/components/mdx/placeholders/TryIt.tsx

Verified:
- astro check: 0 errors (0 new warnings)
- All 15 canonical URLs return 200
- `<TryIt />` registered in mdx-components; mount site (frontmatter
  `httpInfo` or explicit tag) is handled by later plumbing

Closes Sprint 2 §S7.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-19 01:26:53 +08:00
twosugar 535dc86a7a feat(migrate): port ApiReference (Scalar-style) to React workspace package
Sprint 2 §S6. Ports legacy `docs/.vitepress/theme/components/ApiReference.vue`
(1370 lines) to React inside a new `packages/api-reference` workspace
published as `@longbridge/openapi-api-reference`. Zero use of
`@scalar/*` or any third-party OpenAPI viewer — this is a manual 1:1 port.

Match legacy behaviour:
- Hash routing via `?op=<epId>` and `?page=<pageId>` + popstate listener
- Three views: intro / page / endpoint
- Sidebar with search + tag groups + method-color badges (GET/POST/PUT/DELETE)
- markdown-it prose rendering + external-link renderer patch
- Schema tree walker with `$ref` resolution + envelope detection
- Code-sample tabs (JS/Python/Rust/Java/Go/C++) via inline regex highlighter
- `QuotePermission` badge sourced from `quote-permissions.yaml`
- Locale-aware doc-link rewrites (`localizeDocLinks`)
- Dark mode double-guard `[data-theme="dark"]` + `prefers-color-scheme`

Files created:
- `packages/api-reference/package.json` — bun workspace, deps js-yaml + markdown-it
- `packages/api-reference/tsconfig.json` — extends root, includes .astro types
- `packages/api-reference/src/index.ts` — barrel
- `packages/api-reference/src/openapi-loader.ts` — yaml.load + $ref resolver
- `packages/api-reference/src/ApiReference.tsx` — top-level CSR component
- `packages/api-reference/src/CodeSample.tsx` — code panel + syntax highlight
- `packages/api-reference/src/QuotePermission.tsx` — permissions badge
- `packages/api-reference/src/api-reference.css` — 280px sidebar + fluid main +
  440px code panel + method colors + dark-mode

Files modified:
- `src/layouts/ApiReferenceLayout.astro` — mounts <ApiReference client:load
  rawYaml={rawYaml} locale={locale} /> with the CSS import (needed subpath in
  the package's `exports` field to resolve the CSS through the workspace name)
- `src/data/locale.{en,zh-CN,zh-HK}.ts` — api.* keys (search, section labels,
  copy states, intro copy, param labels, fallback, pathCopy)
- `src/mdx-components.tsx` — remove dead ApiReference entry (mounted via
  layout, not mdx tag)
- root `package.json` — workspace dep `@longbridge/openapi-api-reference`

Files deleted:
- `src/components/mdx/placeholders/ApiReference.tsx`

Runtime bugfix (post-subagent): package.json `exports` field only exposed
`.` and rejected `./src/api-reference.css` subpath, throwing a 500 on every
route once the layout tried to import the CSS. Added the CSS subpath to
`exports`. All 15 canonical URLs return 200 after fix.

Verified:
- astro check: 0 errors (85 files)
- /docs/api renders with sidebar (Overview / Real-Time Market Data / Error
  Codes + tag groups Watchlist Management / Market Temperature / Portfolio
  & Cash / News & Filings + method-color badges) + intro cards
  (REST API / WebSocket) — screenshot in gate/s6-verify-api.png
- /zh-CN/docs/api, /zh-HK/docs/api, /docs/quote/overview all 200
- `data-lbus-component` on api-reference / api-sidebar / api-intro

Closes Sprint 2 §S6 (gate finding A13 / A14).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-19 01:00:50 +08:00
twosugar 0e2dcb4c81 refactor(migrate): extract @longbridge/openapi-utils workspace package
Sprint 2 §S5: move src/lib/{slug,region,navigation,i18n}.ts + tests
into a new bun workspace `packages/utils` published as
`@longbridge/openapi-utils`. Consumers import from the package name
instead of relative paths or `@lib/*` aliases.

Files moved (git mv preserves history):
- src/lib/slug{,.test}.ts       → packages/utils/src/
- src/lib/region{,.test}.ts     → packages/utils/src/
- src/lib/navigation{,.test}.ts → packages/utils/src/
- src/lib/i18n.ts               → packages/utils/src/

New package skeleton:
- packages/utils/package.json (private workspace, "@longbridge/openapi-utils")
- packages/utils/tsconfig.json (extends root, includes .astro types
  so `astro:content` resolves in isolated TS server)
- packages/utils/src/index.ts (barrel re-exports)

Consumer updates (22 files): shell components, layouts, [...slug]
routes on all 3 locales, llms.txt endpoints, md endpoint — all import
from `@longbridge/openapi-utils` now.

tsconfig.json — removed `@lib/*` alias (dead after the move); other
aliases (`@/*`, `@components/*`, `@styles/*`, `@data/*`) intact.

Two slug.test.ts expectations updated to reflect the T3 semantics
locked in during Sprint 1.5:
- absolute slug in `en/docs/**` → `/docs/{slug}` (was `/{slug}`)
- absolute slug in `zh-CN/docs/**` → `/zh-CN/docs/{slug}` (was `/zh-CN/{slug}`)
- new coverage: absolute slug for `en/{marketing}.mdx` still site-absolute
The test file was carrying pre-T3 expectations; §S5 is when
they had to move regardless, so the correction lands here.

Verified:
- astro check: 0 errors (81 files)
- vitest: 23/23 pass
- 8 canonical URLs: all 200
- zero residual `../lib/*` / `@lib/*` import paths anywhere in
  src/ or packages/

Known deferred:
- `packages/utils/src/i18n.ts` still reads locale data via
  `../../../src/data/locale.*` (cross-boundary). Acceptable for §S5
  scope; §S10 may relocate locale data into the utils package.

Closes Sprint 2 §S5.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-18 22:13:43 +08:00
twosugar ae2121ff50 feat(migrate): render vitepress ::: callouts and Tabs UI
Sprint 1.5 mini §S11 gate flagged (A8, A12, A20):
- vitepress `:::warning`/`:::tip`/`:::success` containers render as raw
  text ("`:::warning Package Renamed`" appears in body) — 335 usages
- `<Tabs><TabItem>` ships to browser but tab bar never appears; all
  TabItems stack under each other (e.g. macOS/Windows/Linux install
  commands, /sdk language SDK panels)

A8 — Callout directive rendering
--------------------------------

remark-directive v4 (micromark-extension-directive) rejects the bare
title form `:::warning Package Renamed` and only accepts bracket labels.
Two-part fix:

- Preflight Rule 10 rewrites `:::name Title` → `:::name[Title]` in mdx
  source before the remark pipeline; scoped to known names
  (success/warning/tip/info/danger/note/caution) and never rewrites
  lines that already use `[…]` or `{…}` syntax.
- New remark plugin `src/integrations/remark-callout.ts` transforms
  parsed `containerDirective` AST nodes into
  `<div class="callout callout-{name}" role="note"
    data-lbus-component="callout-{name}">` with an optional
  `<p class="callout-title">` from the directive label (default:
  capitalised name).
- `src/styles/callout.css` maps each variant to `--lb-status-*` /
  `--lb-brand` tokens: warning=orange, danger=red, tip=teal,
  success=green, info/note/caution=blue.

A12/A20 — Tabs SSR + client hydration
--------------------------------------

Root cause: Astro renders each React component in mdx in its own React
root — `<Tabs>` children arrive as pre-serialised HTML, so
`React.Children.forEach` yields nothing, and `<TabItem>` never sees
`TabsContext.Provider`. The `useState`+`useEffect`+`registerTab` pattern
was silently no-op'ing.

Rebuilt as progressive-enhancement:

- `packages/ui/src/TabItem.tsx` — `!ctx` branch emits
  `data-tab-value`/`-label`/`-default` attrs for a client script to
  discover. TabItem's public props unchanged.
- `packages/ui/src/Tabs.tsx` — removes broken `useMemo` introspection;
  SSR renders `<div data-lbus-component="tabs" data-tabs-group-id=…
  data-tabs-variant=…>` with an empty `<div data-tabs-bar>` placeholder
  and children below. `registerTab`/localStorage machinery retained
  for future client:load hydration paths.
- `src/scripts/tabs-hydrate.ts` — vanilla-JS module bundled by Vite.
  On `DOMContentLoaded` walks `[data-lbus-component="tabs"]` wrappers,
  reads TabItem attrs, builds `<button>`s into the empty bar, hides
  non-active TabItems via inline style, wires click handlers, honours
  the existing localStorage `vitepress-tabs-{groupId}` key + syncs
  cross-instance via `__LBTabsState` / `__LBTabsListeners`.
- `src/layouts/BaseLayout.astro` — appends
  `<script>import '../scripts/tabs-hydrate'</script>` before `</body>`.

The vanilla-JS path deliberately mirrors the pre-existing React
`__LBTabsState` API so future migrations back to a React-hydrated Tabs
(e.g. under `client:load`) can coexist without behavioural diff.

Verified:
- astro-check green (after adding `export {}` to tabs-hydrate.ts so
  `declare global` is legal in a module context)
- 8 canonical URLs return 200
- chrome-devtools MCP 1440×900 hard-reload:
  - /docs/cli/install shows 4 tabs (macOS Homebrew / Linux macOS
    Script / Windows Scoop / Windows PowerShell), only active tab's
    code visible
  - /sdk shows orange "Package Renamed" callout with border-left +
    tinted background; 6 language tabs (Python / JavaScript / Rust /
    Java / Go / C++) render, only active tab visible

Closes Sprint 1.5 T5. Sprint 1.5 remediation complete — next: re-run
mini §S11 gate before beginning Sprint 2.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-18 17:53:36 +08:00
twosugar 56e3e60562 refactor(migrate): codemod BEM classNames to Tailwind utilities
Stage-1 shipped skeleton with semantic BEM classNames (top-nav,
docs-layout, sidebar, etc.) but no CSS. Hotfix 7d8f5ff4 added a 567-line
stopgap src/styles/shell.css to unblock the demo. This commit migrates
each component's className strings to inline Tailwind v4 utility classes
per spec §T3, then removes the stopgap file:

- 15 shell/ components (TopNav, Footer, Breadcrumb, LocalNav, Sidebar,
  SidebarItem, Backdrop, TOC, PrevNext, ThemeToggle, LanguageSwitcher,
  SearchButton, SearchDialog, SearchResults, UserAvatar) — BEM → Tailwind
  utility, dark mode via CSS token auto-swap.
- 3 packages/ui/ components — Tabs (`.tab-line-btn` removed; inline
  style already complete), TabItem (`.tab-item` → `py-4`), CliCommand
  (legacy `.language-bash .vp-adaptive-theme .cli-command-block` classes
  removed; `.relative` inline).
- shell.css deleted; @import removed from global.css.

Layout grid (`.docs-layout`) and mdx-emit typography (`.docs-content`
h1/h2/pre/code/blockquote) extracted to src/styles/docs.css and
imported from global.css — these style DOM emitted by mdx that cannot
be Tailwind-utility-inlined.

Token references normalised: previously-undefined `--lbus-c-border`,
`--lbus-c-text-muted`, `--lbus-c-brand`, `--lbus-c-bg-soft` (which
fell back to `currentColor` / transparent in the stopgap) replaced with
their real values in tokens.css: `--lb-stroke`, `--lb-fg-2`,
`--lb-brand`, `--lb-bg-2`.

Verified:
- astro-check green (0 errors, 5 pre-existing hints)
- 884/884 dev URLs return 200
- Chrome DevTools MCP screenshot 1440x900: top nav / sidebar / content /
  TOC / footer all render (verified against vitepress baseline; residual
  pixel-parity gaps — Features dropdown, GitHub / Get Started CTAs,
  sidebar emoji icons, breadcrumb full path, mdx table styling — are
  stage-1 skeleton residuals not introduced by this codemod; queued for
  Sprint 1.5 mini §S11 gate).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-18 15:52:05 +08:00
twosugar 4a3647e5c7 fix(migrate): add types field to @longbridge/openapi-ui package.json
Without an explicit "types" field, VS Code tsserver falls back to
seeking .d.ts files and emits TS2307 for the workspace import.
astro check is unaffected (Vite bundler resolver reads exports map)
but the editor diagnostic appears in every developer session.
Ruling in
.superpowers/sdd/2026-08-17-astro-migration-stage-1/progress.md.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-17 19:38:06 +08:00