ESLint

eslint-plugin-textjs: konsola uygun JSX, hücre genişliğinde glifler, kare hızına uyumlu zamanlayıcılar ve App Router denetimleri.

eslint-plugin-textjs, Text.js hatalarını editörde yakalar: konsol bileşenlerindeki DOM etiketleri, metin içindeki kutular, Menlo’da bulunmayan glifler, araya giren console.log çağrıları ve sessizce yok sayılan App Router dışa aktarımları.

Kurulum

bun add -d eslint eslint-plugin-textjs typescript-eslint
eslint.config.jsjs
import { defineConfig } from "eslint/config";import tseslint from "typescript-eslint";import textjs from "eslint-plugin-textjs";export default defineConfig(tseslint.configs.recommended, textjs.configs.recommended);

Eklenti, düz yapılandırma ile ESLint 9 ve 10’u destekler. Kurallar sözdizimseldir; tür bilgisine veya parserOptions.project ayarına ihtiyaç duymaz. TypeScript ve JSX’i anlayan her ayrıştırıcı çalışır.

Yapılandırmalar

YapılandırmaEtkinleştirdikleri
textjs.configs.recommendedTüm doğruluk kuralları hata; konsol, zamanlayıcı ve kare zamanlama kuralları uyarı olarak
textjs.configs.strictHer şey hata, ayrıca prefer-use-keymap uyarı olarak

Bunun yerine kuralları tek tek seçin:

eslint.config.jsjs
import textjs from "eslint-plugin-textjs";export default [  {    plugins: { textjs },    rules: {      "textjs/no-box-in-text": "error",      "textjs/no-console-in-components": ["warn", { allow: ["error"], logger: "log" }],    },  },];

Konsol dosyaları

Çoğu kural yalnızca konsola render eden dosyalara uygulanır: @textjs/app veya @textjs/react paketinden bir bileşen ya da hook (Box, Text, useInput, …) içe aktaran dosyalar. react-dom veya @textjs/react/dom içe aktaran dosyalar sayfa kodudur ve bunlara dokunulmaz; böylece bir web sitesi aynı projede DOM sayfalarını ve konsol uygulamalarını bir arada kullanabilir. tokenize veya parseMarkdown gibi bir yardımcı işlevi içe aktarmak, dosyayı konsol dosyası yapmaz.

