Skip to content

@tabula-css/core

Tabula のコード契約レイヤー: 他のすべての Tabula パッケージが合意する、凍結されたテーブル・純粋関数・エラーコード・JSON スキーマです。ランタイム依存はゼロです。

インストール

ほとんどのプロジェクトは @tabula-css/core を直接インストールすることはありません — これは @tabula-css/tokens@tabula-css/registry@tabula-css/merge@tabula-css/preset の推移的依存であり、これらすべてがその不変条件をここからインポートしています。診断カタログ、凍結テーブル、JSON スキーマだけを、パイプラインの他の部分を引き込まずに必要とするカスタムツールを書く場合にのみ、直接インストールしてください。

bash
npm install @tabula-css/core

概要

@tabula-css/core は、プロファイルの語彙とその診断が定義される唯一の場所であり、これにより CLI・レジストリジェネレーター・リンター・MCP サーバーが互いに乖離することを防ぎます。I/O を持たず、Tailwind への依存もありません。エクスポートされるものはすべて、凍結されたデータテーブル(正規の CSS スロット、名前空間 → ユーティリティファミリーのマップ、バリアントテーブル、禁止リスト)、純粋関数(rank()checkLaminarity()computeSpecificity())、JSON スキーマ(tabula.config.json、トークンファイル、registry.jsonmanifest.json 用)、または安定した TAB-Exxx/TAB-Wxxx エラーカタログのいずれかです。下流のすべて — @tabula-css/tokens のバリデーター、@tabula-css/registry のジェネレーター、@tabula-css/merge のランタイム — はこれらのテーブルを再導出するのではなく読み取ります。

エクスポート

診断

システム内のすべての TAB-Exxx/TAB-Wxxx コードの元となる、安定した診断カタログです — 文脈の中でのコードについては Concepts § the registry is ground truthGetting started を参照してください。

ts
export type Severity = 'error' | 'warning';

export interface Diagnostic {
  readonly code: string;
  readonly severity: Severity;
  readonly message: string;
  readonly subject?: string;
  readonly hint?: string;
}

export type ErrorCode = keyof typeof ERROR_CATALOG; // e.g. 'TAB-E109' | 'TAB-E300' | …
export const ERROR_CATALOG: Readonly<Record<ErrorCode, { severity: Severity; summary: string; teach: string }>>;
export const ERROR_CODES: readonly ErrorCode[];

export function formatMessage(
  template: string,
  params?: Readonly<Record<string, string | number>>,
): string;

export function makeDiagnostic(
  code: ErrorCode,
  params?: Readonly<Record<string, string | number>>,
  opts?: { readonly subject?: string; readonly hint?: string },
): Diagnostic;

ERROR_CATALOG は、すべてのコードをその重大度、{name} テンプレート化された summary、そして tabula explain <code> が出力する 1 行の teach 文字列にマッピングします。makeDiagnostic() は、システム内のすべてのパッケージが Diagnostic を構築するために使う唯一のコンストラクターです。コードのテンプレートを検索し、formatMessage() 経由で params を埋め込み、任意の subject(診断対象のトークンパスまたはクラス名)と hint(実行可能な次の一手)を付加します。

ts
import { makeDiagnostic } from '@tabula-css/core';

makeDiagnostic('TAB-E109', { path: 'color.surface' });
// → { code: 'TAB-E109', severity: 'error',
//     message: "Token 'color.surface' requires a $description ≥ 20 chars, not byte-equal to its value.", … }

このカタログは、構造的なトークンファイルエラー(TAB-E1xx)、値セマンティクス(TAB-E15xE16x)、バリアント閉包(設定の TAB-E170E172、スキャンの TAB-E230)、ビルド不変条件(TAB-E21x)、CSS ガバナンス(TAB-E22x)、イジェクトの前提条件(TAB-E240/TAB-W402)、マージランタイム(TAB-E3xx)、生成アーティファクトの整合性(TAB-E601)、CLI の使用法(TAB-E9xx)にまたがります — E22x ファミリーについては特に CSS governance を参照してください。

凍結テーブル

@tabula-css/core は、プロファイルの不変条件が照合されるすべてのテーブルの正規のコピーを 1 つずつ凍結します。対象ごとにグループ化すると次のとおりです。

