diff --git a/.changeset/type-alias-declarations.md b/.changeset/type-alias-declarations.md new file mode 100644 index 0000000..7e1c717 --- /dev/null +++ b/.changeset/type-alias-declarations.md @@ -0,0 +1,6 @@ +--- +'@vortexlabs/kirari': patch +'@vortexlabs/kirari-react': patch +--- + +Public object types such as `Token`, `Rule`, `Language`, `RenderOptions`, `Decoration`, `TokenPatch`, `TokenStream`, and `StreamedTokens` are now type aliases instead of interfaces. Their members are unchanged, but they can no longer be extended through declaration merging (module augmentation). Types that extend another type, such as `HighlightOptions` and `CodeProps`, remain interfaces. diff --git a/docs/decorations.md b/docs/decorations.md index 35c7193..d96a46e 100644 --- a/docs/decorations.md +++ b/docs/decorations.md @@ -19,7 +19,7 @@ The range decorates `answer`. Supply your own CSS for `search-match`, `active-li ## API ```ts -interface Decoration { +type Decoration = { readonly start: number readonly end: number readonly className: string diff --git a/packages/benchmarks/benchmark.ts b/packages/benchmarks/benchmark.ts index 7fec9d4..8f7b5f2 100644 --- a/packages/benchmarks/benchmark.ts +++ b/packages/benchmarks/benchmark.ts @@ -9,7 +9,7 @@ import { corpus } from '../kirari/test/corpus/fixtures.js' import { bundleEntry, highlight, languageNames } from './adapters.js' import type { LanguageName } from './adapters.js' -export interface Input { +export type Input = { id: string language: LanguageName source: string diff --git a/packages/kirari/scripts/themes.ts b/packages/kirari/scripts/themes.ts index 7f4870a..76d5f5f 100644 --- a/packages/kirari/scripts/themes.ts +++ b/packages/kirari/scripts/themes.ts @@ -4,7 +4,7 @@ import { tokenTypes, type TokenType } from '../src/types.js' type Colors = Partial> & { background: string; text: string; keyword: string; function: string; string: string; number: string; comment: string } -interface Theme { +type Theme = { id: string label: string appearance: 'light' | 'dark' diff --git a/packages/kirari/src/decorations.ts b/packages/kirari/src/decorations.ts index 8369282..4fe998c 100644 --- a/packages/kirari/src/decorations.ts +++ b/packages/kirari/src/decorations.ts @@ -1,7 +1,7 @@ import { escape, render, tokenClasses } from './render.js' import type { RenderOptions, Token } from './types.js' -export interface Decoration { +export type Decoration = { readonly start: number readonly end: number readonly className: string diff --git a/packages/kirari/src/grammars/definitions/state.ts b/packages/kirari/src/grammars/definitions/state.ts index 5ef23b0..75546f8 100644 --- a/packages/kirari/src/grammars/definitions/state.ts +++ b/packages/kirari/src/grammars/definitions/state.ts @@ -9,7 +9,7 @@ const backReference = /^(def|\*|&|\.|:|\?\.|->|\?->|::|>+)$/ * Significant-token state before a point in Python source, tracked so a stream can tell when * `classifyDefinitions` results before that point no longer depend on later tokens. */ -export interface DefinitionState { +export type DefinitionState = { /** Open brackets, as in `matchBrackets`, with the value before each opening. */ brackets: { close: string; before: string }[] /** Bracket depths of `name:` annotation scans that have not reached `=` or a stop token. */ diff --git a/packages/kirari/src/grammars/functions.ts b/packages/kirari/src/grammars/functions.ts index d2feae4..892320e 100644 --- a/packages/kirari/src/grammars/functions.ts +++ b/packages/kirari/src/grammars/functions.ts @@ -5,10 +5,10 @@ import { lastLineBreak } from '../scanner/lexical.js' type Result = { function: boolean; pending: boolean } type Group = { end: number; complete: boolean } /** Source-wide lookahead data; share only between scanners of the same immutable source. */ -export interface FunctionLookupCache { +export type FunctionLookupCache = { lastLine?: number } -export interface LookupOptions { +export type LookupOptions = { /** A colon after the name may introduce a property value or a typed binding. */ readonly colon: boolean /** The name may take type parameters, as after `function` or in a method position. */ diff --git a/packages/kirari/src/grammars/markup/types.ts b/packages/kirari/src/grammars/markup/types.ts index 5b4a484..816b861 100644 --- a/packages/kirari/src/grammars/markup/types.ts +++ b/packages/kirari/src/grammars/markup/types.ts @@ -49,7 +49,7 @@ export type MarkupState = { } /** Where a JSX scan starts, and where to report root-level newlines it can resume from. */ -export interface MarkupResume { +export type MarkupResume = { /** Restart point in the full source; omission starts scanning at offset zero. */ readonly from?: ResumePoint | undefined /** Reports safe restart points with indexes in this scan's returned token array. */ diff --git a/packages/kirari/src/registry.ts b/packages/kirari/src/registry.ts index 82a575c..74eb47f 100644 --- a/packages/kirari/src/registry.ts +++ b/packages/kirari/src/registry.ts @@ -36,7 +36,7 @@ const aliases: Readonly> = { yaml: ['yml'], } -export interface LanguageRegistry { +export type LanguageRegistry = { resolve(input: string): Language | undefined } diff --git a/packages/kirari/src/resumable.ts b/packages/kirari/src/resumable.ts index 9699e2e..10869e3 100644 --- a/packages/kirari/src/resumable.ts +++ b/packages/kirari/src/resumable.ts @@ -2,7 +2,7 @@ import type { ScanContext } from './tokenize.js' import type { Language, Token } from './types.js' /** A root-level point where scanning can restart with the same results as a full scan. */ -export interface ResumePoint { +export type ResumePoint = { readonly offset: number readonly previous: Token | undefined /** Script scan state at the point, for grammars that embed JavaScript. */ diff --git a/packages/kirari/src/stream.ts b/packages/kirari/src/stream.ts index d033107..fecc9ce 100644 --- a/packages/kirari/src/stream.ts +++ b/packages/kirari/src/stream.ts @@ -9,14 +9,14 @@ import { createResumableStream } from './stream/resumable.js' import { isSignificant } from './types.js' import type { Language, Token } from './types.js' -export interface TokenPatch { +export type TokenPatch = { /** Replace previous tokens from this UTF-16 source offset onward. */ readonly from: number readonly tokens: readonly Token[] readonly length: number } -export interface TokenStream { +export type TokenStream = { readonly mode: 'checkpoint' | 'full' write(chunk: string): TokenPatch end(chunk?: string): TokenPatch diff --git a/packages/kirari/src/tokenize.ts b/packages/kirari/src/tokenize.ts index 7d30dbe..f56dbc5 100644 --- a/packages/kirari/src/tokenize.ts +++ b/packages/kirari/src/tokenize.ts @@ -22,7 +22,7 @@ import { canStartRegex, escapedIdentifierEnd, nextVisibleChar, regexEnd, templat export type Frame = { kind: 'template'; opening: boolean } | { kind: 'expression'; depth: number } /** Lexical state for JavaScript-like languages, carried between scanner steps. */ -export interface ScanContext { +export type ScanContext = { parentheses: { control: boolean; braces: number }[] braces?: number afterControl?: boolean diff --git a/packages/kirari/src/types.ts b/packages/kirari/src/types.ts index 7a466d9..5ef08b4 100644 --- a/packages/kirari/src/types.ts +++ b/packages/kirari/src/types.ts @@ -12,7 +12,7 @@ export type TokenType = (typeof tokenTypes)[number] export const isSignificant = (type: string): boolean => type !== 'text' && type !== 'comment' /** An unchanged source slice with UTF-16 offsets into the original source. */ -export interface Token { +export type Token = { /** Category used for the `kirari-${type}` CSS class; custom names are supported. */ readonly type: string /** Exact source text between `start` and `end`. */ @@ -24,7 +24,7 @@ export interface Token { } /** A lexical rule tried at the current source offset; the first matching rule wins. */ -export interface Rule { +export type Rule = { /** Category assigned to the matched source text. */ readonly type: string /** Cloned with `g`/`y` replaced by sticky `y`; supplied `lastIndex` is untouched. Empty matches throw. */ @@ -32,7 +32,7 @@ export interface Rule { } /** Scanner rules and optional structural processing for a language. */ -export interface Language { +export type Language = { /** Language identifier used by diagnostics and grammar-specific scanning. */ readonly name: string /** Ordered lexical rules used by the default scanner. */ @@ -58,7 +58,7 @@ export interface Language { } /** Extra CSS classes added alongside the renderer's standard token classes. */ -export interface RenderOptions { +export type RenderOptions = { /** Additional classes by token category, including custom categories. */ readonly classes?: Readonly> /** Additional classes per token, combined with `classes`; `undefined` adds nothing. */ diff --git a/packages/kirari/test/corpus/fixtures.ts b/packages/kirari/test/corpus/fixtures.ts index fab8d91..f618999 100644 --- a/packages/kirari/test/corpus/fixtures.ts +++ b/packages/kirari/test/corpus/fixtures.ts @@ -1,6 +1,6 @@ export type CorpusLanguage = 'javascript' | 'typescript' | 'tsx' | 'python' | 'json' | 'shell' -export interface CorpusAssertion { +export type CorpusAssertion = { text: string type: string occurrence?: number @@ -10,7 +10,7 @@ export interface CorpusGap extends CorpusAssertion { reason: string } -export interface CorpusFixture { +export type CorpusFixture = { id: string language: CorpusLanguage source: string diff --git a/packages/react/src/stream.ts b/packages/react/src/stream.ts index 2c59f19..d27be1b 100644 --- a/packages/react/src/stream.ts +++ b/packages/react/src/stream.ts @@ -5,7 +5,7 @@ import type { Language, Token } from '@vortexlabs/kirari/core' import { createTokenStream } from '@vortexlabs/kirari/stream' import type { TokenPatch, TokenStream } from '@vortexlabs/kirari/stream' -export interface StreamedTokens { +export type StreamedTokens = { readonly tokens: readonly Token[] write(chunk: string): void end(chunk?: string): void diff --git a/packages/react/src/types.ts b/packages/react/src/types.ts index 093e797..9133756 100644 --- a/packages/react/src/types.ts +++ b/packages/react/src/types.ts @@ -6,7 +6,7 @@ import type { Decoration } from '@vortexlabs/kirari/decorations' export type LineRange = number | readonly [first: number, last: number] /** A rendered source line; CRLF, CR, and LF separators sit outside its wrapper. */ -export interface Line { +export type Line = { /** One-based line number. */ readonly number: number /** Inclusive UTF-16 offset into the complete source. */