eslint.config.jsjs
import textjs from "eslint-plugin-textjs";export default [  textjs.configs.recommended,  {    settings: {      textjs: {        packages: ["@acme/console-ui"], // also re-exports Text.js components        consoleFiles: "imports", // or "all"      },    },  },];

App Router kuralları, src/app/ dahil herhangi bir app/ dizininde dosya adına (page.tsx, layout.tsx, route.ts, …) göre çalışır. Dizininizin adı farklıysa valid-route-module, valid-metadata ve route-handler-exports kurallarına { appDir: "routes" } geçirin.

Kurallar

KuralÖnerilenDüzeltme
no-dom-elementshataöneri
no-box-in-texthata
no-unsupported-glyphshataotomatik düzeltme, öneri
no-console-in-componentsuyarıöneri
prefer-use-intervaluyarıöneri
no-sub-frame-timersuyarı
prefer-use-keymapyalnızca strict
valid-route-modulehata
valid-metadatahata
route-handler-exportshataöneri

no-dom-elements

<div>, <span>, özel öğeler ve diğer DOM etiketleri konsolda bulunmaz. Uzlaştırıcı yalnızca kendi ana düğümlerini tanır ve diğer her şey için TX003 hatası fırlatır.

<div className="flex-col">       // ✗<Box className="flex-col">       // ✓<strong>Deployed</strong>        // ✗<Text bold>Deployed</Text>       // ✓

Öneri, etiketi en yakın bileşenle (div → Box, span/p → Text, strong → Text bold, a → Link, input → Input, hr → Divider, …) değiştirir ve içe aktarımı ekler.

no-box-in-text

<Text>, biçimlendirilmiş span dizisidir; kutu içeremez. İçine <Box> veya kökü kutu olan herhangi bir bileşen (<ScrollBox>, <Input>, <Code>, <ProgressBar>, <Divider>, …) yerleştirmek, render sırasında TX004 hatası fırlatır. Bu kural ise hatayı editörde bulur; &&, üçlü koşul ifadeleri, fragment’ler ve .map() içindekiler de buna dahildir.

<Text>Status <Box /></Text>                     // ✗<Box className="flex-row gap-1"><Text>Status</Text><Box /></Box>  // ✓<Text>Press <Kbd>⌘K</Kbd> <Spinner /></Text>     // ✓ inline components

no-unsupported-glyphs

Text.js her karakteri sabit bir hücre ızgarasına yerleştirir. macOS’teki DevTools konsol yazı tipi Menlo’da bulunmayan glifler, bir hücreden daha geniş olan yedek bir yazı tipiyle render edilir; bu yüzden ardından gelen tüm hücreler kayar.

  • Braille (U+2800–U+28FF, klasik terminal yükleme göstergesi kareleri): blok veya çeyrek blok karakterlerini (▘▝▗▖), <Spinner variant="dots"> bileşenini ya da grafiklerde marker="quadrant" ayarını kullanın. Yalnızca terminalde text run ile çalışan uygulamalar için { allowBraille: true } ayarlayın.
  • Çeşitli semboller ve oklar (U+2B00–U+2BFF, küçük kare U+2B1D gibi): öneriler Menlo’daki karşılığını (·, ●, ←) sunar.
  • Tek hücrelik sembollerde emoji sunumu (ardından U+FE0F gelen ▶ veya ↩): ızgara bir hücre ayırırken varyasyon seçicisi bunları iki hücrelik emojiye dönüştürür. Otomatik düzeltme bunu kaldırır.

Geniş emojiler (🚀, ✅) sorun oluşturmaz: Text.js bunları iki hücre olarak ölçer.

no-console-in-components

Her kare bir console.log çağrısıdır. Kendi günlükleriniz karelerin arasına girer, sonraki kareyle kaydırılıp gider ve alta sabitlenen görünümün altında gizlenir. console.clear() uygulamanın kendisini siler.

"textjs/no-console-in-components": ["warn", { allow: ["error"], logger: "log" }]

Mesajları arayüzde useToast() veya bir günlük <ScrollBox> bileşeniyle gösterin ya da durumu [▼] Dev Overlay içinde inceleyin (Ctrl+`). logger ile öneri, console.warn(…) çağrısını log.warn(…) olarak yeniden yazar. Test dosyaları ve @textjs/app/testing render işlemleri atlanır.

prefer-use-interval

Bir bileşende doğrudan kullanılan setInterval, eski durum değerlerini kullanmamak için bir effect, bir temizleme işlemi ve bir ref gerektirir. useInterval üçünü de yapar ve null onu durdurur.

useEffect(() => {  if (paused) return;  const id = setInterval(tick, 1000);  return () => clearInterval(id);}, [paused]);useInterval(tick, paused ? null : 1000); // the suggestion

Animasyon için useAnimationFrame, render motorunun kare zamanlamasını izler ve çıktı duraklatıldığında durur. Yardımcı hook’lar bölümüne bakın.

no-sub-frame-timers

Text.js her 66 ms’de en fazla bir kare üretir (yaklaşık 15 fps). 16 ms’lik bir aralık, üretilen her kare başına dört kez render eder; ek kareler birleştirilir ve yalnızca CPU tüketir. minInterval (varsayılan 66) altındaki setInterval/useInterval gecikmelerini ve fps değeri 15’in üzerindeki useAnimationFrame kullanımlarını bildirir.

prefer-use-keymap

e.key değerini elle karşılaştırmak çalışır, ancak kısayollar görünmez. useKeymap, etiketli tuş atamalarını <KeyHelp>, <KeyHints> (hint: true içeren atamalar) ve komut paletine yerleştirir, g g gibi dizileri işler ve eşleşen tuşlar için yayılımı durdurur. İki veya daha fazla tuş sabitini (minKeys) karşılaştıran useInput işleyicilerini bildirir ve yazı girişi için e.input okuyan işleyicileri atlar.

useKeymap({  "up, k": { label: "Increment", run: inc, hint: true },  "down, j": { label: "Decrement", run: dec, hint: true },});

Klavye kısayolları bölümüne bakın.

valid-route-module

  • page, layout, loading, error ve not-found dosyaları bir bileşeni varsayılan olarak dışa aktarmalıdır (TX015).
  • export const dynamic, "auto", "force-static" veya "force-dynamic" olmalıdır (TX031). Text.js, Next.js’in "error" değerini desteklemez. Bu değer sayfalardan, layout’lardan ve rota işleyicilerinden okunur. Sayfalarda ve layout’larda bunu düz bir dize sabiti olarak yazın: text build modülü çalıştırmadan kaynak koddan okur.

valid-metadata

Metadata önce layout’lardan, ardından sayfadan (veya not-found dosyasından) birleştirilir. Kural, yönlendiricinin sessizce yok sayacağı durumları bildirir:

  • loading veya error dosyalarındaki metadata ya da generateMetadata
  • aynı dosyada her iki dışa aktarımın bulunması
  • async generateMetadata: eşzamanlı çağrıldığı için bir Promise başlığı hiçbir zaman ayarlamaz
  • dize veya { default, template?, absolute? } olmayan bir title ya da yanlış yazılmış bir anahtar
  • %s içermeyen veya hiçbir etkisinin olmadığı bir sayfada bulunan title.template
  • dize olmayan bir description

route-handler-exports

route.ts dosyaları yalnızca dışa aktardıkları HTTP yöntemlerine yanıt verir: GET, HEAD, POST, PUT, PATCH, DELETE ve OPTIONS. Küçük harfle başlayan get veya Post hiçbir zaman çağrılmaz (istekler 405 alır); öneri bunları yeniden adlandırır. dynamic ve revalidate rota segmenti yapılandırması dışında varsayılan dışa aktarımlar, işlev olmayan işleyiciler ve diğer dışa aktarımlar bildirilir. Paylaşılan kodu lib/ dizinine taşıyın veya ek adları { allow: [...] } ile listeleyin.

app/api/health/route.tsts
export function get() { … }   // ✗ never calledexport function GET() { … }   // ✓
Bu sayfayı GitHub’da düzenle