ExportTypePurpose
CANONICAL_SLOT_PROPERTIESreadonly string[]正規のロングハンド CSS プロパティの順序付きリスト。スロットの id はそのインデックスです。
CANONICAL_SLOTSReadonly<Record<string, string>>slotId → propertyregistry.jsonslots マップと一致します。
SLOT_ALIASESReadonly<Record<string, string>>ブロック論理 → 物理ブロックの正規化(padding-block-start → padding-top)。
PHYSICAL_INLINE_TWINSReadonly<Record<string, string>>論理インラインプロパティ → その(未登録の)物理インラインの対。「両方は禁止」ユニットテスト用。
slotIdOf(property)(string) => SlotId | undefined正規プロパティに対応するスロット id。なければ undefined
SHORTHAND_EXPANSIONSReadonly<Record<string, readonly string[]>>CSS ショートハンド → ロングハンドリーフへの展開(padding → その 4 辺)。1 階層のみ。
INHERITED_PROPERTIES{ tier1, tier2 }2 層の継承プロパティテーブル: Tier 1(閉包が必須: type-*/ink-* のみ)と Tier 2(アンビエント、境界あり)。
INHERITABLE_PROPERTIESreadonly string[]Tier 1 ∪ Tier 2 を安定した順序で並べたもの — base レベルのアンビエントベースラインが :root で一度だけ設定しなければならない厳密な集合。
AMBIENT_BASELINE_DEFAULTSReadonly<Record<string, string>>すべての Tier 2 プロパティに対する凍結されたリテラルの :root デフォルト値。
TYPE_COMPOSITE_FIELDS8 個の文字列からなるタプルtype コンポジットのフィールド名(fontFamilyfontSize など)。
TYPE_FIELD_TO_PROPERTYReadonly<Record<string, string>>type フィールドを、それが書き込む CSS プロパティにマッピングします。
inheritanceTier(property)(string) => 0 | 1 | 2プロパティの継承 tier。継承しない場合は 0
NAMESPACE_FAMILY_TABLEReadonly<Record<string, NamespaceEntry>>名前空間 → それが合成するユーティリティファミリー。名前空間(colorspacingsizeradius など)をキーとします。
ALL_FAMILIESreadonly FamilyDef[]すべての名前空間にまたがるすべてのファミリー。familyIndex 順。
NAMESPACESreadonly string[]合法な名前空間名の集合。
isKnownNamespace(ns)(string) => boolean名前空間名が合法かどうか。
familyInLevel(family, level) / familiesForLevel(entry, level)ファミリー/名前空間のエントリを profileLevel(basestrict)でフィルタリングします。
familyBreadth(family)(FamilyDef) => number非合成スロット数 + 書き込まれるカスタムプロパティ数 — rank() の主要キー。
STATIC_UTILITIESReadonly<Record<string, StaticUtility>>プロファイルが認める値を持たないユーティリティ(flexsr-onlycursor-pointer など)。クラス名をキーとします。
STATIC_UTILITY_NAMESreadonly string[]すべての静的ユーティリティのクラス名。
staticUtilityNamesForLevel(level)(ProfileLevel) => readonly string[]指定したプロファイルレベルの下で登録されている静的ユーティリティ名。
VARIANT_TABLEReadonly<Record<string, VariantDef>>すべての名前付きバリアント(hovermdgroup-hover/* など)と、そのセレクター/条件およびランク帯。
CONDITION_RANK_SCALEnumber(1_000_000)合計された条件ランクに適用される乗数。条件が外側の帯を形成するようにします。
BANLISTreadonly BanPattern[]レジストリに依存しない禁止フロア(space-*divide-**:in-*rtl:/ltr: など)。
matchBan(token)(string) => string | undefinedクラストークンを禁止フロアと照合します。該当する禁止 id を返します。
betterTailwindcssBanlist()() => { restrict: … }eslint-plugin-better-tailwindcssno-restricted-classes オプション向けに整形された禁止フロア。
QUARANTINE_ATTRIBUTEQUARANTINE_KINDQUARANTINE_FENCE_CLASSQUARANTINE_SAFE_FAMILIESQUARANTINE_SELECTORQUARANTINE_CSS文字列 / readonly string[]プローズ隔離境界のマーカー、フェンスクラス、安全なユーティリティファミリー、生成される除外 CSS — Concepts を参照してください。
isQuarantineSafe(className)(string) => boolean隔離境界要素上でそのクラスが合法かどうか。

純粋関数

ts
export function expandShorthand(property: string): readonly string[];
export function canonicalizeProperty(property: string): string;
export function isComposedValue(value: string): boolean;

export interface ClassMeta {
  readonly breadth: number;
  readonly familyIndex: number;
  readonly valueIndex: number;
}
export function rank(meta: ClassMeta): number; // throws RankError out of range
export class RankError extends Error {}
export const MAX_BREADTH: number; // 32
export const VALUE_SPAN: number; // 100_000
export const FAMILY_SPAN: number; // 10_000

export interface SlotBearing {
  readonly class: string;
  readonly slots: Iterable<number>;
  readonly atomic?: boolean;
}
export interface LaminarityViolation {
  readonly a: string;
  readonly b: string;
  readonly shared: readonly number[];
  readonly onlyA: readonly number[];
  readonly onlyB: readonly number[];
}
export function checkLaminarity(classes: readonly SlotBearing[]): LaminarityViolation[];

export type Specificity = readonly [number, number, number];
export function computeSpecificity(selector: string): Specificity;
export function compareSpecificity(a: Specificity, b: Specificity): number;
export function formatSpecificity(s: Specificity): string; // "(0,1,0)"
export function hasPseudoElement(selector: string): boolean;

rank() は、クラスの (breadth, familyIndex, valueIndex) の三つ組を、語彙を全順序付ける単一の整数に還元します(Draft A §5.2: lex(−breadth, familyIndex, valueIndex))— Concepts § the merge: a total order, not a cascade simulation を参照してください。いずれかの成分がサポートされる範囲を外れている場合は RankError を投げます。サイレントなオーバーフローは順序を破壊してしまうためです。

ts
import { rank } from '@tabula-css/core';

rank({ breadth: 4, familyIndex: 1, valueIndex: 0 }); // a p-* class: writes 4 slots

checkLaminarity() は不変条件 I2(Draft A §5.3)です: ある条件を共有するクラス同士は、そのスロット集合が入れ子になるか互いに素でなければならず、部分的に重なることは決して許されません。違反しているすべてのペアを返します(空であれば laminar です)。アトミックなリセットユーティリティ(sr-only)は例外として除外されます。

computeSpecificity() は、ランタイム依存なしに CSS Selectors Level 4 の詳細度を実装します。:where()(常に (0,0,0))、:is()/:not()/:has()(その中で最も詳細度の高い引数の詳細度)、擬似要素を理解します。これは不変条件 I4 を支えます — すべてのユーティリティルールは (0,1,0)(擬似要素の場合は (0,1,1))に正規化されなければなりません。

設定スキーマと型

tabula.config.json のスキーマと、それに対応する TypeScript 型です — Getting started § 3. Declare your axes を参照してください。

ts
export type ProfileLevel = 'base' | 'strict';
export const PROFILE_LEVELS: readonly ProfileLevel[];
export const DEFAULT_PROFILE_LEVEL: ProfileLevel; // 'base'

export interface AxisConfig {
  readonly values: readonly string[];
  readonly default: string;
  readonly attribute?: string;
  readonly media?: Readonly<Record<string, string>>;
}
export interface TabulaConfig {
  readonly profileId: string;
  readonly profileLevel?: ProfileLevel;
  readonly axes: Readonly<Record<string, AxisConfig>>;
  readonly baseline?: BaselineConfig;
  readonly groups?: readonly string[];
  readonly variantChainMaxLength?: number;
  readonly dynamicProperties?: Readonly<Record<string, DynamicPropertyConfig>>;
  readonly foreignClasses?: readonly string[];
  readonly textLeafComponents?: readonly string[];
  readonly gamut?: 'srgb' | 'p3' | 'rec2020';
  readonly budgets?: BudgetsConfig;
  readonly scan?: ScanConfig;
  readonly variants?: VariantsConfig; // declared variant products (contract J22)
}

export const configSchema: JsonSchemaObject; // JSON Schema (2020-12) for tabula.config.json

variants セクションは、どのバリアントチェーンが CSS を生成するかを宣言します — v0.2 で出荷された閉包の修正です:

ts
export type VariantPreset = 'interaction' | 'all-len1' | 'none';
export const VARIANT_PRESETS: readonly VariantPreset[];

export interface VariantsConfig {
  /** Seeds the product map before `products` are merged over it. Absent ⇒ `interaction`. */
  readonly preset?: VariantPreset;
  /** Canonical chain prefix → the families it may prefix (`"*"` = every non-atomic family). */
  readonly products?: Readonly<Record<string, '*' | readonly string[]>>;
  /** Hard cap on materialized chain candidates. Absent ⇒ DEFAULT_MAX_CHAIN_CANDIDATES. */
  readonly maxChainCandidates?: number;
}

