voicss 0.1.4
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 +66 -0
- package/dist/index.d.mts +4 -0
- package/dist/index.mjs +4 -0
- package/dist/next.d.mts +8 -0
- package/dist/next.mjs +23 -0
- package/dist/vite.d.mts +5 -0
- package/dist/vite.mjs +47 -0
- package/package.json +38 -0
package/README.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<picture>
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/kh4f/vois/refs/heads/assets/logo-dark.png">
|
|
4
|
+
<img alt="logo" src="https://raw.githubusercontent.com/kh4f/vois/refs/heads/assets/logo-light.png">
|
|
5
|
+
</picture>
|
|
6
|
+
<br>
|
|
7
|
+
A lightweight <b>zero-runtime CSS-in-TS</b> toolkit
|
|
8
|
+
<br><br>
|
|
9
|
+
<p>
|
|
10
|
+
<a href="https://www.npmjs.com/package/vois"><img src="https://img.shields.io/npm/v/vois?style=flat-square&logo=npm&label=npm&labelColor=612838&color=D8C8C2" alt="npm version"/></a>
|
|
11
|
+
<a href="https://github.com/kh4f/vois/issues?q=is%3Aissue+is%3Aopen+label%3Abug"><img src="https://img.shields.io/github/issues/kh4f/vois/bug?style=flat-square&label=%F0%9F%90%9B%20Bugs&labelColor=612838&color=D8C8C2" alt="bugs"></a>
|
|
12
|
+
<a href="https://github.com/kh4f/vois/blob/main/LICENSE"><img src="https://img.shields.io/github/license/kh4f/vois?style=flat-square&label=%F0%9F%9B%A1%EF%B8%8F%20License&labelColor=612838&color=D8C8C2" alt="license"></a>
|
|
13
|
+
</p>
|
|
14
|
+
<p><b>
|
|
15
|
+
<a href="#-overview">Overview</a> โข
|
|
16
|
+
<a href="#-quick-start">Quick Start</a> โข
|
|
17
|
+
<a href="#%EF%B8%8F-usage">Usage</a>
|
|
18
|
+
</b></p>
|
|
19
|
+
<img alt="demo" src="https://raw.githubusercontent.com/kh4f/vois/refs/heads/assets/demo.png">
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
## ๐ Overview
|
|
23
|
+
**Vois** is a bundler plugin that extracts `` void `css ...` `` blocks from `.ts(x)` files into native CSS.
|
|
24
|
+
|
|
25
|
+
### ๐ฅ Features
|
|
26
|
+
- **โก True zero-runtime:** styles are extracted at build time, no JS in production
|
|
27
|
+
- **๐ Native CSS:** write standard CSS with all modern features
|
|
28
|
+
- **๐ฆ Modern bundlers:** first-class support for Next.js and Vite
|
|
29
|
+
- **๐ฅ HMR:** instant style updates during development
|
|
30
|
+
- **๐งฉ [VS Code extension](https://github.com/kh4f/vois-vscode):** syntax highlighting, autocomplete, validation, and more
|
|
31
|
+
- **๐งน [ESLint plugin](https://github.com/kh4f/vois-eslint):** CSS linting in template literals
|
|
32
|
+
|
|
33
|
+
## ๐ Quick Start
|
|
34
|
+
Scaffold a [demo project](templates) for your platform (Next.js/Vite/tsdown):
|
|
35
|
+
```bash
|
|
36
|
+
bun create vois
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## ๐น๏ธ Usage
|
|
40
|
+
### Vite
|
|
41
|
+
```bash
|
|
42
|
+
bun add -D vois
|
|
43
|
+
```
|
|
44
|
+
```ts
|
|
45
|
+
// vite.config.ts
|
|
46
|
+
import type { UserConfig } from 'vite'
|
|
47
|
+
import vois from 'vois/vite'
|
|
48
|
+
|
|
49
|
+
export default {
|
|
50
|
+
plugins: [vois()],
|
|
51
|
+
} satisfies UserConfig
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Next.js
|
|
55
|
+
```bash
|
|
56
|
+
bun add -D vois
|
|
57
|
+
```
|
|
58
|
+
```ts
|
|
59
|
+
// next.config.ts
|
|
60
|
+
import type { NextConfig } from 'next'
|
|
61
|
+
import { voisTurboRule } from 'vois/next'
|
|
62
|
+
|
|
63
|
+
export default {
|
|
64
|
+
turbopack: { rules: { ...voisTurboRule } },
|
|
65
|
+
} satisfies NextConfig
|
|
66
|
+
```
|
package/dist/index.d.mts
ADDED
package/dist/index.mjs
ADDED
package/dist/next.d.mts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { NextConfig } from "next";
|
|
2
|
+
//#region src/next.d.ts
|
|
3
|
+
declare const voisTurboRule: Required<Required<NextConfig>['turbopack']>['rules'];
|
|
4
|
+
declare function export_default(this: {
|
|
5
|
+
resourcePath: string;
|
|
6
|
+
}, source: string): string;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { export_default as default, voisTurboRule };
|
package/dist/next.mjs
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { extractCss } from "./index.mjs";
|
|
2
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { dirname, join, relative, resolve } from "node:path";
|
|
4
|
+
import { createHash } from "node:crypto";
|
|
5
|
+
//#region src/next.ts
|
|
6
|
+
const voisTurboRule = { "*": {
|
|
7
|
+
loaders: ["vois/next"],
|
|
8
|
+
condition: { all: [{ not: "foreign" }, { path: /\.(ts|tsx)$/ }] }
|
|
9
|
+
} };
|
|
10
|
+
function next_default(source) {
|
|
11
|
+
const css = extractCss(source);
|
|
12
|
+
if (!css) return source;
|
|
13
|
+
const fileHash = createHash("md5").update(this.resourcePath).digest("hex");
|
|
14
|
+
const cacheDir = resolve("node_modules", ".vois");
|
|
15
|
+
const cssFilePath = join(cacheDir, `${fileHash}.css`);
|
|
16
|
+
mkdirSync(cacheDir, { recursive: true });
|
|
17
|
+
writeFileSync(cssFilePath, css, "utf8");
|
|
18
|
+
let importPath = relative(dirname(this.resourcePath), cssFilePath).replace(/\\/g, "/");
|
|
19
|
+
if (!importPath.startsWith(".")) importPath = `./${importPath}`;
|
|
20
|
+
return source.replace(/^\w/m, `import '${importPath}';\n$&`);
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { next_default as default, voisTurboRule };
|
package/dist/vite.d.mts
ADDED
package/dist/vite.mjs
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { extractCss } from "./index.mjs";
|
|
2
|
+
import MagicString from "magic-string";
|
|
3
|
+
//#region src/vite.ts
|
|
4
|
+
const CSS_EXTRACTABLE_FILES = /\.(ts|tsx)$/;
|
|
5
|
+
const VIRTUAL_PREFIX = "virtual:vois/";
|
|
6
|
+
const RESOLVED_PREFIX = `\0${VIRTUAL_PREFIX}`;
|
|
7
|
+
const styles = /* @__PURE__ */ new Map();
|
|
8
|
+
var vite_default = () => ({
|
|
9
|
+
name: "vois-vite",
|
|
10
|
+
enforce: "pre",
|
|
11
|
+
resolveId(id) {
|
|
12
|
+
if (id.startsWith(VIRTUAL_PREFIX)) return RESOLVED_PREFIX + normalizePath(id.slice(13));
|
|
13
|
+
},
|
|
14
|
+
load(id) {
|
|
15
|
+
if (id.startsWith(RESOLVED_PREFIX)) {
|
|
16
|
+
const cssId = normalizePath(id.slice(RESOLVED_PREFIX.length));
|
|
17
|
+
return styles.get(cssId);
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
transform(code, id) {
|
|
21
|
+
if (!CSS_EXTRACTABLE_FILES.test(id)) return;
|
|
22
|
+
const css = extractCss(code);
|
|
23
|
+
if (!css) return;
|
|
24
|
+
const cssId = normalizePath(id + ".css");
|
|
25
|
+
styles.set(cssId, css);
|
|
26
|
+
const s = new MagicString(code);
|
|
27
|
+
s.prepend(`import '${VIRTUAL_PREFIX}${cssId}';`);
|
|
28
|
+
return {
|
|
29
|
+
code: s.toString(),
|
|
30
|
+
map: s.generateMap({ hires: true })
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
async handleHotUpdate({ file, server, modules, read }) {
|
|
34
|
+
if (!CSS_EXTRACTABLE_FILES.test(file)) return;
|
|
35
|
+
const sourceCode = await read();
|
|
36
|
+
const css = extractCss(sourceCode);
|
|
37
|
+
if (!css) return;
|
|
38
|
+
const cssId = normalizePath(file + ".css");
|
|
39
|
+
const virtualId = RESOLVED_PREFIX + cssId;
|
|
40
|
+
const mod = server.moduleGraph.getModuleById(virtualId);
|
|
41
|
+
styles.set(cssId, css);
|
|
42
|
+
if (mod) return [...modules, mod];
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
const normalizePath = (p) => p.replace(/\\/g, "/");
|
|
46
|
+
//#endregion
|
|
47
|
+
export { vite_default as default };
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "voicss",
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"description": "โก Ultra-Light Compile-Time CSS-in-TS",
|
|
5
|
+
"author": "kh4f",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": "https://github.com/kh4f/voicss",
|
|
8
|
+
"homepage": "https://github.com/kh4f/voicss",
|
|
9
|
+
"bugs": "https://github.com/kh4f/voicss/issues",
|
|
10
|
+
"keywords": ["css-in-ts", "compile-time-css", "zero-runtime-css", "vite-plugin", "next-plugin"],
|
|
11
|
+
"files": ["dist", "README.md"],
|
|
12
|
+
"exports": {
|
|
13
|
+
".": { "import": "./dist/index.mjs", "types": "./dist/index.d.mts" },
|
|
14
|
+
"./vite": { "import": "./dist/vite.mjs", "types": "./dist/vite.d.mts" },
|
|
15
|
+
"./next": { "default": "./dist/next.mjs", "types": "./dist/next.d.mts" }
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsdown src/{index,vite,next}.ts",
|
|
19
|
+
"lint": "tsc && eslint",
|
|
20
|
+
"prepack": "cp ../../README.md .",
|
|
21
|
+
"postpack": "rm README.md"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"magic-string": "^1.2.3"
|
|
25
|
+
},
|
|
26
|
+
"peerDependencies": {
|
|
27
|
+
"next": "^16",
|
|
28
|
+
"vite": "^8"
|
|
29
|
+
},
|
|
30
|
+
"peerDependenciesMeta": {
|
|
31
|
+
"next": { "optional": true },
|
|
32
|
+
"vite": { "optional": true }
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"next": "^16.3.4",
|
|
36
|
+
"vite": "^8.0.16"
|
|
37
|
+
}
|
|
38
|
+
}
|