Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion .github/actions/setup-node-pnpm/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,18 @@ inputs:
description: pnpm version
required: false
default: "10.33.0"
registry-url:
description: Optional npm registry URL to configure for npm publish/auth steps
required: false
default: ""
install:
description: Whether to run pnpm install
required: false
default: "true"
install-filter:
description: Optional pnpm filter selector to limit install scope
required: false
default: ""

runs:
using: composite
Expand All @@ -29,8 +37,16 @@ runs:
node-version: ${{ inputs.node-version }}
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
registry-url: ${{ inputs.registry-url }}

- name: Install workspace dependencies
if: inputs.install == 'true'
if: inputs.install == 'true' && inputs['install-filter'] == ''
shell: bash
run: pnpm install --frozen-lockfile --ignore-scripts

- name: Install filtered workspace dependencies
if: inputs.install == 'true' && inputs['install-filter'] != ''
shell: bash
run: pnpm install --frozen-lockfile --ignore-scripts --filter "$INSTALL_FILTER"
env:
INSTALL_FILTER: ${{ inputs['install-filter'] }}
20 changes: 19 additions & 1 deletion .github/workflows/deploy-doc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ on:
- main
paths:
- doc/**
- .github/actions/setup-node-pnpm/action.yml
- .github/workflows/deploy-doc.yml
- .github/workflows/pull-request-doc.yml
- package.json
- pnpm-lock.yaml
- pnpm-workspace.yaml
- turbo.json
workflow_dispatch:

permissions:
Expand All @@ -25,9 +32,11 @@ jobs:
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- uses: ./.github/actions/setup-node-pnpm
with:
install-filter: "@truenine/memory-sync-docs..."

- name: Preflight Vercel secrets
shell: bash
Expand All @@ -49,11 +58,20 @@ jobs:
exit 1
fi

- name: Lint docs
run: pnpm -C doc run lint

- name: Typecheck docs
run: pnpm -C doc run typecheck

- name: Pull Vercel production settings
working-directory: ./doc
run: pnpm dlx vercel@latest pull --yes --environment=production --token="$VERCEL_TOKEN"

- name: Build docs on Vercel
working-directory: ./doc
run: pnpm dlx vercel@latest build --prod --token="$VERCEL_TOKEN"

- name: Deploy docs to Vercel production
working-directory: ./doc
run: pnpm dlx vercel@latest deploy --prebuilt --prod --token="$VERCEL_TOKEN"
47 changes: 47 additions & 0 deletions .github/workflows/pull-request-doc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Pull Request Docs

on:
pull_request:
branches:
- main
types: [opened, synchronize, reopened, ready_for_review]
paths:
- doc/**
- .github/actions/setup-node-pnpm/action.yml
- .github/workflows/deploy-doc.yml
- .github/workflows/pull-request-doc.yml
- package.json
- pnpm-lock.yaml
- pnpm-workspace.yaml
- turbo.json

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true

jobs:
check-doc:
if: github.event.pull_request.draft == false
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- uses: actions/checkout@v6

- uses: ./.github/actions/setup-node-pnpm
with:
install-filter: "@truenine/memory-sync-docs..."

- name: Validate docs content
run: pnpm -C doc run validate:content

- name: Lint docs
run: pnpm -C doc run lint

- name: Typecheck docs
run: pnpm -C doc run typecheck

- name: Build docs
run: pnpm -C doc run build
3 changes: 3 additions & 0 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ on:
- CODE_OF_CONDUCT.md
- LICENSE
- SECURITY.md
- doc/**
- .github/workflows/deploy-doc.yml
- .github/workflows/pull-request-doc.yml

permissions:
contents: read
Expand Down
15 changes: 2 additions & 13 deletions .github/workflows/release-cli.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
name: Release Packages

env:
NODE_VERSION: "25.6.1"
NPM_REGISTRY_URL: https://registry.npmjs.org/
NPM_PUBLISH_VERIFY_ATTEMPTS: "90"
NPM_PUBLISH_VERIFY_DELAY_SECONDS: "10"
Expand Down Expand Up @@ -57,9 +56,9 @@ jobs:
version: ${{ steps.check.outputs.version }}
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
- uses: ./.github/actions/setup-node-pnpm
with:
node-version: ${{ env.NODE_VERSION }}
install: "false"

- name: Check if should publish
id: check
Expand Down Expand Up @@ -240,10 +239,6 @@ jobs:
- uses: ./.github/actions/setup-node-pnpm
with:
install: "true"
- name: Setup npm registry
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
registry-url: https://registry.npmjs.org/
- name: Preflight npm auth
shell: bash
Expand Down Expand Up @@ -464,10 +459,7 @@ jobs:
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/setup-node-pnpm
- name: Setup npm registry
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
registry-url: https://registry.npmjs.org/
- name: Preflight npm auth
shell: bash
Expand Down Expand Up @@ -590,10 +582,7 @@ jobs:
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/setup-node-pnpm
- name: Setup npm registry
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
registry-url: https://registry.npmjs.org/
- name: Preflight npm auth
shell: bash
Expand Down
2 changes: 1 addition & 1 deletion doc/app/docs/[[...mdxPath]]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default async function DocsLayout({
const firstSegment = params.mdxPath?.[0]
const section = firstSegment != null && isDocSectionName(firstSegment)
? firstSegment
: undefined
: void 0
const pageMap = await getPageMap(section ? `/docs/${section}` : '/docs')

return (
Expand Down
52 changes: 26 additions & 26 deletions doc/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,55 +1,55 @@
import type { Metadata } from "next";
import { Inter, JetBrains_Mono } from "next/font/google";
import { getSiteUrl, siteConfig } from "../lib/site";
import "nextra-theme-docs/style.css";
import "./globals.scss";
import type {Metadata} from 'next'
import {Inter, JetBrains_Mono} from 'next/font/google'
import {getSiteUrl, siteConfig} from '../lib/site'
import 'nextra-theme-docs/style.css'
import './globals.scss'

const sans = Inter({
variable: "--font-sans",
variable: '--font-sans',
preload: true,
subsets: ["latin"],
});
subsets: ['latin']
})

const mono = JetBrains_Mono({
variable: "--font-mono",
subsets: ["latin"],
preload: true,
});
variable: '--font-mono',
subsets: ['latin'],
preload: true
})

export const metadata: Metadata = {
metadataBase: getSiteUrl(),
title: {
default: siteConfig.title,
template: `%s | ${siteConfig.productName}`,
template: `%s | ${siteConfig.productName}`
},
description: siteConfig.description,
applicationName: siteConfig.shortName,
alternates: {
canonical: "/",
canonical: '/'
},
category: "developer tools",
manifest: "/manifest.webmanifest",
category: 'developer tools',
manifest: '/manifest.webmanifest',
openGraph: {
type: "website",
url: "/",
type: 'website',
url: '/',
title: siteConfig.title,
description: siteConfig.description,
siteName: siteConfig.title,
locale: "zh_CN",
locale: 'zh_CN'
},
twitter: {
card: "summary_large_image",
card: 'summary_large_image',
title: siteConfig.title,
description: siteConfig.description,
},
};
description: siteConfig.description
}
}

export default function RootLayout({ children }: { readonly children: React.ReactNode }) {
export default function RootLayout({children}: {readonly children: React.ReactNode}) {
return (
<html lang="zh-CN" className="dark" style={{ colorScheme: "dark", backgroundColor: "#0b0c10" }} suppressHydrationWarning>
<html lang="zh-CN" className="dark" style={{colorScheme: 'dark', backgroundColor: '#0b0c10'}} suppressHydrationWarning>
<body className={`${sans.variable} ${mono.variable}`} suppressHydrationWarning>
{children}
</body>
</html>
);
)
}
40 changes: 23 additions & 17 deletions doc/components/docs-callout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ type CalloutTone = 'note' | 'tip' | 'important' | 'warning' | 'caution'
type BlockquoteProps = ComponentPropsWithoutRef<'blockquote'>

const CALLOUT_PATTERN = /^\s*\[!(note|tip|important|warning|caution)\]\s*/i
const CALLOUT_TONES = new Set<CalloutTone>(['note', 'tip', 'important', 'warning', 'caution'])