宣言済みのバリアントプロダクトは、登録済みの集合(ベース語彙 ∪ プロダクト)を広げ、バリアントが前置されたクラスが CSS を生成できるようにする一方で、生成されるスタイルシートはプロファイルの純粋な関数のままです — Concepts § Variants を参照してください。構造的な形は configSchema によってチェックされます。値セマンティクスのゲート(チェーンの文法、ファミリー名、メディア→ブレークポイント要件の TAB-E170、不正なプロダクトのチェックである TAB-E171、そして maxChainCandidates の予算である TAB-E172)は @tabula-css/tokensvalidateConfig にあります。

DynamicPropertyConfig.syntax はリテラルの '*' であってはなりません — 汎用的な @property 構文を持つ --d-* 動的カスタムプロパティ(dyn() を通じて書き込まれます)は、システム内のどこにおいても何も検証しないことになるため、このスキーマと @tabula-css/tokensvalidateConfig の両方がこれを拒否します(TAB-E127)。

スキーマと並んでエクスポートされるその他のデフォルト値と上限: DEFAULT_VARIANT_CHAIN_MAX_LENGTH(2。emitter が実際に生成する長さに合わせて v0.2 で 3 から引き下げられました)、DEFAULT_VARIANT_PRESET('interaction')、DEFAULT_MAX_CHAIN_CANDIDATES(20,000 — variants.maxChainCandidates の予算)、DEFAULT_GAMUT('srgb')、DEFAULT_MAX_ESCAPES(25)、DEFAULT_MAX_SUPPRESSIONS(0)、DEFAULT_SCAN_SOURCES/DEFAULT_SCAN_IGNORE(tabula scan 用の glob デフォルト)、MAX_AXIS_CROSS_PRODUCT(16)。

