@tabula-css/core
Tabula のコード契約レイヤー: 他のすべての Tabula パッケージが合意する、凍結されたテーブル・純粋関数・エラーコード・JSON スキーマです。ランタイム依存はゼロです。
インストール
ほとんどのプロジェクトは @tabula-css/core を直接インストールすることはありません — これは @tabula-css/tokens、@tabula-css/registry、@tabula-css/merge、@tabula-css/preset の推移的依存であり、これらすべてがその不変条件をここからインポートしています。診断カタログ、凍結テーブル、JSON スキーマだけを、パイプラインの他の部分を引き込まずに必要とするカスタムツールを書く場合にのみ、直接インストールしてください。
npm install @tabula-css/core概要
@tabula-css/core は、プロファイルの語彙とその診断が定義される唯一の場所であり、これにより CLI・レジストリジェネレーター・リンター・MCP サーバーが互いに乖離することを防ぎます。I/O を持たず、Tailwind への依存もありません。エクスポートされるものはすべて、凍結されたデータテーブル(正規の CSS スロット、名前空間 → ユーティリティファミリーのマップ、バリアントテーブル、禁止リスト)、純粋関数(rank()、checkLaminarity()、computeSpecificity())、JSON スキーマ(tabula.config.json、トークンファイル、registry.json、manifest.json 用)、または安定した TAB-Exxx/TAB-Wxxx エラーカタログのいずれかです。下流のすべて — @tabula-css/tokens のバリデーター、@tabula-css/registry のジェネレーター、@tabula-css/merge のランタイム — はこれらのテーブルを再導出するのではなく読み取ります。
エクスポート
診断
システム内のすべての TAB-Exxx/TAB-Wxxx コードの元となる、安定した診断カタログです — 文脈の中でのコードについては Concepts § the registry is ground truth と Getting started を参照してください。
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(実行可能な次の一手)を付加します。
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-E15x–E16x)、バリアント閉包(設定の TAB-E170–E172、スキャンの 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 つずつ凍結します。対象ごとにグループ化すると次のとおりです。
| Export | Type | Purpose |
|---|---|---|
CANONICAL_SLOT_PROPERTIES | readonly string[] | 正規のロングハンド CSS プロパティの順序付きリスト。スロットの id はそのインデックスです。 |
CANONICAL_SLOTS | Readonly<Record<string, string>> | slotId → property。registry.json の slots マップと一致します。 |
SLOT_ALIASES | Readonly<Record<string, string>> | ブロック論理 → 物理ブロックの正規化(padding-block-start → padding-top)。 |
PHYSICAL_INLINE_TWINS | Readonly<Record<string, string>> | 論理インラインプロパティ → その(未登録の)物理インラインの対。「両方は禁止」ユニットテスト用。 |
slotIdOf(property) | (string) => SlotId | undefined | 正規プロパティに対応するスロット id。なければ undefined。 |
SHORTHAND_EXPANSIONS | Readonly<Record<string, readonly string[]>> | CSS ショートハンド → ロングハンドリーフへの展開(padding → その 4 辺)。1 階層のみ。 |
INHERITED_PROPERTIES | { tier1, tier2 } | 2 層の継承プロパティテーブル: Tier 1(閉包が必須: type-*/ink-* のみ)と Tier 2(アンビエント、境界あり)。 |
INHERITABLE_PROPERTIES | readonly string[] | Tier 1 ∪ Tier 2 を安定した順序で並べたもの — base レベルのアンビエントベースラインが :root で一度だけ設定しなければならない厳密な集合。 |
AMBIENT_BASELINE_DEFAULTS | Readonly<Record<string, string>> | すべての Tier 2 プロパティに対する凍結されたリテラルの :root デフォルト値。 |
TYPE_COMPOSITE_FIELDS | 8 個の文字列からなるタプル | type コンポジットのフィールド名(fontFamily、fontSize など)。 |
TYPE_FIELD_TO_PROPERTY | Readonly<Record<string, string>> | 各 type フィールドを、それが書き込む CSS プロパティにマッピングします。 |
inheritanceTier(property) | (string) => 0 | 1 | 2 | プロパティの継承 tier。継承しない場合は 0。 |
NAMESPACE_FAMILY_TABLE | Readonly<Record<string, NamespaceEntry>> | 名前空間 → それが合成するユーティリティファミリー。名前空間(color、spacing、size、radius など)をキーとします。 |
ALL_FAMILIES | readonly FamilyDef[] | すべての名前空間にまたがるすべてのファミリー。familyIndex 順。 |
NAMESPACES | readonly string[] | 合法な名前空間名の集合。 |
isKnownNamespace(ns) | (string) => boolean | 名前空間名が合法かどうか。 |
familyInLevel(family, level) / familiesForLevel(entry, level) | — | ファミリー/名前空間のエントリを profileLevel(base 対 strict)でフィルタリングします。 |
familyBreadth(family) | (FamilyDef) => number | 非合成スロット数 + 書き込まれるカスタムプロパティ数 — rank() の主要キー。 |
STATIC_UTILITIES | Readonly<Record<string, StaticUtility>> | プロファイルが認める値を持たないユーティリティ(flex、sr-only、cursor-pointer など)。クラス名をキーとします。 |
STATIC_UTILITY_NAMES | readonly string[] | すべての静的ユーティリティのクラス名。 |
staticUtilityNamesForLevel(level) | (ProfileLevel) => readonly string[] | 指定したプロファイルレベルの下で登録されている静的ユーティリティ名。 |
VARIANT_TABLE | Readonly<Record<string, VariantDef>> | すべての名前付きバリアント(hover、md、group-hover/* など)と、そのセレクター/条件およびランク帯。 |
CONDITION_RANK_SCALE | number(1_000_000) | 合計された条件ランクに適用される乗数。条件が外側の帯を形成するようにします。 |
BANLIST | readonly BanPattern[] | レジストリに依存しない禁止フロア(space-*、divide-*、*:、in-*、rtl:/ltr: など)。 |
matchBan(token) | (string) => string | undefined | クラストークンを禁止フロアと照合します。該当する禁止 id を返します。 |
betterTailwindcssBanlist() | () => { restrict: … } | eslint-plugin-better-tailwindcss の no-restricted-classes オプション向けに整形された禁止フロア。 |
QUARANTINE_ATTRIBUTE、QUARANTINE_KIND、QUARANTINE_FENCE_CLASS、QUARANTINE_SAFE_FAMILIES、QUARANTINE_SELECTOR、QUARANTINE_CSS | 文字列 / readonly string[] | プローズ隔離境界のマーカー、フェンスクラス、安全なユーティリティファミリー、生成される除外 CSS — Concepts を参照してください。 |
isQuarantineSafe(className) | (string) => boolean | 隔離境界要素上でそのクラスが合法かどうか。 |
純粋関数
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 を投げます。サイレントなオーバーフローは順序を破壊してしまうためです。
import { rank } from '@tabula-css/core';
rank({ breadth: 4, familyIndex: 1, valueIndex: 0 }); // a p-* class: writes 4 slotscheckLaminarity() は不変条件 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 を参照してください。
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.jsonvariants セクションは、どのバリアントチェーンが CSS を生成するかを宣言します — v0.2 で出荷された閉包の修正です:
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/tokens の validateConfig にあります。
DynamicPropertyConfig.syntax はリテラルの '*' であってはなりません — 汎用的な @property 構文を持つ --d-* 動的カスタムプロパティ(dyn() を通じて書き込まれます)は、システム内のどこにおいても何も検証しないことになるため、このスキーマと @tabula-css/tokens の validateConfig の両方がこれを拒否します(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)。
トークン・レジストリ・マニフェストスキーマ
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 内のカスタムパスです。registrySchema と manifestSchema は、@tabula-css/registry のリーダーが registry.json と manifest.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 — これらのテーブルが符号化する局所性、レジストリ、マージアルゴリズム、禁止メカニズムのカタログ。