const CALLOUT_LABELS: Record<CalloutTone, string> = {
note: 'Note',
Expand Down Expand Up @@ -43,46 +44,51 @@ function getMeaningfulChildren(children: ReactNode): ReactNode[] {

function stripMarkerFromChildren(children: ReactNode): ReactNode {
const items = getMeaningfulChildren(children)
const strippedItems: ReactNode[] = []

return items.map((item, index) => {
for (const [index, item] of items.entries()) {
if (index !== 0) {
return item
strippedItems.push(item)
continue
}

if (typeof item === 'string') {
return item.replace(CALLOUT_PATTERN, '')
strippedItems.push(item.replace(CALLOUT_PATTERN, ''))
continue
}

if (!isValidElement(item)) {
return item
strippedItems.push(item)
continue
}

const element = item as ReactElement<{children?: ReactNode}>
const text = extractText(element.props.children)

if (!CALLOUT_PATTERN.test(text)) {
return item
strippedItems.push(item)
continue
}

return cloneElement(element, {
strippedItems.push(cloneElement(element, {
...element.props,
children: text.replace(CALLOUT_PATTERN, '')
})
})
}))
}

return strippedItems
}

function isCalloutTone(value: string | undefined): value is CalloutTone {
return value != null && CALLOUT_TONES.has(value as CalloutTone)
}

function resolveCalloutTone(children: ReactNode): CalloutTone | null {
const firstChild = getMeaningfulChildren(children)[0]
const firstText = extractText(firstChild).trimStart()
const matched = firstText.match(CALLOUT_PATTERN)?.[1]?.toLowerCase()

if (
matched === 'note'
|| matched === 'tip'
|| matched === 'important'
|| matched === 'warning'
|| matched === 'caution'
) {
const matched = CALLOUT_PATTERN.exec(firstText)?.[1]?.toLowerCase()

if (isCalloutTone(matched)) {
return matched
}

Expand Down
Loading
Loading