トークン・レジストリ・マニフェストスキーマ

ts
export const TOKEN_TYPES: readonly string[]; // 'color' | 'dimension' | 'number' | … | 'type' | 'shadow'
export const tokensSchema: JsonSchemaObject; // JSON Schema for a flat-DTCG token file
export interface Token {
  readonly $type: string;
  readonly $value: TokenValue;
  readonly $description: string;
  readonly $deprecated?: Deprecation;
  readonly $extensions?: TokenExtensions;
}
export type TokensFile = Readonly<Record<string, TokenNamespace>>;
export function isLiteralEscape(meta: ExceptionMeta): boolean;

export const registrySchema: JsonSchemaObject; // JSON Schema for registry.json (schema version 3)
export interface RegistryFile { /* registrySchemaVersion (3), classes, variants, exceptions, variantProducts, chainCount, chainExceptions, … */ }
export interface RegistryClass { /* family, slots, rank, declarations, … */ }

export const manifestSchema: JsonSchemaObject; // JSON Schema for manifest.json
export const MANIFEST_FORMAT_VERSION: number; // 1
export interface ManifestFile { /* formatVersion, sourceHash, inputsHash, artifacts, … */ }

tokensSchema は、トークンファイル契約のうち構造的な部分(深さ 2 のネスト、閉じた $type 列挙、必須の $description、ケバブケースのトークン名)をカバーします。JSON スキーマでは表現できない値セマンティクス(軸の網羅性、コントラスト、寸法のドメイン)は、@tabula-css/tokens 内のカスタムパスです。registrySchemamanifestSchema は、@tabula-css/registry のリーダーが registry.jsonmanifest.json を、その内容を信頼する前に検証するために使用します。レジストリスキーマは(v0.2 において)バージョン 3 です:宣言済みバリアントプロダクトのフィールドである variantProducts(チェーンプレフィックス → ソート済みファミリーリスト)と chainCount、そしてオプションの chainExceptions(厳密な単一クラスのチェーン許可)を追加しています。それより古いスキーマバージョンで書かれたレジストリは、リーダーによって TAB-E302 で拒否されます。

すべての JSON スキーマは、core が併せてエクスポートする最小限の JsonSchema/JsonSchemaObject 形状(この 4 つのスキーマを表現するのに十分な JSON Schema draft 2020-12 のサブセットで、any ではなく unknown 型のインデックスシグネチャを持ちます)を通じて型付けされています。

関連パッケージ

  • @tabula-css/tokens — core のテーブルとスキーマを利用するバリデーターとリゾルバー。
  • @tabula-css/registry — core のスキーマに対して registry.json/manifest.json を検証するリーダー。
  • @tabula-css/merge — core の TAB-E3xx 診断を投げるランタイム。
  • Concepts — これらのテーブルが符号化する局所性、レジストリ、マージアルゴリズム、禁止メカニズムのカタログ。

Released under the MIT License.