Text.js 0.1
Text.js 0.1 добавляет согласователь React 19, макет Yoga и файловый App Router для приложений, которые рендерятся в консоли DevTools.
Для Text.js 0.1 создан тег. Это первая версия со всеми тремя слоями: @textjs/core рисует кадры в консоли, @textjs/react рендерит React 19 в эти кадры, а textjs добавляет App Router и CLI.
App Router
Маршруты — это папки в app/, организованные по соглашениям Next.js App Router. Вот шаблон dashboard из create-text-app:
app/├── layout.tsx├── page.tsx├── not-found.tsx├── deployments/│ └── [id]/│ └── page.tsx└── api/ └── metrics/ └── route.tsМакет оборачивает каждую вложенную страницу и сохраняет своё состояние при навигации. <Link> принимает shortcut, позволяя перейти по ссылке нажатием одной клавиши, а activeClassName задаёт стиль ссылки на текущий маршрут:
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.
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:
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:
export function GET(): Response { return Response.json({ cpu: Math.random(), memory: Math.random(), at: new Date().toISOString() });}Маршрутизатор синхронизирует window.location через history.pushState, поэтому работают кнопки «Назад», «Вперёд» и прямые ссылки, а 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.
Полный список — в журнале изменений.