@teacss/core 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ # MIT License
2
+
3
+ Copyright (c) 2021-PRESENT Anthony Fu <https://github.com/antfu>
4
+ Copyright (c) 2026-PRESENT Billgo <hi@billgo.me>
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,124 @@
1
+ # @teacss/core
2
+
3
+ **The framework-neutral TeaCSS engine.**
4
+
5
+ ## Purpose
6
+
7
+ `@teacss/core` parses colon-syntax tokens, resolves the shared `@` condition
8
+ axis, matches rules, and emits layered CSS. It owns mechanism only; presets own
9
+ the vocabulary.
10
+
11
+ Preset, integration, and tooling authors use this package directly. It does
12
+ not discover filesystem configuration, manage build-tool module lifecycles, or
13
+ provide runtime class composition; higher-level packages own those boundaries.
14
+ A negated condition stays unmatched when its owning resolver cannot express a
15
+ negative form; it is never silently emitted as the positive condition.
16
+
17
+ ## Usage
18
+
19
+ ```sh
20
+ bun add @teacss/core @teacss/preset-standard
21
+ ```
22
+
23
+ ```ts
24
+ import { createGenerator } from "@teacss/core";
25
+ import { presetStandard } from "@teacss/preset-standard";
26
+
27
+ const generator = await createGenerator({
28
+ presets: [presetStandard()],
29
+ });
30
+
31
+ const { css } = await generator.generate("p:4 bg-color:red-500@hover");
32
+ ```
33
+
34
+ Large direct-input builds can cap concurrent token parsing to reduce peak memory:
35
+
36
+ ```ts
37
+ const { css } = await generator.generate(tokens, {
38
+ tokenConcurrency: 256,
39
+ });
40
+ ```
41
+
42
+ The limit must be a positive integer. It is opt-in because custom asynchronous
43
+ rules may intentionally coordinate work across tokens; omitting it preserves the
44
+ existing unbounded scheduling behavior. Matched tokens and emitted CSS remain in
45
+ the same deterministic order as default scheduling; matched-token iteration
46
+ continues to follow input order. CSS string tie-breakers use
47
+ locale-independent UTF-16 code-unit order.
48
+
49
+ Most apps should install `teacss`. Use `@teacss/core` directly when building
50
+ presets, generators, or tooling.
51
+
52
+ Class-list integrations can use `splitClassTokens()` to split whitespace while
53
+ preserving spaces inside attached `[]` literal regions. It intentionally keeps
54
+ quotes, semicolons, and group syntax as ordinary token content; source
55
+ extraction remains a separate, broader boundary. The default source extractor
56
+ also recognizes valid unquoted HTML class values such as `class=p:4` and
57
+ distributes grouped conditions in HTML values such as
58
+ `class={p:4;m:2}@hover`. Braced attributes in JSX/TSX remain host expression
59
+ containers rather than HTML class groups. Known JavaScript, TypeScript, JSX,
60
+ TSX, and MDX file IDs stay on that host-source path, so invalid unquoted JSX
61
+ attributes are not reinterpreted as HTML. File-aware grouping treats
62
+ `.ts`/`.mts`/`.cts` as non-JSX host source and `.jsx`/`.tsx`/`.mdx` with JSX
63
+ raw-text semantics, avoiding ambiguous angle assertions and text delimiters.
64
+ Only `.tsx` applies TSX generic-arrow disambiguation; JSX, MDX, and mixed
65
+ documents retain their own or conservative auto-detection semantics.
66
+
67
+ Use `expandGroups()` when scanning host source, where valid TeaCSS groups may
68
+ sit inside JavaScript strings or arrays. Use `expandClassGroups()` only after a
69
+ class list has been isolated; it expands top-level groups while preserving
70
+ group-like braces inside attached `[]` values and `()` CSS functions.
71
+
72
+ Generic runtime class merging is intentionally separate from the generator:
73
+
74
+ ```sh
75
+ bun add @teacss/classes
76
+ ```
77
+
78
+ ```ts
79
+ import { createMerger } from "@teacss/classes";
80
+ ```
81
+
82
+ ## Theme merging
83
+
84
+ Plain theme objects from presets and user configuration are deep-merged. A
85
+ non-plain theme, such as a class instance, is treated as one atomic value so its
86
+ prototype and private state remain valid: a later non-plain theme replaces an
87
+ earlier one, and an empty plain overlay leaves it unchanged. To replace it with
88
+ a plain theme, use a top-level `{ $reset: true, ... }` value. To combine
89
+ class-backed state with another theme, use `extendTheme` and perform the
90
+ class-aware merge there. A non-empty plain overlay on a non-plain theme is
91
+ rejected instead of manufacturing an invalid class instance.
92
+
93
+ ## Transactional configuration
94
+
95
+ Runtime integrations that reload configuration can stage work without mutating
96
+ the live generator:
97
+
98
+ ```ts
99
+ const prepared = await generator.prepareConfig(nextConfig);
100
+ const candidates = await prepared.generator.applyExtractors(source, id);
101
+
102
+ if (validationPassed) generator.commitConfig(prepared);
103
+ ```
104
+
105
+ `prepared.generator` is isolated but shares the candidate resolved config that
106
+ will be committed. `commitConfig()` returns `false` when a newer preparation has
107
+ superseded the candidate or the candidate generator was reconfigured. The
108
+ prepared snapshot is frozen, while its resolved config remains mutable for
109
+ staged transformer work. A successful commit keeps the live generator identity
110
+ and notifies every `config` observer; preparation and failed validation emit
111
+ nothing. Observer failures are reported as diagnostics after the commit and do
112
+ not roll the active configuration back.
113
+
114
+ ## Preflight context
115
+
116
+ Preset preflights receive the generator and theme through their `getCSS(context)`
117
+ callback. `context.generated` additionally exposes the utilities produced by the
118
+ current `generate()` call after postprocessing, including cache hits and excluding
119
+ preflights. Demand-driven preflights can inspect this read-only list without
120
+ sharing mutable state across generation calls.
121
+
122
+ ## Status
123
+
124
+ Pre-1.0. Public engine APIs may change before the stable release.