@teacss/vite 0.9.4 → 0.10.3
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/README.md +29 -46
- package/dist/index.d.ts +4 -8
- package/dist/index.js +3 -1
- package/dist/plugin.d.ts +19 -0
- package/dist/plugin.js +380 -0
- package/dist/virtual.d.ts +35 -0
- package/dist/virtual.js +62 -0
- package/package.json +39 -30
- package/dist/easing-imports-DvRhTc2n.js +0 -1
- package/dist/impl.d.ts +0 -6
- package/dist/impl.js +0 -2
- package/dist/types-BplrH0_C.d.ts +0 -32
package/README.md
CHANGED
|
@@ -1,59 +1,42 @@
|
|
|
1
1
|
# @teacss/vite
|
|
2
2
|
|
|
3
|
-
Vite plugin for TeaCSS.
|
|
3
|
+
The Vite plugin for TeaCSS. It runs the Rust engine (`@teacss/engine`) in process and generates the CSS for the class tokens your project uses. It needs Node.js 26 or later and Vite 7 or later.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
import { defineConfig } from "vite";
|
|
7
|
-
import { pluginTeacss } from "@teacss/vite";
|
|
5
|
+
## Install
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
});
|
|
7
|
+
```sh
|
|
8
|
+
npm install --save-dev @teacss/vite vite
|
|
12
9
|
```
|
|
13
10
|
|
|
11
|
+
## Use
|
|
12
|
+
|
|
14
13
|
```ts
|
|
15
|
-
|
|
14
|
+
// vite.config.ts
|
|
15
|
+
import { teacss } from "@teacss/vite";
|
|
16
|
+
import { defineConfig } from "vite";
|
|
17
|
+
|
|
18
|
+
export default defineConfig({ plugins: [teacss()] });
|
|
16
19
|
```
|
|
17
20
|
|
|
21
|
+
Configuration lives in a CSS entry. Create `index.css` at the project root:
|
|
22
|
+
|
|
18
23
|
```css
|
|
19
|
-
@presets "standard";
|
|
20
|
-
@source "./src/**/*.{ts,tsx}";
|
|
24
|
+
@presets "standard,icons,official";
|
|
25
|
+
@source "./src/**/*.{js,jsx,ts,tsx,html}";
|
|
21
26
|
@teacss;
|
|
22
27
|
```
|
|
23
28
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
native behavior. Preprocessor hooks run once; compiler options, worker selection
|
|
39
|
-
and import resolution remain Vite-owned. No transformer change is needed.
|
|
40
|
-
See the [easing audit](../../docs/knowledge/steps-and-cubic-bezier-easing.md#authored-css-exposure)
|
|
41
|
-
for coverage and limitations.
|
|
42
|
-
|
|
43
|
-
Astro projects should use `@teacss/astro`. Add `@teacss/inspector` only for
|
|
44
|
-
development inspection.
|
|
45
|
-
|
|
46
|
-
Pre-1.0. Install this adapter and `teacss` as development dependencies.
|
|
47
|
-
|
|
48
|
-
Development and production watch builds track source-scanned CSS declarations,
|
|
49
|
-
including new files, deleted files, recreated files, and initially missing external
|
|
50
|
-
absolute `@source` roots. This updates shortcuts and safelists; utility extraction
|
|
51
|
-
still follows Vite's loaded module graph and pipeline filters.
|
|
52
|
-
A bounded declaration check every 500 ms also recovers changes omitted by native
|
|
53
|
-
callbacks; unchanged declarations do not reload configuration or rebuild.
|
|
54
|
-
|
|
55
|
-
Glob-matched CSS file symlinks observe their physical file targets through
|
|
56
|
-
filtered shallow parent watches, including recovery after a failed member read.
|
|
57
|
-
Nested source directory symlinks observe physical target changes, including empty
|
|
58
|
-
targets and target deletion or recreation. Missing routes use shallow parent
|
|
59
|
-
observation. Failed reads retain the last accepted configuration.
|
|
29
|
+
Import the generated CSS once from the application entry:
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
// src/main.ts
|
|
33
|
+
import "virtual:teacss.css";
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The dev server also serves the inspector at `/__teacss`; pass `inspector: false` to turn it off.
|
|
37
|
+
|
|
38
|
+
## Documentation
|
|
39
|
+
|
|
40
|
+
- [Setup](https://github.com/teacss/teacss-rs/blob/master/skills/teacss/references/setup.md#vite) and [the CSS entry](https://github.com/teacss/teacss-rs/blob/master/skills/teacss/references/setup.md#css-entry)
|
|
41
|
+
- [Plugin options](https://github.com/teacss/teacss-rs/blob/master/skills/teacss/references/integrations.md#options) and [Lightning CSS](https://github.com/teacss/teacss-rs/blob/master/skills/teacss/references/integrations.md#lightning-css)
|
|
42
|
+
- [The TeaCSS skill](https://github.com/teacss/teacss-rs/blob/master/skills/teacss/SKILL.md) for syntax, presets and tooling
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
//#
|
|
5
|
-
export declare function defineConfig<Theme extends object>(config: TeacssVitePluginConfig<Theme>): TeacssVitePluginConfig<Theme>;
|
|
6
|
-
export declare function pluginTeacss<Theme extends object>(configOrPath?: TeacssVitePluginConfig<Theme> | string, defaults?: UserConfigDefaults): Plugin[];
|
|
7
|
-
//#endregion
|
|
8
|
-
export { TeacssVitePluginAPI, TeacssVitePluginConfig };
|
|
1
|
+
export type { ShellOptions } from "@teacss/engine";
|
|
2
|
+
export { INSPECTOR_BASE, type TeacssViteOptions, type TeacssVitePluginApi, teacss } from "./plugin.js";
|
|
3
|
+
export { BUILD_PLACEHOLDER, DEFAULT_PIPELINE_INCLUDE, ENTRY_IDS, MINIFIED_PLACEHOLDER, RESOLVED_ENTRY } from "./virtual.js";
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1 +1,3 @@
|
|
|
1
|
-
|
|
1
|
+
export { INSPECTOR_BASE, teacss } from "./plugin.js";
|
|
2
|
+
export { BUILD_PLACEHOLDER, DEFAULT_PIPELINE_INCLUDE, ENTRY_IDS, MINIFIED_PLACEHOLDER, RESOLVED_ENTRY } from "./virtual.js";
|
|
3
|
+
//# sourceMappingURL=index.js.map
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type Project, type ShellOptions } from "@teacss/engine";
|
|
2
|
+
import type { Plugin } from "vite";
|
|
3
|
+
export interface TeacssViteOptions extends ShellOptions {
|
|
4
|
+
/** v10.2 §3.6: serve `@teacss/inspector` at `INSPECTOR_BASE` on the dev server. Default true; a build never mounts it. */
|
|
5
|
+
inspector?: boolean;
|
|
6
|
+
/**
|
|
7
|
+
* In a build, set `css.transformer` and `build.cssMinify` to "lightningcss" where the user left them
|
|
8
|
+
* unset, top level and per environment (`cssMinify` only where `build.minify` is not false). Default:
|
|
9
|
+
* only when `lightningcss` resolves from the project root (it is Vite's optional peer).
|
|
10
|
+
*/
|
|
11
|
+
lightningcss?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface TeacssVitePluginApi {
|
|
14
|
+
getProject(): Project;
|
|
15
|
+
}
|
|
16
|
+
/** The dev-server path the inspector's UI and `/api` routes live under; the UI's built asset URLs assume it. */
|
|
17
|
+
export declare const INSPECTOR_BASE = "/__teacss";
|
|
18
|
+
export declare function teacss(options?: TeacssViteOptions): Plugin[];
|
|
19
|
+
//# sourceMappingURL=plugin.d.ts.map
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { join, posix, resolve } from "node:path";
|
|
4
|
+
import { createProject, extractBundledFonts, isCssId, markers, replaceEntryWithMap } from "@teacss/engine";
|
|
5
|
+
import { createInspectorMiddleware } from "@teacss/inspector";
|
|
6
|
+
import { buildPlaceholder, hmrPath, isResolvedEntry, resolveEntryId, shouldTransform } from "./virtual.js";
|
|
7
|
+
const INCLUDE_COMMENT = markers().includeComment;
|
|
8
|
+
/** architecture §5: the files `loadProjectFromRoot` discovers the entry through. */
|
|
9
|
+
const ENTRY_CANDIDATES = ["package.json", "index.css", "src/index.css"];
|
|
10
|
+
/** Collapses the invalidations of one burst of transforms into one client update. */
|
|
11
|
+
const INVALIDATION_DELAY_MS = 10;
|
|
12
|
+
/** The dev-server path the inspector's UI and `/api` routes live under; the UI's built asset URLs assume it. */
|
|
13
|
+
export const INSPECTOR_BASE = "/__teacss";
|
|
14
|
+
const HTML_ENTRY = /\.html$/;
|
|
15
|
+
export function teacss(options = {}) {
|
|
16
|
+
const { inspector = true, lightningcss, ...shell } = options;
|
|
17
|
+
let project;
|
|
18
|
+
let config;
|
|
19
|
+
let server;
|
|
20
|
+
let viteVersion = "";
|
|
21
|
+
/** When `config` sets `build.cssMinify`: the environments whose own `build.cssMinify` the user set. */
|
|
22
|
+
let userCssMinify;
|
|
23
|
+
let invalidation;
|
|
24
|
+
/** What the last watcher event threw, shown in the error overlay until an event succeeds. */
|
|
25
|
+
let failure;
|
|
26
|
+
/** No live project yet, or `dispose()` released it. */
|
|
27
|
+
let disposed = true;
|
|
28
|
+
/** `@source` files registered as modules from disk, so the ones Vite never imports still count. */
|
|
29
|
+
const sources = new Set();
|
|
30
|
+
/** Stylesheet ids whose `@teacss;` took the generated CSS; they are invalidated with the virtual entry. */
|
|
31
|
+
const entries = new Set();
|
|
32
|
+
/** `@source` directories already reported as unreadable: Vite's builder resolves the config once per environment. */
|
|
33
|
+
const unreadable = new Set();
|
|
34
|
+
function warnUnreadable() {
|
|
35
|
+
for (const path of project.info.unreadableDirectories) {
|
|
36
|
+
if (unreadable.has(path))
|
|
37
|
+
continue;
|
|
38
|
+
unreadable.add(path);
|
|
39
|
+
config.logger.warn(`[@teacss/vite] cannot read ${path} (E_IO)`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function scanSource(file) {
|
|
43
|
+
let code;
|
|
44
|
+
try {
|
|
45
|
+
code = readFileSync(file, "utf8");
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
sources.delete(file);
|
|
49
|
+
return project.removeModule(file);
|
|
50
|
+
}
|
|
51
|
+
sources.add(file);
|
|
52
|
+
return project.transform(file, code).changed;
|
|
53
|
+
}
|
|
54
|
+
function syncSources() {
|
|
55
|
+
const next = new Set(project.info.sourceFiles);
|
|
56
|
+
let changed = false;
|
|
57
|
+
for (const file of sources) {
|
|
58
|
+
if (next.has(file))
|
|
59
|
+
continue;
|
|
60
|
+
sources.delete(file);
|
|
61
|
+
changed = project.removeModule(file) || changed;
|
|
62
|
+
}
|
|
63
|
+
for (const file of next) {
|
|
64
|
+
if (sources.has(file))
|
|
65
|
+
continue;
|
|
66
|
+
server?.watcher.add(file);
|
|
67
|
+
changed = scanSource(file) || changed;
|
|
68
|
+
}
|
|
69
|
+
return changed;
|
|
70
|
+
}
|
|
71
|
+
function isConfigFile(file) {
|
|
72
|
+
return project.engine.configFiles().includes(file) || ENTRY_CANDIDATES.some((candidate) => join(project.root, candidate) === file);
|
|
73
|
+
}
|
|
74
|
+
/** Forgets the modules `transform` registered for a deleted file, its `?query` variants included. */
|
|
75
|
+
function removeTransformed(file) {
|
|
76
|
+
let changed = false;
|
|
77
|
+
for (const id of project.modules()) {
|
|
78
|
+
if (id === file || id.startsWith(`${file}?`))
|
|
79
|
+
changed = project.removeModule(id) || changed;
|
|
80
|
+
}
|
|
81
|
+
return changed;
|
|
82
|
+
}
|
|
83
|
+
function onFileChange(file, event) {
|
|
84
|
+
if (event === "update" && !isConfigFile(file)) {
|
|
85
|
+
if (sources.has(file) && scanSource(file))
|
|
86
|
+
invalidateEntry();
|
|
87
|
+
// While the last reload failed, `configFiles()` is the last good program's: the file may be an import only the failed load read.
|
|
88
|
+
if (!failure)
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const removed = event === "delete" && removeTransformed(file);
|
|
92
|
+
const programChanged = project.reload();
|
|
93
|
+
watchConfig();
|
|
94
|
+
warnUnreadable();
|
|
95
|
+
const sourcesChanged = syncSources();
|
|
96
|
+
// After a failure the page also reloads to drop the error overlay, even when the fix restored the last good program.
|
|
97
|
+
if (programChanged || failure)
|
|
98
|
+
fullReload();
|
|
99
|
+
else if (sourcesChanged || removed)
|
|
100
|
+
invalidateEntry();
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* A dev server's watcher event. An error, such as a configuration error in the saved entry, goes to the log and
|
|
104
|
+
* the error overlay instead of ending the process; the engine keeps its last good program. Until a reload
|
|
105
|
+
* succeeds, every event reloads the project, and the one that succeeds reloads the page.
|
|
106
|
+
*/
|
|
107
|
+
function onWatcherEvent(file, event) {
|
|
108
|
+
try {
|
|
109
|
+
onFileChange(file, event);
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
const message = describeError(error);
|
|
113
|
+
failure = { message, stack: error instanceof Error ? (error.stack ?? "") : "", plugin: "teacss", id: failure?.id ?? file };
|
|
114
|
+
config.logger.error(`[@teacss/vite] ${message}`, { timestamp: true, error: error instanceof Error ? error : undefined });
|
|
115
|
+
server?.hot.send({ type: "error", err: failure });
|
|
116
|
+
watchFailedImports();
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
failure = undefined;
|
|
120
|
+
}
|
|
121
|
+
/** The entry's imports can sit outside the root Vite watches, and chokidar reports a missing path once it appears. */
|
|
122
|
+
function watchConfig() {
|
|
123
|
+
server?.watcher.add([...project.engine.configFiles(), ...project.engine.missingImports()]);
|
|
124
|
+
}
|
|
125
|
+
/** The files the failed load read: a fix saved to an import outside the root then reaches the watcher too. */
|
|
126
|
+
function watchFailedImports() {
|
|
127
|
+
const { entryPath } = project.info;
|
|
128
|
+
if (!server || entryPath === null)
|
|
129
|
+
return;
|
|
130
|
+
try {
|
|
131
|
+
server.watcher.add(project.engine.inspectEntry({ root: project.root, entryPath }).configFiles);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// An unreadable entry is reported by the root watcher when it comes back.
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function fullReload() {
|
|
138
|
+
if (!server)
|
|
139
|
+
return;
|
|
140
|
+
server.moduleGraph.invalidateAll();
|
|
141
|
+
server.hot.send({ type: "full-reload" });
|
|
142
|
+
}
|
|
143
|
+
function invalidateEntry() {
|
|
144
|
+
if (!server || invalidation)
|
|
145
|
+
return;
|
|
146
|
+
invalidation = setTimeout(() => {
|
|
147
|
+
invalidation = undefined;
|
|
148
|
+
sendEntryUpdate();
|
|
149
|
+
}, INVALIDATION_DELAY_MS);
|
|
150
|
+
}
|
|
151
|
+
function sendEntryUpdate() {
|
|
152
|
+
if (!server)
|
|
153
|
+
return;
|
|
154
|
+
const timestamp = Date.now();
|
|
155
|
+
const updates = [];
|
|
156
|
+
for (const [id, mod] of server.moduleGraph.idToModuleMap) {
|
|
157
|
+
if (!isResolvedEntry(id) && !entries.has(id))
|
|
158
|
+
continue;
|
|
159
|
+
server.moduleGraph.invalidateModule(mod);
|
|
160
|
+
// As in Vite's own HMR: a stylesheet requested directly (`<link>`, `?direct`) has no JS importer to accept a js-update.
|
|
161
|
+
const path = hmrPath(mod.url, viteVersion);
|
|
162
|
+
updates.push({ type: mod.type === "css" ? "css-update" : "js-update", path, acceptedPath: path, timestamp });
|
|
163
|
+
}
|
|
164
|
+
if (updates.length > 0)
|
|
165
|
+
server.hot.send({ type: "update", updates });
|
|
166
|
+
}
|
|
167
|
+
function open() {
|
|
168
|
+
const isBuild = config.command === "build";
|
|
169
|
+
project = createProject({
|
|
170
|
+
...shell,
|
|
171
|
+
root: shell.root ?? config.root,
|
|
172
|
+
envMode: shell.envMode ?? (isBuild ? "build" : "dev"),
|
|
173
|
+
minify: shell.minify ?? (isBuild && Boolean(config.build.cssMinify)),
|
|
174
|
+
});
|
|
175
|
+
disposed = false;
|
|
176
|
+
sources.clear();
|
|
177
|
+
entries.clear();
|
|
178
|
+
warnUnreadable();
|
|
179
|
+
syncSources();
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* What stands for the generated CSS: the placeholder `generateBundle` replaces in a build, the CSS itself in dev.
|
|
183
|
+
* While a watcher event has failed, the error goes out again: Vite's own update of a changed entry stylesheet
|
|
184
|
+
* clears the overlay before the client requests it.
|
|
185
|
+
*/
|
|
186
|
+
function generated(warn) {
|
|
187
|
+
if (config.command === "build")
|
|
188
|
+
return buildPlaceholder(config.build.cssMinify, viteVersion);
|
|
189
|
+
if (failure)
|
|
190
|
+
server?.hot.send({ type: "error", err: failure });
|
|
191
|
+
const result = project.css();
|
|
192
|
+
project.reportUnmatched(result, { warn });
|
|
193
|
+
return result.css;
|
|
194
|
+
}
|
|
195
|
+
function dispose() {
|
|
196
|
+
if (invalidation)
|
|
197
|
+
clearTimeout(invalidation);
|
|
198
|
+
invalidation = undefined;
|
|
199
|
+
server = undefined;
|
|
200
|
+
if (disposed)
|
|
201
|
+
return;
|
|
202
|
+
disposed = true;
|
|
203
|
+
project.dispose();
|
|
204
|
+
}
|
|
205
|
+
const main = {
|
|
206
|
+
name: "teacss",
|
|
207
|
+
enforce: "pre",
|
|
208
|
+
config(user, env) {
|
|
209
|
+
userCssMinify = undefined;
|
|
210
|
+
if (lightningcss === false || env.command !== "build")
|
|
211
|
+
return null;
|
|
212
|
+
if (lightningcss === undefined && !resolves("lightningcss", user.root ?? process.cwd()))
|
|
213
|
+
return null;
|
|
214
|
+
const patch = {};
|
|
215
|
+
if (user.css?.transformer === undefined)
|
|
216
|
+
patch.css = { transformer: "lightningcss" };
|
|
217
|
+
if (user.build?.cssMinify !== undefined)
|
|
218
|
+
return patch;
|
|
219
|
+
userCssMinify = new Set(Object.entries(user.environments ?? {}).flatMap(([name, options]) => (options.build?.cssMinify === undefined ? [] : [name])));
|
|
220
|
+
// With `build.minify: false` Vite resolves an unset `cssMinify` to off; keep it that way.
|
|
221
|
+
if (user.build?.minify !== false)
|
|
222
|
+
patch.build = { cssMinify: "lightningcss" };
|
|
223
|
+
return patch;
|
|
224
|
+
},
|
|
225
|
+
// An environment's options carry the top-level `build` after every plugin's `config` hook, the
|
|
226
|
+
// `cssMinify` set above included, so a later plugin's choice is kept and an environment's own
|
|
227
|
+
// `build.minify: false` turns ours back off.
|
|
228
|
+
configEnvironment(name, environment) {
|
|
229
|
+
if (!userCssMinify || userCssMinify.has(name))
|
|
230
|
+
return null;
|
|
231
|
+
const { cssMinify, minify } = environment.build ?? {};
|
|
232
|
+
if (cssMinify === undefined)
|
|
233
|
+
return minify === false ? null : { build: { cssMinify: "lightningcss" } };
|
|
234
|
+
return cssMinify === "lightningcss" && minify === false ? { build: { cssMinify: false } } : null;
|
|
235
|
+
},
|
|
236
|
+
// Vite's builder (`vite build --app`, Astro) resolves the config once per environment on the same
|
|
237
|
+
// plugin objects, then builds the environments one after another, closing each bundle.
|
|
238
|
+
configResolved(resolved) {
|
|
239
|
+
dispose();
|
|
240
|
+
config = resolved;
|
|
241
|
+
viteVersion = this.meta.viteVersion;
|
|
242
|
+
open();
|
|
243
|
+
},
|
|
244
|
+
buildStart() {
|
|
245
|
+
if (disposed)
|
|
246
|
+
open();
|
|
247
|
+
for (const file of [...project.watchFiles(), ...project.engine.missingImports()])
|
|
248
|
+
this.addWatchFile(file);
|
|
249
|
+
},
|
|
250
|
+
configureServer(devServer) {
|
|
251
|
+
server = devServer;
|
|
252
|
+
watchConfig();
|
|
253
|
+
devServer.watcher
|
|
254
|
+
.on("add", (file) => onWatcherEvent(file, "create"))
|
|
255
|
+
.on("change", (file) => onWatcherEvent(file, "update"))
|
|
256
|
+
.on("unlink", (file) => onWatcherEvent(file, "delete"));
|
|
257
|
+
// Vite's client reloads the page on its first update while an overlay is open, which drops the overlay.
|
|
258
|
+
devServer.hot.on("vite:client:connect", (_data, client) => {
|
|
259
|
+
if (failure)
|
|
260
|
+
client.send({ type: "error", err: failure });
|
|
261
|
+
});
|
|
262
|
+
if (inspector)
|
|
263
|
+
devServer.middlewares.use(INSPECTOR_BASE, createInspectorMiddleware(project));
|
|
264
|
+
},
|
|
265
|
+
watchChange(id, change) {
|
|
266
|
+
if (!server)
|
|
267
|
+
onFileChange(id, change.event);
|
|
268
|
+
},
|
|
269
|
+
resolveId(id) {
|
|
270
|
+
return resolveEntryId(id);
|
|
271
|
+
},
|
|
272
|
+
load(id) {
|
|
273
|
+
if (!isResolvedEntry(id))
|
|
274
|
+
return null;
|
|
275
|
+
return generated((message) => this.warn(message));
|
|
276
|
+
},
|
|
277
|
+
transform(code, id) {
|
|
278
|
+
// An HTML entry goes through `transformIndexHtml`; in a build Vite also hands it to `transform`
|
|
279
|
+
// first, and registering both the source and the rewritten page would drop its `:css:` groups.
|
|
280
|
+
if (HTML_ENTRY.test(id) || !shouldTransform(id, code, INCLUDE_COMMENT))
|
|
281
|
+
return null;
|
|
282
|
+
const result = project.transform(id, code);
|
|
283
|
+
const stylesheet = isCssId(id);
|
|
284
|
+
const entry = stylesheet ? replaceEntryWithMap(result.code, () => generated((message) => this.warn(message)), { id: id.split("?")[0] ?? id, original: code, map: result.map }) : null;
|
|
285
|
+
if (entry !== null) {
|
|
286
|
+
entries.add(id);
|
|
287
|
+
return { code: entry.code, map: { ...entry.map, file: entry.map.file ?? undefined } };
|
|
288
|
+
}
|
|
289
|
+
// A stylesheet's `changed` only means its code was rewritten: it registers no tokens, and
|
|
290
|
+
// invalidating on it would re-transform an entry stylesheet without end.
|
|
291
|
+
if (result.changed && !stylesheet)
|
|
292
|
+
invalidateEntry();
|
|
293
|
+
if (result.code === code)
|
|
294
|
+
return null;
|
|
295
|
+
return { code: result.code, map: result.map ? { ...result.map, file: result.map.file ?? undefined } : null };
|
|
296
|
+
},
|
|
297
|
+
transformIndexHtml: {
|
|
298
|
+
order: "pre",
|
|
299
|
+
handler(html, { filename }) {
|
|
300
|
+
const result = project.transform(filename, html);
|
|
301
|
+
if (result.changed)
|
|
302
|
+
invalidateEntry();
|
|
303
|
+
return result.code;
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
generateBundle(_options, bundle) {
|
|
307
|
+
const placeholder = buildPlaceholder(config.build.cssMinify, viteVersion);
|
|
308
|
+
let css;
|
|
309
|
+
const fonts = new Map();
|
|
310
|
+
for (const file of Object.values(bundle)) {
|
|
311
|
+
if (file.type !== "asset" || !file.fileName.endsWith(".css"))
|
|
312
|
+
continue;
|
|
313
|
+
const source = typeof file.source === "string" ? file.source : new TextDecoder().decode(file.source);
|
|
314
|
+
if (!source.includes(placeholder))
|
|
315
|
+
continue;
|
|
316
|
+
if (css === undefined) {
|
|
317
|
+
const result = project.css();
|
|
318
|
+
project.reportUnmatched(result, { warn: (message) => this.warn(message) });
|
|
319
|
+
css = result.css;
|
|
320
|
+
}
|
|
321
|
+
const emitted = new Set();
|
|
322
|
+
const spliced = extractBundledFonts(css, (digest, bytes) => {
|
|
323
|
+
let reference = fonts.get(digest);
|
|
324
|
+
if (reference === undefined) {
|
|
325
|
+
reference = this.emitFile({ type: "asset", name: `teacss-${digest}.woff2`, source: bytes });
|
|
326
|
+
fonts.set(digest, reference);
|
|
327
|
+
}
|
|
328
|
+
const fileName = this.getFileName(reference);
|
|
329
|
+
emitted.add(fileName);
|
|
330
|
+
return assetUrl(config.base, file.fileName, fileName);
|
|
331
|
+
}).css;
|
|
332
|
+
file.source = source.replaceAll(placeholder, spliced);
|
|
333
|
+
// Vite's manifest lists a chunk's assets from `viteMetadata.importedAssets`; Astro moves the
|
|
334
|
+
// fonts of its server build to the client output from that list.
|
|
335
|
+
for (const chunk of Object.values(bundle)) {
|
|
336
|
+
if (chunk.type !== "chunk" || !chunk.viteMetadata?.importedCss.has(file.fileName))
|
|
337
|
+
continue;
|
|
338
|
+
for (const fileName of emitted)
|
|
339
|
+
chunk.viteMetadata.importedAssets.add(fileName);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
closeBundle() {
|
|
344
|
+
if (!config.build.watch)
|
|
345
|
+
dispose();
|
|
346
|
+
},
|
|
347
|
+
closeWatcher() {
|
|
348
|
+
dispose();
|
|
349
|
+
},
|
|
350
|
+
};
|
|
351
|
+
const api = {
|
|
352
|
+
name: "teacss:api",
|
|
353
|
+
enforce: "post",
|
|
354
|
+
api: { getProject: () => project },
|
|
355
|
+
};
|
|
356
|
+
return [main, api];
|
|
357
|
+
}
|
|
358
|
+
/** The URL a stylesheet at `cssFileName` uses for an emitted asset under Vite's `base`. */
|
|
359
|
+
function assetUrl(base, cssFileName, assetFileName) {
|
|
360
|
+
if (base === "./" || base === "")
|
|
361
|
+
return `./${posix.relative(posix.dirname(cssFileName), assetFileName)}`;
|
|
362
|
+
return `${base}${assetFileName}`;
|
|
363
|
+
}
|
|
364
|
+
/** `E_CODE: message` for an engine error, the message otherwise. */
|
|
365
|
+
function describeError(error) {
|
|
366
|
+
if (!(error instanceof Error))
|
|
367
|
+
return String(error);
|
|
368
|
+
const { code } = error;
|
|
369
|
+
return typeof code === "string" && code.startsWith("E_") ? `${code}: ${error.message}` : error.message;
|
|
370
|
+
}
|
|
371
|
+
function resolves(specifier, root) {
|
|
372
|
+
try {
|
|
373
|
+
createRequire(join(resolve(root), "package.json")).resolve(specifier);
|
|
374
|
+
return true;
|
|
375
|
+
}
|
|
376
|
+
catch {
|
|
377
|
+
return false;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** The ids a user imports to get the generated stylesheet (teacss-ts `ENTRY_IDS`). */
|
|
2
|
+
export declare const ENTRY_IDS: ReadonlySet<string>;
|
|
3
|
+
/** The resolved id of the virtual entry; Vite's CSS pipeline treats it as a `.css` module. */
|
|
4
|
+
export declare const RESOLVED_ENTRY = "\0virtual:teacss.css";
|
|
5
|
+
/** What `load` returns for the entry in a build; `generateBundle` replaces it with the generated CSS. */
|
|
6
|
+
export declare const BUILD_PLACEHOLDER: string;
|
|
7
|
+
/**
|
|
8
|
+
* The placeholder for a build whose `cssMinify` is esbuild: Vite minifies with `legalComments: "none"`,
|
|
9
|
+
* which drops the comment, while an unknown at-rule passes esbuild untouched and without a warning.
|
|
10
|
+
* lightningcss keeps the comment and would warn about the at-rule, so it gets `BUILD_PLACEHOLDER`.
|
|
11
|
+
*/
|
|
12
|
+
export declare const MINIFIED_PLACEHOLDER: string;
|
|
13
|
+
/**
|
|
14
|
+
* The placeholder a build with Vite's resolved `build.cssMinify` keeps until `generateBundle`. `true`
|
|
15
|
+
* minifies with esbuild on Vite 7 and with lightningcss on Vite 8.
|
|
16
|
+
*/
|
|
17
|
+
export declare function buildPlaceholder(cssMinify: boolean | "esbuild" | "lightningcss", viteVersion: string): string;
|
|
18
|
+
/** Resolves `virtual:teacss.css`, `teacss.css`, their `/`-prefixed forms and the resolved id itself, keeping a `?query`. */
|
|
19
|
+
export declare function resolveEntryId(id: string): string | null;
|
|
20
|
+
/**
|
|
21
|
+
* The path an HMR update names a module by: the id the client registered the module's hot context under.
|
|
22
|
+
* Vite 7 wraps a URL that is not a path (`\0virtual:teacss.css` → `/@id/__x00__virtual:teacss.css`, its
|
|
23
|
+
* `normalizeHmrUrl`); Vite 8 registers and sends the module graph's URL as is, and its client wraps it.
|
|
24
|
+
*/
|
|
25
|
+
export declare function hmrPath(url: string, viteVersion: string): string;
|
|
26
|
+
/** Whether `id` is the resolved entry, with or without a `?query`. */
|
|
27
|
+
export declare function isResolvedEntry(id: string): boolean;
|
|
28
|
+
export declare const DEFAULT_PIPELINE_INCLUDE: RegExp;
|
|
29
|
+
/**
|
|
30
|
+
* Which modules `transform` hands to the project: never a virtual one; any module whose code carries
|
|
31
|
+
* `includeComment` (`@teacss-include`); otherwise, outside `node_modules`, CSS ids (`transformStylesheet`)
|
|
32
|
+
* and the ids `DEFAULT_PIPELINE_INCLUDE` matches. `@source` files are scanned from disk regardless.
|
|
33
|
+
*/
|
|
34
|
+
export declare function shouldTransform(id: string, code: string, includeComment: string): boolean;
|
|
35
|
+
//# sourceMappingURL=virtual.d.ts.map
|
package/dist/virtual.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { CSS_PLACEHOLDER, isCssId } from "@teacss/engine";
|
|
2
|
+
/** The ids a user imports to get the generated stylesheet (teacss-ts `ENTRY_IDS`). */
|
|
3
|
+
export const ENTRY_IDS = new Set(["virtual:teacss.css", "teacss.css"]);
|
|
4
|
+
/** The resolved id of the virtual entry; Vite's CSS pipeline treats it as a `.css` module. */
|
|
5
|
+
export const RESOLVED_ENTRY = "\0virtual:teacss.css";
|
|
6
|
+
/** What `load` returns for the entry in a build; `generateBundle` replaces it with the generated CSS. */
|
|
7
|
+
export const BUILD_PLACEHOLDER = `/*! ${CSS_PLACEHOLDER} */`;
|
|
8
|
+
/**
|
|
9
|
+
* The placeholder for a build whose `cssMinify` is esbuild: Vite minifies with `legalComments: "none"`,
|
|
10
|
+
* which drops the comment, while an unknown at-rule passes esbuild untouched and without a warning.
|
|
11
|
+
* lightningcss keeps the comment and would warn about the at-rule, so it gets `BUILD_PLACEHOLDER`.
|
|
12
|
+
*/
|
|
13
|
+
export const MINIFIED_PLACEHOLDER = `${CSS_PLACEHOLDER};`;
|
|
14
|
+
/**
|
|
15
|
+
* The placeholder a build with Vite's resolved `build.cssMinify` keeps until `generateBundle`. `true`
|
|
16
|
+
* minifies with esbuild on Vite 7 and with lightningcss on Vite 8.
|
|
17
|
+
*/
|
|
18
|
+
export function buildPlaceholder(cssMinify, viteVersion) {
|
|
19
|
+
const esbuild = cssMinify === "esbuild" || (cssMinify === true && Number.parseInt(viteVersion, 10) < 8);
|
|
20
|
+
return esbuild ? MINIFIED_PLACEHOLDER : BUILD_PLACEHOLDER;
|
|
21
|
+
}
|
|
22
|
+
/** Resolves `virtual:teacss.css`, `teacss.css`, their `/`-prefixed forms and the resolved id itself, keeping a `?query`. */
|
|
23
|
+
export function resolveEntryId(id) {
|
|
24
|
+
const [bare = "", query] = splitQuery(id);
|
|
25
|
+
const isEntry = bare === RESOLVED_ENTRY || ENTRY_IDS.has(bare) || ENTRY_IDS.has(bare.replace(/^\//, ""));
|
|
26
|
+
return isEntry ? (query === undefined ? RESOLVED_ENTRY : `${RESOLVED_ENTRY}?${query}`) : null;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The path an HMR update names a module by: the id the client registered the module's hot context under.
|
|
30
|
+
* Vite 7 wraps a URL that is not a path (`\0virtual:teacss.css` → `/@id/__x00__virtual:teacss.css`, its
|
|
31
|
+
* `normalizeHmrUrl`); Vite 8 registers and sends the module graph's URL as is, and its client wraps it.
|
|
32
|
+
*/
|
|
33
|
+
export function hmrPath(url, viteVersion) {
|
|
34
|
+
if (Number.parseInt(viteVersion, 10) >= 8 || url.startsWith("/") || url.startsWith("."))
|
|
35
|
+
return url;
|
|
36
|
+
return `/@id/${url.replace("\0", "__x00__")}`;
|
|
37
|
+
}
|
|
38
|
+
/** Whether `id` is the resolved entry, with or without a `?query`. */
|
|
39
|
+
export function isResolvedEntry(id) {
|
|
40
|
+
return splitQuery(id)[0] === RESOLVED_ENTRY;
|
|
41
|
+
}
|
|
42
|
+
function splitQuery(id) {
|
|
43
|
+
const index = id.indexOf("?");
|
|
44
|
+
return index === -1 ? [id, undefined] : [id.slice(0, index), id.slice(index + 1)];
|
|
45
|
+
}
|
|
46
|
+
// same as teacss-ts runtime defaultPipelineInclude
|
|
47
|
+
export const DEFAULT_PIPELINE_INCLUDE = /\.(vue|svelte|[jt]sx|vine\.ts|mdx?|astro|elm|php|phtml|marko|html)($|\?)/;
|
|
48
|
+
/**
|
|
49
|
+
* Which modules `transform` hands to the project: never a virtual one; any module whose code carries
|
|
50
|
+
* `includeComment` (`@teacss-include`); otherwise, outside `node_modules`, CSS ids (`transformStylesheet`)
|
|
51
|
+
* and the ids `DEFAULT_PIPELINE_INCLUDE` matches. `@source` files are scanned from disk regardless.
|
|
52
|
+
*/
|
|
53
|
+
export function shouldTransform(id, code, includeComment) {
|
|
54
|
+
if (id.startsWith("\0"))
|
|
55
|
+
return false;
|
|
56
|
+
if (code.includes(includeComment))
|
|
57
|
+
return true;
|
|
58
|
+
if (id.includes("/node_modules/"))
|
|
59
|
+
return false;
|
|
60
|
+
return isCssId(id) || DEFAULT_PIPELINE_INCLUDE.test(id);
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=virtual.js.map
|
package/package.json
CHANGED
|
@@ -1,48 +1,57 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teacss/vite",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Vite plugin for TeaCSS
|
|
5
|
-
"homepage": "https://css.teasim.com",
|
|
6
|
-
"funding": "https://github.com/sponsors/billgo",
|
|
3
|
+
"version": "0.10.3",
|
|
4
|
+
"description": "Vite plugin for TeaCSS on the Rust engine (@teacss/engine)",
|
|
7
5
|
"license": "MIT",
|
|
8
|
-
"author": "Billgo <hi@billgo.me>",
|
|
9
|
-
"sideEffects": false,
|
|
10
6
|
"type": "module",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/teacss/teacss-rs.git",
|
|
10
|
+
"directory": "packages/vite"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/teacss/teacss-rs/tree/master/packages/vite#readme",
|
|
13
|
+
"main": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
11
15
|
"exports": {
|
|
12
|
-
".":
|
|
13
|
-
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"default": "./dist/index.js"
|
|
19
|
+
},
|
|
14
20
|
"./package.json": "./package.json"
|
|
15
21
|
},
|
|
16
|
-
"
|
|
22
|
+
"imports": {
|
|
23
|
+
"#src/*": "./dist/*"
|
|
24
|
+
},
|
|
17
25
|
"files": [
|
|
18
|
-
"dist",
|
|
19
|
-
"
|
|
26
|
+
"dist/**/*.js",
|
|
27
|
+
"dist/**/*.d.ts",
|
|
28
|
+
"README.md",
|
|
29
|
+
"LICENSE"
|
|
20
30
|
],
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
"
|
|
31
|
+
"sideEffects": false,
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=26"
|
|
34
|
+
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"vite": ">=7"
|
|
24
37
|
},
|
|
25
38
|
"dependencies": {
|
|
26
|
-
"@
|
|
27
|
-
"@teacss/
|
|
28
|
-
"@teacss/core": "0.9.4",
|
|
29
|
-
"@teacss/directives": "0.9.4",
|
|
30
|
-
"@teacss/engine": "0.9.4",
|
|
31
|
-
"@teacss/runtime": "0.9.4",
|
|
32
|
-
"lightningcss": "^1.33.0",
|
|
33
|
-
"magic-string": "^1.2.3"
|
|
39
|
+
"@teacss/engine": "0.10.3",
|
|
40
|
+
"@teacss/inspector": "0.10.3"
|
|
34
41
|
},
|
|
35
42
|
"devDependencies": {
|
|
36
|
-
"
|
|
37
|
-
"
|
|
43
|
+
"@types/node": "^22.20.5",
|
|
44
|
+
"typescript": "^5.9.3",
|
|
45
|
+
"vite": "^7.3.7"
|
|
38
46
|
},
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
47
|
+
"scripts": {
|
|
48
|
+
"build:ts": "node -e \"for (const d of ['build','dist']) require('fs').rmSync(d,{recursive:true,force:true})\" && tsc -p tsconfig.json && tsc -p tsconfig.test.json",
|
|
49
|
+
"build": "npm run build:ts",
|
|
50
|
+
"check:types": "tsc -p tsconfig.json && tsc -p tsconfig.test.json --noEmit",
|
|
51
|
+
"test": "npm run build:ts && node --test \"build/tests/**/*.test.js\""
|
|
44
52
|
},
|
|
45
53
|
"publishConfig": {
|
|
46
|
-
"access": "public"
|
|
54
|
+
"access": "public",
|
|
55
|
+
"registry": "https://registry.npmjs.org/"
|
|
47
56
|
}
|
|
48
57
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{readFileSync as e}from"node:fs";import{prepareEasingStylesheet as t}from"@teacss/directives/internal/easing";import{composeVisitors as n,transform as r}from"lightningcss";const i=new Set([`animation`,`animation-timing-function`,`transition`,`transition-timing-function`]);function a(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function o(e){if(!a(e)||typeof e.type!=`string`||!a(e.value)||!a(e.value.loc))return;let{line:t,column:n}=e.value.loc;if(typeof t==`number`&&typeof n==`number`&&typeof e.value.loc.source_index==`number`)return{type:e.type,value:e.value,key:`${e.type}:${t}:${n}`}}function s(e,t=[]){if(Array.isArray(e))for(let n of e)s(n,t);else if(a(e)){let n=o(e);n&&t.push(n);for(let n of Object.values(e))s(n,t)}return t}function c(e,t=[]){if(Array.isArray(e))for(let n of e)c(n,t);else if(a(e)){if(o(e))return t;if(Array.isArray(e.declarations)&&Array.isArray(e.importantDeclarations))t.push(e);else for(let n of Object.values(e))c(n,t)}return t}function l(e){return a(e)&&typeof e.property==`string`&&i.has(e.property)}function u(e,t){return JSON.stringify(e)===JSON.stringify(t)}function d(e,t,n){let i=[];return r({...n,filename:t,code:Buffer.from(e),minify:!1,sourceMap:!1,visitor:{StyleSheet(e){i=s(e.rules)}}}),i}function f(n,r,i){let a=new Map;if(i===void 0&&!/\.css$/i.test(n))return a;let o=i??e(n,`utf8`),s=t(o);if(o===s)return a;let f=d(o,n,r),p=d(s,n,r);if(f.length!==p.length)return a;for(let e=0;e<f.length;e++){let t=f[e],n=p[e];if(t.type!==n.type)continue;let r=c(t.value),i=c(n.value);if(r.length!==i.length)continue;let o=[];for(let e=0;e<r.length;e++)for(let t of[`declarations`,`importantDeclarations`]){let n=r[e][t].filter(l),a=i[e][t].filter(l);n.length===a.length&&!u(n,a)&&o.push({before:n,after:a,block:e,field:t})}o.length&&a.set(t.key,o)}return a}function p(e,t=!1,r=()=>!1){return function(i){if(this&&r(this.filename))return typeof e.visitor==`function`?e.visitor.call(this,i):e.visitor??{};function d(e){if(t&&typeof e?.resolver?.read!=`function`&&!(e?.code instanceof Uint8Array))throw Error(`TeaCSS requires the Lightning CSS visitor factory to expose native source input before parsing.`)}d(this);let p=typeof e.visitor==`function`?e.visitor.call(this,i):e.visitor;d(this);let m=new Map;this?.code&&m.set(this.filename,Buffer.from(this.code).toString());let h=this?.resolver,g=h?.read;this&&h&&g&&(this.resolver={...h,resolve:h.resolve?.bind(h),async read(e){let t=await g.call(h,e);return m.set(e,t),t}});let _=n([{Rule(){},RuleExit(){},Declaration(){}},p??{}]),v=[],y=this,b=e,x=!1,S=[],C=new Map,w=[];function T(e){if(!a(e.value.loc))return;let n=e.value.loc.source_index;if(typeof n!=`number`)return;let r=m.get(v[n]);if(t&&r===void 0)throw Error(`TeaCSS did not capture Lightning CSS input for ${v[n]}. The native source boundary is incompatible.`);if(n===0&&r===void 0)return;let i=C.get(n);return i||(i=f(v[n],b,r),C.set(n,i)),i.get(e.key)}function E(e){let t=T(e);if(!t)return;let n=c(e.value);for(let e of t){let t=n[e.block]?.[e.field];if(!t||!u(t.filter(l),e.before))continue;let r=0;for(let n=0;n<t.length;n++)l(t[n])&&(t[n]=e.after[r++])}}return{...p,StyleSheet(t){v=t.sources;let n=/\.module\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\?)/.test(v[0]);if(b=y?{...y,cssModules:y.cssModules??!1}:{...e,cssModules:n?e.cssModules??!0:!1},!p?.StyleSheet)return;for(let e of s(t.rules))E(e);let r=p.StyleSheet(t);return x=!!r,r},Rule(e){w=[];let t=x||S.at(-1)?.authoritative===!0;S.push({authoritative:t,exits:1});let n=o(e),r=!t&&n?T(n):void 0;if(n&&r){let e=c(n.value);for(let t=0;t<e.length;t++)for(let n of[`importantDeclarations`,`declarations`]){let i=e[t][n].filter(l),a=r.find(e=>e.block===t&&e.field===n&&u(i,e.before));for(let e=0;e<i.length;e++)w.push({before:i[e],after:a?.after[e]??i[e]})}}if(!p?.Rule)return;if(!t)for(let t of s(e))E(t);let i=_.Rule(e);if(i){w=[];let e=S[S.length-1];e.authoritative=!0,e.exits=Array.isArray(i)?i.length:1,e.exits===0&&S.pop()}return i},RuleExit(e){let t=S.at(-1);return t&&--t.exits===0&&S.pop(),_.RuleExit(e)},Declaration(e){let t=e;if(l(e)){let n=w.shift();n&&u(e,n.before)?t=n.after:w=[]}let n=_.Declaration(t);if(n)return n;if(!u(e,t))return t}}}}export{p as createEasingImportVisitor};
|
package/dist/impl.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { n as TeacssVitePluginConfig } from "./types-BplrH0_C.js";
|
|
2
|
-
import { UserConfigDefaults } from "@teacss/core";
|
|
3
|
-
import { Plugin } from "vite";
|
|
4
|
-
//#region src/impl.d.ts
|
|
5
|
-
export declare function createTeacssPlugins<Theme extends object>(configOrPath?: TeacssVitePluginConfig<Theme> | string, defaults?: UserConfigDefaults): Plugin[];
|
|
6
|
-
//#endregion
|
package/dist/impl.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{createHash as e}from"node:crypto";import{mkdtempSync as t,realpathSync as n,rmSync as r,watch as i,writeFileSync as a}from"node:fs";import{tmpdir as o}from"node:os";import{basename as s,join as c,posix as l,resolve as u}from"node:path";import d from"node:process";import f from"@jridgewell/remapping";import{entryDiscoveryFiles as p}from"@teacss/config";import{SourceWatchRegistry as m,createSourceDeclarationCheck as h,planSourceWatches as g,probeSourceDeclarations as _,sourceDeclarationMemberPaths as v,sourceDeclarationStateOf as ee,sourceDeclarationWatchTargets as y}from"@teacss/config/internal/source-scan";import{CSS_PLACEHOLDER as b,isCssId as x}from"@teacss/core";import{prepareEasingCss as te,prepareEasingStylesheet as ne}from"@teacss/directives/internal/easing";import{applyTransformerPipeline as re,createContext as ie,getModuleOutput as ae}from"@teacss/runtime";import{bundledAssetName as S,collectBundledAssets as oe,rewriteBundledAssets as se}from"@teacss/runtime/internal/bundled-assets";import ce from"magic-string";import{normalizePath as C,preprocessCSS as le,transformWithEsbuild as ue}from"vite";function w(e){return e.includes(`@apply`)||e.includes(`--at-apply`)||e.includes(`@screen`)||e.includes(`theme(`)||e.includes(`icon(`)}const T=async()=>{let{default:e}=await import(`@teacss/directives`);return e()};function de(e=T){let t;return{name:`@teacss/directives`,idFilter:x,async transform(n,r,i){if(w(n.original))return await(await(t??=e())).transform?.(n,r,i)}}}function fe(e,t,n){let r,a=!1,o=0,s,c=Promise.resolve(),l=new m((e,t,n)=>i(e,{recursive:n},t),()=>f(),n),u=h(e,async e=>{await c,!a&&e.signature!==r?.signature&&await f()},n);function d(){l.reconcile(g(y(e())))}function f(){if(!a)return c=c.then(async()=>{if(a)return;d();let n=o,i=s,c=await _(e()),l=await i;if(a||n!==o||(l&&(r=l),s=void 0,c.signature===r?.signature))return;let u=r;r=c;try{await t()}catch(e){throw r=u,e}!a&&n===o&&(r=c)}).catch(n),c}function p(){a=!0,u.retire(),l.retire()}return{resolved(){a||(d(),o++,s=_(e(),!0,r),s.catch(n),f())},retire:p,async close(){p(),await u.close(),await c}}}const pe=new Set([`virtual:teacss.css`,`teacss.css`]),E=`/*! ${b} */`,me=`teacss:css-ready`;function D(e,t,n){let r=e.lastIndexOf(t);return r<0||r+t.length!==e.length||r>0&&e[r-1]!==`/`?e:`${e.slice(0,r)}${n}`}function he(e,t,n){let r;try{r=JSON.parse(e)}catch{return e}let i=!1,a=e=>{if(typeof e==`string`){let r=D(e,t,n);return i||=r!==e,r}if(Array.isArray(e))return e.map(a);if(e&&typeof e==`object`)for(let[t,n]of Object.entries(e))e[t]=a(n);return e};return a(r),i?JSON.stringify(r,void 0,2):e}function ge(e,t){let n=0,r=``;for(let i=t;i<e.length;i++){let t=e[i];if(r){t===`\\`?i++:t===r&&(r=``);continue}if(t===`"`||t===`'`||t==="`")r=t;else if(t===`[`)n++;else if(t===`]`&&--n===0)return i}return-1}function O(e,t,n=0){for(let r=n;r<e.length;r++){let n=e[r];if(n===`'`||n===`"`||n==="`"){let t=n;for(r++;r<e.length;r++)if(e[r]===`\\`)r++;else if(e[r]===t)break;continue}if(n===`/`&&e[r+1]===`/`){let t=e.indexOf(`
|
|
2
|
-
`,r+2);if(t<0)return-1;r=t;continue}if(n===`/`&&e[r+1]===`*`){let t=e.indexOf(`*/`,r+2);if(t<0)return-1;r=t+1;continue}if(e.startsWith(t,r))return r}return-1}function _e(e,t,n){let r=O(e,`const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=`);if(r<0)return e;let i=r+56;if(e[i]!==`[`)return e;let a=ge(e,i);if(a<0||!e.startsWith(`)))=>i.map(i=>d[i]);`,a+1)||O(e,`__vite__mapDeps([`,a+20+1)<0)return e;let o=JSON.stringify(t),s=e.slice(i,a+1),c=s.replaceAll(o,JSON.stringify(n));return c===s?e:`${e.slice(0,i)}${c}${e.slice(a+1)}`}const k={chrome:`chrome`,edge:`edge`,firefox:`firefox`,hermes:!1,ie:`ie`,ios:`ios_saf`,node:!1,opera:`opera`,rhino:!1,safari:`safari`},A={2015:[`chrome49`,`edge13`,`safari10`,`ios10`,`firefox44`,`opera36`],2016:[`chrome50`,`edge13`,`safari10`,`ios10`,`firefox43`,`opera37`],2017:[`chrome58`,`edge15`,`safari11`,`ios11`,`firefox52`,`opera45`],2018:[`chrome63`,`edge79`,`safari12`,`ios12`,`firefox58`,`opera50`],2019:[`chrome73`,`edge79`,`safari12.1`,`ios12.1`,`firefox64`,`opera60`],2020:[`chrome80`,`edge80`,`safari14.1`,`ios14.5`,`firefox80`,`opera67`],2021:[`chrome85`,`edge85`,`safari14.1`,`ios14.5`,`firefox80`,`opera71`],2022:[`chrome94`,`edge94`,`safari16.4`,`ios16.4`,`firefox93`,`opera80`],2023:[`chrome110`,`edge110`,`safari16.4`,`ios16.4`,`firefox146`,`opera96`],2024:[`chrome119`,`edge119`,`safari17.4`,`ios17.4`,`firefox145`,`opera105`],2025:[`chrome136`,`edge136`,`safari26.0`,`ios26.0`,`firefox138`,`opera121`]};function ve(e){let t={},n=(Array.isArray(e)?e:e?[e]:[]).flatMap(e=>{let t=/^es(6|\d{4})$/.exec(e);if(!t)return e;let n=t[1]===`6`?2015:Number(t[1]),r=A[n];if(!r)throw Error(`Unsupported target "${e}"`);return r});for(let e of n){if(e===`esnext`)continue;let n=/^([a-z_]+)(\d+)(?:\.(\d+))?$/i.exec(e),r=n&&k[n[1].toLowerCase()];if(r===!1)continue;if(!n||!r)throw Error(`Unsupported target "${e}"`);let i=Number(n[2])<<16|Number(n[3]??0)<<8;(!t[r]||i<t[r])&&(t[r]=i)}return t}function j(i,m={}){let h,g=i;if(i&&typeof i==`object`){h=i.lightningcss;let e={...i};delete e.lightningcss,delete e.mode,Object.keys(e).length===1&&e.engine!==void 0&&(m.engine!==`ts`&&(m={...m,engine:e.engine}),delete e.engine),g=Object.keys(e).length?e:void 0}let _,y=ie(g,{envMode:d.env.NODE_ENV===`development`?`dev`:`build`,...m,transformers:[...m.transformers??[],de()]},e=>{_=ee(e)}),b=`/__tea.css`,x,w=!1,T=!0,D,ge,O,k,A=!1,j,M,N=new Set,P,F,I,ye=0;async function L(){P??=fe(()=>_,async()=>{w?await He():I&&a(I,String(++ye))},e=>x?.logger.error(e instanceof Error?e.message:String(e)));try{await P.resolved()}catch(e){throw P.retire(),P=void 0,e}}async function R(){let e=P;P=void 0,await e?.close(),F&&r(F,{recursive:!0,force:!0}),F=void 0,I=void 0}function be(e){let t=new Set(v(_).map(C));for(let n of N)t.has(n)||e(n);I&&e(I)}let z=new Map,B=new Map,V=new Map,H=new Set,U,W,G=0,xe=!1,K,q,J=0,Y=0,X,Z;function Se(){Z=void 0}function Ce(e=y.root){let t=y.getConfigFileList().map(C),n=new Set(t);if(typeof g==`object`){N=n;return}let r=C(typeof g==`string`?u(e,g):e);if(!t.includes(r))for(let e of p)n.add(C(c(r,e)));N=n}async function we(){let{prefix:e}=await y.getVMPRegexes();return b=`/${e}.css`,b}let Te=new Map,Q=new WeakMap,$=new WeakMap;function Ee(e){let t=S(e);return Te.set(t,e),`${x?.base??`/`}__teacss_fonts/${t}`}async function De(){let e=`url(${JSON.stringify(`${x?.base??`/`}__teacss_fonts/`).slice(0,-1)}`,t=(await se(await Oe(),Ee)).toString().replaceAll(e,`URL${e.slice(3)}`);return T=/@import/i.test(t),t}async function Oe(){await y.flushTasks();let e=Z;if(e&&e.config===y.generator.config&&e.tokens.length===y.tokens.size){let t=0,n=!0;for(let r of y.tokens)if(e.tokens[t++]!==r){n=!1;break}if(n)return await e.promise}let t=[...y.tokens],n={config:y.generator.config,promise:y.generator.generate(t,{minify:!1}).then(({css:e})=>e),tokens:t};Z=n;try{return await n.promise}catch(e){throw Z===n&&(Z=void 0),e}}async function ke(){let e=await Oe(),t=x;if(!t||!(`environments`in t))return e;let n=u(t.root,b.slice(1)),r=t.css.transformer===`lightningcss`,i=r?ne(e):e;if(r&&t.build.cssMinify===`lightningcss`&&!/@import/i.test(i))return Ae(i,n,t);let a=r&&t.build.cssMinify?{...t,build:{...t.build,cssMinify:!1}}:t,o=(await le(i,n,a)).code;if(!t.build.cssMinify)return o;if(t.build.cssMinify===`esbuild`){let e=t.esbuild||{},r={charset:e.charset,legalComments:e.legalComments,logLevel:e.logLevel,logLimit:e.logLimit,logOverride:e.logOverride},i=e.minifyIdentifiers!=null||e.minifySyntax!=null||e.minifyWhitespace!=null?{minifyIdentifiers:e.minifyIdentifiers??!0,minifySyntax:e.minifySyntax??!0,minifyWhitespace:e.minifyWhitespace??!0}:{minify:!0},a=await ue(o,n,{...r,...i,loader:`css`,sourcemap:!1,target:t.build.cssTarget||void 0},void 0,t,void 0,!0);for(let e of a.warnings)t.logger.warn(`[esbuild css minify] ${e.text}`);return a.code}return Ae(ne(o),n,t)}async function Ae(e,t,n){let{transform:r}=await import(`lightningcss`),i=n.css.lightningcss?.visitor,a=r({...n.css.lightningcss,visitor:i===D?ge:i,code:Buffer.from(e),cssModules:void 0,filename:t,minify:!0,targets:ve(n.build.cssTarget)});for(let e of a.warnings)n.logger.warn(`[lightningcss minify] ${e.message}`);return new TextDecoder().decode(a.code)}function je(){if(!O)return;let e=O;U&&clearTimeout(U),U=setTimeout(()=>{U=void 0;let t=W,n=(async()=>{if(t&&await t.catch(()=>{}),O!==e||(A?Y:J)>=G||(await Be(),await e.waitForRequestsIdle?.(),O!==e||(A?Y:J)>=G))return;let n=G,r=e.moduleGraph.getModuleById(b);if(!r){J=n,A&&(Y=n);return}A?(e.moduleGraph.invalidateModule(r),e.watcher.emit(`change`,r.file??b),Y=n,J=n):(e.moduleGraph.invalidateModule(r),J=n)})();W=n,n.then(()=>{W===n&&(W=void 0,O===e&&(A?Y:J)<G&&je())},t=>{W===n&&(W=void 0),e.config.logger.error(`TeaCSS failed to invalidate its virtual stylesheet`,{error:t})})},20)}function Me(){Se(),O&&(G++,je())}function Ne(e){if(!O)return;let t=!1;for(let n of e){let e=O.moduleGraph.getModuleById(n);e&&(O.moduleGraph.invalidateModule(e),t=!0)}t&&O.ws.send({type:`full-reload`})}function Pe(){U&&clearTimeout(U),U=void 0,A=!1,j?.(),j=void 0,M?.(),M=void 0,O=void 0,W=void 0}function Fe(){k??=y.onInvalidate(Me)}function Ie(){Se(),Pe(),k?.(),k=void 0}async function Le(e,t){let n={};z.set(t,n),B.set(t,e);try{let r=await re(y,e,t);return z.get(t)===n?(r?V.set(t,r.code):V.delete(t),y.filter(e,t)?await y.extract(r?.code??e,t):y.modules.has(t)&&await y.extract(``,t),r??null):r??null}finally{z.get(t)===n&&z.delete(t)}}async function Re(e,t){X&&await X;let n=Le(e,t),r=n.then(()=>{},()=>{});H.add(r);try{return await n}finally{H.delete(r)}}async function ze(e){let t=new Set(e),n=new Set([...B.keys(),...V.keys()]),r=[];for(let e of n)t.has(e)||(z.delete(e),B.delete(e),V.delete(e),r.push(y.extract(``,e)));await Promise.all(r)}async function Be(){for(;H.size;)await Promise.all(H)}async function Ve(){let e=Array.from(B),t=new Map(e.map(([e,t])=>[e,V.get(e)??t]));try{await y.reloadConfig()}finally{Ce(y.root),(O||I)&&await L()}await we();let n=[];for(let[r,i]of e){let e=ae(y,r)??i;e===i?V.delete(r):V.set(r,e),e!==t.get(r)&&n.push(r)}Ne(n)}async function He(){let e=X,t=(async()=>{e&&await e.catch(()=>{}),await Be(),await Ve()})();X=t;try{await t}finally{X===t&&(X=void 0)}}let Ue={name:`teacss`,enforce:`pre`,config(e,t){if(h===!1)return;let n=typeof h==`object`?h:void 0,r={};return e.css?.transformer===void 0&&(t.command===`build`||h!==void 0)&&(r.css={transformer:`lightningcss`,...n?{lightningcss:n}:{}}),e.build?.cssMinify===void 0&&(r.build={cssMinify:`lightningcss`}),r},async configResolved(e){if(x=e,e.css.transformer===`lightningcss`){let{createEasingImportVisitor:t}=await import(`./easing-imports-DvRhTc2n.js`),n=e.css.lightningcss??{};ge=n.visitor,D=t(n,!0,e=>w&&e===b&&!T),e.css.lightningcss={...n,visitor:D}}w=e.command===`serve`,await y.updateRoot(e.root),Ce(e.root),await we(),Fe()},async buildStart(){Q.set(this.environment??y,new Map),$.set(this.environment??y,new Set),xe=!1,K=void 0,q=void 0,Fe(),Ce(),!w&&x?.build?.watch?(I||(F=n(t(c(o(),`teacss-vite-watch-`))),I=c(F,`invalidate`),a(I,`0`)),be(e=>this.addWatchFile(e)),await L()):be(e=>this.addWatchFile(e))},async buildEnd(t){if(w||t)return;if(typeof this.getModuleIds==`function`&&await ze(this.getModuleIds()),!(xe||typeof this.getModuleInfo==`function`&&this.getModuleInfo(b)!=null)){q=void 0;return}K=await ke();let n=Q.get(this.environment??y)??new Map;Q.set(this.environment??y,n);for(let{asset:e}of oe(K))n.has(e.digest)||n.set(e.digest,this.emitFile({type:`asset`,name:S(e),source:e.bytes}));q=e(`sha256`).update(K).digest(`hex`)},configureServer(e){Pe(),O=e,e.middlewares?.use((t,n,r)=>{let i=`${e.config.base}__teacss_fonts/`,a=t.url?.split(`?`,1)[0],o=a?.startsWith(i)?Te.get(a.slice(i.length)):void 0;if(!o)return r();n.setHeader(`Content-Type`,`font/woff2`),n.setHeader(`Cache-Control`,`public, max-age=31536000, immutable`),n.end(o.bytes)}),L().catch(t=>e.config?.logger.error(String(t))),Fe();let t=()=>{O===e&&(A=!0,Y<G&&je())};if(e.hot?.on(me,t),j=()=>e.hot?.off(me,t),e.httpServer){let t=()=>{O===e&&(Ie(),R())};e.httpServer.once(`close`,t),M=()=>e.httpServer?.off(`close`,t)}},async closeBundle(){Ie(),(w||!x?.build?.watch)&&await R()},async closeWatcher(){Ie(),await R()},transformIndexHtml:{order:`pre`,async handler(e,{filename:t}){y.filter(e,t)?await y.extract(e,t):y.modules.has(t)&&await y.extract(``,t)}},async resolveId(e){return pe.has(e)||pe.has(e.replace(/^\//,``))||e.startsWith(`${b}?`)?b:null},async load(e){return e===b?w?await De():(xe=!0,E):null},async transform(e,t){if(t===b)return null;let n=await Re(e,t);if(!w||!/\.css(?:$|\?)/i.test(t))return n;let r=await se(n?.code??e,Ee);if(!r.hasChanged())return n;let i=r.generateMap({hires:!0,includeContent:!0,source:t});return{code:r.toString(),map:n?.map?f([i,n.map],()=>null).toString():i}},async watchChange(e,t){if(e===I||N.has(C(e)))try{await He()}finally{be(e=>this.addWatchFile(e))}else X&&await X;if(t.event===`delete`){let t=new Set([e]);for(let n of[...y.modules.keys(),...z.keys(),...B.keys()])(n===e||n.startsWith(`${e}?`))&&t.add(n);for(let e of t)z.delete(e),B.delete(e),V.delete(e);await Promise.all(Array.from(t,e=>y.extract(``,e)))}},async generateBundle(e,t){if(w)return;let n,r=Q.get(this.environment??y)??new Map;for(let[i,a]of Object.entries(t)){if(a.type!==`asset`||!a.fileName.endsWith(`.css`))continue;let o=typeof a.source==`string`?a.source:new TextDecoder().decode(a.source);if(!o.includes(E)&&!o.includes(`;teacss=v1-`))continue;o.includes(E)&&(n??=K??await ke());let c=new Set,u=async e=>(await se(o.replaceAll(E,n??``),t=>{let n=r.get(t.digest);n||(n=this.emitFile({type:`asset`,name:S(t),source:t.bytes}),r.set(t.digest,n));let i=this.getFileName(n);c.add(i);let a=x?.base??`/`;return a===`./`||a===``?`./${l.relative(l.dirname(e),i)}`:`${a}${i}`})).toString(),d=await u(a.fileName);for(let e of Object.values(t))if(e.type===`chunk`&&e.viteMetadata?.importedCss.has(a.fileName))for(let t of c)e.viteMetadata.importedAssets.add(t);let f=typeof e.assetFileNames!=`string`||e.assetFileNames.includes(`[hash`);if(typeof e.assetFileNames==`function`){let t={name:a.name,names:a.names,originalFileName:a.originalFileName??void 0,originalFileNames:a.originalFileNames,type:`asset`},n=e.assetFileNames({...t,source:a.source}),r=e.assetFileNames({...t,source:d});f=r.includes(`[hash`)||r!==n}if(!x||!(`environments`in x)||!f){a.source=d;continue}let p=e=>this.getFileName(this.emitFile({type:`asset`,name:a.name||s(a.fileName),...a.originalFileName?{originalFileName:a.originalFileName}:{},source:e})),m=p(d),h=await u(m);if(h!==d){let e=$.get(this.environment??y)??new Set;if(e.add(m),$.set(this.environment??y,e),d=h,m=p(d),await u(m)!==d)throw Error(`TeaCSS CSS output naming changes its font-relative directory after URL resolution`)}let g=new Set,_=x.build.manifest,v=x.build.ssrManifest;_&&g.add(typeof _==`string`?_:`.vite/manifest.json`),v&&g.add(typeof v==`string`?v:`.vite/ssr-manifest.json`);for(let e of Object.values(t))e.viteMetadata?.importedCss.delete(a.fileName)&&e.viteMetadata.importedCss.add(m),e.type===`chunk`?e.code=_e(e.code,a.fileName,m):e!==a&&typeof e.source==`string`&&g.has(e.fileName)&&(e.source=he(e.source,a.fileName,m));delete t[i]}}},We={name:`teacss:api`,enforce:`post`,api:{getContext:()=>y,getMode:()=>`global`},transform(e,t){return!w||t!==b||!e.includes(`import.meta.hot`)?null:`${e}\nimport.meta.hot.send(${JSON.stringify(me)});`},augmentChunkHash(){return q},generateBundle:{order:`post`,async handler(e,t){let n=Ue.generateBundle;typeof n==`function`&&await n.call(this,e,t,!1);let r=$.get(this.environment??y);for(let e of r??[])delete t[e];r?.clear()}}};function Ge(e){return{name:e?`teacss:easing-source`:`teacss:easing-output`,enforce:e,transform(t,n){let r=x;if(!r||r.css.transformer!==`lightningcss`&&r.build.cssMinify!==`lightningcss`||!/\.(?:css|scss|sass|less|styl|stylus|sss)(?:$|\?)/i.test(n)||/[?&](?:raw|url)(?:&|$)/.test(n)||e&&(r.css.transformer!==`lightningcss`||!/\.css(?:$|\?)/i.test(n)))return null;let i=new ce(t);return te(i),i.hasChanged()?{code:i.toString(),map:i.generateMap({hires:!0,includeContent:!0,source:n})}:null}}}return[Ue,We,Ge(`pre`),Ge()]}export{j as createTeacssPlugins};
|
package/dist/types-BplrH0_C.d.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { TeacssPluginContext, UserConfig } from "@teacss/core";
|
|
2
|
-
import { LightningCSSOptions } from "vite";
|
|
3
|
-
//#region src/types.d.ts
|
|
4
|
-
interface TeacssVitePluginConfig<Theme extends object = object> extends UserConfig<Theme> {
|
|
5
|
-
/**
|
|
6
|
-
* Generation mode. Only `global` is supported (a single virtual stylesheet
|
|
7
|
-
* collecting every utility found across the project).
|
|
8
|
-
*
|
|
9
|
-
* @default "global"
|
|
10
|
-
*/
|
|
11
|
-
mode?: "global";
|
|
12
|
-
/**
|
|
13
|
-
* Drive Vite's CSS pipeline with **lightningcss** instead of PostCSS + esbuild:
|
|
14
|
-
* sets `css.transformer: "lightningcss"` (replaces PostCSS) and
|
|
15
|
-
* `build.cssMinify: "lightningcss"` (replaces esbuild's CSS minifier). On by
|
|
16
|
-
* default — pass `false` to keep Vite's PostCSS + esbuild pipeline, or an
|
|
17
|
-
* object to forward lightningcss options (e.g. `targets`, `drafts`). Only
|
|
18
|
-
* fields you haven't set yourself are touched, so an explicit
|
|
19
|
-
* `css.transformer` / `build.cssMinify` always wins. Left unset, the
|
|
20
|
-
* transformer applies to builds only and the dev server keeps PostCSS;
|
|
21
|
-
* `true` or an options object applies it to the dev server too.
|
|
22
|
-
*
|
|
23
|
-
* @default true
|
|
24
|
-
*/
|
|
25
|
-
lightningcss?: boolean | LightningCSSOptions;
|
|
26
|
-
}
|
|
27
|
-
interface TeacssVitePluginAPI {
|
|
28
|
-
getContext: () => TeacssPluginContext<TeacssVitePluginConfig>;
|
|
29
|
-
getMode: () => "global";
|
|
30
|
-
}
|
|
31
|
-
//#endregion
|
|
32
|
-
export { TeacssVitePluginConfig as n, TeacssVitePluginAPI as t };
|