@bluefly/openstandardagents 0.2.5-RC → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.devfile.yaml +1 -1
- package/.env.example +1 -1
- package/.github/ISSUE_TEMPLATE/bug_report.yml +63 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +40 -0
- package/.github/workflows/dependabot-comment.yml +34 -0
- package/.github/workflows/pr-comment.yml +33 -0
- package/.husky/pre-commit +5 -0
- package/.kiro/config.json +21 -0
- package/.kiro/settings/mcp.json +61 -0
- package/.kiro/specs/scripts-migration-api-first/design.md +883 -0
- package/.kiro/specs/scripts-migration-api-first/requirements.md +165 -0
- package/.kiro/specs/scripts-migration-api-first/tasks.md +539 -0
- package/.kiro/specs/{website-design-audit → website-brand-identity}/design.md +381 -0
- package/.kiro/specs/{website-design-audit → website-brand-identity}/requirements.md +88 -0
- package/.kiro/specs/website-brand-identity/tasks.md +981 -0
- package/.version.json +2 -2
- package/.wiki-config.json +24 -0
- package/CHANGELOG.md +34 -18
- package/CODEOWNERS +75 -0
- package/CONTRIBUTING.md +1 -1
- package/README.md +176 -239
- package/bin/ossa-dev +42 -0
- package/bin/ossa-export +32 -0
- package/bin/ossa-generate +60 -0
- package/bin/ossa-health +40 -0
- package/bin/ossa-init +26 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/repositories/schema.repository.d.ts +6 -1
- package/dist/repositories/schema.repository.d.ts.map +1 -1
- package/dist/repositories/schema.repository.js +63 -36
- package/dist/repositories/schema.repository.js.map +1 -1
- package/dist/services/github-sync/github-client.d.ts +14 -0
- package/dist/services/github-sync/github-client.d.ts.map +1 -0
- package/dist/services/github-sync/github-client.js +41 -0
- package/dist/services/github-sync/github-client.js.map +1 -0
- package/dist/services/github-sync/gitlab-client.d.ts +17 -0
- package/dist/services/github-sync/gitlab-client.d.ts.map +1 -0
- package/dist/services/github-sync/gitlab-client.js +42 -0
- package/dist/services/github-sync/gitlab-client.js.map +1 -0
- package/dist/services/github-sync/schemas.d.ts +46 -0
- package/dist/services/github-sync/schemas.d.ts.map +1 -0
- package/dist/services/github-sync/schemas.js +36 -0
- package/dist/services/github-sync/schemas.js.map +1 -0
- package/dist/services/github-sync/sync.service.d.ts +27 -0
- package/dist/services/github-sync/sync.service.d.ts.map +1 -0
- package/dist/services/github-sync/sync.service.js +99 -0
- package/dist/services/github-sync/sync.service.js.map +1 -0
- package/dist/services/migration.service.d.ts +4 -3
- package/dist/services/migration.service.d.ts.map +1 -1
- package/dist/services/migration.service.js +11 -10
- package/dist/services/migration.service.js.map +1 -1
- package/dist/services/release-automation/release.service.js +1 -1
- package/dist/services/release-automation/release.service.js.map +1 -1
- package/dist/services/release-automation/schemas/release.schema.js +1 -1
- package/dist/services/runtime/claude/capability-mapper.d.ts +84 -0
- package/dist/services/runtime/claude/capability-mapper.d.ts.map +1 -0
- package/dist/services/runtime/claude/capability-mapper.js +245 -0
- package/dist/services/runtime/claude/capability-mapper.js.map +1 -0
- package/dist/services/runtime/claude/claude-adapter.d.ts +80 -0
- package/dist/services/runtime/claude/claude-adapter.d.ts.map +1 -0
- package/dist/services/runtime/claude/claude-adapter.js +287 -0
- package/dist/services/runtime/claude/claude-adapter.js.map +1 -0
- package/dist/services/runtime/claude/manifest-parser.d.ts +77 -0
- package/dist/services/runtime/claude/manifest-parser.d.ts.map +1 -0
- package/dist/services/runtime/claude/manifest-parser.js +169 -0
- package/dist/services/runtime/claude/manifest-parser.js.map +1 -0
- package/dist/services/runtime/claude/types.d.ts +115 -0
- package/dist/services/runtime/claude/types.d.ts.map +1 -0
- package/dist/services/runtime/claude/types.js +6 -0
- package/dist/services/runtime/claude/types.js.map +1 -0
- package/dist/services/validation.service.d.ts.map +1 -1
- package/dist/services/validation.service.js +12 -1
- package/dist/services/validation.service.js.map +1 -1
- package/dist/spec/v0.2.4/ossa-0.2.4.schema.json +85 -208
- package/dist/spec/v0.2.6/CHANGELOG.md +401 -0
- package/dist/spec/v0.2.6/README.md +72 -0
- package/dist/spec/v0.2.6/migrations/v0.2.3-to-v0.2.4.md +599 -0
- package/dist/spec/v0.2.6/migrations/v0.2.5-RC-to-v0.2.6.md +65 -0
- package/dist/spec/{v0.2.4/ossa-0.2.4-dev.schema.json → v0.2.6/ossa-0.2.6.schema.json} +128 -38
- package/dist/spec/v0.2.6/ossa-0.2.6.yaml +581 -0
- package/dist/spec/v0.2.6-dev/CHANGELOG.md +164 -0
- package/dist/spec/v0.2.6-dev/README.md +75 -0
- package/dist/spec/v0.2.6-dev/migrations/v0.2.2-to-v0.2.3.md +343 -0
- package/dist/spec/v0.2.6-dev/migrations/v0.2.3-to-v0.2.4.md +599 -0
- package/dist/spec/v0.2.6-dev/ossa-0.2.5.yaml +581 -0
- package/dist/spec/v0.2.6-dev/ossa-0.2.6-dev.yaml +448 -0
- package/dist/spec/v0.2.7/core/agentgraph.md +324 -0
- package/dist/spec/v0.2.7/resources/agentgraph.yaml +135 -0
- package/dist/spec/v0.2.8/CHANGELOG.md +401 -0
- package/dist/spec/v0.2.8/README.md +72 -0
- package/dist/spec/v0.2.8/migrations/v0.2.3-to-v0.2.4.md +599 -0
- package/dist/spec/v0.2.8/migrations/v0.2.5-RC-to-v0.2.6.md +65 -0
- package/dist/spec/v0.2.8/migrations/v0.2.6-to-v0.2.8.md +81 -0
- package/dist/spec/v0.2.8/ossa-0.2.8.schema.json +3153 -0
- package/dist/spec/v0.2.8/ossa-0.2.8.yaml +581 -0
- package/dist/types/index.d.ts +3 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/version.d.ts +68 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +156 -0
- package/dist/utils/version.js.map +1 -0
- package/docs/brand-guide/01-brand-overview.md +37 -0
- package/docs/brand-guide/02-logo-usage.md +43 -0
- package/docs/brand-guide/03-color-palette.md +70 -0
- package/docs/brand-guide/04-typography.md +82 -0
- package/docs/brand-guide/05-voice-and-tone.md +108 -0
- package/docs/brand-guide/06-visual-elements.md +137 -0
- package/docs/brand-guide/07-application-examples.md +153 -0
- package/docs/brand-guide/OssaLogo/OssA_Logo.svg +21 -0
- package/docs/brand-guide/OssaLogo/brand.af +0 -0
- package/docs/brand-guide/README.md +107 -0
- package/docs/comparison.md +315 -0
- package/docs/operations/automation-roadmap.md +245 -0
- package/docs/operations/github-sync-strategy.md +357 -0
- package/eslint-report.json +1 -0
- package/examples/adk-integration/code-review-workflow.yml +1 -1
- package/examples/adk-integration/customer-support.yml +1 -1
- package/examples/adk-integration/data-pipeline.yml +1 -1
- package/examples/advanced/workflows/hybrid-model-strategy.yaml +1 -1
- package/examples/agent-manifests/critics/critic-agent.yaml +1 -1
- package/examples/agent-manifests/governors/governor-agent.yaml +1 -1
- package/examples/agent-manifests/integrators/integrator-agent.yaml +1 -1
- package/examples/agent-manifests/judges/judge-agent.yaml +1 -1
- package/examples/agent-manifests/monitors/monitor-agent.yaml +1 -1
- package/examples/agent-manifests/orchestrators/orchestrator-agent.yaml +1 -1
- package/examples/agent-manifests/sample-compliant-agent.yaml +1 -1
- package/examples/agent-manifests/workers/worker-agent.yaml +1 -1
- package/examples/anthropic/claude-assistant.ossa.json +5 -4
- package/examples/autogen/multi-agent.ossa.json +6 -4
- package/examples/claude-code/code-reviewer.ossa.yaml +78 -0
- package/examples/claude-code/ossa-validator.ossa.yaml +80 -0
- package/examples/common_npm/agent-router.ossa.yaml +1 -0
- package/examples/common_npm/agent-router.v0.2.2.ossa.yaml +1 -1
- package/examples/crewai/research-team.ossa.json +14 -5
- package/examples/cursor/code-review-agent.ossa.json +21 -6
- package/examples/drupal/gitlab-ml-recommender.ossa.yaml +1 -0
- package/examples/drupal/gitlab-ml-recommender.v0.2.2.ossa.yaml +1 -1
- package/examples/extensions/drupal-v1.yml +1 -1
- package/examples/extensions/kagent-v1.yml +1 -1
- package/examples/getting-started/hello-world-complete.ossa.yaml +1 -1
- package/examples/integration-patterns/agent-to-agent-orchestration.ossa.yaml +4 -4
- package/examples/kagent/compliance-validator.ossa.yaml +1 -1
- package/examples/kagent/cost-optimizer.ossa.yaml +1 -1
- package/examples/kagent/documentation-agent.ossa.yaml +1 -1
- package/examples/kagent/k8s-troubleshooter-v1.ossa.yaml +1 -0
- package/examples/kagent/k8s-troubleshooter-v1.v0.2.2.ossa.yaml +1 -1
- package/examples/kagent/k8s-troubleshooter.ossa.yaml +1 -1
- package/examples/kagent/security-scanner.ossa.yaml +1 -1
- package/examples/langchain/chain-agent.ossa.json +21 -5
- package/examples/langflow/workflow-agent.ossa.json +2 -3
- package/examples/langgraph/state-machine-agent.ossa.json +2 -3
- package/examples/llamaindex/rag-agent.ossa.json +2 -3
- package/examples/migration-guides/from-langchain-to-ossa.yaml +4 -4
- package/examples/multi-agent/README.md +74 -0
- package/examples/multi-agent/conditional-router.ossa.yaml +42 -0
- package/examples/multi-agent/parallel-execution.ossa.yaml +54 -0
- package/examples/multi-agent/sequential-pipeline.ossa.yaml +45 -0
- package/examples/openai/basic-agent.ossa.yaml +1 -1
- package/examples/openai/multi-tool-agent.ossa.json +33 -10
- package/examples/openai/swarm-agent.ossa.json +18 -5
- package/examples/production/document-analyzer-openai.yml +1 -1
- package/examples/quickstart/support-agent.ossa.yaml +1 -1
- package/examples/spec-examples/audit-agent.yml +1 -1
- package/examples/spec-examples/chat-agent.yml +1 -1
- package/examples/spec-examples/compliance-agent.yml +1 -1
- package/examples/spec-examples/monitoring-agent.yml +1 -1
- package/examples/spec-examples/workflow-agent.yml +1 -1
- package/examples/templates/ossa-compliance.yaml +1 -1
- package/examples/vercel/edge-agent.ossa.json +5 -4
- package/gl-code-quality-report.json +62 -0
- package/llms-ctx-full.txt +39 -0
- package/llms-ctx.txt +39 -0
- package/llms.txt +47 -0
- package/openapi/github-sync.yaml +115 -0
- package/package.json +26 -4
- package/scripts/README.md +103 -0
- package/scripts/auto-rebase-mrs.ts +106 -0
- package/scripts/batch-dependabot.sh +57 -0
- package/scripts/configure-gitlab-branch-protection.ts +95 -0
- package/scripts/create-issue-helper.ts +238 -0
- package/scripts/create-milestone-issue.ts +73 -0
- package/scripts/eslint-to-codequality.cjs +34 -0
- package/scripts/fix-schema-formats.js +82 -0
- package/scripts/generate-agents-catalog.ts +77 -0
- package/scripts/generate-api-docs.ts +218 -0
- package/scripts/generate-cli-docs.ts +410 -0
- package/scripts/generate-config-docs.ts +109 -0
- package/scripts/generate-errors-docs.ts +76 -0
- package/scripts/generate-examples-docs.ts +99 -0
- package/scripts/generate-llms-ctx.sh +17 -0
- package/scripts/generate-schema-docs.ts +317 -0
- package/scripts/generate-types-docs.ts +48 -0
- package/scripts/lowercase-docs.ts +43 -0
- package/scripts/manage-milestone-mrs.ts +279 -0
- package/scripts/rebase-all-mrs.sh +75 -0
- package/scripts/sync-github-pr.sh +48 -0
- package/scripts/sync-version.js +32 -0
- package/scripts/sync-wiki.sh +50 -0
- package/scripts/validate-all.js +127 -0
- package/scripts/validate-schema.ts +2 -1
- package/spec/v0.2.4/ossa-0.2.4.schema.json +85 -208
- package/spec/v0.2.6/CHANGELOG.md +401 -0
- package/spec/v0.2.6/README.md +72 -0
- package/spec/v0.2.6/migrations/v0.2.3-to-v0.2.4.md +599 -0
- package/spec/v0.2.6/migrations/v0.2.5-RC-to-v0.2.6.md +65 -0
- package/spec/{v0.2.4/ossa-0.2.4-dev.schema.json → v0.2.6/ossa-0.2.6.schema.json} +128 -38
- package/spec/v0.2.6/ossa-0.2.6.yaml +581 -0
- package/spec/v0.2.6-dev/CHANGELOG.md +164 -0
- package/spec/v0.2.6-dev/README.md +75 -0
- package/spec/v0.2.6-dev/migrations/v0.2.2-to-v0.2.3.md +343 -0
- package/spec/v0.2.6-dev/migrations/v0.2.3-to-v0.2.4.md +599 -0
- package/spec/v0.2.6-dev/ossa-0.2.5.yaml +581 -0
- package/spec/v0.2.6-dev/ossa-0.2.6-dev.yaml +448 -0
- package/spec/v0.2.7/core/agentgraph.md +324 -0
- package/spec/v0.2.7/resources/agentgraph.yaml +135 -0
- package/spec/v0.2.8/CHANGELOG.md +401 -0
- package/spec/v0.2.8/README.md +72 -0
- package/spec/v0.2.8/migrations/v0.2.3-to-v0.2.4.md +599 -0
- package/spec/v0.2.8/migrations/v0.2.5-RC-to-v0.2.6.md +65 -0
- package/spec/v0.2.8/migrations/v0.2.6-to-v0.2.8.md +81 -0
- package/spec/v0.2.8/ossa-0.2.8.schema.json +3153 -0
- package/spec/v0.2.8/ossa-0.2.8.yaml +581 -0
- package/test-results/junit.xml +299 -0
- package/.kiro/specs/agent-buildkit-templates/design.md +0 -495
- package/.kiro/specs/agent-buildkit-templates/requirements.md +0 -165
- package/.kiro/specs/kiro-ide-supercharger/README.md +0 -202
- package/.kiro/specs/kiro-ide-supercharger/design.md +0 -1005
- package/.kiro/specs/kiro-ide-supercharger/requirements.md +0 -141
- package/.kiro/specs/kiro-ide-supercharger/tasks.md +0 -507
- package/bin/validate-ossa-0.2.5-RC.ts +0 -244
- package/docs/issue-19-completion-summary.md +0 -648
- package/docs/issue-19-validation.md +0 -351
- package/scripts/lib/exec.ts +0 -37
- package/scripts/lib/file-ops.ts +0 -58
- package/scripts/lib/version.ts +0 -83
- package/website/.lighthouserc.ts +0 -24
- package/website/.prettierrc +0 -10
- package/website/Dockerfile +0 -30
- package/website/app/about/page.tsx +0 -295
- package/website/app/blog/[slug]/page.tsx +0 -208
- package/website/app/blog/page.tsx +0 -249
- package/website/app/design-guide/page.tsx +0 -511
- package/website/app/docs/[[...slug]]/page.tsx +0 -847
- package/website/app/docs/core-concepts/project-structure/page.tsx +0 -349
- package/website/app/ecosystem/page.tsx +0 -375
- package/website/app/examples/page.tsx +0 -133
- package/website/app/globals.scss +0 -135
- package/website/app/layout.tsx +0 -106
- package/website/app/license/page.tsx +0 -183
- package/website/app/not-found.tsx +0 -18
- package/website/app/page.tsx +0 -474
- package/website/app/playground/page.tsx +0 -487
- package/website/app/robots.ts +0 -19
- package/website/app/rss.xml/route.ts +0 -74
- package/website/app/schema/page.tsx +0 -1001
- package/website/app/sitemap.ts +0 -56
- package/website/app/specification/page.tsx +0 -287
- package/website/components/InstallCommand.tsx +0 -96
- package/website/components/Logo.tsx +0 -97
- package/website/components/StructuredData.tsx +0 -65
- package/website/components/docs/DocsSearch.tsx +0 -104
- package/website/components/docs/DocsSidebar.tsx +0 -155
- package/website/components/docs/MarkdownContent.tsx +0 -401
- package/website/components/docs/VersionSelector.tsx +0 -105
- package/website/components/examples/ExamplesViewer.tsx +0 -293
- package/website/components/layout/Footer.tsx +0 -116
- package/website/components/layout/Header.tsx +0 -168
- package/website/components/schema/SchemaComponentsAccordion.tsx +0 -84
- package/website/components/schema/SchemaExplorer.tsx +0 -213
- package/website/content/blog/OpenAPI-AI-Agents-Standard.md +0 -285
- package/website/content/blog/Why-Formal-Standards-Matter-Now.md +0 -198
- package/website/content/blog/gitlab-kubernetes-agent-ecosystem.md +0 -286
- package/website/content/blog/introducing-ossa-framework.md +0 -328
- package/website/content/blog/ossa-production-results.md +0 -279
- package/website/content/blog/welcome-to-ossa.md +0 -43
- package/website/content/blog/why-ai-agents-need-open-standard.md +0 -98
- package/website/content/docs/00-HOME.md +0 -153
- package/website/content/docs/AIFlow-Framework-Integration-with-OSSA.md +0 -107
- package/website/content/docs/Examples.md +0 -71
- package/website/content/docs/OpenAPI-Extensions.md +0 -934
- package/website/content/docs/adapters/openai-adapter.md +0 -693
- package/website/content/docs/architecture/execution-flow.md +0 -335
- package/website/content/docs/architecture/multi-agent-systems.md +0 -737
- package/website/content/docs/architecture/overview.md +0 -121
- package/website/content/docs/architecture/stack-integration.md +0 -461
- package/website/content/docs/changelog.md +0 -246
- package/website/content/docs/contributing.md +0 -599
- package/website/content/docs/core-concepts/Project-Structure.md +0 -348
- package/website/content/docs/ecosystem/framework-support.md +0 -819
- package/website/content/docs/ecosystem/overview.md +0 -366
- package/website/content/docs/examples/AIFlow-Framework-Integration-with-OSSA.md +0 -107
- package/website/content/docs/examples/Migration-Guides.md +0 -214
- package/website/content/docs/for-audiences/Architects.md +0 -224
- package/website/content/docs/for-audiences/Developers.md +0 -220
- package/website/content/docs/for-audiences/Enterprises.md +0 -256
- package/website/content/docs/for-audiences/Students-Researchers.md +0 -122
- package/website/content/docs/getting-started/5-Minute-Overview.md +0 -85
- package/website/content/docs/getting-started/First-Agent.md +0 -196
- package/website/content/docs/getting-started/Hello-World.md +0 -184
- package/website/content/docs/getting-started/Installation.md +0 -155
- package/website/content/docs/getting-started/index.md +0 -92
- package/website/content/docs/getting-started/running-agents.md +0 -309
- package/website/content/docs/getting-started.md +0 -91
- package/website/content/docs/integrations/aiflow.md +0 -104
- package/website/content/docs/integrations/drupal.md +0 -105
- package/website/content/docs/migration-guides/00-INDEX.md +0 -76
- package/website/content/docs/migration-guides/README.md +0 -133
- package/website/content/docs/migration-guides/agent-schema-comparison.md +0 -232
- package/website/content/docs/migration-guides/anthropic-mcp-to-ossa.md +0 -1750
- package/website/content/docs/migration-guides/crewai-to-ossa.md +0 -274
- package/website/content/docs/migration-guides/drupal-eca-to-ossa.md +0 -2017
- package/website/content/docs/migration-guides/general-agent-schema.yml +0 -247
- package/website/content/docs/migration-guides/index.md +0 -133
- package/website/content/docs/migration-guides/langchain-to-ossa.md +0 -1714
- package/website/content/docs/migration-guides/langflow-to-ossa.md +0 -2075
- package/website/content/docs/migration-guides/migration-manifest.json +0 -64
- package/website/content/docs/migration-guides/openai-to-ossa.md +0 -1202
- package/website/content/docs/openapi-extensions/examples.md +0 -550
- package/website/content/docs/openapi-extensions/index.md +0 -551
- package/website/content/docs/openapi-extensions/operation-extensions.md +0 -457
- package/website/content/docs/openapi-extensions/root-extensions.md +0 -410
- package/website/content/docs/ossa-compliant-badge.md +0 -251
- package/website/content/docs/pre-release/index.md +0 -175
- package/website/content/docs/quick-reference.md +0 -17
- package/website/content/docs/readme.md +0 -35
- package/website/content/docs/schema-reference/agent-spec.md +0 -406
- package/website/content/docs/schema-reference/autonomy.md +0 -568
- package/website/content/docs/schema-reference/constraints.md +0 -543
- package/website/content/docs/schema-reference/index.md +0 -176
- package/website/content/docs/schema-reference/llm-config.md +0 -445
- package/website/content/docs/schema-reference/observability.md +0 -654
- package/website/content/docs/schema-reference/ossa-manifest.md +0 -309
- package/website/content/docs/schema-reference/taxonomy.md +0 -509
- package/website/content/docs/schema-reference/tools.md +0 -628
- package/website/content/docs/templates/blog-post.md +0 -43
- package/website/content/docs/use-cases/00-index.md +0 -395
- package/website/content/docs/use-cases/cicd-code-review.md +0 -1236
- package/website/content/docs/use-cases/customer-support.md +0 -1234
- package/website/content/docs/use-cases/enterprise-compliance.md +0 -1208
- package/website/content/docs/use-cases/research-multi-agent.md +0 -1161
- package/website/content/docs/versioning.md +0 -288
- package/website/lib/version.ts +0 -35
- package/website/lib/versions.json +0 -78
- package/website/next.config.ts +0 -18
- package/website/nginx.conf +0 -32
- package/website/package-lock.json +0 -9679
- package/website/package.json +0 -59
- package/website/postcss.config.mjs +0 -9
- package/website/scripts/fetch-versions.js +0 -166
- package/website/scripts/generate-examples-index.js +0 -163
- package/website/scripts/merge-docs-to-wiki.ts +0 -207
- package/website/scripts/sync-version.js +0 -72
- package/website/scripts/sync-wiki.ts +0 -322
- package/website/scripts/upload-wiki.ts +0 -199
- package/website/styles/_variables.scss +0 -36
- package/website/tailwind.config.ts +0 -136
- /package/dist/spec/v0.2.4/{ossa-0.2.4-dev.yaml → ossa-0.2.4.yaml} +0 -0
- /package/spec/v0.2.4/{ossa-0.2.4-dev.yaml → ossa-0.2.4.yaml} +0 -0
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { useState, useMemo } from 'react';
|
|
4
|
-
import Link from 'next/link';
|
|
5
|
-
|
|
6
|
-
interface SearchResult {
|
|
7
|
-
title: string;
|
|
8
|
-
href: string;
|
|
9
|
-
category: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const allDocs: SearchResult[] = [
|
|
13
|
-
{ title: '5-Minute Overview', href: '/docs/getting-started/5-minute-overview', category: 'Getting Started' },
|
|
14
|
-
{ title: 'Installation', href: '/docs/getting-started/installation', category: 'Getting Started' },
|
|
15
|
-
{ title: 'Hello World', href: '/docs/getting-started/hello-world', category: 'Getting Started' },
|
|
16
|
-
{ title: 'First Agent', href: '/docs/getting-started/first-agent', category: 'Getting Started' },
|
|
17
|
-
{ title: 'For Developers', href: '/docs/for-audiences/developers', category: 'For Audiences' },
|
|
18
|
-
{ title: 'For Architects', href: '/docs/for-audiences/architects', category: 'For Audiences' },
|
|
19
|
-
{ title: 'For Enterprises', href: '/docs/for-audiences/enterprises', category: 'For Audiences' },
|
|
20
|
-
{ title: 'For Students & Researchers', href: '/docs/for-audiences/students-researchers', category: 'For Audiences' },
|
|
21
|
-
{ title: 'Migration Guides', href: '/docs/examples/migration-guides', category: 'Examples' },
|
|
22
|
-
];
|
|
23
|
-
|
|
24
|
-
export function DocsSearch() {
|
|
25
|
-
const [query, setQuery] = useState('');
|
|
26
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
27
|
-
|
|
28
|
-
const results = useMemo(() => {
|
|
29
|
-
if (!query.trim()) {
|
|
30
|
-
return [];
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const lowerQuery = query.toLowerCase();
|
|
34
|
-
return allDocs.filter(
|
|
35
|
-
(doc) =>
|
|
36
|
-
doc.title.toLowerCase().includes(lowerQuery) ||
|
|
37
|
-
doc.category.toLowerCase().includes(lowerQuery)
|
|
38
|
-
);
|
|
39
|
-
}, [query]);
|
|
40
|
-
|
|
41
|
-
return (
|
|
42
|
-
<div className="relative">
|
|
43
|
-
<div className="relative">
|
|
44
|
-
<input
|
|
45
|
-
type="search"
|
|
46
|
-
placeholder="Search documentation..."
|
|
47
|
-
value={query}
|
|
48
|
-
onChange={(e) => setQuery(e.target.value)}
|
|
49
|
-
onFocus={() => setIsOpen(true)}
|
|
50
|
-
onBlur={() => setTimeout(() => setIsOpen(false), 200)}
|
|
51
|
-
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary"
|
|
52
|
-
aria-label="Search documentation"
|
|
53
|
-
aria-describedby="search-description"
|
|
54
|
-
role="searchbox"
|
|
55
|
-
/>
|
|
56
|
-
<svg
|
|
57
|
-
className="absolute right-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400"
|
|
58
|
-
fill="none"
|
|
59
|
-
stroke="currentColor"
|
|
60
|
-
viewBox="0 0 24 24"
|
|
61
|
-
>
|
|
62
|
-
<path
|
|
63
|
-
strokeLinecap="round"
|
|
64
|
-
strokeLinejoin="round"
|
|
65
|
-
strokeWidth={2}
|
|
66
|
-
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
|
67
|
-
/>
|
|
68
|
-
</svg>
|
|
69
|
-
</div>
|
|
70
|
-
|
|
71
|
-
{isOpen && results.length > 0 && (
|
|
72
|
-
<div
|
|
73
|
-
className="absolute z-50 w-full mt-2 bg-white border border-gray-300 rounded-lg shadow-lg max-h-96 overflow-y-auto"
|
|
74
|
-
role="listbox"
|
|
75
|
-
aria-label="Search results"
|
|
76
|
-
>
|
|
77
|
-
{results.map((result) => (
|
|
78
|
-
<Link
|
|
79
|
-
key={result.href}
|
|
80
|
-
href={result.href}
|
|
81
|
-
className="block px-4 py-3 hover:bg-gray-100 transition-colors focus:outline-none focus:ring-2 focus:ring-primary"
|
|
82
|
-
onClick={() => {
|
|
83
|
-
setQuery('');
|
|
84
|
-
setIsOpen(false);
|
|
85
|
-
}}
|
|
86
|
-
role="option"
|
|
87
|
-
aria-label={`${result.title} in ${result.category}`}
|
|
88
|
-
>
|
|
89
|
-
<div className="font-semibold text-gray-900">{result.title}</div>
|
|
90
|
-
<div className="text-sm text-gray-500">{result.category}</div>
|
|
91
|
-
</Link>
|
|
92
|
-
))}
|
|
93
|
-
</div>
|
|
94
|
-
)}
|
|
95
|
-
|
|
96
|
-
{isOpen && query.trim() && results.length === 0 && (
|
|
97
|
-
<div className="absolute z-50 w-full mt-2 bg-white border border-gray-300 rounded-lg shadow-lg p-4">
|
|
98
|
-
<p className="text-gray-500">No results found</p>
|
|
99
|
-
</div>
|
|
100
|
-
)}
|
|
101
|
-
</div>
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import Link from 'next/link';
|
|
4
|
-
import { usePathname } from 'next/navigation';
|
|
5
|
-
import { useState, useEffect } from 'react';
|
|
6
|
-
import { DocsSearch } from './DocsSearch';
|
|
7
|
-
import { VersionSelector } from './VersionSelector';
|
|
8
|
-
|
|
9
|
-
const navigation = [
|
|
10
|
-
{
|
|
11
|
-
title: 'Getting Started',
|
|
12
|
-
items: [
|
|
13
|
-
{ href: '/docs/getting-started/5-minute-overview', label: '5-Minute Overview' },
|
|
14
|
-
{ href: '/docs/getting-started/installation', label: 'Installation' },
|
|
15
|
-
{ href: '/docs/getting-started/hello-world', label: 'Hello World' },
|
|
16
|
-
{ href: '/docs/getting-started/first-agent', label: 'First Agent' },
|
|
17
|
-
],
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
title: 'For Audiences',
|
|
21
|
-
items: [
|
|
22
|
-
{ href: '/docs/for-audiences/developers', label: 'Developers' },
|
|
23
|
-
{ href: '/docs/for-audiences/architects', label: 'Architects' },
|
|
24
|
-
{ href: '/docs/for-audiences/enterprises', label: 'Enterprises' },
|
|
25
|
-
{ href: '/docs/for-audiences/students-researchers', label: 'Students & Researchers' },
|
|
26
|
-
],
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
title: 'Migration Guides',
|
|
30
|
-
items: [
|
|
31
|
-
{ href: '/docs/migration-guides/anthropic-mcp-to-ossa', label: 'Anthropic MCP to OSSA' },
|
|
32
|
-
{ href: '/docs/migration-guides/openai-to-ossa', label: 'OpenAI to OSSA' },
|
|
33
|
-
{ href: '/docs/migration-guides/langchain-to-ossa', label: 'LangChain to OSSA' },
|
|
34
|
-
{ href: '/docs/migration-guides/crewai-to-ossa', label: 'CrewAI to OSSA' },
|
|
35
|
-
{ href: '/docs/migration-guides/langflow-to-ossa', label: 'Langflow to OSSA' },
|
|
36
|
-
{ href: '/docs/migration-guides/drupal-eca-to-ossa', label: 'Drupal ECA to OSSA' },
|
|
37
|
-
],
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
title: 'Ecosystem',
|
|
41
|
-
items: [
|
|
42
|
-
{ href: '/docs/ecosystem/overview', label: 'Ecosystem Overview' },
|
|
43
|
-
{ href: '/docs/ecosystem/framework-support', label: 'Framework Support' },
|
|
44
|
-
],
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
title: 'Reference',
|
|
48
|
-
items: [
|
|
49
|
-
{ href: '/docs/openapi-extensions', label: 'OpenAPI Extensions' },
|
|
50
|
-
{ href: '/docs/quick-reference', label: 'Quick Reference' },
|
|
51
|
-
{ href: '/docs/changelog', label: 'Changelog' },
|
|
52
|
-
],
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
title: 'Contributing',
|
|
56
|
-
items: [
|
|
57
|
-
{ href: '/docs/contributing', label: 'Contributing Guide' },
|
|
58
|
-
{ href: '/docs/aiflow-framework-integration-with-ossa', label: 'AIFlow Framework Integration' },
|
|
59
|
-
],
|
|
60
|
-
},
|
|
61
|
-
];
|
|
62
|
-
|
|
63
|
-
export function DocsSidebar() {
|
|
64
|
-
const pathname = usePathname();
|
|
65
|
-
|
|
66
|
-
// Calculate initial open sections based on pathname to avoid hydration mismatch
|
|
67
|
-
const getInitialOpenSections = (): string[] => {
|
|
68
|
-
const sections: string[] = ['Getting Started'];
|
|
69
|
-
const currentSection = navigation.find((section) =>
|
|
70
|
-
section.items.some((item) => item.href === pathname)
|
|
71
|
-
);
|
|
72
|
-
if (currentSection && !sections.includes(currentSection.title)) {
|
|
73
|
-
sections.push(currentSection.title);
|
|
74
|
-
}
|
|
75
|
-
return sections;
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const [openSections, setOpenSections] = useState<string[]>(getInitialOpenSections);
|
|
79
|
-
|
|
80
|
-
// Update open sections when pathname changes (for client-side navigation)
|
|
81
|
-
useEffect(() => {
|
|
82
|
-
const currentSection = navigation.find((section) =>
|
|
83
|
-
section.items.some((item) => item.href === pathname)
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
if (currentSection) {
|
|
87
|
-
setOpenSections((prev) => {
|
|
88
|
-
// Only add if not already in the array
|
|
89
|
-
if (!prev.includes(currentSection.title)) {
|
|
90
|
-
return [...prev, currentSection.title];
|
|
91
|
-
}
|
|
92
|
-
return prev;
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
}, [pathname]);
|
|
96
|
-
|
|
97
|
-
const toggleSection = (title: string): void => {
|
|
98
|
-
setOpenSections((prev) =>
|
|
99
|
-
prev.includes(title)
|
|
100
|
-
? prev.filter((t) => t !== title)
|
|
101
|
-
: [...prev, title]
|
|
102
|
-
);
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
return (
|
|
106
|
-
<aside className="w-64 bg-gray-100 border-r border-gray-300 p-4 overflow-y-auto h-screen sticky top-0">
|
|
107
|
-
<nav>
|
|
108
|
-
<Link href="/docs" className="block mb-6 font-semibold text-primary hover:text-accent">
|
|
109
|
-
Documentation
|
|
110
|
-
</Link>
|
|
111
|
-
<div className="mb-6">
|
|
112
|
-
<DocsSearch />
|
|
113
|
-
</div>
|
|
114
|
-
<div className="mb-6">
|
|
115
|
-
<VersionSelector />
|
|
116
|
-
</div>
|
|
117
|
-
{navigation.map((section) => (
|
|
118
|
-
<div key={section.title} className="mb-4">
|
|
119
|
-
<button
|
|
120
|
-
onClick={() => toggleSection(section.title)}
|
|
121
|
-
className="w-full text-left font-semibold text-gray-900 mb-2 flex items-center justify-between"
|
|
122
|
-
>
|
|
123
|
-
<span>{section.title}</span>
|
|
124
|
-
<span className="text-gray-500">
|
|
125
|
-
{openSections.includes(section.title) ? '−' : '+'}
|
|
126
|
-
</span>
|
|
127
|
-
</button>
|
|
128
|
-
{openSections.includes(section.title) && (
|
|
129
|
-
<ul className="space-y-1 ml-2">
|
|
130
|
-
{section.items.map((item) => {
|
|
131
|
-
const isActive = pathname === item.href;
|
|
132
|
-
return (
|
|
133
|
-
<li key={item.href}>
|
|
134
|
-
<Link
|
|
135
|
-
href={item.href}
|
|
136
|
-
className={`block px-2 py-1 rounded text-sm transition-colors ${
|
|
137
|
-
isActive
|
|
138
|
-
? 'bg-primary text-white'
|
|
139
|
-
: 'text-gray-700 hover:bg-gray-200'
|
|
140
|
-
}`}
|
|
141
|
-
>
|
|
142
|
-
{item.label}
|
|
143
|
-
</Link>
|
|
144
|
-
</li>
|
|
145
|
-
);
|
|
146
|
-
})}
|
|
147
|
-
</ul>
|
|
148
|
-
)}
|
|
149
|
-
</div>
|
|
150
|
-
))}
|
|
151
|
-
</nav>
|
|
152
|
-
</aside>
|
|
153
|
-
);
|
|
154
|
-
}
|
|
155
|
-
|
|
@@ -1,401 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import React, { useEffect } from 'react';
|
|
4
|
-
import ReactMarkdown from 'react-markdown';
|
|
5
|
-
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
|
6
|
-
import { vscDarkPlus } from 'react-syntax-highlighter/dist/cjs/styles/prism';
|
|
7
|
-
import remarkGfm from 'remark-gfm';
|
|
8
|
-
import Link from 'next/link';
|
|
9
|
-
import { usePathname } from 'next/navigation';
|
|
10
|
-
|
|
11
|
-
interface MarkdownContentProps {
|
|
12
|
-
content: string;
|
|
13
|
-
currentPath?: string; // Current pathname for resolving relative links
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// Helper function to generate ID from heading text
|
|
17
|
-
function generateId(text: string): string {
|
|
18
|
-
// Extract ID from {#id} syntax if present
|
|
19
|
-
const idMatch = text.match(/\{#([^}]+)\}/);
|
|
20
|
-
if (idMatch) {
|
|
21
|
-
return idMatch[1];
|
|
22
|
-
}
|
|
23
|
-
// Otherwise generate from text
|
|
24
|
-
return text
|
|
25
|
-
.toString()
|
|
26
|
-
.toLowerCase()
|
|
27
|
-
.replace(/[^\w\s-]/g, '')
|
|
28
|
-
.replace(/\s+/g, '-')
|
|
29
|
-
.replace(/-+/g, '-')
|
|
30
|
-
.trim();
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Helper function to clean heading text (remove {#id} syntax)
|
|
34
|
-
function cleanHeadingText(text: string): string {
|
|
35
|
-
return text.replace(/\s*\{#[^}]+\}\s*$/, '').trim();
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Helper function to fix markdown bold syntax with spaces
|
|
39
|
-
function fixMarkdownBold(content: string): string {
|
|
40
|
-
// Fix patterns like "** text**" or "**text **" to "**text**"
|
|
41
|
-
// Also handle cases where ** is at the start of a line or after a heading
|
|
42
|
-
return content
|
|
43
|
-
// Fix "** text" patterns (space after opening **)
|
|
44
|
-
.replace(/\*\* +([^*]+?)\*\*/g, '**$1**')
|
|
45
|
-
// Fix "text **" patterns (space before closing **)
|
|
46
|
-
.replace(/\*\*([^*]+?) +\*\*/g, '**$1**')
|
|
47
|
-
// Fix "** text **" patterns (spaces on both sides)
|
|
48
|
-
.replace(/\*\* +([^*]+?) +\*\*/g, '**$1**');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Helper function to resolve relative markdown links to Next.js routes
|
|
52
|
-
function resolveMarkdownLink(href: string, currentPath: string): string {
|
|
53
|
-
// Already absolute or external
|
|
54
|
-
if (href.startsWith('/') || href.startsWith('http') || href.startsWith('#')) {
|
|
55
|
-
return href;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Split anchor from path
|
|
59
|
-
const [pathPart, anchor] = href.split('#');
|
|
60
|
-
const anchorPart = anchor ? `#${anchor}` : '';
|
|
61
|
-
|
|
62
|
-
// Remove .md extension
|
|
63
|
-
let normalized = pathPart.replace(/\.md$/, '');
|
|
64
|
-
|
|
65
|
-
// Handle relative paths starting with ./
|
|
66
|
-
if (normalized.startsWith('./')) {
|
|
67
|
-
normalized = normalized.slice(2);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Convert PascalCase/CamelCase to kebab-case
|
|
71
|
-
normalized = normalized
|
|
72
|
-
.replace(/([a-z])([A-Z])/g, '$1-$2') // Insert dash before capital letters
|
|
73
|
-
.toLowerCase()
|
|
74
|
-
.replace(/[^a-z0-9/-]/g, '-') // Replace non-alphanumeric with dash
|
|
75
|
-
.replace(/-+/g, '-') // Collapse multiple dashes
|
|
76
|
-
.replace(/^-|-$/g, ''); // Remove leading/trailing dashes
|
|
77
|
-
|
|
78
|
-
// If currentPath is provided, resolve relative to it
|
|
79
|
-
if (currentPath && !normalized.startsWith('/')) {
|
|
80
|
-
// Get the directory of the current page
|
|
81
|
-
const pathParts = currentPath.split('/').filter(Boolean);
|
|
82
|
-
// Remove the last part (current file) to get directory
|
|
83
|
-
const currentDir = pathParts.slice(0, -1);
|
|
84
|
-
|
|
85
|
-
// Handle parent directory references (../)
|
|
86
|
-
if (normalized.startsWith('../')) {
|
|
87
|
-
const upLevels = (normalized.match(/\.\.\//g) || []).length;
|
|
88
|
-
normalized = normalized.replace(/\.\.\//g, '');
|
|
89
|
-
const newDir = currentDir.slice(0, -upLevels);
|
|
90
|
-
return `/docs/${newDir.join('/')}/${normalized}${anchorPart}`;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Same directory or subdirectory
|
|
94
|
-
if (currentDir.length > 0) {
|
|
95
|
-
return `/docs/${currentDir.join('/')}/${normalized}${anchorPart}`;
|
|
96
|
-
}
|
|
97
|
-
return `/docs/${normalized}${anchorPart}`;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Default to /docs/ prefix if no current path
|
|
101
|
-
return `/docs/${normalized}${anchorPart}`;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export function MarkdownContent({ content, currentPath }: MarkdownContentProps) {
|
|
105
|
-
const pathname = usePathname();
|
|
106
|
-
const basePath = currentPath || pathname;
|
|
107
|
-
|
|
108
|
-
// Handle anchor link scrolling on mount and hash changes
|
|
109
|
-
useEffect(() => {
|
|
110
|
-
const handleHashChange = () => {
|
|
111
|
-
const hash = window.location.hash.slice(1);
|
|
112
|
-
if (hash) {
|
|
113
|
-
setTimeout(() => {
|
|
114
|
-
const element = document.getElementById(hash);
|
|
115
|
-
if (element) {
|
|
116
|
-
element.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
117
|
-
// Offset for sticky header
|
|
118
|
-
window.scrollBy(0, -80);
|
|
119
|
-
}
|
|
120
|
-
}, 100);
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
handleHashChange();
|
|
125
|
-
window.addEventListener('hashchange', handleHashChange);
|
|
126
|
-
return () => window.removeEventListener('hashchange', handleHashChange);
|
|
127
|
-
}, [pathname]);
|
|
128
|
-
|
|
129
|
-
// Fix markdown bold syntax issues
|
|
130
|
-
const fixedContent = fixMarkdownBold(content);
|
|
131
|
-
|
|
132
|
-
return (
|
|
133
|
-
<div className="markdown-content [&_pre_code]:bg-transparent [&_pre_code]:text-code-text">
|
|
134
|
-
<ReactMarkdown
|
|
135
|
-
remarkPlugins={[remarkGfm]}
|
|
136
|
-
components={{
|
|
137
|
-
// Headings with IDs
|
|
138
|
-
h1: ({ children }) => {
|
|
139
|
-
const text = React.Children.toArray(children).join('');
|
|
140
|
-
const id = generateId(text);
|
|
141
|
-
const cleanText = cleanHeadingText(text);
|
|
142
|
-
return (
|
|
143
|
-
<h1
|
|
144
|
-
id={id}
|
|
145
|
-
className="text-3xl md:text-4xl font-bold text-gray-900 mt-8 mb-4 pb-2 border-b border-gray-200 scroll-mt-20"
|
|
146
|
-
>
|
|
147
|
-
{cleanText}
|
|
148
|
-
</h1>
|
|
149
|
-
);
|
|
150
|
-
},
|
|
151
|
-
h2: ({ children }) => {
|
|
152
|
-
const text = React.Children.toArray(children).join('');
|
|
153
|
-
const id = generateId(text);
|
|
154
|
-
const cleanText = cleanHeadingText(text);
|
|
155
|
-
return (
|
|
156
|
-
<h2
|
|
157
|
-
id={id}
|
|
158
|
-
className="text-2xl md:text-3xl font-semibold text-gray-900 mt-8 mb-4 scroll-mt-20"
|
|
159
|
-
>
|
|
160
|
-
{cleanText}
|
|
161
|
-
</h2>
|
|
162
|
-
);
|
|
163
|
-
},
|
|
164
|
-
h3: ({ children }) => {
|
|
165
|
-
const text = React.Children.toArray(children).join('');
|
|
166
|
-
const id = generateId(text);
|
|
167
|
-
const cleanText = cleanHeadingText(text);
|
|
168
|
-
return (
|
|
169
|
-
<h3
|
|
170
|
-
id={id}
|
|
171
|
-
className="text-xl md:text-2xl font-semibold text-gray-900 mt-6 mb-3 scroll-mt-20"
|
|
172
|
-
>
|
|
173
|
-
{cleanText}
|
|
174
|
-
</h3>
|
|
175
|
-
);
|
|
176
|
-
},
|
|
177
|
-
h4: ({ children }) => {
|
|
178
|
-
const text = React.Children.toArray(children).join('');
|
|
179
|
-
const id = generateId(text);
|
|
180
|
-
const cleanText = cleanHeadingText(text);
|
|
181
|
-
return (
|
|
182
|
-
<h4
|
|
183
|
-
id={id}
|
|
184
|
-
className="text-lg md:text-xl font-semibold text-gray-900 mt-4 mb-2 scroll-mt-20"
|
|
185
|
-
>
|
|
186
|
-
{cleanText}
|
|
187
|
-
</h4>
|
|
188
|
-
);
|
|
189
|
-
},
|
|
190
|
-
|
|
191
|
-
// Paragraphs
|
|
192
|
-
p: ({ children }) => (
|
|
193
|
-
<p className="text-gray-700 leading-7 mb-4">
|
|
194
|
-
{children}
|
|
195
|
-
</p>
|
|
196
|
-
),
|
|
197
|
-
|
|
198
|
-
// Links - handle anchor links and internal/external links
|
|
199
|
-
a: ({ href, children }) => {
|
|
200
|
-
if (!href) return <>{children}</>;
|
|
201
|
-
|
|
202
|
-
// Handle anchor links (starting with #)
|
|
203
|
-
if (href.startsWith('#')) {
|
|
204
|
-
return (
|
|
205
|
-
<a
|
|
206
|
-
href={href}
|
|
207
|
-
onClick={(e) => {
|
|
208
|
-
e.preventDefault();
|
|
209
|
-
const id = href.slice(1);
|
|
210
|
-
const element = document.getElementById(id);
|
|
211
|
-
if (element) {
|
|
212
|
-
element.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
213
|
-
// Offset for sticky header
|
|
214
|
-
window.scrollBy(0, -80);
|
|
215
|
-
// Update URL without scrolling
|
|
216
|
-
window.history.pushState(null, '', `${pathname}${href}`);
|
|
217
|
-
}
|
|
218
|
-
}}
|
|
219
|
-
className="text-primary hover:text-accent underline"
|
|
220
|
-
>
|
|
221
|
-
{children}
|
|
222
|
-
</a>
|
|
223
|
-
);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// Handle external links
|
|
227
|
-
if (href.startsWith('http')) {
|
|
228
|
-
return (
|
|
229
|
-
<a
|
|
230
|
-
href={href}
|
|
231
|
-
className="text-primary hover:text-accent underline"
|
|
232
|
-
target="_blank"
|
|
233
|
-
rel="noopener noreferrer"
|
|
234
|
-
>
|
|
235
|
-
{children}
|
|
236
|
-
</a>
|
|
237
|
-
);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// Resolve relative markdown links to Next.js routes
|
|
241
|
-
const resolvedHref = resolveMarkdownLink(href, basePath);
|
|
242
|
-
|
|
243
|
-
// Handle internal links
|
|
244
|
-
return (
|
|
245
|
-
<Link
|
|
246
|
-
href={resolvedHref}
|
|
247
|
-
className="text-primary hover:text-primary-dark underline"
|
|
248
|
-
>
|
|
249
|
-
{children}
|
|
250
|
-
</Link>
|
|
251
|
-
);
|
|
252
|
-
},
|
|
253
|
-
|
|
254
|
-
// Lists - Tighter spacing for technical documentation
|
|
255
|
-
ul: ({ children }) => (
|
|
256
|
-
<ul className="list-disc list-outside mb-3 ml-5 space-y-1 text-gray-700 text-base">
|
|
257
|
-
{children}
|
|
258
|
-
</ul>
|
|
259
|
-
),
|
|
260
|
-
ol: ({ children }) => (
|
|
261
|
-
<ol className="list-decimal list-outside mb-3 ml-5 space-y-1 text-gray-700 text-base">
|
|
262
|
-
{children}
|
|
263
|
-
</ol>
|
|
264
|
-
),
|
|
265
|
-
li: ({ children }) => (
|
|
266
|
-
<li className="leading-relaxed pl-1">
|
|
267
|
-
{children}
|
|
268
|
-
</li>
|
|
269
|
-
),
|
|
270
|
-
|
|
271
|
-
// Blockquotes
|
|
272
|
-
blockquote: ({ children }) => (
|
|
273
|
-
<blockquote className="border-l-4 border-blue-500 pl-4 py-2 my-4 bg-blue-50 text-gray-700 italic">
|
|
274
|
-
{children}
|
|
275
|
-
</blockquote>
|
|
276
|
-
),
|
|
277
|
-
|
|
278
|
-
// Tables
|
|
279
|
-
table: ({ children }) => (
|
|
280
|
-
<div className="overflow-x-auto my-6">
|
|
281
|
-
<table className="min-w-full divide-y divide-gray-200 border border-gray-200 rounded-lg">
|
|
282
|
-
{children}
|
|
283
|
-
</table>
|
|
284
|
-
</div>
|
|
285
|
-
),
|
|
286
|
-
thead: ({ children }) => (
|
|
287
|
-
<thead className="bg-gray-50">
|
|
288
|
-
{children}
|
|
289
|
-
</thead>
|
|
290
|
-
),
|
|
291
|
-
th: ({ children }) => (
|
|
292
|
-
<th className="px-4 py-3 text-left text-sm font-semibold text-gray-900 border-b">
|
|
293
|
-
{children}
|
|
294
|
-
</th>
|
|
295
|
-
),
|
|
296
|
-
td: ({ children }) => (
|
|
297
|
-
<td className="px-4 py-3 text-sm text-gray-700 border-b border-gray-100">
|
|
298
|
-
{children}
|
|
299
|
-
</td>
|
|
300
|
-
),
|
|
301
|
-
tr: ({ children }) => (
|
|
302
|
-
<tr className="hover:bg-gray-50">
|
|
303
|
-
{children}
|
|
304
|
-
</tr>
|
|
305
|
-
),
|
|
306
|
-
|
|
307
|
-
// Code
|
|
308
|
-
code({ className, children, ...props }: any) {
|
|
309
|
-
const match = /language-(\w+)/.exec(className || '');
|
|
310
|
-
const isInline = !match;
|
|
311
|
-
|
|
312
|
-
// Check if this code is inside a pre tag (block code)
|
|
313
|
-
const isBlockCode = (props.node?.parent as any)?.tagName === 'pre';
|
|
314
|
-
|
|
315
|
-
if (match) {
|
|
316
|
-
return (
|
|
317
|
-
<div className="my-4 rounded-lg overflow-hidden overflow-x-auto">
|
|
318
|
-
<SyntaxHighlighter
|
|
319
|
-
style={vscDarkPlus as any}
|
|
320
|
-
language={match[1]}
|
|
321
|
-
PreTag="div"
|
|
322
|
-
customStyle={{
|
|
323
|
-
margin: 0,
|
|
324
|
-
borderRadius: '0.5rem',
|
|
325
|
-
fontSize: '0.875rem',
|
|
326
|
-
backgroundColor: '#1e1e1e',
|
|
327
|
-
color: '#d4d4d4',
|
|
328
|
-
}}
|
|
329
|
-
>
|
|
330
|
-
{String(children).replace(/\n$/, '')}
|
|
331
|
-
</SyntaxHighlighter>
|
|
332
|
-
</div>
|
|
333
|
-
);
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
// If it's a block code (inside pre), use dark background - no light background
|
|
337
|
-
if (isBlockCode) {
|
|
338
|
-
return (
|
|
339
|
-
<code className="bg-transparent text-code-text text-sm font-mono whitespace-pre">
|
|
340
|
-
{children}
|
|
341
|
-
</code>
|
|
342
|
-
);
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
// Inline code
|
|
346
|
-
return (
|
|
347
|
-
<code className="bg-gray-100 text-primary px-1.5 py-0.5 rounded text-sm font-mono">
|
|
348
|
-
{children}
|
|
349
|
-
</code>
|
|
350
|
-
);
|
|
351
|
-
},
|
|
352
|
-
|
|
353
|
-
// Pre (for code blocks without language)
|
|
354
|
-
pre: ({ children }) => {
|
|
355
|
-
// Check if children contain a code element
|
|
356
|
-
const hasCode = React.Children.toArray(children).some(
|
|
357
|
-
(child: any) => child?.type === 'code' || child?.props?.node?.tagName === 'code'
|
|
358
|
-
);
|
|
359
|
-
|
|
360
|
-
return (
|
|
361
|
-
<pre className="bg-code-bg text-code-text p-4 rounded-lg overflow-x-auto my-4 text-sm font-mono">
|
|
362
|
-
{children}
|
|
363
|
-
</pre>
|
|
364
|
-
);
|
|
365
|
-
},
|
|
366
|
-
|
|
367
|
-
// Horizontal rule
|
|
368
|
-
hr: () => (
|
|
369
|
-
<hr className="my-8 border-t border-gray-200" />
|
|
370
|
-
),
|
|
371
|
-
|
|
372
|
-
// Strong/Bold
|
|
373
|
-
strong: ({ children }) => (
|
|
374
|
-
<strong className="font-semibold text-gray-900">
|
|
375
|
-
{children}
|
|
376
|
-
</strong>
|
|
377
|
-
),
|
|
378
|
-
|
|
379
|
-
// Emphasis/Italic
|
|
380
|
-
em: ({ children }) => (
|
|
381
|
-
<em className="italic">
|
|
382
|
-
{children}
|
|
383
|
-
</em>
|
|
384
|
-
),
|
|
385
|
-
|
|
386
|
-
// Images
|
|
387
|
-
img: ({ src, alt }) => (
|
|
388
|
-
<img
|
|
389
|
-
src={src}
|
|
390
|
-
alt={alt || ''}
|
|
391
|
-
className="max-w-full h-auto rounded-lg my-4 shadow-sm"
|
|
392
|
-
/>
|
|
393
|
-
),
|
|
394
|
-
}}
|
|
395
|
-
>
|
|
396
|
-
{content}
|
|
397
|
-
</ReactMarkdown>
|
|
398
|
-
</div>
|
|
399
|
-
);
|
|
400
|
-
}
|
|
401
|
-
|