Что нового в Text.js

Все значимые изменения Text.js описаны в этом файле.

  1. Не выпущено

    Добавлено

    • 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 пикселей.
  2. v1.5.0

    Добавлено

    • @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. Строка над примером в консоли теперь гласит «▼ Документация › Счётчик» вместо «▼ Документация › Введение › Счётчик».
  3. v1.4.1

    Добавлено

    • 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 на тик вперёд в каждом кадре анимации и обратном вызове таймера.
  4. v1.4.0

    Добавлено

    • @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> рисует фотографию рядом с текстом полублоками, как консоль, вместо изображения.
  5. v1.3.0

    Добавлено

    • @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 кадров.
  6. v1.2.0

    Добавлено

    • @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/app 1.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 не может запустить обёртку npm opencode.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/app 1.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.
  7. v1.1.0

    Добавлено

    • 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/opencode 1.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.
  8. v1.0.4

    Добавлено

    • OpenCode Lite: просматривайте изменения по файлам и историю промптов, настраивайте сочетания с ведущей клавишей и управляйте аккаунтами провайдеров и серверами MCP. Песочница включает панель терминала со сценарным поведением.
    • OpenCode Lite: введите / для поиска команд или @ для прикрепления файла проекта. Tab открывает каталог в меню файлов. Подключённые сессии ищут в проекте сервера; песочница ищет в своём примере репозитория.
    • textjs.org/coffee: демо terminal.shop следует размеру консоли, как SSH-приложение, с малым, средним и большим макетами и сообщением «ваш терминал слишком мал» при размере менее 20 × 10. В аккаунт добавлены способы оплаты, профиль с редактируемым именем и изменение еженедельного расписания подписок. Без входа доступны корзина и разделы аккаунта с частыми вопросами, сведениями о сервисе и отладочной информацией.
  9. v1.0.3

    Производительность

    • @textjs/react: Box и Text передают согласователю заранее очищенные свойства сцены вместо копирования объектов свойств при монтировании и обновлении.
    • @textjs/core: SceneNode.getTextModel() пропускает обходы строчного дерева для листьев <Text> с одной строкой и повторно использует кешированные обнулённые буферы Uint16Array runOf. CssConsoleDriver сканирует последовательные ячейки BMP с одинаковым стилем во внутреннем цикле, а ConsoleRenderer пропускает countYogaNodes() для неизменённых кадров.
    • textjs.org: маршруты и вкладки панели консоли разделены на JS- и CSS-чанки для каждого маршрута. Фотографии магазина перекодированы из оригиналов photos/final, а дополнительные снимки товаров загружаются при наведении или смене слайда.

    Исправлено

    • <ViewportControl> использует пиксельный minWidth вместо 20ch и перечисляет запасные шрифты с совпадающими метриками вместе с <FocusPad>, поэтому выбор размера сохраняет ширину при загрузке Geist Mono.
  10. v1.0.2

    Добавлено

    • @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 Pages text build сам записывает резервный index.html. Пример перезаписи теперь использует _redirects Netlify.
    • eslint-plugin-textjs: route-handler-exports разрешает экспорты dynamic и revalidate в route.ts, а valid-route-module проверяет там значения dynamic.
  11. v1.0.1

    Добавлено

    • 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().
  12. v1.0.0

    Первый стабильный релиз. ▼ 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 она закрепляла главный блок под липким заголовком.
  13. v0.4.0

    Кадры без мигания и серверный рендеринг.

    Изменено

    • Кадры дописываются вместо вызова 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 при записи и сообщает об ошибках одной строкой.
  14. v0.3.0

    Изменено

    • Дискретный ввод (нажатие клавиши, вставка) рендерится синхронно в той же задаче, не ожидая следующего кадра анимации.
    • Сокращённый TUI OpenCode, соответствующий настоящему.
    • Полная доработка мобильной и адаптивной версии textjs.org.

    Добавлено

    • @textjs/font: парсер и рендерер шрифтов FIGlet с 17 встроенными шрифтами для <FigletText> и <AsciiFont>. Вывод совпадает с 273 эталонами, записанными из бинарного файла figlet 2.2.5.
    • text proxy: локальный CORS-мост для связи textjs.org с вашим сервером OpenCode.
  15. v0.2.0

    Добавлено

    • apps/opencode-console: подключённый клиент OpenCode, отрендеренный в console.log, с переходом в деморежим, когда сервер не запущен.
    • Шаблон opencode для create-text-app.
    • textjs.org: новая главная страница, интерактивная панель управления консолью, Playground, страница OpenCode и документация.
    • Процесс развёртывания на GitHub Pages с генерацией статических маршрутов.
  16. v0.1.0

    Первый этап.

    Добавлено

    • @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.