← وبلاگ

⁦Text.js 0.1⁩

⁦Text.js 0.1⁩ یک reconciler برای ⁦React 19⁩، چیدمان Yoga و ⁦App Router⁩ مبتنی بر سیستم فایل را به برنامه‌هایی می‌آورد که در کنسول DevTools رندر می‌شوند.

Adam

نسخهٔ ⁦Text.js 0.1⁩ تگ‌گذاری شد. این نخستین نسخه با هر سه لایه است: @textjs/core فریم‌ها را در کنسول ترسیم می‌کند، @textjs/react خروجی ⁦React 19⁩ را در آن فریم‌ها رندر می‌کند و textjs یک ⁦App Router⁩ و یک CLI اضافه می‌کند.

App Router

مسیرها پوشه‌هایی در app/ هستند که از قراردادهای ⁦App Router⁩ در Next.js پیروی می‌کنند. این قالب dashboard از create-text-app است:

app/├── layout.tsx├── page.tsx├── not-found.tsx├── deployments/│   └── [id]/│       └── page.tsx└── api/    └── metrics/        └── route.ts

چیدمان هر صفحهٔ زیرمجموعهٔ خود را در بر می‌گیرد و وضعیت خود را در طول ناوبری حفظ می‌کند. کامپوننت <Link> یک shortcut می‌پذیرد تا با فشردن یک کلید پیوند باز شود، و activeClassName به پیوند مسیر فعلی سبک می‌دهد:

app/layout.tsxtsx
import type { ReactNode } from "react";import { Box, KeyHint, Text, useTheme, type Metadata } from "textjs";import Link from "textjs/link";export const metadata: Metadata = { title: { default: "Acme", template: "%s · Acme" } };export default function RootLayout({ children }: { children?: ReactNode }): ReactNode {  const theme = useTheme();  return (    <Box className="flex-col w-full h-full">      <Box className="flex-row h-1 px-1 gap-3 bg-surface shrink-0">        <Text bold color={theme.fg} wrap="nowrap">          ▼ Acme        </Text>        <Link href="/" shortcut="1" className="text-muted no-underline" activeClassName="text-fg bold">          1 Metrics        </Link>        <Link href="/deployments/dpl_a1" shortcut="2" className="text-muted no-underline" activeClassName="text-fg bold">          2 Latest deploy        </Link>      </Box>      <Box className="grow flex-col px-2 pt-1">{children}</Box>      <Box className="flex-row h-1 gap-2 pl-6 shrink-0 bg-surface">        <KeyHint keys="1-2" label="navigate" />        <KeyHint keys="tab" label="focus" />        <KeyHint keys="F2" label="devtools" />      </Box>    </Box>  );}

بخش‌های پویا مانند Next.js کار می‌کنند. بخش [id] به پارامتر تبدیل می‌شود، [...slug] بقیهٔ مسیر را می‌گیرد و [[...slug]] با والد نیز مطابقت دارد. بخش‌های ایستا بر بخش‌های پویا اولویت دارند و گروه‌های مسیر مانند (marketing) فایل‌ها را بدون افزودن چیزی به URL سازمان‌دهی می‌کنند.

app/deployments/[id]/page.tsxtsx
import { Box, Text, useInput } from "textjs";import { notFound, useParams, useRouter } from "textjs/navigation";import { DEPLOYMENTS } from "../../../lib/data";export default function DeploymentPage() {  const router = useRouter();  const { id } = useParams<{ id: string }>();  const deployment = DEPLOYMENTS.find((d) => d.id === id);  useInput((e) => {    if (e.key === "escape") router.back();  });  if (!deployment) notFound();  return (    <Box className="flex-col gap-1">      <Text bold>{deployment.id}</Text>      <Text>{deployment.branch}</Text>    </Box>  );}

فایل‌های loading.tsx و error.tsx یک بخش را در مرز Suspense و مرز خطا قرار می‌دهند. کامپوننت خطا، خطا و تابع reset را دریافت می‌کند:

app/deployments/error.tsxtsx
import { Box, Text, useInput, type ErrorComponentProps } from "textjs";export default function DeploymentsError({ error, reset }: ErrorComponentProps) {  useInput((e) => {    if (e.key === "r") reset();  });  return (    <Box className="flex-col grow items-center justify-center gap-1">      <Text bold>Something went wrong loading deployments.</Text>      <Text>{error.message}</Text>    </Box>  );}

کنترل‌گرهای مسیر در app/api قرار دارند و یک Response استاندارد برمی‌گردانند:

app/api/metrics/route.tsts
export function GET(): Response {  return Response.json({ cpu: Math.random(), memory: Math.random(), at: new Date().toISOString() });}

مسیریاب از طریق history.pushState مقدار window.location را همگام نگه می‌دارد، بنابراین دکمه‌های برگشت و جلو و پیوندهای عمیق کار می‌کنند و مقدار metadata.title در document.title نوشته می‌شود. برنامه در کنسول ترسیم می‌شود و صفحه میزبان یک پد فوکوس است که ورودی را جمع‌آوری می‌کند.

CLI

  • دستور text dev، Vite را با ⁦React Fast Refresh⁩ راه‌اندازی می‌کند. ذخیره کردن فایل، کنسول را درجا به‌روزرسانی می‌کند.
  • دستور text build یک بیلد آمادهٔ تولید از برنامه و کنترل‌گرهای مسیر آن می‌نویسد.
  • دستور text start بیلد و کنترل‌گرهای مسیر را سرو می‌کند.

ابزار create-text-app ساختار اولیهٔ پروژه را از قالب starter یا dashboard می‌سازد.

بازرس

در برنامهٔ در حال اجرا، کلید Ctrl+` یا F2 را فشار دهید تا بازرس [▼] در کنسول باز شود. این بازرس مسیر تطبیق‌یافته و پارامترهای آن، اندازهٔ فریم، تعداد span و زمان‌بندی مرحله‌ها و تعداد فریم‌هایی را که دروازهٔ تغییرات رد کرده است نشان می‌دهد. کلید W چیدمان Yoga را به‌صورت وایرفریم ترسیم می‌کند.

سایر امکانات در 0.1

بستهٔ @textjs/react با کامپوننت‌های PascalCase ‏(Box، Text، ScrollBox، Input، Textarea، Select، Tabs، Code، Markdown، Diff، Modal، Spinner)، ابزارهای کمکی className به سبک Tailwind که در سلول‌ها کار می‌کنند و پوسته‌ها عرضه می‌شود. چیدمان با Yoga در WebAssembly اجرا می‌شود.

فهرست کامل در گزارش تغییرات آمده است.