feat(website): drop hash-based router
This commit is contained in:
@@ -46,6 +46,15 @@
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script>
|
||||
// Restore SPA path from 404.html redirect (GitHub Pages)
|
||||
;(function () {
|
||||
var p = new URLSearchParams(window.location.search).get('p')
|
||||
if (p) {
|
||||
window.history.replaceState(null, '', window.location.pathname + p + window.location.hash)
|
||||
}
|
||||
})()
|
||||
</script>
|
||||
<script type="module" src="./src/main.tsx"></script>
|
||||
<script>
|
||||
// Dynamically update html lang attribute based on i18n detection
|
||||
|
||||
34
packages/website/public/404.html
Normal file
34
packages/website/public/404.html
Normal file
@@ -0,0 +1,34 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Redirecting...</title>
|
||||
<script>
|
||||
// SPA fallback for GitHub Pages
|
||||
// Preserves the path so the SPA router can handle it after redirect
|
||||
var seg = 1 // number of path segments to keep (repo name = /page-agent)
|
||||
var loc = window.location
|
||||
loc.replace(
|
||||
loc.protocol +
|
||||
'//' +
|
||||
loc.hostname +
|
||||
(loc.port ? ':' + loc.port : '') +
|
||||
loc.pathname
|
||||
.split('/')
|
||||
.slice(0, 1 + seg)
|
||||
.join('/') +
|
||||
'/?p=' +
|
||||
encodeURIComponent(
|
||||
loc.pathname
|
||||
.slice(1)
|
||||
.split('/')
|
||||
.slice(seg)
|
||||
.join('/') +
|
||||
loc.search +
|
||||
loc.hash
|
||||
)
|
||||
)
|
||||
</script>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
||||
@@ -23,7 +23,7 @@ export default function Header() {
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
{/* Logo */}
|
||||
<Link
|
||||
href="~/"
|
||||
href="/"
|
||||
className="flex items-center gap-2 sm:gap-3 group shrink-0"
|
||||
aria-label={isZh ? 'page-agent 首页' : 'page-agent home'}
|
||||
onClick={() => setMobileMenuOpen(false)}
|
||||
@@ -56,7 +56,7 @@ export default function Header() {
|
||||
aria-label="Mobile navigation"
|
||||
>
|
||||
<Link
|
||||
href="~/docs/introduction/overview"
|
||||
href="/docs/introduction/overview"
|
||||
className="p-2 rounded-lg text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-blue-600 dark:hover:text-blue-400 transition-colors duration-200 shrink-0"
|
||||
aria-label={isZh ? '文档' : 'Docs'}
|
||||
>
|
||||
@@ -90,7 +90,7 @@ export default function Header() {
|
||||
{import.meta.env.VERSION}
|
||||
</span>
|
||||
<Link
|
||||
href="~/docs/introduction/overview"
|
||||
href="/docs/introduction/overview"
|
||||
className="flex items-center gap-1.5 text-gray-600 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 transition-colors duration-200"
|
||||
>
|
||||
<BookOpen className="w-4 h-4" />
|
||||
@@ -138,7 +138,7 @@ export default function Header() {
|
||||
role="navigation"
|
||||
>
|
||||
<Link
|
||||
href="~/docs/introduction/overview"
|
||||
href="/docs/introduction/overview"
|
||||
className="flex items-center gap-2 px-3 py-2 rounded-lg text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-blue-600 dark:hover:text-blue-400 transition-colors duration-200"
|
||||
onClick={() => setMobileMenuOpen(false)}
|
||||
>
|
||||
|
||||
37
packages/website/src/components/Heading.tsx
Normal file
37
packages/website/src/components/Heading.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import { ComponentPropsWithoutRef, useEffect, useRef } from 'react'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
type Level = 2 | 3
|
||||
|
||||
interface HeadingProps extends Omit<ComponentPropsWithoutRef<'h2'>, 'children'> {
|
||||
id: string
|
||||
level: Level
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
const tags = { 2: 'h2', 3: 'h3' } as const
|
||||
|
||||
export function Heading({ id, level, className, children, ...props }: HeadingProps) {
|
||||
const ref = useRef<HTMLHeadingElement>(null)
|
||||
const Tag = tags[level]
|
||||
|
||||
useEffect(() => {
|
||||
if (window.location.hash === `#${id}`) {
|
||||
ref.current?.scrollIntoView({ behavior: 'smooth' })
|
||||
}
|
||||
}, [id])
|
||||
|
||||
return (
|
||||
<Tag ref={ref} id={id} className={cn('group relative scroll-mt-20', className)} {...props}>
|
||||
<a
|
||||
href={`#${id}`}
|
||||
className="absolute -left-5 top-1/2 -translate-y-1/2 opacity-0 group-hover:opacity-100 text-gray-400 hover:text-blue-500 transition-opacity no-underline"
|
||||
aria-label={`Link to ${id}`}
|
||||
>
|
||||
#
|
||||
</a>
|
||||
{children}
|
||||
</Tag>
|
||||
)
|
||||
}
|
||||
@@ -1,15 +1,21 @@
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import { Router } from 'wouter'
|
||||
import { useHashLocation } from 'wouter/use-hash-location'
|
||||
|
||||
import { LanguageProvider } from './i18n/context'
|
||||
import { default as PagesRouter } from './router'
|
||||
|
||||
import './index.css'
|
||||
|
||||
// Redirect legacy hash routes (e.g. /#/docs/foo) to clean paths
|
||||
const { hash } = window.location
|
||||
if (hash.length > 1 && hash.includes('/')) {
|
||||
const path = hash.replace(/^#\/?/, '/')
|
||||
history.replaceState(null, '', '/page-agent' + path)
|
||||
}
|
||||
|
||||
createRoot(document.getElementById('root')!).render(
|
||||
<LanguageProvider>
|
||||
<Router hook={useHashLocation}>
|
||||
<Router base="/page-agent">
|
||||
<PagesRouter />
|
||||
</Router>
|
||||
</LanguageProvider>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import CodeEditor from '@/components/CodeEditor'
|
||||
import { Heading } from '@/components/Heading'
|
||||
import { APIDivider, APIReference } from '@/components/ui/api-reference'
|
||||
import { useLanguage } from '@/i18n/context'
|
||||
|
||||
@@ -17,7 +18,9 @@ export default function CustomUIDocs() {
|
||||
|
||||
{/* Architecture */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">{isZh ? '架构' : 'Architecture'}</h2>
|
||||
<Heading id="architecture" level={2} className="text-2xl font-semibold mb-4">
|
||||
{isZh ? '架构' : 'Architecture'}
|
||||
</Heading>
|
||||
<p className="text-gray-600 dark:text-gray-400 mb-4">
|
||||
{isZh
|
||||
? 'PageAgent 由三个独立模块组成,可自由组合:'
|
||||
@@ -45,7 +48,9 @@ export default function CustomUIDocs() {
|
||||
|
||||
{/* Two Event Streams */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">{isZh ? '两个事件流' : 'Two Event Streams'}</h2>
|
||||
<Heading id="two-event-streams" level={2} className="text-2xl font-semibold mb-4">
|
||||
{isZh ? '两个事件流' : 'Two Event Streams'}
|
||||
</Heading>
|
||||
<p className="text-gray-600 dark:text-gray-400 mb-4">
|
||||
{isZh
|
||||
? 'PageAgentCore 提供两种不同性质的事件流,方便 UI 渲染:'
|
||||
@@ -120,7 +125,9 @@ export default function CustomUIDocs() {
|
||||
|
||||
{/* All Events */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">{isZh ? '所有事件' : 'All Events'}</h2>
|
||||
<Heading id="all-events" level={2} className="text-2xl font-semibold mb-4">
|
||||
{isZh ? '所有事件' : 'All Events'}
|
||||
</Heading>
|
||||
<APIReference
|
||||
properties={[
|
||||
{
|
||||
@@ -155,7 +162,9 @@ export default function CustomUIDocs() {
|
||||
|
||||
{/* HistoricalEvent Types */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">HistoricalEvent</h2>
|
||||
<Heading id="historicalevent" level={2} className="text-2xl font-semibold mb-4">
|
||||
HistoricalEvent
|
||||
</Heading>
|
||||
<p className="text-gray-600 dark:text-gray-400 mb-4">
|
||||
{isZh ? 'agent.history 数组中的事件类型:' : 'Event types in agent.history array:'}
|
||||
</p>
|
||||
@@ -172,7 +181,9 @@ export default function CustomUIDocs() {
|
||||
|
||||
{/* AgentActivity Types */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">AgentActivity</h2>
|
||||
<Heading id="agentactivity" level={2} className="text-2xl font-semibold mb-4">
|
||||
AgentActivity
|
||||
</Heading>
|
||||
<p className="text-gray-600 dark:text-gray-400 mb-4">
|
||||
{isZh ? 'activity 事件的 detail 类型:' : 'The detail type of activity events:'}
|
||||
</p>
|
||||
@@ -191,9 +202,9 @@ export default function CustomUIDocs() {
|
||||
|
||||
{/* React Hooks Example */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">
|
||||
<Heading id="using-react-hooks" level={2} className="text-2xl font-semibold mb-4">
|
||||
{isZh ? '使用 React Hooks' : 'Using React Hooks'}
|
||||
</h2>
|
||||
</Heading>
|
||||
<p className="text-gray-600 dark:text-gray-400 mb-4">
|
||||
{isZh ? '监听事件并更新 React 状态:' : 'Listen to events and update React state:'}
|
||||
</p>
|
||||
@@ -229,9 +240,13 @@ export default function CustomUIDocs() {
|
||||
|
||||
{/* Assembly Example */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">
|
||||
<Heading
|
||||
id="assembling-core-controller-custom-ui"
|
||||
level={2}
|
||||
className="text-2xl font-semibold mb-4"
|
||||
>
|
||||
{isZh ? '组装 Core + Controller + 自定义 UI' : 'Assembling Core + Controller + Custom UI'}
|
||||
</h2>
|
||||
</Heading>
|
||||
<p className="text-gray-600 dark:text-gray-400 mb-4">
|
||||
{isZh
|
||||
? '参考内置 PageAgent 的实现方式,用自定义 UI 替换 Panel:'
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import CodeEditor from '@/components/CodeEditor'
|
||||
import { Heading } from '@/components/Heading'
|
||||
import { APIDivider, APIReference, TypeRef } from '@/components/ui/api-reference'
|
||||
import { useLanguage } from '@/i18n/context'
|
||||
|
||||
@@ -17,9 +18,9 @@ export default function PageAgentCoreDocs() {
|
||||
|
||||
{/* When to use */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">
|
||||
<Heading id="when-to-use-pageagentcore" level={2} className="text-2xl font-semibold mb-4">
|
||||
{isZh ? '何时使用 PageAgentCore' : 'When to Use PageAgentCore'}
|
||||
</h2>
|
||||
</Heading>
|
||||
<ul className="list-disc list-inside text-gray-600 dark:text-gray-400 space-y-2">
|
||||
<li>{isZh ? '需要自定义 UI 界面' : 'Need a custom UI interface'}</li>
|
||||
<li>{isZh ? '在自动化测试中无头运行' : 'Running headless in automated tests'}</li>
|
||||
@@ -38,7 +39,9 @@ export default function PageAgentCoreDocs() {
|
||||
|
||||
{/* Basic Usage */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">{isZh ? '基本用法' : 'Basic Usage'}</h2>
|
||||
<Heading id="basic-usage" level={2} className="text-2xl font-semibold mb-4">
|
||||
{isZh ? '基本用法' : 'Basic Usage'}
|
||||
</Heading>
|
||||
<CodeEditor
|
||||
language="typescript"
|
||||
code={`import { PageAgentCore } from '@page-agent/core'
|
||||
@@ -76,7 +79,9 @@ const result = await agent.execute('Fill in the form with test data')`}
|
||||
|
||||
{/* LLM Configuration */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">LLMConfig</h2>
|
||||
<Heading id="llmconfig" level={2} className="text-2xl font-semibold mb-4">
|
||||
LLMConfig
|
||||
</Heading>
|
||||
<p className="text-gray-600 dark:text-gray-400 mb-4">
|
||||
{isZh
|
||||
? '配置与大语言模型的连接参数。支持 OpenAI 兼容的 API。'
|
||||
@@ -133,7 +138,9 @@ const result = await agent.execute('Fill in the form with test data')`}
|
||||
|
||||
{/* Agent Configuration */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">AgentConfig</h2>
|
||||
<Heading id="agentconfig" level={2} className="text-2xl font-semibold mb-4">
|
||||
AgentConfig
|
||||
</Heading>
|
||||
<p className="text-gray-600 dark:text-gray-400 mb-4">
|
||||
{isZh
|
||||
? '配置 Agent 的行为、生命周期钩子和扩展能力。'
|
||||
@@ -210,7 +217,9 @@ const result = await agent.execute('Fill in the form with test data')`}
|
||||
|
||||
{/* Lifecycle Hooks */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">{isZh ? '生命周期钩子' : 'Lifecycle Hooks'}</h2>
|
||||
<Heading id="lifecycle-hooks" level={2} className="text-2xl font-semibold mb-4">
|
||||
{isZh ? '生命周期钩子' : 'Lifecycle Hooks'}
|
||||
</Heading>
|
||||
<div className="bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg p-4 mb-4">
|
||||
<p className="text-amber-800 dark:text-amber-200 text-sm">
|
||||
<strong>⚠️ {isZh ? '警告' : 'Warning'}:</strong>{' '}
|
||||
@@ -262,7 +271,9 @@ const result = await agent.execute('Fill in the form with test data')`}
|
||||
|
||||
{/* PageController Configuration */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">PageControllerConfig</h2>
|
||||
<Heading id="pagecontrollerconfig" level={2} className="text-2xl font-semibold mb-4">
|
||||
PageControllerConfig
|
||||
</Heading>
|
||||
<p className="text-gray-600 dark:text-gray-400 mb-4">
|
||||
{isZh
|
||||
? '配置 DOM 提取、元素交互和视觉反馈。'
|
||||
@@ -321,7 +332,9 @@ const result = await agent.execute('Fill in the form with test data')`}
|
||||
|
||||
{/* Properties */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">{isZh ? '属性' : 'Properties'}</h2>
|
||||
<Heading id="properties" level={2} className="text-2xl font-semibold mb-4">
|
||||
{isZh ? '属性' : 'Properties'}
|
||||
</Heading>
|
||||
<APIReference
|
||||
properties={[
|
||||
{
|
||||
@@ -366,7 +379,9 @@ const result = await agent.execute('Fill in the form with test data')`}
|
||||
|
||||
{/* Methods */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">{isZh ? '方法' : 'Methods'}</h2>
|
||||
<Heading id="methods" level={2} className="text-2xl font-semibold mb-4">
|
||||
{isZh ? '方法' : 'Methods'}
|
||||
</Heading>
|
||||
<APIReference
|
||||
properties={[
|
||||
{
|
||||
@@ -389,7 +404,9 @@ const result = await agent.execute('Fill in the form with test data')`}
|
||||
|
||||
{/* Events */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">{isZh ? '事件' : 'Events'}</h2>
|
||||
<Heading id="events" level={2} className="text-2xl font-semibold mb-4">
|
||||
{isZh ? '事件' : 'Events'}
|
||||
</Heading>
|
||||
<p className="text-gray-600 dark:text-gray-400 mb-4">
|
||||
{isZh ? (
|
||||
<>
|
||||
@@ -438,7 +455,9 @@ const result = await agent.execute('Fill in the form with test data')`}
|
||||
|
||||
{/* ExecutionResult */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">ExecutionResult</h2>
|
||||
<Heading id="executionresult" level={2} className="text-2xl font-semibold mb-4">
|
||||
ExecutionResult
|
||||
</Heading>
|
||||
<CodeEditor
|
||||
language="typescript"
|
||||
code={`interface ExecutionResult {
|
||||
@@ -454,7 +473,9 @@ const result = await agent.execute('Fill in the form with test data')`}
|
||||
|
||||
{/* AgentActivity */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">AgentActivity</h2>
|
||||
<Heading id="agentactivity" level={2} className="text-2xl font-semibold mb-4">
|
||||
AgentActivity
|
||||
</Heading>
|
||||
<CodeEditor
|
||||
language="typescript"
|
||||
code={`type AgentActivity =
|
||||
@@ -470,7 +491,9 @@ const result = await agent.execute('Fill in the form with test data')`}
|
||||
|
||||
{/* Headless Usage */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">{isZh ? '无头模式' : 'Headless Mode'}</h2>
|
||||
<Heading id="headless-mode" level={2} className="text-2xl font-semibold mb-4">
|
||||
{isZh ? '无头模式' : 'Headless Mode'}
|
||||
</Heading>
|
||||
<p className="text-gray-600 dark:text-gray-400 mb-4">
|
||||
{isZh
|
||||
? '在非 DOM 环境中,你必须实现自定义的 PageController(例如远程操作页面或 Puppeteer)。'
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Link } from 'wouter'
|
||||
|
||||
import CodeEditor from '@/components/CodeEditor'
|
||||
import { Heading } from '@/components/Heading'
|
||||
import { APIReference, TypeRef } from '@/components/ui/api-reference'
|
||||
import { useLanguage } from '@/i18n/context'
|
||||
|
||||
@@ -19,9 +20,9 @@ export default function PageAgentDocs() {
|
||||
|
||||
{/* When to use */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">
|
||||
<Heading id="when-to-use-pageagent" level={2} className="text-2xl font-semibold mb-4">
|
||||
{isZh ? '何时使用 PageAgent' : 'When to Use PageAgent'}
|
||||
</h2>
|
||||
</Heading>
|
||||
<p className="text-gray-600 dark:text-gray-400 mb-4">
|
||||
{isZh
|
||||
? '在大多数场景下,你应该使用 PageAgent。它提供了开箱即用的完整体验:'
|
||||
@@ -43,7 +44,9 @@ export default function PageAgentDocs() {
|
||||
|
||||
{/* Basic Usage */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">{isZh ? '基本用法' : 'Basic Usage'}</h2>
|
||||
<Heading id="basic-usage" level={2} className="text-2xl font-semibold mb-4">
|
||||
{isZh ? '基本用法' : 'Basic Usage'}
|
||||
</Heading>
|
||||
<CodeEditor
|
||||
language="typescript"
|
||||
code={`import { PageAgent } from 'page-agent'
|
||||
@@ -69,7 +72,9 @@ console.log(result.history) // Full execution history`}
|
||||
|
||||
{/* Class Definition */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">{isZh ? '类定义' : 'Class Definition'}</h2>
|
||||
<Heading id="class-definition" level={2} className="text-2xl font-semibold mb-4">
|
||||
{isZh ? '类定义' : 'Class Definition'}
|
||||
</Heading>
|
||||
<CodeEditor
|
||||
language="typescript"
|
||||
code={`class PageAgent extends PageAgentCore {
|
||||
@@ -109,7 +114,9 @@ console.log(result.history) // Full execution history`}
|
||||
|
||||
{/* Configuration */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">{isZh ? '配置' : 'Configuration'}</h2>
|
||||
<Heading id="configuration" level={2} className="text-2xl font-semibold mb-4">
|
||||
{isZh ? '配置' : 'Configuration'}
|
||||
</Heading>
|
||||
<p className="text-gray-600 dark:text-gray-400 mb-4">
|
||||
{isZh
|
||||
? 'PageAgent 使用与 PageAgentCore 相同的配置接口。'
|
||||
@@ -144,7 +151,9 @@ console.log(result.history) // Full execution history`}
|
||||
|
||||
{/* Panel Property */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">{isZh ? 'Panel 属性' : 'Panel Property'}</h2>
|
||||
<Heading id="panel-property" level={2} className="text-2xl font-semibold mb-4">
|
||||
{isZh ? 'Panel 属性' : 'Panel Property'}
|
||||
</Heading>
|
||||
<p className="text-gray-600 dark:text-gray-400 mb-4">
|
||||
{isZh
|
||||
? 'PageAgent 自动创建一个 Panel 实例。你可以通过 panel 属性访问它来控制 UI:'
|
||||
@@ -185,9 +194,9 @@ agent.panel.dispose()`}
|
||||
|
||||
{/* Comparison with PageAgentCore */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">
|
||||
<Heading id="pageagent-vs-pageagentcore" level={2} className="text-2xl font-semibold mb-4">
|
||||
{isZh ? 'PageAgent vs PageAgentCore' : 'PageAgent vs PageAgentCore'}
|
||||
</h2>
|
||||
</Heading>
|
||||
<div className="overflow-hidden rounded-lg border border-gray-200 dark:border-gray-700">
|
||||
<table className="w-full text-sm">
|
||||
<thead>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { siChromewebstore, siGithub } from 'simple-icons'
|
||||
|
||||
import CodeEditor from '@/components/CodeEditor'
|
||||
import { Heading } from '@/components/Heading'
|
||||
import { useLanguage } from '@/i18n/context'
|
||||
|
||||
export default function ChromeExtension() {
|
||||
@@ -22,7 +23,9 @@ export default function ChromeExtension() {
|
||||
<div className="space-y-8 mt-8">
|
||||
{/* Features */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-4">{isZh ? '核心特性' : 'Key Features'}</h2>
|
||||
<Heading id="key-features" level={2} className="text-2xl font-bold mb-4">
|
||||
{isZh ? '核心特性' : 'Key Features'}
|
||||
</Heading>
|
||||
<div className="grid md:grid-cols-3 gap-4">
|
||||
<div className="p-4 bg-gray-50 dark:bg-gray-800 rounded-lg">
|
||||
<h3 className="font-semibold mb-2">🔓 {isZh ? '多页任务' : 'Multi-Page Tasks'}</h3>
|
||||
@@ -57,7 +60,9 @@ export default function ChromeExtension() {
|
||||
|
||||
{/* Install */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-4">{isZh ? '获取扩展' : 'Get the Extension'}</h2>
|
||||
<Heading id="get-the-extension" level={2} className="text-2xl font-bold mb-4">
|
||||
{isZh ? '获取扩展' : 'Get the Extension'}
|
||||
</Heading>
|
||||
<div className="flex flex-wrap gap-3">
|
||||
<a
|
||||
href={chromeWebStoreUrl}
|
||||
@@ -86,9 +91,13 @@ export default function ChromeExtension() {
|
||||
|
||||
{/* Relationship with PageAgent.js */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-4">
|
||||
<Heading
|
||||
id="how-it-relates-to-page-agent-js"
|
||||
level={2}
|
||||
className="text-2xl font-bold mb-4"
|
||||
>
|
||||
{isZh ? '与 PageAgent.js 的关系' : 'How It Relates to PageAgent.js'}
|
||||
</h2>
|
||||
</Heading>
|
||||
<div className="p-5 bg-gray-50 dark:bg-gray-800 rounded-lg space-y-3 text-gray-600 dark:text-gray-300">
|
||||
<p>
|
||||
{isZh
|
||||
@@ -105,9 +114,9 @@ export default function ChromeExtension() {
|
||||
|
||||
{/* Third-party Integration */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-4">
|
||||
<Heading id="third-party-integration" level={2} className="text-2xl font-bold mb-4">
|
||||
{isZh ? '第三方接入' : 'Third-Party Integration'}
|
||||
</h2>
|
||||
</Heading>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
{isZh
|
||||
? '通过页面 JavaScript 调用 `window.PAGE_AGENT_EXT`,你的应用可以发起跨页面任务并控制浏览器行为。'
|
||||
@@ -145,7 +154,9 @@ localStorage.setItem('PageAgentExtUserAuthToken', '<your-token-from-extension>')
|
||||
|
||||
{/* API Reference */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-4">{isZh ? 'API 参考' : 'API Reference'}</h2>
|
||||
<Heading id="api-reference" level={2} className="text-2xl font-bold mb-4">
|
||||
{isZh ? 'API 参考' : 'API Reference'}
|
||||
</Heading>
|
||||
|
||||
{/* AI Assistant Instructions */}
|
||||
<section className="p-4 bg-purple-50 dark:bg-purple-900/20 rounded-lg">
|
||||
@@ -170,9 +181,9 @@ localStorage.setItem('PageAgentExtUserAuthToken', '<your-token-from-extension>')
|
||||
</section>
|
||||
|
||||
{/* TypeScript Declaration */}
|
||||
<h2 className="text-2xl font-bold mb-4">
|
||||
<Heading id="typescript-declaration" level={2} className="text-2xl font-bold mb-4">
|
||||
{isZh ? 'TypeScript 类型声明' : 'TypeScript Declaration'}
|
||||
</h2>
|
||||
</Heading>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
{isZh
|
||||
? '推荐把 `execute` 的类型声明加入你的项目,获得完整类型提示。'
|
||||
@@ -304,11 +315,15 @@ window.PAGE_AGENT_EXT.stop()`
|
||||
|
||||
{/* Integration Guide */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-4">
|
||||
<Heading
|
||||
id="integrate-multipageagent-into-your-extension"
|
||||
level={2}
|
||||
className="text-2xl font-bold mb-4"
|
||||
>
|
||||
{isZh
|
||||
? '将 MultiPageAgent 集成你自己的插件'
|
||||
: 'Integrate MultiPageAgent into Your Extension'}
|
||||
</h2>
|
||||
</Heading>
|
||||
<p>@TODO</p>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
{isZh
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import CodeEditor from '@/components/CodeEditor'
|
||||
import { Heading } from '@/components/Heading'
|
||||
import { useLanguage } from '@/i18n/context'
|
||||
|
||||
export default function Instructions() {
|
||||
@@ -16,9 +17,9 @@ export default function Instructions() {
|
||||
|
||||
{/* System Instructions */}
|
||||
<section className="mb-12">
|
||||
<h2 className="text-3xl font-bold mb-6">
|
||||
<Heading id="system-instructions" level={2} className="text-3xl font-bold mb-6">
|
||||
{isZh ? '系统级指导 (System Instructions)' : 'System Instructions'}
|
||||
</h2>
|
||||
</Heading>
|
||||
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
{isZh
|
||||
@@ -46,9 +47,9 @@ Guidelines:
|
||||
|
||||
{/* Page Instructions */}
|
||||
<section className="mb-12">
|
||||
<h2 className="text-3xl font-bold mb-6">
|
||||
<Heading id="page-instructions" level={2} className="text-3xl font-bold mb-6">
|
||||
{isZh ? '页面级指导 (Page Instructions)' : 'Page Instructions'}
|
||||
</h2>
|
||||
</Heading>
|
||||
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
{isZh
|
||||
@@ -90,7 +91,9 @@ This is the product listing page.
|
||||
|
||||
{/* How It Works */}
|
||||
<section className="mb-12">
|
||||
<h2 className="text-3xl font-bold mb-6">{isZh ? '工作原理' : 'How It Works'}</h2>
|
||||
<Heading id="how-it-works" level={2} className="text-3xl font-bold mb-6">
|
||||
{isZh ? '工作原理' : 'How It Works'}
|
||||
</Heading>
|
||||
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
{isZh
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import BetaNotice from '@/components/BetaNotice'
|
||||
import CodeEditor from '@/components/CodeEditor'
|
||||
import { Heading } from '@/components/Heading'
|
||||
import { useLanguage } from '@/i18n/context'
|
||||
|
||||
export default function CustomTools() {
|
||||
@@ -17,7 +18,9 @@ export default function CustomTools() {
|
||||
|
||||
<div className="space-y-8">
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-4">{isZh ? '工具注册' : 'Tool Registration'}</h2>
|
||||
<Heading id="tool-registration" level={2} className="text-2xl font-bold mb-4">
|
||||
{isZh ? '工具注册' : 'Tool Registration'}
|
||||
</Heading>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
{isZh
|
||||
? '每个自定义工具需要定义四个核心属性:name、description、input schema 和 execute 函数。'
|
||||
@@ -55,7 +58,9 @@ const pageAgent = new PageAgent({customTools})
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-4">{isZh ? '页面过滤器' : 'Page Filter'}</h2>
|
||||
<Heading id="page-filter" level={2} className="text-2xl font-bold mb-4">
|
||||
{isZh ? '页面过滤器' : 'Page Filter'}
|
||||
</Heading>
|
||||
|
||||
<BetaNotice />
|
||||
|
||||
@@ -89,7 +94,9 @@ const pageAgent = new PageAgent({customTools})
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-4">{isZh ? '最佳实践' : 'Best Practices'}</h2>
|
||||
<Heading id="best-practices" level={2} className="text-2xl font-bold mb-4">
|
||||
{isZh ? '最佳实践' : 'Best Practices'}
|
||||
</Heading>
|
||||
<div className="space-y-4">
|
||||
<div className="p-4 bg-yellow-50 dark:bg-yellow-900/20 rounded-lg">
|
||||
<h3 className="text-lg font-semibold text-yellow-900 dark:text-yellow-300 mb-2">
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import CodeEditor from '@/components/CodeEditor'
|
||||
import { Heading } from '@/components/Heading'
|
||||
import { useLanguage } from '@/i18n/context'
|
||||
|
||||
export default function DataMasking() {
|
||||
@@ -15,7 +16,9 @@ export default function DataMasking() {
|
||||
</p>
|
||||
|
||||
<section className="mb-12">
|
||||
<h2 className="text-3xl font-bold mb-6">{isZh ? '接口定义' : 'API Definition'}</h2>
|
||||
<Heading id="api-definition" level={2} className="text-3xl font-bold mb-6">
|
||||
{isZh ? '接口定义' : 'API Definition'}
|
||||
</Heading>
|
||||
|
||||
<CodeEditor
|
||||
className="mb-6"
|
||||
@@ -30,9 +33,9 @@ export default function DataMasking() {
|
||||
</section>
|
||||
|
||||
<section className="mb-12">
|
||||
<h2 className="text-3xl font-bold mb-6">
|
||||
<Heading id="common-masking-patterns" level={2} className="text-3xl font-bold mb-6">
|
||||
{isZh ? '常用脱敏规则' : 'Common Masking Patterns'}
|
||||
</h2>
|
||||
</Heading>
|
||||
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||
{isZh
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Fragment } from 'react'
|
||||
|
||||
import CodeEditor from '@/components/CodeEditor'
|
||||
import { Heading } from '@/components/Heading'
|
||||
import { useLanguage } from '@/i18n/context'
|
||||
|
||||
const BASELINE = new Set([
|
||||
@@ -63,7 +64,9 @@ export default function Models() {
|
||||
|
||||
{/* Models Section */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-3">{isZh ? '已测试模型' : 'Tested Models'}</h2>
|
||||
<Heading id="tested-models" level={2} className="text-2xl font-semibold mb-3">
|
||||
{isZh ? '已测试模型' : 'Tested Models'}
|
||||
</Heading>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400 mb-4">
|
||||
{isZh
|
||||
? '推荐使用 ToolCall 能力强的轻量级模型。'
|
||||
@@ -141,7 +144,9 @@ export default function Models() {
|
||||
|
||||
{/* Configuration Section */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">{isZh ? '配置方式' : 'Configuration'}</h2>
|
||||
<Heading id="configuration" level={2} className="text-2xl font-semibold mb-4">
|
||||
{isZh ? '配置方式' : 'Configuration'}
|
||||
</Heading>
|
||||
<CodeEditor
|
||||
code={`// OpenAI-compatible services (e.g., Alibaba Bailian)
|
||||
const pageAgent = new PageAgent({
|
||||
@@ -163,9 +168,9 @@ const pageAgent = new PageAgent({
|
||||
|
||||
{/* Free Testing API Section */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">
|
||||
<Heading id="free-testing-api" level={2} className="text-2xl font-semibold mb-4">
|
||||
{isZh ? '免费测试接口' : 'Free Testing API'}
|
||||
</h2>
|
||||
</Heading>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400 mb-4">
|
||||
{isZh
|
||||
? '以下免费测试接口仅供 PageAgent.js 和 PageAgent Extension 的技术评估使用。有速率限制,可能随时变更。请勿用于生产环境。'
|
||||
@@ -215,7 +220,9 @@ LLM_API_KEY="NA"`}
|
||||
|
||||
{/* Ollama Section */}
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-semibold mb-4">Ollama</h2>
|
||||
<Heading id="ollama" level={2} className="text-2xl font-semibold mb-4">
|
||||
Ollama
|
||||
</Heading>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400 mb-4">
|
||||
{isZh
|
||||
? '已在 Ollama 0.15 + qwen3:14b (RTX3090 24GB) 上测试通过。'
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { Suspense } from 'react'
|
||||
import { Route, Switch } from 'wouter'
|
||||
|
||||
import Footer from '../../components/Footer'
|
||||
import Header from '../../components/Header'
|
||||
import DocsLayout from './Layout'
|
||||
import CustomUIDocs from './advanced/custom-ui/page'
|
||||
import PageAgentCoreDocs from './advanced/page-agent-core/page'
|
||||
@@ -25,15 +23,9 @@ import Troubleshooting from './introduction/troubleshooting/page'
|
||||
|
||||
function DocsPage({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="min-h-screen bg-white dark:bg-gray-900 flex flex-col">
|
||||
<Header />
|
||||
<div className="flex-1">
|
||||
<DocsLayout>
|
||||
<Suspense>{children}</Suspense>
|
||||
</DocsLayout>
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
<DocsLayout>
|
||||
<Suspense>{children}</Suspense>
|
||||
</DocsLayout>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import BetaNotice from '@/components/BetaNotice'
|
||||
import { Heading } from '@/components/Heading'
|
||||
import { useLanguage } from '@/i18n/context'
|
||||
|
||||
export default function SecurityPermissions() {
|
||||
@@ -18,9 +19,13 @@ export default function SecurityPermissions() {
|
||||
|
||||
<div className="space-y-6">
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-3">
|
||||
<Heading
|
||||
id="element-interaction-allowlist-blocklist"
|
||||
level={2}
|
||||
className="text-2xl font-bold mb-3"
|
||||
>
|
||||
{isZh ? '元素操作黑白名单' : 'Element Interaction Allowlist/Blocklist'}
|
||||
</h2>
|
||||
</Heading>
|
||||
<div className="space-y-3">
|
||||
<div className="p-4 bg-red-50 dark:bg-red-900/20 rounded-lg">
|
||||
<h3 className="text-lg font-semibold text-red-900 dark:text-red-300">
|
||||
@@ -46,9 +51,13 @@ export default function SecurityPermissions() {
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-3">
|
||||
<Heading
|
||||
id="instruction-safety-constraints"
|
||||
level={2}
|
||||
className="text-2xl font-bold mb-3"
|
||||
>
|
||||
{isZh ? 'Instruction 安全约束' : 'Instruction Safety Constraints'}
|
||||
</h2>
|
||||
</Heading>
|
||||
<div className="p-4 bg-yellow-50 dark:bg-yellow-900/20 rounded-lg">
|
||||
<h3 className="text-lg font-semibold mb-2 text-yellow-900 dark:text-yellow-300">
|
||||
⚠️ {isZh ? '高危操作控制' : 'High-Risk Operation Control'}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import CodeEditor from '@/components/CodeEditor'
|
||||
import { Heading } from '@/components/Heading'
|
||||
import { useLanguage } from '@/i18n/context'
|
||||
|
||||
export default function ThirdPartyAgentPage() {
|
||||
@@ -26,7 +27,9 @@ export default function ThirdPartyAgentPage() {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h2 className="text-2xl font-bold mb-4">{isZh ? '集成方式' : 'Integration Method'}</h2>
|
||||
<Heading id="integration-method" level={2} className="text-2xl font-bold mb-4">
|
||||
{isZh ? '集成方式' : 'Integration Method'}
|
||||
</Heading>
|
||||
|
||||
<div className="space-y-4 mb-6">
|
||||
<div className="p-4 bg-green-50 dark:bg-green-900/20 rounded-lg">
|
||||
@@ -57,7 +60,9 @@ const pageAgentTool = {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 className="text-2xl font-bold mb-4">{isZh ? '应用场景' : 'Use Cases'}</h2>
|
||||
<Heading id="use-cases" level={2} className="text-2xl font-bold mb-4">
|
||||
{isZh ? '应用场景' : 'Use Cases'}
|
||||
</Heading>
|
||||
<div className="grid md:grid-cols-2 gap-4 mb-6">
|
||||
<div className="bg-linear-to-br from-blue-50 to-purple-50 dark:from-gray-800 dark:to-gray-700 p-4 rounded-lg">
|
||||
<h4 className="font-semibold mb-2 text-gray-900 dark:text-white">
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Link } from 'wouter'
|
||||
|
||||
import { Heading } from '@/components/Heading'
|
||||
import { useLanguage } from '@/i18n/context'
|
||||
|
||||
export default function LimitationsPage() {
|
||||
@@ -20,9 +21,9 @@ export default function LimitationsPage() {
|
||||
|
||||
<div className="prose prose-lg dark:prose-invert max-w-none">
|
||||
{/* PageAgent.js vs PageAgentExt */}
|
||||
<h2 className="text-2xl font-bold mb-3">
|
||||
<Heading id="pageagent-js-vs-pageagentext" level={2} className="text-2xl font-bold mb-3">
|
||||
{isZh ? 'PageAgent.js vs PageAgentExt' : 'PageAgent.js vs PageAgentExt'}
|
||||
</h2>
|
||||
</Heading>
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||
{isZh
|
||||
? 'PageAgent.js 是核心库,运行在页面内。PageAgentExt 是可选的浏览器扩展,提供额外的浏览器级控制能力。'
|
||||
@@ -37,7 +38,7 @@ export default function LimitationsPage() {
|
||||
<th className="text-left py-3 pl-4 font-semibold">
|
||||
PageAgentExt{' '}
|
||||
<Link
|
||||
href="/docs/features/chrome-extension"
|
||||
href="/features/chrome-extension"
|
||||
className="text-xs font-normal text-blue-600 dark:text-blue-400 hover:underline"
|
||||
>
|
||||
{isZh ? '了解更多' : 'learn more'}
|
||||
@@ -82,9 +83,9 @@ export default function LimitationsPage() {
|
||||
</div>
|
||||
|
||||
{/* Interaction Limitations */}
|
||||
<h2 className="text-2xl font-bold mb-3">
|
||||
<Heading id="interaction-capabilities" level={2} className="text-2xl font-bold mb-3">
|
||||
{isZh ? '交互能力' : 'Interaction Capabilities'}
|
||||
</h2>
|
||||
</Heading>
|
||||
<div className="bg-gray-50 dark:bg-gray-800 rounded-lg p-6 mb-6">
|
||||
<div className="grid md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
@@ -127,7 +128,9 @@ export default function LimitationsPage() {
|
||||
</div>
|
||||
|
||||
{/* Understanding Limitations */}
|
||||
<h2 className="text-2xl font-bold mb-3">{isZh ? '理解能力' : 'Understanding'}</h2>
|
||||
<Heading id="understanding" level={2} className="text-2xl font-bold mb-3">
|
||||
{isZh ? '理解能力' : 'Understanding'}
|
||||
</Heading>
|
||||
<div className="bg-amber-50 dark:bg-amber-900/20 border-l-4 border-amber-400 p-4 mb-6">
|
||||
<p className="text-amber-800 dark:text-amber-200 mb-2 font-medium">
|
||||
{isZh
|
||||
@@ -142,9 +145,9 @@ export default function LimitationsPage() {
|
||||
</div>
|
||||
|
||||
{/* Website Quality */}
|
||||
<h2 className="text-2xl font-bold mb-3">
|
||||
<Heading id="page-quality-matters" level={2} className="text-2xl font-bold mb-3">
|
||||
{isZh ? '网页质量影响' : 'Page Quality Matters'}
|
||||
</h2>
|
||||
</Heading>
|
||||
<div className="bg-gray-50 dark:bg-gray-800 rounded-lg p-6">
|
||||
<p className="text-gray-600 dark:text-gray-300 text-sm">
|
||||
{isZh
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Heading } from '@/components/Heading'
|
||||
import { useLanguage } from '@/i18n/context'
|
||||
|
||||
export default function Overview() {
|
||||
@@ -48,9 +49,9 @@ export default function Overview() {
|
||||
</div>
|
||||
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-4">
|
||||
<Heading id="what-is-page-agent" level={2} className="text-2xl font-bold mb-4">
|
||||
{isZh ? '什么是 page-agent?' : 'What is page-agent?'}
|
||||
</h2>
|
||||
</Heading>
|
||||
|
||||
<p className="text-gray-600 dark:text-gray-300 mb-8 leading-relaxed ">
|
||||
{isZh
|
||||
@@ -60,7 +61,9 @@ export default function Overview() {
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-3">{isZh ? '核心特性' : 'Core Features'}</h2>
|
||||
<Heading id="core-features" level={2} className="text-2xl font-bold mb-3">
|
||||
{isZh ? '核心特性' : 'Core Features'}
|
||||
</Heading>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-4 mb-8" role="list">
|
||||
<div className="p-4 bg-blue-50 dark:bg-blue-900/20 rounded-lg">
|
||||
@@ -108,9 +111,9 @@ export default function Overview() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 className="text-2xl font-bold mb-4">
|
||||
<Heading id="vs-browser-use" level={2} className="text-2xl font-bold mb-4">
|
||||
{isZh ? '与 browser-use 的区别' : 'vs. browser-use'}
|
||||
</h2>
|
||||
</Heading>
|
||||
|
||||
<div className="overflow-x-auto mb-8">
|
||||
<table className="w-full border-collapse border border-gray-300 dark:border-gray-600">
|
||||
@@ -174,7 +177,9 @@ export default function Overview() {
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h2 className="text-2xl font-bold mb-4">{isZh ? '应用场景' : 'Use Cases'}</h2>
|
||||
<Heading id="use-cases" level={2} className="text-2xl font-bold mb-4">
|
||||
{isZh ? '应用场景' : 'Use Cases'}
|
||||
</Heading>
|
||||
|
||||
<ul className="space-y-4 mb-8">
|
||||
<li className="flex items-start space-x-3">
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import CodeEditor from '@/components/CodeEditor'
|
||||
import { Heading } from '@/components/Heading'
|
||||
import { CDN_DEMO_CN_URL, CDN_DEMO_URL } from '@/constants'
|
||||
import { useLanguage } from '@/i18n/context'
|
||||
|
||||
@@ -13,7 +14,9 @@ export default function QuickStart() {
|
||||
{isZh ? '几分钟内完成 page-agent 的集成。' : 'Integrate page-agent in minutes.'}
|
||||
</p>
|
||||
|
||||
<h2 className="text-2xl font-bold mb-3">{isZh ? '安装步骤' : 'Installation Steps'}</h2>
|
||||
<Heading id="installation-steps" level={2} className="text-2xl font-bold mb-3">
|
||||
{isZh ? '安装步骤' : 'Installation Steps'}
|
||||
</Heading>
|
||||
|
||||
<div className="space-y-4 mb-6">
|
||||
{/* Demo CDN - One Line */}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useEffect, useRef, useState } from 'react'
|
||||
import { Link } from 'wouter'
|
||||
|
||||
import CodeEditor from '@/components/CodeEditor'
|
||||
import { Heading } from '@/components/Heading'
|
||||
import { useLanguage } from '@/i18n/context'
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -369,10 +370,14 @@ export default function TroubleshootingPage() {
|
||||
{/* Main content */}
|
||||
<div className="flex-1 min-w-0 space-y-12">
|
||||
{SECTIONS.map((section) => (
|
||||
<section key={section.id} id={section.id} className="scroll-mt-24">
|
||||
<h2 className="text-2xl font-bold mb-4 text-gray-900 dark:text-white">
|
||||
<section key={section.id} className="scroll-mt-24">
|
||||
<Heading
|
||||
id={section.id}
|
||||
level={2}
|
||||
className="text-2xl font-bold mb-4 text-gray-900 dark:text-white"
|
||||
>
|
||||
{isZh ? section.title.zh : section.title.en}
|
||||
</h2>
|
||||
</Heading>
|
||||
|
||||
{/* Symptom callout */}
|
||||
<div
|
||||
|
||||
15
packages/website/src/pages/home/HomeContent.tsx
Normal file
15
packages/website/src/pages/home/HomeContent.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import FeaturesSection from './FeaturesSection'
|
||||
import HeroSection from './HeroSection'
|
||||
import OneMoreThingSection from './OneMoreThingSection'
|
||||
import ScenariosSection from './ScenariosSection'
|
||||
|
||||
export default function HomeContent() {
|
||||
return (
|
||||
<>
|
||||
<HeroSection />
|
||||
<FeaturesSection />
|
||||
<ScenariosSection />
|
||||
<OneMoreThingSection />
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Suspense, lazy, useLayoutEffect } from 'react'
|
||||
import { Suspense, useLayoutEffect } from 'react'
|
||||
import { Route, Switch, useLocation } from 'wouter'
|
||||
|
||||
import HomePage from './pages/Home'
|
||||
import Footer from './components/Footer'
|
||||
import Header from './components/Header'
|
||||
import DocsPages from './pages/docs/index'
|
||||
|
||||
// const DocsPages = lazy(() => import('./pages/docs/index'))
|
||||
import HomeContent from './pages/home/HomeContent'
|
||||
|
||||
function ScrollToTop() {
|
||||
const [pathname] = useLocation()
|
||||
@@ -16,29 +16,37 @@ function ScrollToTop() {
|
||||
|
||||
export default function Router() {
|
||||
return (
|
||||
<Suspense>
|
||||
<ScrollToTop />
|
||||
<Switch>
|
||||
{/* Home page */}
|
||||
<Route path="/">
|
||||
<HomePage />
|
||||
</Route>
|
||||
<>
|
||||
<Header />
|
||||
<Suspense>
|
||||
<ScrollToTop />
|
||||
<Switch>
|
||||
<Route path="/">
|
||||
<main
|
||||
id="main-content"
|
||||
className="min-h-screen bg-linear-to-br from-blue-50 to-purple-50 dark:from-gray-900 dark:to-gray-800"
|
||||
>
|
||||
<HomeContent />
|
||||
</main>
|
||||
</Route>
|
||||
|
||||
{/* All docs pages */}
|
||||
<Route path="/docs" nest>
|
||||
<DocsPages />
|
||||
</Route>
|
||||
|
||||
{/* 404 */}
|
||||
<Route>
|
||||
<div className="min-h-screen bg-white dark:bg-gray-900 flex items-center justify-center">
|
||||
<div className="text-center">
|
||||
<h1 className="text-4xl font-bold mb-4 text-gray-900 dark:text-white">404</h1>
|
||||
<p className="text-xl text-gray-600 dark:text-gray-300">页面未找到</p>
|
||||
<Route path="/docs" nest>
|
||||
<div className="min-h-screen bg-white dark:bg-gray-900">
|
||||
<DocsPages />
|
||||
</div>
|
||||
</div>
|
||||
</Route>
|
||||
</Switch>
|
||||
</Suspense>
|
||||
</Route>
|
||||
|
||||
<Route>
|
||||
<div className="min-h-screen bg-white dark:bg-gray-900 flex items-center justify-center">
|
||||
<div className="text-center">
|
||||
<h1 className="text-4xl font-bold mb-4 text-gray-900 dark:text-white">404</h1>
|
||||
<p className="text-xl text-gray-600 dark:text-gray-300">Page not found</p>
|
||||
</div>
|
||||
</div>
|
||||
</Route>
|
||||
</Switch>
|
||||
</Suspense>
|
||||
<Footer />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ dotenvConfig({ path: resolve(__dirname, '../../.env') })
|
||||
|
||||
// Website Config (React Documentation Site)
|
||||
export default defineConfig(({ mode }) => ({
|
||||
base: './',
|
||||
base: '/page-agent/',
|
||||
clearScreen: false,
|
||||
plugins: [react(), tailwindcss()],
|
||||
build: {
|
||||
|
||||
Reference in New Issue
Block a user