Что нового в Text.js
Все значимые изменения Text.js описаны в этом файле.
Добавлено
- textjs.org: испанская, французская, немецкая, бразильская португальская, корейская версии, а также версии на упрощённом и традиционном китайском вышли из чернового состояния и доступны по адресам textjs.org/es, /fr, /de, /pt-br, /ko, /zh-cn и /zh-tw. Выбор языка в подвале и кнопка языка браузера предлагают их наряду с японским. Поисковые системы индексируют переведённые страницы и сопоставляют каждую с её английской версией.
- textjs.org: итальянская, русская, турецкая, польская, индонезийская, вьетнамская версии и версия на хинди вышли из чернового состояния и доступны по адресам textjs.org/it, /ru, /tr, /pl, /id, /vi и /hi. Выбор языка в подвале и кнопка языка браузера предлагают их наряду с другими языками. Поисковые системы индексируют переведённые страницы и сопоставляют каждую с её английской версией.
Изменено
@textjs/react:<FocusPad>и<ViewportControl>используют для моноширинных подписей стек шрифтов страницы--mono, если он задан, а иначе, как и прежде, используют Geist Mono. Страница с подписями на арабском или иврите может добавить шрифты своей письменности в--mono.
Исправлено
- textjs.org: на телефонах встроенный код, который длиннее строки, переносится, а не расширяет страницу. Страница textjs.org/docs/internationalization была на 92 пикселя шире экрана шириной 390 пикселей.
Добавлено
@textjs/react:<FocusPad messages>заменяет любые встроенные строки панели для переведённых сайтов. Это охватывает каждую строку, подписи для программ чтения с экрана и элемент управления размером консоли.<TextCanvas>и<ViewportControl>тоже принимаютmessages.<ViewportControl>использует только ключи элемента управления размером. Строки со значением, например «Затем щёлкните здесь и нажмите ↑ ↓.», задаются функциями, которые возвращают предложение целиком.defaultFocusPadMessagesсодержит английский текст. См. Перевод панели фокуса.@textjs/react: на страницах с письмом справа налево панель фокуса сохраняет направление слева направо для обозначений клавиш, таких как ⌘ ⌥ J, и размеров консоли, таких как 120×36, а элемент управления размером и индикатор шагов отображает зеркально. На китайских и японских страницах она убирает пробел между двумя предложениями; на корейских сохраняет его.- textjs.org: textjs.org/ja больше не черновик. Переключатель языка в подвале открывает ту же страницу на английском или японском. В браузере с японским языком появляется кнопка «Читать на японском», а в браузере с английским языком на textjs.org/ja появляется кнопка «Читать на английском». Кнопка перестаёт появляться после выбора языка или её закрытия. Поисковые системы индексируют переведённые японские страницы и сопоставляют каждую с её английской версией.
- textjs.org: на textjs.org/ja панель фокуса переведена на японский на каждой странице, включая подписи под клавишами каждого демо.
Изменено
@textjs/core: консоли Chromium и Firefox очищают вывод анимированных спрайтов при 16 МБ вместо 4 МБ, поэтому textjs.org/doom показывает «Консоль очищена» примерно каждые 19 секунд вместо 4,5. Для Safari и спрайтов, нарисованных полублоками▀, остаётся 4 МБ. Пиковый размер кучи страницы textjs.org/doom растёт с 10,8 МБ примерно до 12–13 МБ.- textjs.org: страница документации загружает только свой Markdown вместо всех 33 страниц, поэтому английские страницы документации загружают на 43–47 КБ меньше JavaScript (gzip), а страницы /ja на 60–64 КБ меньше. Наведение или установка фокуса на ссылку на другую страницу документации заранее загружает эту страницу, поэтому она по-прежнему открывается сразу.
Исправлено
- textjs.org/ja: поиск ⌘K показывает японские заголовки документации и сопоставляет с ними японские запросы. Раньше он выводил английские заголовки под японскими названиями страниц. Английские названия по-прежнему находят страницы:
routingнаходит ルーティング, аopen the consoleнаходит コンソールを開く. - textjs.org: изменения примера документации, работающего в вашей консоли, снова видны в предпросмотре страницы на textjs.org/ja, а также для примера «Двунаправленный текст» на textjs.org/docs/internationalization. Строка над примером в консоли теперь гласит «▼ Документация › Счётчик» вместо «▼ Документация › Введение › Счётчик».
Добавлено
- textjs.org/doom воспроизводит звуковые эффекты Doom с его собственным стереопанорамированием и затуханием с расстоянием. Звук начинается с первого щелчка или нажатия клавиши на странице, приостанавливается вместе с игрой и следует настройке Sfx Volume в меню Doom Options → Sound Volume. Музыки нет.
Изменено
@textjs/react,@textjs/app: подсказка фокуса («Щёлкните страницу, чтобы использовать клавиатуру») теперь представляет собой янтарную полосу с жирным чёрным текстом во всех темах. Раньше она использовала инвертированные цвета темы. При каждом появлении она мигает 4 раза примерно за 6 секунд, затем остаётся янтарной. При включённом уменьшении движения она не мигает. Каждый цикл мигания выводит до 8 дополнительных кадров консоли.- textjs.org: Doom перемещён на textjs.org/doom. textjs.org/playground/doom перенаправляет туда.
Исправлено
@textjs/core,@textjs/react: панель «Проблемы» Chrome больше не сообщает «Элемент поля формы должен иметь атрибут id или name» на каждой странице. Скрытый клавиатурный<textarea>имеет имяtextjs-input, а<select>размера консоли вViewportControl(также вsizeControlкомпонентаFocusPad) имеетidи имяtextjs-console-size. Клавиатурный<textarea>также отключает обработку со стороны 1Password, LastPass, Bitwarden и Dashlane.- textjs.org: заголовок консоли на textjs.org/doom гласит «Text.js / doom» вместо «Text.js / playground / doom».
- textjs.org/doom: в узком окне больше не остаётся лишняя «·» после «Посмотреть исходный код».
- textjs.org: в узком окне список демо Playground плавно исчезает у края, за которым есть ещё демо для прокрутки, вместо обрезки последнего посреди слова.
- textjs.org/doom работает с частотой Doom в 35 тиков в секунду. На уровне игра работала в 3,8 раза быстрее на дисплее 60 Гц (131 тик в секунду) и в 5,5 раза быстрее на 120 Гц (192), потому что страница принимала дополнительные чтения часов, которые Doom делает при отрисовке уровня, за активное ожидание и сдвигала часы Doom на тик вперёд в каждом кадре анимации и обратном вызове таймера.
Добавлено
@textjs/react:<Image renderMode="halfblock">везде рисует полублоки▀, как<Image>в 1.3.@textjs/core/experimental:drawPixelsпринимаетencoding: "rgba"для спрайта без потерь с плавной прозрачностью и более чем 256 цветами, а также функциюfallback, которая рисует ячейки там, где спрайт нельзя показать.@textjs/app: curl, Wget, HTTPie и xh получают первый кадр страницы как ANSI-текст с truecolor вместо HTML-страницы вtext dev,text startи адаптерахbun,vercelиcloudflare.text buildвыполняет пререндеринг кадров статических страниц.text startиbunрендерят динамические и отрендеренные на сервере страницы по запросу, а на неизвестные пути отвечают страницей приложения «не найдено» и кодом404. Размер кадров по умолчанию 80 × 24. Измените размер или отключите кадры с помощьюansiвtext.config.tsилиexport const ansiна странице. Адаптерstaticотдаёт curl HTML-страницу. См. curl и терминальные клиенты.@textjs/app/ansiэкспортируетwantsAnsiиansiResponseдля серверов, не использующихtext startили адаптер, а@textjs/reactэкспортируетframeToAnsi.- textjs.org: черновая японская версия на textjs.org/ja, начиная с разделов документации «Введение», «Установка», «Маршрутизация» и интерфейса сайта. Непереведённые абзацы показываются на английском. Версия пока не индексируется и не предлагается в выборе языка.
Изменено
@textjs/react:<Image>теперь рисует пиксельный спрайт в консолях Chromium и Firefox, до 8 × 16 пикселей на ячейку для пиксельной графики и 4 × 8 для фотографий. Это намеренно нарушает обещание политики поддержки сохранять вид кадров между минорными релизами. ПередайтеrenderMode="halfblock", чтобы сохранить полублоки из 1.3. Safari, терминалы (включаяtext run), ANSI и обычный текстовый вывод, а также отрендеренные на сервере страницы (runtime = "server") по-прежнему рисуют полублоки.@textjs/app: скрипты и проверки доступности, запрашивающие страницы через curl, Wget, HTTPie или xh, теперь получают ANSI-текст. Чтобы продолжить получать HTML, отправляйтеAccept: text/htmlили задайтеansi: falseвtext.config.ts.@textjs/app: асинхронные серверные компоненты больше не запускаются, покаtext buildвыполняет пререндеринг оболочки страницы. Как и раньше, они показывают резервное содержимое<Suspense>, не запуская запросы данных во время сборки.@textjs/app: проигрыватель кадров для отрендеренных на сервере страниц стал на 3 КБ меньше: 22,4 КБ gzip вместо 25,4 КБ дляexamples/dashboard. Он больше не включает методы рисованияCellBuffer, границы блоков и усечение текста.
Исправлено
@textjs/core: графики и спиннеры сохраняют сетку в Windows 10. Шрифт её консоли Consolas не содержит блоков в восьмую долю ▁▂▃▅▆▇, квадрантов, Брайля, ▶ или ✓, и подставляемые глифы выводили строки за правый край кадра.CssConsoleDriverтеперь однократно измеряет, какие из этих глифов шрифт консоли рисует с отклонением более чем на пятую часть ячейки, и заменяет их ближайшими глифами Consolas:_▄▌█для восьмых долей, полублоками для квадрантов и Брайля,►◄√×для стрелок, галочек и крестиков. Шрифты, в которых они помещаются, например Cascadia Mono в Windows 11 и Menlo в macOS, рисуют оригиналы.measureText: falseотключает это.@textjs/core: больше нет вертикальных линий толщиной 1 пкс между соседними фонами в DevTools Chrome и Edge, например рядом с «аккаунт» и «количество» на textjs.org/coffee. Chromium привязывает каждый span%cк пикселям устройства отдельно и мог оставить пиксель на стыке двух span неокрашенным.CssConsoleDriverтеперь продлевает фон span на 1 пкс под непрозрачного соседа справа (padding-right:1px;margin-right:-1px). Кадры Firefox и Safari не меняются.@textjs/core: спрайты<Image>в Chrome и Edge следуют тому же правилу 1 пкс, что и текст. Текст слева от прозрачного спрайта больше не рисует полосу своего фона шириной 1 пкс поверх левого края спрайта, а спрайт смыкается с непрозрачным текстом справа, включая инверсный текст. Спрайт, занимающий строки в одиночку, теперь достигает правого края кадра, как текстовые строки над ним и под ним.@textjs/react:<ConsoleMirror>рисует фотографию рядом с текстом полублоками, как консоль, вместо изображения.
Добавлено
@textjs/react/experimentalэкспортирует<Pixels>для живых буферов кадров иuseKeyStateдля удерживаемых клавиш;@textjs/core/experimentalэкспортируетdrawPixels. Они могут измениться в минорном релизе.- textjs.org/playground/doom: играйте в условно-бесплатный эпизод Doom в консоли DevTools.
@textjs/react,@textjs/app: пока страница не в фокусе, последняя строка кадра консоли гласит «Щёлкните страницу, чтобы использовать клавиатуру», чтобы посетитель, щёлкнувший приложение в консоли, понимал, почему клавиши перестали работать. Подсказка появляется, если у приложения есть обработчикuseInputилиusePasteлибо цель фокуса, только в консоли браузера, включая отрендеренные на сервере маршруты. Встроенные зеркала и предпросмотр VS Code её не показывают. Отключите её с помощьюfocusHint: falseвtext.config.tsилиcreateConsoleRoot.@textjs/react:usePageFocus()возвращает, находится ли страница в фокусе. Чтобы самостоятельно решать, когда приложению нужна клавиатура, задайтеfocusHint: falseи рендерите<FocusHint active={…}>.useInput(handler, { ambient: true })помечает постоянно активное сочетание клавиш, которое само по себе не показывает подсказку.
Изменено
@textjs/core: пока спрайт<Pixels>анимируется,ConsoleRendererгруппирует ключевые кадры каждые 51 мс в Chromium, задаёт интервал кадров 33 мс в Safari и очищает дописанный вывод вCssConsoleDriverпри 4 МБ (SPRITE_MAX_BYTES). Статические спрайты и текстовые приложения сохраняют прежние интервалы и предел очистки в 300 кадров.
Добавлено
@textjs/core:bindTextSink(element, onText)читает текст, подтверждённый IME или мёртвой клавишей, из скрытого textarea или input, один раз на подтверждение и никогда в процессе композиции.engine.bindTextSink(element)подключает textarea, который вы рендерите сами, кInputEngine. Оба возвращают функцию, удаляющую слушатели.@textjs/app:POST /__textjs/inputпринимает{ type: "text", text }для текста IME и мёртвых клавиш.InputMessageиparseInputMessageв@textjs/app/frame-protocolвключают его.
Изменено
@textjs/app: middleware и обработчики маршрутов получают канонический путь./docs/и/docs//introприходят как/docsи/docs/intro, поэтому middleware, перенаправляющий для добавления завершающего слеша, теперь перенаправляет бесконечно. Удалите это перенаправление. Динамический сегмент не может содержать закодированный слеш:/files/a%2Fbвозвращает400.@textjs/app: при наличии middleware--adapter cloudflareотправляет каждый запрос воркеру, включая ресурсы с хешами, а при наличииbasePathтакже отправляет запросы за пределами базового пути. Каждый запрос, запускающий воркер, считается одним вызовом Functions и учитывается в вашей квоте запросов Workers. На тарифе Workers Free настройте проект Pages на закрытие доступа при сбое (Settings → Runtime → Fail open / closed), иначе после исчерпания дневной квоты Pages отдаёт ваши файлы без middleware.
Исправлено
- Китайские, японские и корейские IME и мёртвые клавиши работают во встроенных консолях textjs.org. Консоли очищали textarea в процессе композиции, поэтому приложение получало исходные буквы или неверный символ.
<FocusPad>сохраняет клавиатурный фокус на приложении после щелчка. Раньше фокус сразу терялся, поэтому китайские, японские и корейские IME не могли составлять текст.- Мёртвые клавиши, не образующие композицию (Windows и Linux без IME), достигают приложения при фокусе на скрытом textarea. В раскладке US-International
', затемeдаютé, а', затемtдают't.InputEngineблокировал keydown, завершающий мёртвую клавишу, поэтому браузер ничего не вставлял.DeadKeyTrackerв@textjs/coreпропускает этот keydown, и предпросмотр VS Code тоже его использует. - Предпросмотр VS Code доставляет текст IME и мёртвых клавиш, который раньше отбрасывал, и больше не пересылает приложению мёртвые клавиши или нажатия при композиции IME. С сервером
text devиз@textjs/app1.1.0 или более ранней версии он отправляет текст как нажатия клавиш или вставку. @textjs/core:InputEngine.handleTextInputигнорирует текст, покаshouldCaptureвозвращаетfalse, как уже происходило с вводом клавиш и вставкой.text devпредварительно собирает@textjs/app/live-stubи@textjs/app/live-player. Приложение со страницейruntime = "server"обнаруживало их только после первой загрузки страницы, поэтому Vite собирал их заново посреди загрузки, вызывая ошибки 404 для устаревших чанков и «Недопустимый вызов хука» из-за двух копий React.- Графики и спиннеры помещаются в кадр в Windows. В Consolas нет блоков ▁▂▃▅▆▇, квадрантов, Брайля, ▶ или ✓, поэтому Windows рисовала их запасными шрифтами шириной до 1,8 ячейки, и строки графиков выходили за правый край кадра. Набор шрифтов консоли теперь
"SF Mono",Menlo,"Cascadia Mono",Consolas,monospace, и Windows 11 рисует весь кадр в Cascadia Mono.<ConsoleMirror>, предпросмотр VS Code и просмотр кадров расширения DevTools тоже ставят Cascadia Mono перед Consolas. @textjs/opencode: под Node в Windows мост находит OpenCode, установленный черезnpm i -g opencode-ai. Node не может запустить обёртку npmopencode.cmdпо имени, поэтому мост вёл себя так, будто OpenCode не установлен. Теперь он ищет вPATHс каждым расширениемPATHEXTи запускает обёртки.cmdчерезcmd.exe. Под Bun (bunx) это уже работало.text buildработает в Windows. Команда завершалась неудачно для всех шаблонов сCould not resolve entry module "virtual:textjs/api"или без сообщения об ошибке.text buildвыводит ошибку, если пререндеринг оболочек консоли или сборка отрендеренных на сервере маршрутов завершается неудачно. Раньше команда завершалась с кодом 1 после строки Vite «Сборка не удалась», без причины.text devв Windows повторно рендерит отрендеренные на сервере маршруты при редактировании файла и перезагружает браузер, когда страница меняет экспортruntime.text devв Windows больше не запускаетmiddleware.tsдля исходных файлов, которые Vite отдаёт как модули, например/app/page.tsx, поэтому перенаправление авторизации больше не ломает клиент разработки.text runиtext mcpработают, когда путь проекта содержит короткое имя Windows 8.3, напримерC:\Users\RUNNER~1. Они показывали «Ошибка приложения», потому что CLI и приложение загружали@textjs/appдважды.dist/, собранный в Windows, отдаёт страницы после пререндеринга в Linux и macOS. Манифест живых маршрутов хранил пути с обратными слешами.text buildработает, когда параметрviteвtext.config.tsзадаётbuild.rollupOptions.input. Этот параметр заменял точки входа сборок API, отрендеренных на сервере маршрутов и адаптеров, и сборка завершалась неудачно.text devзавершается, когда вы останавливаете его в первые секунды после загрузки страницы, аserver.close()разрешается. Закрытие Vite во время оптимизации вновь обнаруженных зависимостей никогда не завершалось (vitejs/vite#22934).
Безопасность
@textjs/app1.1.0 и более ранние версии позволяли запросу обходитьmiddleware.ts, записав защищённый путь иначе, например/ad%6din,/api//adminили/admin%2Fx. Middleware сопоставлял путь в отправленном виде, а страницы, обработчики маршрутов и статические файлы искались после декодирования (дважды для обработчиков маршрутов). Это затрагивалоtext dev,text startи сборки--adapter bun,vercelиcloudflare. Статические сборки не могут использовать middleware и не затронуты. Обновитесь до 1.2.0, затем пересоберите и разверните заново:.vercel/outputдля Vercel,dist/для Cloudflare Pages и весьdist/для Bun (перезапустите сервер). Удалите старые развёртывания, всё ещё доступные по собственным URL, или защитите их.- Каждый хост теперь вычисляет один канонический путь для каждого запроса и использует его для сопоставления,
request.nextUrlи всех поисков. Он декодирует процентное кодирование и заново кодирует путь так, как его записываетnew URL(), разрешает сегменты.и..и удаляет повторяющиеся и завершающие слеши. Пути с%2F,%5Cили неверным процентным кодированием получают400.text dev,text startи адаптер Bun отдают статические файлы только под точным именем, поэтому в macOS и Windows/ADMIN/report.txtбольше не отдаётpublic/admin/report.txt. - Шаблоны сопоставления, исходные пути перезаписи, сегменты маршрутов и
basePathсравниваются в той же закодированной форме, что и пути запросов, поэтомуmatcher: "/café/:path*"и"/caf%c3%a9/:path*"защищают/caf%C3%A9, а"/ops%40corp/:path*"защищает/ops@corp. Middleware без шаблона сопоставления не запускается за пределамиbasePath. Шаблон с завершающим слешем, например/admin/, соответствует/admin, а условиеhostигнорирует завершающую точку в имени хоста. - Живая сессия маршрута
runtime = "server"не рендерит страницу, для которой middleware переписал путь или запрос, например с/restrictedна/login, либо ответил статусом ошибки, напримерNextResponse.next({ status: 403 }). --adapter vercel: функция обработчика маршрута получает путь в заголовке запроса, который задают только сгенерированные маршруты, поэтому/api/x/%252e%252e/adminбольше не достигает/api/admin, и ни один вариант записи/_textjs/*не запускает функцию. Сгенерированные маршруты учитывают регистр, поэтому/LEGACY/xбольше не попадает в перезапись для/legacy/:path*, которую middleware не проверял. Каждый потенциально неканонический путь, включая незакодированные символы вроде{, проходит через edge-middleware, который теперь включён в каждую сборку Vercel и переписывает запрос на канонический путь.--adapter cloudflare: статические файлы ищутся по закодированному пути, поэтому/x/%252e%252e/admin/report.txtбольше не отдаёт/admin/report.txt. При наличииbasePathфайлы за его пределами больше не отдаются без воркера.text devне отдаёт файлыpublic/по путям/public/…или/@fs/…, серверные исходники вродеmiddleware.tsиtext.config.tsв другом регистре, по закодированному пути/@fs/, как запросы модулей без расширения (/text.config?import) или через перезапись конфигурации, а также обработчики маршрутов за пределамиbasePath.
Добавлено
- Text.js рендерит в консолях Firefox и Safari.
CssConsoleDriverопределяет браузер проверками поддержки CSS. Там, где span%cостаются строчными, он задаёт высоту строки 14 пкс без внешних отступов, отключает мягкий перенос и использует завесуline-height: 100vh. - Адаптивный размер оставляет место для столбца ссылок на исходники Firefox. Safari ставит Menlo первым в наборе шрифтов: его страницы не могут использовать установленный пользователем SF Mono, которым может рисовать Web Inspector.
- Передайте
browser: "chromium" | "firefox" | "safari"вcreateConsoleRoot,ConsoleRendererилиCssConsoleDriver, чтобы выбрать консоль. - Оболочки после пререндеринга содержат CSS для обоих видов консоли.
<FocusPad>показывает сочетание клавиш консоли для браузера посетителя: ⌘⌥K или Ctrl+Shift+K в Firefox и ⌘⌥C в Safari с указанием включить «Показывать функции для веб-разработчиков».<FocusPad>после пререндеринга отображает сочетания клавиш всех браузеров. Задайтеdata-browser(firefoxилиsafari) иdata-os(mac) на<html>до первой отрисовки, чтобы показать только сочетание посетителя; без них до гидратации показывается сочетание Chrome для Windows и Linux.
Исправлено
- ⌘⌥K и Ctrl+Shift+K (сочетания клавиш консоли Firefox) передаются браузеру вместо приложения.
- Адаптивный размер запоминает панели инструментов браузера высотой менее 60 пкс (Safari и Firefox), пока DevTools закрыт, поэтому закреплённая снизу консоль получает все помещающиеся строки.
<FocusPad>использует запомненную высоту, чтобы определить, закреплён ли DevTools. <FocusPad>записывает сочетания клавиш Windows и Linux в состоянии ожидания щелчка какCtrl+Shift+J.
Безопасность
@textjs/opencode: мост выводит код сопряжения при запуске, а textjs.org/opencode запрашивает его при первом подключении. Пока страница не отправит код, мост отвечает428и ничего не пересылает в OpenCode, даже для разрешённых источников. Каждый код действует в течение одного запуска моста, возвращаемый токен работает только с источника, выполнившего сопряжение, а десять неверных кодов блокируют сопряжение до перезапуска моста.@textjs/opencode: предварительные развёртывания textjs.org в Cloudflare Pages больше не разрешены по умолчанию. Передайте--allow-origin, чтобы использовать одно из них.- textjs.org/opencode отклоняет мосты из
@textjs/opencode1.0.x. Запуститеbunx @textjs/opencode@latest proxy. - textjs.org отправляет Content-Security-Policy,
Strict-Transport-Security,Cross-Origin-Opener-PolicyиCross-Origin-Resource-Policy. Страница OpenCode подключается только к серверам на127.0.0.1илиlocalhost.
- Text.js рендерит в консолях Firefox и Safari.
Добавлено
- OpenCode Lite: просматривайте изменения по файлам и историю промптов, настраивайте сочетания с ведущей клавишей и управляйте аккаунтами провайдеров и серверами MCP. Песочница включает панель терминала со сценарным поведением.
- OpenCode Lite: введите
/для поиска команд или@для прикрепления файла проекта. Tab открывает каталог в меню файлов. Подключённые сессии ищут в проекте сервера; песочница ищет в своём примере репозитория. - textjs.org/coffee: демо terminal.shop следует размеру консоли, как SSH-приложение, с малым, средним и большим макетами и сообщением «ваш терминал слишком мал» при размере менее 20 × 10. В аккаунт добавлены способы оплаты, профиль с редактируемым именем и изменение еженедельного расписания подписок. Без входа доступны корзина и разделы аккаунта с частыми вопросами, сведениями о сервисе и отладочной информацией.
Производительность
@textjs/react:BoxиTextпередают согласователю заранее очищенные свойства сцены вместо копирования объектов свойств при монтировании и обновлении.@textjs/core:SceneNode.getTextModel()пропускает обходы строчного дерева для листьев<Text>с одной строкой и повторно использует кешированные обнулённые буферыUint16ArrayrunOf.CssConsoleDriverсканирует последовательные ячейки BMP с одинаковым стилем во внутреннем цикле, аConsoleRendererпропускаетcountYogaNodes()для неизменённых кадров.- textjs.org: маршруты и вкладки панели консоли разделены на JS- и CSS-чанки для каждого маршрута. Фотографии магазина перекодированы из оригиналов
photos/final, а дополнительные снимки товаров загружаются при наведении или смене слайда.
Исправлено
<ViewportControl>использует пиксельныйminWidthвместо20chи перечисляет запасные шрифты с совпадающими метриками вместе с<FocusPad>, поэтому выбор размера сохраняет ширину при загрузкеGeist Mono.
Добавлено
@textjs/opencode: мост textjs.org/opencode выделен в отдельный пакет без зависимостей. Запуститеbunx @textjs/opencode proxy(илиnpx), чтобы запустить его без установки Vite, React и MCP SDK.text proxyпо-прежнему работает и запускает тот же мост.
Изменено
- Пакет фреймворка и CLI теперь называется
@textjs/app, он переименован из@textjs/next, чтобы название не подразумевало официальную интеграцию с Next.js.@textjs/nextустарел в пользу@textjs/appи больше не получает релизов. Для перехода запуститеbun remove @textjs/next && bun add @textjs/appи замените@textjs/nextна@textjs/appв импортах, включая подпути вроде@textjs/app/link. CLI по-прежнему называетсяtext, а шаблоны create-text-app зависят от@textjs/app. - Кнопка
[▼]и инспектор в консоли называются Dev Overlay, а заголовок инспектора гласит▼ Dev Overlay · Turbolog. Text.js DevTools называется только расширение Chrome.<TextDevOverlay>и его свойства не изменились. - Обработчики маршрутов, экспортирующие
dynamic = "error", завершаются сTX031. Text.js трактовал это как"force-static", не проверяя, читает ли обработчик запрос, что и означает это значение в Next.js. Используйте"force-static".
Исправлено
text startотвечает на заблокированныйHostкодомTX028, как иtext dev. Каждый сервер указывает читаемую настройку:vite.server.allowedHostsдляtext devиserver.allowedHostsдляtext start.- textjs.org: глава «Публикация» раздела «Обучение» больше не предлагает добавить перезапись в
vercel.json. В Vercel и Cloudflare Pagestext buildсам записывает резервныйindex.html. Пример перезаписи теперь использует_redirectsNetlify. eslint-plugin-textjs:route-handler-exportsразрешает экспортыdynamicиrevalidateвroute.ts, аvalid-route-moduleпроверяет там значенияdynamic.
Добавлено
- textjs.org: воспроизводимое видео главы раздела «Обучение» перемещается в мини-плеер в углу, когда вы прокручиваете страницу мимо него. Кнопка «Субтитры» под каждым видео включает или выключает субтитры и запоминает выбор.
<TextDevOverlay>принимает свойстваpill,shortcutиshell, чтобы приложения без App Router могли монтировать инспектор со своими клавишами и элементами управления темой.<FocusPad>принимаетbanner, который показывается первой строкой сообщения (например, словесный логотип приложения) и над уведомлением на сенсорных устройствах.
Изменено
- textjs.org: список Playground включает «Панель мониторинга», «Потоковый вывод», «Змейку», OpenCode и «Кофе» (terminal.shop). У каждого демо свой URL: OpenCode находится на
/opencode, а terminal.shop на/coffee, и их словесные логотипы возглавляют сообщение. «Счётчик» и «Форма» перенесены из Playground; документация по-прежнему запускает оба как живые примеры. <FocusPad>получил новый макет. Каждое состояние показывает полосу прогресса из трёх частей, заголовок, один крупный элемент и строку текста. До открытия консоли крупный элемент представляет собой сочетание клавиш DevTools. При ожидании щелчка это указатель. После запуска этоhintsприложения в виде клавиш, которые подсвечиваются при нажатиях, а клавиши без подсказок отображаются ниже. Подписи шагов, отдельный значок «В эфире» и строка «Смотрите в консоль.» удалены. Строки плавно появляются при смене состояния, но не при первой отрисовке, а приprefers-reduced-motionдвижение отключено. Вторичный текст соответствует контрастности WCAG AA в обоих вариантах оформления, а выбор размера консоли показывает обводку фокуса при переходе с клавиатуры.- textjs.org: Playground использует новый макет
<FocusPad>. Текущее демо в списке имеет поверхность клавиш, поле команды OpenCode повторяет углы и размер шрифта поля URL, заметка terminal.shop занимает две строки вместо трёх, «Посмотреть исходный код» находится на базовой линии элемента управления размером, а приглушённый текст панели соответствует контрастности AA.
Исправлено
text devобслуживает путиproxyчерез прокси для каждого запроса.fetch()отправляетAccept: */*, поэтому сервер разработки сначала отвечал HTML приложения, а шаблон opencode при первом запуске выдавал «Неожиданный токен '<'».text devбольше не загружает вторую копию React, когда сканирование зависимостей Vite читает серверный файл. Сканирование запускало проверку серверных импортов, которая выводила трассировку стека, затем «Недопустимый вызов хука» в консоли и ломала Fast Refresh.text devобрабатывает URL страниц со строкой запроса, например/?demo. Vite считал их папкой проекта и отслеживал весь диск, поэтому в Linux страница не загружалась.- create-text-app: кнопка разработки больше не перекрывает первую подсказку клавиши на начальном экране любого шаблона, имя проекта по умолчанию
my-appсоответствует документации, шаблоны проходят рекомендуемую конфигурациюeslint-plugin-textjs, а README панели мониторинга объясняет сборку--adapter static. <FocusPad>и<ViewportControl>задают границы только отдельными свойствами. React предупреждал «Обновление свойства стиля при повторном рендеринге (border)» в режиме разработки при каждой вспышке подсказки клавиши.- Текст, являющийся последним элементом строки, теперь сохраняет положение, когда становится короче. После
<Spacer>он оставался там, где его оставил самый длинный текст, а соседние элементы, сжатые для размещения переполненной строки, оставались сжатыми. <FocusPad>заменяет шаги, подзаголовок и строки клавиш при измененииactionилиhints, поэтому переключение демо в одной панели не регистрируется как сдвиг макета.@textjs/react/testingзагружает Yoga при импорте, поэтому тест может подменитьfetchдо первогоrender().
Первый стабильный релиз.
▼ Text.js 1.0.0 (Turbolog).Изменено
- Несовместимое изменение: пакет фреймворка и CLI теперь называется
@textjs/next(textjsзанят в npm). Обновите импорты сtextjsна@textjs/next. - Мост OpenCode запускается командой
bunx @textjs/app proxyи работает из любого каталога. - Консоль по умолчанию подстраивается под закреплённую панель DevTools (снизу, слева или справа, масштаб страницы, перенос панели инструментов). Для незакреплённого DevTools используется
120×36. Панели получили элемент управления размером.
Добавлено
useKeymapс автоматическим экраном справки?, подсказками клавиш и палитрой командCtrl+K.- Компоненты данных:
List(виртуализированный),Table,Tree. - Графики:
LineChart,BarChart,Sparkline,ProgressBar, а такжеGradientиImage. - Элементы управления:
Button,Checkbox,Switch,RadioGroup,Slider,Dialog,Confirmи всплывающие уведомления. - Макет:
Center,Stack,Grid,SplitPane,FocusScope. - Хуки для таймеров, анимации, измерений, контрольных точек, хранилища и буфера обмена.
- Текст справа налево. Text.js реализует двунаправленный алгоритм Unicode (UAX #9, Unicode 18.0) и проходит все 770 241 тест
BidiTest.txtи 91 707 тестовBidiCharacterTest.txt. Арабские символы получают контекстную форму, а<Text dir>изолирует span. - Стабильные коды ошибок
TX###. Ошибки фреймворка содержат код и ссылку наhttps://textjs.org/errors/<code>. @textjs/react/testingдля рендеринга компонентов в текст в тестах.@textjs/react/terminalиtext run, который рендерит приложение App Router в настоящем терминале.text mcp, который предоставляет приложение через Model Context Protocol, чтобы агенты программирования могли перемещаться по нему, нажимать клавиши и читать кадры без браузера.- Расширение Text.js DevTools, панель рядом с «Консолью» с деревом компонентов, инспектором кадров и временной шкалой.
eslint-plugin-textjsи расширение VS Code с живым предпросмотром.apps/terminal-shop: витрина terminal.shop в консоли с настоящим API (по умолчанию песочница разработки, рабочая среда защищена двумя блокировками).- textjs.org: «Обучение», курс из 10 глав, работающий в консоли. Пререндеринг при сборке с гидратацией, собственные шрифты с совпадающими метриками, маршруты
.htmlбез слешей и новые страницы документации с живым предпросмотром.
Производительность
- Устранена фазовая синхронизация ограничения частоты DevTools после очистки. После кадра с очисткой рендерер однократно ждёт 110 мс, чтобы последующие кадры попадали на немедленный путь DevTools. Задержка отображения p50 снизилась с 63 мс до 10 мс.
- Частичная отрисовка повреждённых полос: перерисовываются только полосы строк, затронутые изменением.
- Кешированные хеши строк, целочисленные идентификаторы стилей и кадры простоя без выделения памяти.
- Ни одного таймера простоя, пока страница скрыта или не в фокусе.
Исправлено
- Нет фантомных пустых span слоя отрисовки на разрывах строк и удвоенной завесы.
- Завеса находится на отдельной строке, поэтому ссылка DevTools на исходник (
VM12:1) никогда не переносит строку 0. - Спиннер по умолчанию точно укладывается в ячейки (в Menlo нет глифов Брайля). Вариант
brailleвключается явно. text buildпод Node больше не включает сборки React для разработки.- textjs.org: совокупный сдвиг макета равен 0 на каждом маршруте. Playground и OpenCode используют один макет панели.
- textjs.org: боковые панели документации и раздела «Обучение» остаются закреплёнными внизу длинных страниц.
- textjs.org: вкладки файлов, блоки кода и текстовые таблицы прокручиваются только горизонтально, поэтому iOS Safari не перехватывает вертикальные свайпы страницы.
- textjs.org:
scrollbar-gutter: stableприменяется только на устройствах с мышью. В iOS Safari он вызывал скачок при первой прокрутке. - textjs.org: привязка прокрутки отключена. В iOS Safari она закрепляла главный блок под липким заголовком.
- Несовместимое изменение: пакет фреймворка и CLI теперь называется
Кадры без мигания и серверный рендеринг.
Изменено
- Кадры дописываются вместо вызова
console.clear()+console.log()для каждого кадра. DevTools выполняет очистку синхронно, но отрисовывает новые сообщения с интервалом 50 мс, поэтому очистка оставляла консоль пустой при 70,6 % отрисовок DevTools на 15 кадрах/с и 81,1 % на 60 кадрах/с. Начальный span-завеса нулевой ширины скрывает предыдущие кадры. Консоль очищается только на первом кадре, послеinvalidate(), в простое после накопления 100 кадров или при 300 кадрах. - Выводимые кадры разделяет интервал не менее 66 мс (около 15 кадров/с). Более частые кадры перезапускают задержку DevTools и отбрасываются: при 60 кадрах/с DevTools отрисовал 67 из 295 выведенных кадров.
- Playground и OpenCode — полноэкранные панели фокуса.
Производительность
- CSS для span только с отдельными свойствами вместо сокращённых, что уменьшает число свойств, которые DevTools копирует в каждую строку, примерно с 33 до 7. Шестнадцатеричные цвета и серии пустых ячеек с ключом только по фону.
- Инкрементальный разбор Markdown и мемоизированные строки
Markdown,CodeиDiff. - Обработка props хост-компонентов за один проход, обновление только изменённых props и отсутствие повторного расчёта макета Yoga, когда размер текста не может измениться.
- Время потокового кадра сократилось с 0,79 мс до 0,14 мс, тика спиннера — с 0,90 мс до 0,056 мс. Вывод побитово идентичен.
Добавлено
- Серверный рендеринг. Страница, экспортирующая
runtime = "server", рендерится на сервере, включая компонентыasync function, и передаёт изменения ячеек по строкам через server-sent events в проигрыватель кадров размером около 19 КБ в gzip. - Частичный пререндеринг.
text buildвстраивает первый кадр каждого статического маршрута в его HTML, поэтому консоль отрисовывается до загрузки любого модуля. middleware.ts, конфигурация сегментов маршрута (dynamic,revalidate) иtextjs/cache(unstable_cache,revalidateTag,revalidatePath).text build --adapter static|bun|vercel|cloudflare.bench/devtools: стенд, который управляет настоящим интерфейсом DevTools и измеряет пустые отрисовки, пропущенные кадры, задержку отображения и загрузку CPU со стороны DevTools.
Исправлено
- DevTools больше не превращает текст
path:line,//host:portиdata:в ссылки. - Мост OpenCode находит управляемый демон (временный порт, базовая аутентификация), отправляет заголовок CSRF при записи и сообщает об ошибках одной строкой.
- Кадры дописываются вместо вызова
Изменено
- Дискретный ввод (нажатие клавиши, вставка) рендерится синхронно в той же задаче, не ожидая следующего кадра анимации.
- Сокращённый TUI OpenCode, соответствующий настоящему.
- Полная доработка мобильной и адаптивной версии textjs.org.
Добавлено
@textjs/font: парсер и рендерер шрифтов FIGlet с 17 встроенными шрифтами для<FigletText>и<AsciiFont>. Вывод совпадает с 273 эталонами, записанными из бинарного файлаfiglet2.2.5.text proxy: локальный CORS-мост для связи textjs.org с вашим сервером OpenCode.
Добавлено
apps/opencode-console: подключённый клиент OpenCode, отрендеренный вconsole.log, с переходом в деморежим, когда сервер не запущен.- Шаблон
opencodeдляcreate-text-app. - textjs.org: новая главная страница, интерактивная панель управления консолью, Playground, страница OpenCode и документация.
- Процесс развёртывания на GitHub Pages с генерацией статических маршрутов.
Первый этап.
Добавлено
@textjs/core:CellBufferна плоских типизированных массивах, расчёт макета Yoga WASM, измерение текста черезIntl.Segmenterи драйвер%cс кодированием длин серий. Одинconsole.logна изменённый кадр и ни одного в простое.@textjs/react: реконсилер React 19, компоненты в PascalCase (Box,Text,ScrollBox,Input,Textarea,Select,Tabs,Code,Markdown,Diff,Modal,Spinnerи другие), утилитыclassNameв стиле Tailwind на уровне ячеек, темы и DOM-компонентFocusPad.textjs: App Router на основе файловой системы (layout,page,loading,error,not-found, динамические сегменты, обработчики маршрутов),text dev,text build,text startи инспектор[▼]в консоли.create-text-appс шаблонамиstarterиdashboard.