@teacss/directives 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 +22 -0
- package/README.md +63 -0
- package/dist/core.d.ts +38 -0
- package/dist/core.js +1 -0
- package/dist/index.d.ts +98 -0
- package/dist/index.js +2 -0
- package/dist/screen-core-DIkTMaQQ.js +1 -0
- package/package.json +44 -0
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,63 @@
|
|
|
1
|
+
# @teacss/directives
|
|
2
|
+
|
|
3
|
+
**CSS directive transforms for TeaCSS.**
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
This package expands authoring helpers such as `@apply`, `@screen`,
|
|
8
|
+
`theme(...)`, and `icon(...)` before CSS is emitted by integrations.
|
|
9
|
+
|
|
10
|
+
It is a shared implementation for TeaCSS build-integration authors. The main
|
|
11
|
+
entry provides the source-transformer and CSS-entry helpers used by official
|
|
12
|
+
pipelines, while `@teacss/directives/core` exposes adapter-neutral primitives
|
|
13
|
+
for other CSS ASTs. It does not own source scanning, watching, or bundler
|
|
14
|
+
lifecycle; applications should normally select a build integration instead.
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```css
|
|
19
|
+
.button {
|
|
20
|
+
@apply p-x:4 p-y:2 radius:2 content:["hello world"];
|
|
21
|
+
color: theme("colors.red.500");
|
|
22
|
+
background-image: icon("carbon-sun");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@screen md {
|
|
26
|
+
.button {
|
|
27
|
+
@apply p-x:6;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`icon()` receives `<collection>-<icon-name>` without the class utility's
|
|
33
|
+
`icon:` property prefix.
|
|
34
|
+
|
|
35
|
+
`@apply` splits only whitespace outside attached `[]` literal regions, so
|
|
36
|
+
spaces in arbitrary values remain part of one TeaCSS utility.
|
|
37
|
+
|
|
38
|
+
Used automatically by the Vite, PostCSS, Rsbuild, Bun, and CLI pipelines.
|
|
39
|
+
When an integration splices a CSS entry, a BOM and native `@charset` remain
|
|
40
|
+
before hoisted `@import` rules.
|
|
41
|
+
|
|
42
|
+
## Integration-author API
|
|
43
|
+
|
|
44
|
+
CSS adapters can reuse the same directive semantics through the public core
|
|
45
|
+
subpath:
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
import {
|
|
49
|
+
prepareApplyUtilities,
|
|
50
|
+
resolveApplyTokens,
|
|
51
|
+
resolveCssFunction,
|
|
52
|
+
resolveScreenQuery,
|
|
53
|
+
} from "@teacss/directives/core";
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The subpath also exports the apply rendering helpers and their public types.
|
|
57
|
+
It does not parse or mutate an adapter's stylesheet; callers provide the host
|
|
58
|
+
AST and source-range operations needed by their CSS implementation.
|
|
59
|
+
|
|
60
|
+
## Status
|
|
61
|
+
|
|
62
|
+
Pre-1.0 public API for integration authors. Most applications should use a
|
|
63
|
+
TeaCSS build integration instead.
|
package/dist/core.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { TeacssGenerator } from "@teacss/core";
|
|
2
|
+
import { FunctionNode, SelectorList } from "css-tree";
|
|
3
|
+
//#region src/apply-core.d.ts
|
|
4
|
+
type ResolvedApplyToken = readonly [name: string, utilities: Awaited<ReturnType<TeacssGenerator["parseToken"]>>];
|
|
5
|
+
type PreparedApplyUtility = {
|
|
6
|
+
readonly kind: "inline";
|
|
7
|
+
readonly body: string;
|
|
8
|
+
} | {
|
|
9
|
+
readonly kind: "standalone";
|
|
10
|
+
readonly selector: string | undefined;
|
|
11
|
+
readonly body: string;
|
|
12
|
+
readonly parent: string | undefined;
|
|
13
|
+
readonly noMerge: boolean;
|
|
14
|
+
};
|
|
15
|
+
type StandaloneApplyUtility = Extract<PreparedApplyUtility, {
|
|
16
|
+
kind: "standalone";
|
|
17
|
+
}>;
|
|
18
|
+
interface ApplyHost {
|
|
19
|
+
readonly prelude: SelectorList;
|
|
20
|
+
readonly selector: string;
|
|
21
|
+
readonly replacementSelector: string;
|
|
22
|
+
}
|
|
23
|
+
declare function resolveApplyTokens(classNames: readonly string[], generator: TeacssGenerator): Promise<ResolvedApplyToken[]>;
|
|
24
|
+
declare function missingApplyTokens(tokens: readonly ResolvedApplyToken[]): string[];
|
|
25
|
+
declare function formatMissingApplyTokens(missing: readonly string[]): string;
|
|
26
|
+
declare function prepareApplyUtilities(tokens: readonly ResolvedApplyToken[], parentOrders: ReadonlyMap<string, number>): PreparedApplyUtility[];
|
|
27
|
+
declare function renderStandaloneApplyUtility(host: ApplyHost, utility: StandaloneApplyUtility): string;
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region src/function-core.d.ts
|
|
30
|
+
type ReadSourceRange = (start: number, end: number) => string;
|
|
31
|
+
/** Resolve a TeaCSS declaration-value function without mutating an adapter's source. */
|
|
32
|
+
declare function resolveCssFunction(generator: TeacssGenerator, node: FunctionNode, readSourceRange: ReadSourceRange, throwOnMissing?: boolean): Promise<string | undefined>;
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region src/screen-core.d.ts
|
|
35
|
+
/** Resolve an `@screen` value to the media-query condition shared by CSS adapters. */
|
|
36
|
+
declare function resolveScreenQuery(rawBreakpoint: string, theme: object): string | undefined;
|
|
37
|
+
//#endregion
|
|
38
|
+
export { type ApplyHost, type PreparedApplyUtility, type ResolvedApplyToken, type StandaloneApplyUtility, formatMissingApplyTokens, missingApplyTokens, prepareApplyUtilities, renderStandaloneApplyUtility, resolveApplyTokens, resolveCssFunction, resolveScreenQuery };
|
package/dist/core.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as e,i as t,n,o as r,r as i,s as a,t as o}from"./screen-core-DIkTMaQQ.js";export{i as formatMissingApplyTokens,t as missingApplyTokens,e as prepareApplyUtilities,r as renderStandaloneApplyUtility,a as resolveApplyTokens,n as resolveCssFunction,o as resolveScreenQuery};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { MagicStringLike, SourceCodeTransformer, TeacssGenerator } from "@teacss/core";
|
|
2
|
+
import { customToTheme, diagnoseCustom, parseEntry, resolvePresets } from "@teacss/config";
|
|
3
|
+
//#region src/types.d.ts
|
|
4
|
+
interface TransformerDirectivesOptions {
|
|
5
|
+
enforce?: SourceCodeTransformer["enforce"];
|
|
6
|
+
/**
|
|
7
|
+
* Throw an error if utils or themes are not found.
|
|
8
|
+
*
|
|
9
|
+
* @default true
|
|
10
|
+
*/
|
|
11
|
+
throwOnMissing?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Treat CSS custom properties as @apply directives for CSS syntax compatibility.
|
|
14
|
+
*
|
|
15
|
+
* Pass `false` to disable.
|
|
16
|
+
*
|
|
17
|
+
* @default ['--at-apply']
|
|
18
|
+
*/
|
|
19
|
+
applyVariable?: false | string | string[];
|
|
20
|
+
/**
|
|
21
|
+
* Treat CSS custom properties as directives for CSS syntax compatibility.
|
|
22
|
+
*
|
|
23
|
+
* Pass `false` to disable, or a string to use as a prefix.
|
|
24
|
+
*
|
|
25
|
+
* @deprecated use `applyVariable` to specify the full var name instead.
|
|
26
|
+
* @default '--at-'
|
|
27
|
+
*/
|
|
28
|
+
varStyle?: false | string;
|
|
29
|
+
}
|
|
30
|
+
interface TransformerDirectivesContext {
|
|
31
|
+
code: MagicStringLike;
|
|
32
|
+
generator: TeacssGenerator;
|
|
33
|
+
options: TransformerDirectivesOptions;
|
|
34
|
+
applyVariable: string[];
|
|
35
|
+
offset?: number;
|
|
36
|
+
filename?: string;
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/generateEntry.d.ts
|
|
40
|
+
interface GenerateEntryOptions {
|
|
41
|
+
/** Entry file directory — base for `@preset` relative specifiers and `@source` globs. */
|
|
42
|
+
base: string;
|
|
43
|
+
/** Read scanned content for the given include/exclude globs. Omit when `contents` is given. */
|
|
44
|
+
readSources?: (includes: string[], excludes: string[]) => Promise<{
|
|
45
|
+
files: string[];
|
|
46
|
+
sources: string[];
|
|
47
|
+
}>;
|
|
48
|
+
/** Inline content to extract utilities from — skips `readSources` (tests / programmatic use). */
|
|
49
|
+
contents?: string[];
|
|
50
|
+
}
|
|
51
|
+
interface GenerateEntryResult {
|
|
52
|
+
/** Generated stylesheet (preflight `:root`/mode theme vars + utilities) to splice at `@teacss`. */
|
|
53
|
+
layers: string;
|
|
54
|
+
/** Absolute paths scanned (for watch registration). */
|
|
55
|
+
files: string[];
|
|
56
|
+
/** `@custom` var names that matched no namespace / illegal step (decision 11 — for LSP diagnostics). */
|
|
57
|
+
unknown: string[];
|
|
58
|
+
/** Number of utilities matched. */
|
|
59
|
+
matched: number;
|
|
60
|
+
/** Whether the entry has a `@teacss;` placeholder. */
|
|
61
|
+
hasTeacss: boolean;
|
|
62
|
+
/** Whether the entry declared at least one `@preset` (false → nothing to generate; caller warns). */
|
|
63
|
+
hasPreset: boolean;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Drive generation from a CSS entry: parse its directives, resolve `@preset`,
|
|
67
|
+
* register `@custom` into the theme, scan `@source` content, and generate.
|
|
68
|
+
* There's no implicit default preset — an entry with no `@preset` yields no
|
|
69
|
+
* utilities and reports `hasPreset: false` for the caller to warn. Returns the
|
|
70
|
+
* generated layers (the theme preflight emits `:root`/mode vars from the
|
|
71
|
+
* registered `@custom`) plus the scanned files and `@custom` diagnostics.
|
|
72
|
+
* Splicing the layers into the entry file (replacing `@teacss`, stripping the
|
|
73
|
+
* consumed directives) is the caller's job. The core engine is untouched — this
|
|
74
|
+
* is integration-layer orchestration.
|
|
75
|
+
*/
|
|
76
|
+
declare function generateEntry(entryCss: string, options: GenerateEntryOptions): Promise<GenerateEntryResult>;
|
|
77
|
+
//#endregion
|
|
78
|
+
//#region src/spliceEntry.d.ts
|
|
79
|
+
/**
|
|
80
|
+
* Produce the final stylesheet from an entry CSS file and the generated layers:
|
|
81
|
+
*
|
|
82
|
+
* - `@teacss;` → replaced by `layers`
|
|
83
|
+
* - `@preset` / `@source` / `@custom {}` → stripped (consumed)
|
|
84
|
+
* - native `@charset` / `@import` → hoisted in CSS-required order
|
|
85
|
+
* - everything else (plain rules, comments, `@media`, …) → kept in place
|
|
86
|
+
*
|
|
87
|
+
* Pure, css-tree-free: exact top-level at-rule ranges are scanned structurally
|
|
88
|
+
* and spliced out of the original.
|
|
89
|
+
*/
|
|
90
|
+
declare function spliceEntry(entryCss: string, layers: string): string;
|
|
91
|
+
//#endregion
|
|
92
|
+
//#region src/transform.d.ts
|
|
93
|
+
declare function transformDirectives(code: MagicStringLike, generator: TeacssGenerator, options: TransformerDirectivesOptions, filename?: string, originalCode?: string, offset?: number): Promise<void>;
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region src/index.d.ts
|
|
96
|
+
declare function transformerDirectives(options?: TransformerDirectivesOptions): SourceCodeTransformer;
|
|
97
|
+
//#endregion
|
|
98
|
+
export { GenerateEntryOptions, GenerateEntryResult, TransformerDirectivesContext, TransformerDirectivesOptions, customToTheme, transformerDirectives as default, diagnoseCustom, generateEntry, parseEntry, resolvePresets, spliceEntry, transformDirectives };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a as e,i as t,n,o as r,r as i,s as a,t as o}from"./screen-core-DIkTMaQQ.js";import{createGenerator as s,expandVariantGroup as c,isCssId as l,splitClassTokens as u,toArray as d}from"@teacss/core";import{generate as f,parse as p,walk as m}from"css-tree";import{hasIconFn as h,hasThemeFn as g}from"@teacss/rule-helpers";import{customToTheme as _,diagnoseCustom as v,parseEntry as y,resolveEntryConfig as b,resolvePresets as x,scanTopLevelAtRules as S}from"@teacss/config";import{generateSources as C}from"@teacss/runtime/source-generation";async function w(e,t,n){let r=[],i=[],a=!1;for(let o of t.block.children)if(o.type===`Raw`)await n(o.value,o.loc.start.offset);else{let n=await T(e,t,o);if(!n)continue;r.push(n.consumedRange),i.push(...n.standaloneCss),a||=n.hasInlineUtility}let o=e.code.original,s=t.block.loc.start.offset+1,c=!1;for(let[e,t]of r){if(o.slice(s,e).trim()){c=!0;break}s=t}c||=!!o.slice(s,t.block.loc.end.offset-1).trim(),!a&&!c&&r.length>0&&e.code.remove(t.loc.start.offset,t.loc.end.offset);for(let n of i)e.code.appendLeft(t.loc.end.offset,n)}async function T({code:n,generator:o,applyVariable:s,options:l,filename:d},p,m){let h=n.original,g;if(m.type===`Atrule`&&m.name===`apply`&&m.prelude&&m.prelude.type===`Raw`)g=E(m.prelude.value.trim());else if(m.type===`Declaration`&&s.includes(m.property)&&(m.value.type===`Value`||m.value.type===`Raw`)){let e=h.slice(m.value.loc.start.offset,m.value.loc.end.offset).trim();e=E(e),g=u(e).map(e=>E(e)).join(` `)}if(!g)return;g=D(g);let _=await a(u(c(g)),o),v=t(_);if(v.length&&(l.throwOnMissing??!0))throw Error(`${i(v)}${d?` in ${d}`:``}`);let y=e(_,o.parentOrders),b=+(h[m.loc.end.offset]===`;`),x=[m.loc.start.offset,m.loc.end.offset+b];if(!y.length)return n.remove(...x),{consumedRange:x,hasInlineUtility:!1,standaloneCss:[]};let S,C=!1,w=[];for(let e of y)if(e.kind===`standalone`){if(!S){let e=p.prelude;S={prelude:e,selector:f(e),replacementSelector:n.slice(p.prelude.loc.start.offset,p.prelude.loc.end.offset)}}let t=r(S,e);w.push(t)}else C=!0,e.body.includes(`@`)?n.appendRight(h.length,e.body):n.appendLeft(m.loc.start.offset,e.body);return x[1]=m.loc.end.offset+b,n.remove(...x),{consumedRange:x,hasInlineUtility:C,standaloneCss:w}}function E(e){return e.replace(/^(['"])(.*)\1$/,`$2`)}function D(e){return e.replace(/\/\*[\s\S]*?\*\//g,``)}async function O({code:e,generator:t,options:r},i){let a=await n(t,i,(t,n)=>e.slice(t,n),r.throwOnMissing??!0);a!==void 0&&e.overwrite(i.loc.start.offset,i.loc.end.offset,a)}const k=/(@screen [^{]+).+/g;function A({code:e,generator:t},n){if(n.prelude?.type!==`Raw`)return;let r=o(n.prelude.value,t.config.theme);if(!r)return;let i=n.loc.start.offset,a=e.original.slice(i,n.loc.end.offset);for(let t of a.matchAll(k))e.overwrite(i+t.index,i+t.index+t[1].length,`@media ${r}`)}async function j(e,t,n,r,i,a){let{applyVariable:o}=n,s=n.varStyle;o===void 0&&(o=s===void 0?[`--at-apply`]:s?[`${s}apply`]:[]),o=d(o||[]);let c=e=>e.includes(`@apply`)||o.some(t=>e.includes(t)),l=i||e.original,u=c(l),f=l.includes(`@screen`),_=g(l)||h(l);if(!u&&!_&&!f)return;let v=p(l,{parseCustomProperty:!0,parseAtrulePrelude:!1,positions:!0,filename:r,offset:a});if(v.type!==`StyleSheet`)return;let y=[],b=new WeakSet,x=new WeakSet,S={options:n,applyVariable:o,generator:t,code:e,filename:r,offset:a},C=(i,a)=>j(e,t,n,r,i,a),T=async e=>{for(let t of e.block.children)t.type===`Raw`&&await C(t.value,t.loc.start.offset)};m(v,function(t){if(f&&t.type===`Atrule`&&t.name===`screen`)A(S,t);else if(_&&t.type===`Function`&&(t.name===`theme`||t.name===`icon`))return y.push(O(S,t)),this.skip;else u&&t.type===`Rule`&&c(e.original.slice(t.loc.start.offset,t.loc.end.offset))?(b.add(t),y.push(w(S,t,C))):t.type===`Raw`&&this.rule&&!b.has(this.rule)&&!x.has(this.rule)&&(x.add(this.rule),y.push(T(this.rule)))}),await Promise.all(y)}async function M(e,t){let{base:n,readSources:r,contents:i}=t,a=await b(e,n),o=await s(a.config),c=[],l=[];for(let e of a.config.content?.filesystem??[])e.startsWith(`!`)?l.push(e.slice(1)):c.push(e);let{files:u,sources:d}=i?{files:[],sources:i}:r?await r(c,l):{files:[],sources:[]},f=await C(o,u,d);return{layers:f.getLayers()||``,files:u,unknown:a.unknown,matched:f.matched.size,hasTeacss:a.hasTeacss,hasPreset:!!a.config.presets?.length}}function N(e,t){let n=[],r=[],i=[];for(let a of S(e))a.name===`charset`&&a.terminator===`;`?(n.push(e.slice(a.start,a.end)),i.push({start:a.start,end:a.end,replacement:``})):a.name===`import`&&a.terminator===`;`?(r.push(e.slice(a.start,a.end)),i.push({start:a.start,end:a.end,replacement:``})):(a.name===`preset`||a.name===`source`)&&a.terminator===`;`||a.name===`custom`&&a.terminator===`block`?i.push({start:a.start,end:a.end,replacement:``}):a.name===`teacss`&&a.prelude===``&&a.terminator!==`block`&&i.push({start:a.start,end:a.end,replacement:t});i.sort((e,t)=>e.start-t.start);let a=``,o=0;for(let t of i)a+=e.slice(o,t.start)+t.replacement,o=t.end;a+=e.slice(o);let s=a.startsWith(``)?``:``;s&&(a=a.slice(1));let c=[...n,...r];return s+(c.length?`${c.join(`
|
|
2
|
+
`)}\n`:``)+a}function P(e={}){return{name:`@teacss/directives`,enforce:e.enforce,idFilter:l,transform:(t,n,r)=>j(t,r.generator,e,n)}}export{_ as customToTheme,P as default,v as diagnoseCustom,M as generateEntry,y as parseEntry,x as resolvePresets,N as spliceEntry,j as transformDirectives};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{notNull as e}from"@teacss/core";import{clone as t,generate as n,parse as r,walk as i}from"css-tree";import{calcMaxWidthBySize as a,hasIconFn as o,hasThemeFn as s,transformThemeFn as c,transformThemeString as l}from"@teacss/rule-helpers";async function u(e,t){return await Promise.all(e.map(async e=>[e,await t.parseToken(e,`-`)]))}function d(e){return e.filter(([,e])=>e==null).map(([e])=>e)}function f(e){return`[@teacss] @apply: no rule matched ${e.map(e=>`"${e}"`).join(`, `)}`}function p(e){let t=!1,n=0,r,i=``;for(let a=0;a<e.length;a++){let o=e[a];if(t){o===`*`&&e[a+1]===`/`&&(t=!1,a++);continue}if(r){o===`\\`?a++:o===r&&(r=void 0);continue}if(o===`/`&&e[a+1]===`*`){t=!0,a++;continue}if(o===`\\`){a++;continue}if(o===`"`||o===`'`){r=o;continue}if(!/\s/.test(o)||e[a+1]!==`$`||e[a+2]!==`$`||!/\s/.test(e[a+3]??``))continue;let s=a+4;for(;s<e.length&&/\s/.test(e[s]);)s++;i+=`${e.slice(n,a)} `,n=s,a=s-1}return n?i+e.slice(n):e}function m(e){let t=[],n=0,r=!1,i=0,a,o=0;for(let s=0;s<e.length;s++){let c=e[s];r?c===`*`&&e[s+1]===`/`&&(r=!1,s++):a?c===`\\`?s++:c===a&&(a=void 0):c===`/`&&e[s+1]===`*`?(r=!0,s++):c===`"`||c===`'`?a=c:c===`(`?i++:c===`)`?i>0&&i--:c===`[`?n++:c===`]`?n>0&&n--:n===0&&i===0&&e.startsWith(` $$ `,s)&&(t.push(e.slice(o,s)),s+=3,o=s+1)}return t.push(e.slice(o)),t}function h(t,n){let r=t.flatMap(([,e])=>e??[]).filter(e).sort((e,t)=>(e[3]?n.get(e[3])??0:0)-(t[3]?n.get(t[3])??0:0)||e[0]-t[0]);if(!r.length)return[];let i=[],a;for(let e of r){if(!a&&i.length===64){a=new Map;for(let e of i)g(a,e)}let t=e[1],n=e[3],r=a?a.get(n)?.get(t):i.find(e=>e[1]===t&&e[3]===n);if(r){r[2]+=e[2];continue}let o=[...e];i.push(o),a&&g(a,o)}return i.map(([,e,t,n,r])=>{let i=e&&p(e),a=!!(i&&r?.noMerge);return n||i&&i!==`.\\-`||a?{kind:`standalone`,selector:i,body:t,parent:n,noMerge:a}:{kind:`inline`,body:t}})}function g(e,t){let n=t[3],r=e.get(n);r||(r=new Map,e.set(n,r)),r.set(t[1],t)}function _(e,t){let n=e.selector;t.selector&&t.selector!==`.\\-`&&(n=v(e.prelude,t.selector));let r=`${n}{${t.body}}`;if(t.parent){let n=m(t.parent);r=n.length>1?`${n.join(`{`)}{${r}${`}`.repeat(n.length)}`:t.parent===`.\\-`?`${e.replacementSelector}{${r}}`:`${t.parent}{${r}}`}return r}function v(e,a){let o=r(`${a}{}`,{context:`rule`}).prelude;if(!a.includes(`.\\-`))return n(o);let s=t(o);return s.children.clear(),e.children.forEach(e=>{o.children.forEach(n=>{let r=t(n);i(r,{visit:`ClassSelector`,enter(n,r,i){n.name===`\\-`&&i.replace(r,t(e).children)}}),s.children.appendData(r)})}),n(s)}async function y(e,t,n,r=!0){switch(t.name){case`theme`:{if(!t.children.size)throw Error(`theme() expect exact one argument`);if(t.children.first.type!==`String`)throw Error(`theme() expect a string argument`);let i;if(t.children.size>1){let e=t.children.toArray().slice(1);if(e[0].type!==`Operator`||e[0].value!==`,`)throw Error(`theme() expect a comma between expression string and default value`);e.length>1&&(i=[e[1].loc.start.offset,t.children.last.loc.end.offset])}let a=l(t.children.first.value,e.config.theme,!i&&r);return a===void 0&&i&&(a=await b(e,n(i[0],i[1]),r)),a}case`icon`:{let n=t.children.toArray().filter(e=>e.type===`String`).map(e=>e.value);if(n.length===0)throw Error(`icon() expects at least one argument`);let[i,a]=n;return a&&=encodeURIComponent(c(a,e.config.theme,r)),x(e,i,a)}}}async function b(e,t,n){if(!s(t)&&!o(t))return t;let a=[],c=[];i(r(t,{context:`value`,parseCustomProperty:!0,positions:!0}),function(r){if(!(r.type!==`Function`||r.name!==`theme`&&r.name!==`icon`||!r.loc))return c.push(y(e,r,(e,n)=>t.slice(e,n),n).then(e=>{e!==void 0&&a.push({start:r.loc.start.offset,end:r.loc.end.offset,value:e})})),this.skip}),await Promise.all(c);let l=t;for(let e of a.sort((e,t)=>t.start-e.start))l=`${l.slice(0,e.start)}${e.value}${l.slice(e.end)}`;return l}async function x(e,t,n){let r=e.config.presets?.flat()?.find(e=>e.name===`@teacss/preset-icons`);if(!r){console.warn(`@teacss/preset-icons not found, icon() directive will be kept as-is`);return}let i=r.api,a=await i.resolveIcon(t);if(!a)return;let o=i.encodeSvgForCss(a.svg);return`url("data:image/svg+xml;utf8,${n?o.replace(/currentcolor/gi,n):o}")`}function S(e,t){let n=e.trim();if(!n)return;let r=``,i=n.match(/^(?:(lt|at)-)?([\w-]+)$/);i&&(r=i[1],n=i[2]);let{breakpoint:o,breakpoints:s}=t,c=o??s??{};if(r!==`at`){if(!Object.hasOwn(c,n))throw Error(`breakpoint ${n} not found`);let e=c[n];return r===`lt`?`(max-width: ${a(e)})`:`(min-width: ${e})`}let l=Object.entries(c).sort((e,t)=>Number.parseFloat(e[1])-Number.parseFloat(t[1])),u=l.findIndex(([e])=>e===n);if(u<0)throw Error(`breakpoint ${n} not found`);return`(min-width: ${l[u][1]})${l[u+1]?` and (max-width: ${a(l[u+1][1])})`:``}`}export{h as a,d as i,y as n,_ as o,f as r,u as s,S as t};
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@teacss/directives",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Build-time CSS directive transformer for TeaCSS — @apply, theme(), icon(), and @screen.",
|
|
5
|
+
"homepage": "https://css.teasim.com",
|
|
6
|
+
"funding": "https://github.com/sponsors/billgo",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"author": "Billgo <hi@billgo.me>",
|
|
9
|
+
"sideEffects": false,
|
|
10
|
+
"type": "module",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": "./dist/index.js",
|
|
13
|
+
"./core": "./dist/core.js",
|
|
14
|
+
"./package.json": "./package.json"
|
|
15
|
+
},
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "bunx rimraf dist && bunx tsdown --config tsdown.config.mts",
|
|
23
|
+
"dev": "tsdown --watch"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@teacss/config": "0.3.0",
|
|
27
|
+
"@teacss/core": "0.3.0",
|
|
28
|
+
"@teacss/rule-helpers": "0.3.0",
|
|
29
|
+
"@teacss/runtime": "0.3.0",
|
|
30
|
+
"@types/css-tree": "^2.3.11",
|
|
31
|
+
"css-tree": "^3.2.1"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@teacss/preset-icons": "0.3.0",
|
|
35
|
+
"@teacss/preset-standard": "0.3.0",
|
|
36
|
+
"magic-string": "^1.1.0"
|
|
37
|
+
},
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=22.12.0"
|
|
40
|
+
},
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public"
|
|
43
|
+
}
|
|
44
|
+
}
|