@jk2908/cxx 0.1.10 → 0.2.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/dist/config.d.ts +5 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/index.d.ts +40 -8
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +196 -6
- package/dist/index.js.map +13 -0
- package/dist/logger.d.ts +54 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/lru.d.ts +21 -0
- package/dist/lru.d.ts.map +1 -0
- package/dist/next/cxx-loader.cjs +412 -5
- package/dist/next/cxx-loader.cjs.map +16 -0
- package/dist/next/index.d.ts +104 -262
- package/dist/next/index.d.ts.map +1 -0
- package/dist/next/index.js +305 -51
- package/dist/next/index.js.map +14 -0
- package/dist/types.d.ts +21 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils.d.ts +4 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/vite/index.d.ts +13 -0
- package/dist/vite/index.d.ts.map +1 -0
- package/dist/vite/index.js +380 -0
- package/dist/vite/index.js.map +15 -0
- package/package.json +11 -26
- package/src/config.ts +4 -0
- package/src/index.ts +218 -9
- package/src/logger.ts +151 -0
- package/src/lru.ts +51 -0
- package/src/next/cxx-loader.js +16 -4
- package/src/next/index.ts +169 -46
- package/src/types.ts +28 -0
- package/src/utils.ts +24 -0
- package/src/vite/index.ts +156 -0
- package/LICENSE +0 -21
- package/README.md +0 -71
- package/dist/inject/index.cjs +0 -60
- package/dist/inject/index.d.ts +0 -8
- package/dist/inject/index.js +0 -58
- package/dist/next/cxx-loader.d.ts +0 -7
- package/dist/next/cxx-loader.js +0 -7
- package/dist/vite-plugin-cxx/index.d.ts +0 -6
- package/dist/vite-plugin-cxx/index.js +0 -16
- package/src/cyrb53.ts +0 -20
- package/src/inject.ts +0 -54
- package/src/vite-plugin-cxx/index.ts +0 -16
package/src/utils.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export function capitalise(str: string) {
|
|
2
|
+
return str.charAt(0).toUpperCase() + str.slice(1)
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function pascalise(str: string) {
|
|
6
|
+
return str
|
|
7
|
+
.split(/[ _-]+/)
|
|
8
|
+
.map(capitalise)
|
|
9
|
+
.join('')
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function debounce<T extends unknown[]>(fn: (...args: T) => void, wait: number) {
|
|
13
|
+
let timeoutId: ReturnType<typeof setTimeout> | null = null
|
|
14
|
+
|
|
15
|
+
return (...args: T) => {
|
|
16
|
+
if (timeoutId) {
|
|
17
|
+
clearTimeout(timeoutId)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
timeoutId = setTimeout(() => {
|
|
21
|
+
fn.apply(null, args)
|
|
22
|
+
}, wait)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { realpathSync } from 'node:fs'
|
|
2
|
+
import fs from 'node:fs/promises'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
|
|
5
|
+
import { type Plugin, type ViteDevServer } from 'vite'
|
|
6
|
+
|
|
7
|
+
import type { BuildContext, PluginConfig } from '../types.js'
|
|
8
|
+
import { GENERATED_DIR } from '../config.js'
|
|
9
|
+
import { collect, flattenTags, isENOENT, writeTypes } from '../index.js'
|
|
10
|
+
import { Logger } from '../logger.js'
|
|
11
|
+
import { debounce } from '../utils.js'
|
|
12
|
+
|
|
13
|
+
const ACCEPTED_EXTENSIONS = new Set(['.js', '.jsx', '.ts', '.tsx'])
|
|
14
|
+
|
|
15
|
+
function normaliseWatchPath(p: string) {
|
|
16
|
+
return p.replace(/\\/g, '/')
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default function cxx(pluginConfig: PluginConfig = {}) {
|
|
20
|
+
const buildContext = {
|
|
21
|
+
tagsByFile: new Map(),
|
|
22
|
+
} satisfies BuildContext
|
|
23
|
+
|
|
24
|
+
const logger = new Logger(
|
|
25
|
+
(pluginConfig?.logger?.level ?? process.env.NODE_ENV === 'production')
|
|
26
|
+
? 'error'
|
|
27
|
+
: 'debug',
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
// write generated files into a hidden folder at the project root
|
|
31
|
+
// keep the generated surface out of src
|
|
32
|
+
const watchRoot = normaliseWatchPath(realpathSync.native(process.cwd()))
|
|
33
|
+
const watchedRoots = [`${watchRoot}/`]
|
|
34
|
+
|
|
35
|
+
let rebuildRunning = false
|
|
36
|
+
let rebuildQueued = false
|
|
37
|
+
|
|
38
|
+
// watcher events can arrive through symlinked paths like /var while cwd has
|
|
39
|
+
// already resolved to /private/var, so canonicalise the parent dir once and
|
|
40
|
+
// reattach the file name for stable prefix checks
|
|
41
|
+
function resolveWatchFile(filePath: string) {
|
|
42
|
+
const absolutePath = path.resolve(watchRoot, filePath)
|
|
43
|
+
const parentPath = path.dirname(absolutePath)
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
const resolvedParentPath = normaliseWatchPath(realpathSync.native(parentPath))
|
|
47
|
+
|
|
48
|
+
return normaliseWatchPath(
|
|
49
|
+
path.join(resolvedParentPath, path.basename(absolutePath)),
|
|
50
|
+
)
|
|
51
|
+
} catch {
|
|
52
|
+
return normaliseWatchPath(absolutePath)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function watchedFile(filePath: string) {
|
|
57
|
+
const resolvedPath = resolveWatchFile(filePath)
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
watchedRoots.some(root => resolvedPath.startsWith(root)) &&
|
|
61
|
+
!resolvedPath.includes(`/${GENERATED_DIR}/`) &&
|
|
62
|
+
ACCEPTED_EXTENSIONS.has(path.extname(resolvedPath))
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const rebuild = debounce((event: 'add' | 'change' | 'unlink', filePath: string) => {
|
|
67
|
+
function queue() {
|
|
68
|
+
void (async () => {
|
|
69
|
+
// collapse bursts of file events into one active rebuild plus a single
|
|
70
|
+
// queued rerun when changes land mid-build
|
|
71
|
+
if (rebuildRunning) {
|
|
72
|
+
rebuildQueued = true
|
|
73
|
+
return
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
rebuildRunning = true
|
|
77
|
+
|
|
78
|
+
do {
|
|
79
|
+
rebuildQueued = false
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
const hadTags = buildContext.tagsByFile.has(file)
|
|
83
|
+
let hasTags = false
|
|
84
|
+
|
|
85
|
+
if (event === 'unlink') {
|
|
86
|
+
buildContext.tagsByFile.delete(file)
|
|
87
|
+
} else {
|
|
88
|
+
const source = await fs.readFile(file, 'utf-8')
|
|
89
|
+
const { tags } = collect(source, file, pluginConfig)
|
|
90
|
+
|
|
91
|
+
hasTags = tags.size > 0
|
|
92
|
+
|
|
93
|
+
if (hasTags) {
|
|
94
|
+
buildContext.tagsByFile.set(file, tags)
|
|
95
|
+
} else {
|
|
96
|
+
buildContext.tagsByFile.delete(file)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (!hadTags && !hasTags) continue
|
|
101
|
+
|
|
102
|
+
await writeTypes(flattenTags(buildContext.tagsByFile))
|
|
103
|
+
logger.info(`updated types from ${file}`)
|
|
104
|
+
} catch (err) {
|
|
105
|
+
if (isENOENT(err)) {
|
|
106
|
+
if (!buildContext.tagsByFile.has(file)) continue
|
|
107
|
+
|
|
108
|
+
buildContext.tagsByFile.delete(file)
|
|
109
|
+
await writeTypes(flattenTags(buildContext.tagsByFile))
|
|
110
|
+
|
|
111
|
+
logger.info(`updated types from ${file}`)
|
|
112
|
+
|
|
113
|
+
continue
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
logger.error(`failed to update types from ${file}`, err)
|
|
117
|
+
}
|
|
118
|
+
} while (rebuildQueued)
|
|
119
|
+
|
|
120
|
+
rebuildRunning = false
|
|
121
|
+
})()
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// ignore anything outside the watched content dirs
|
|
125
|
+
if (!watchedFile(filePath)) return
|
|
126
|
+
|
|
127
|
+
const file = resolveWatchFile(filePath)
|
|
128
|
+
queue()
|
|
129
|
+
}, 75)
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
name: 'cxx',
|
|
133
|
+
enforce: 'pre',
|
|
134
|
+
transform(code, id) {
|
|
135
|
+
const { template, tags } = collect(code, id, pluginConfig)
|
|
136
|
+
|
|
137
|
+
if (tags.size) buildContext.tagsByFile.set(id, tags)
|
|
138
|
+
|
|
139
|
+
return {
|
|
140
|
+
code: template,
|
|
141
|
+
map: null,
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
configureServer(server: ViteDevServer) {
|
|
145
|
+
logger.info('Watching for changes...')
|
|
146
|
+
|
|
147
|
+
server.watcher
|
|
148
|
+
.on('add', (p: string) => rebuild('add', p))
|
|
149
|
+
.on('change', (p: string) => rebuild('change', p))
|
|
150
|
+
.on('unlink', (p: string) => rebuild('unlink', p))
|
|
151
|
+
},
|
|
152
|
+
async writeBundle() {
|
|
153
|
+
await writeTypes(flattenTags(buildContext.tagsByFile))
|
|
154
|
+
},
|
|
155
|
+
} satisfies Plugin
|
|
156
|
+
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Jerome Kenway
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
package/README.md
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
# @jk2908/cxx
|
|
2
|
-
|
|
3
|
-
Build-time CSS template tag utilities for React 19.
|
|
4
|
-
|
|
5
|
-
## Install
|
|
6
|
-
|
|
7
|
-
```sh
|
|
8
|
-
npm install @jk2908/cxx lightningcss react react-dom
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Usage
|
|
12
|
-
|
|
13
|
-
```tsx
|
|
14
|
-
import { cxx } from '@jk2908/cxx'
|
|
15
|
-
|
|
16
|
-
const [css, styles, href] = cxx`
|
|
17
|
-
.header {
|
|
18
|
-
display: flex;
|
|
19
|
-
gap: 0.75rem;
|
|
20
|
-
}
|
|
21
|
-
`
|
|
22
|
-
|
|
23
|
-
export function Header() {
|
|
24
|
-
return (
|
|
25
|
-
<header className={styles.header}>
|
|
26
|
-
<style href={href} precedence="medium">
|
|
27
|
-
{css}
|
|
28
|
-
</style>
|
|
29
|
-
</header>
|
|
30
|
-
)
|
|
31
|
-
}
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
The `cxx` tag is a build-time marker. Use the Vite plugin or Next helper so the placeholders are replaced before runtime. String interpolation inside the template is not supported.
|
|
35
|
-
|
|
36
|
-
## Vite
|
|
37
|
-
|
|
38
|
-
```ts
|
|
39
|
-
import { defineConfig } from 'vite'
|
|
40
|
-
import react from '@vitejs/plugin-react'
|
|
41
|
-
import cxx from '@jk2908/cxx/vite-plugin-cxx'
|
|
42
|
-
|
|
43
|
-
export default defineConfig({
|
|
44
|
-
plugins: [react(), cxx()],
|
|
45
|
-
})
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
## Next
|
|
49
|
-
|
|
50
|
-
```ts
|
|
51
|
-
import { withCxx } from '@jk2908/cxx/next'
|
|
52
|
-
|
|
53
|
-
const nextConfig = {}
|
|
54
|
-
|
|
55
|
-
export default withCxx(nextConfig)
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
Both integrations accept an optional config object with `lightningcss` options. The default transform enables minification and CSS Modules output.
|
|
59
|
-
|
|
60
|
-
```ts
|
|
61
|
-
cxx({
|
|
62
|
-
lightningcss: {
|
|
63
|
-
minify: false,
|
|
64
|
-
cssModules: false,
|
|
65
|
-
},
|
|
66
|
-
})
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
## License
|
|
70
|
-
|
|
71
|
-
MIT
|
package/dist/inject/index.cjs
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2
|
-
|
|
3
|
-
var lightningcss = require('lightningcss');
|
|
4
|
-
|
|
5
|
-
// cyrb53 (c) 2018 bryc (github.com/bryc)
|
|
6
|
-
// https://github.com/bryc/code/blob/master/jshash/experimental/cyrb53.js
|
|
7
|
-
function cyrb53(str, seed = 0) {
|
|
8
|
-
let h1 = 0xdeadbeef ^ seed;
|
|
9
|
-
let h2 = 0x41c6ce57 ^ seed;
|
|
10
|
-
for(let i = 0, ch; i < str.length; i++){
|
|
11
|
-
ch = str.charCodeAt(i);
|
|
12
|
-
h1 = Math.imul(h1 ^ ch, 2654435761);
|
|
13
|
-
h2 = Math.imul(h2 ^ ch, 1597334677);
|
|
14
|
-
}
|
|
15
|
-
h1 = Math.imul(h1 ^ h1 >>> 16, 2246822507);
|
|
16
|
-
h1 ^= Math.imul(h2 ^ h2 >>> 13, 3266489909);
|
|
17
|
-
h2 = Math.imul(h2 ^ h2 >>> 16, 2246822507);
|
|
18
|
-
h2 ^= Math.imul(h1 ^ h1 >>> 13, 3266489909);
|
|
19
|
-
return 4294967296 * (2097151 & h2) + (h1 >>> 0);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const varMatch = /(?:const|var|let)\s*\[(\w+|)\s*,?\s*(\w+|)\s*,?\s*(\w+|)\s*\]\s*=\s*cxx\s*`([\s\S]*?)`/gm;
|
|
23
|
-
const DEFAULT_CONFIG = {
|
|
24
|
-
lightningcss: {
|
|
25
|
-
minify: true,
|
|
26
|
-
cssModules: true
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
function inject(source, id, config = {}) {
|
|
30
|
-
try {
|
|
31
|
-
const tmpl = source.replace(varMatch, (_, ...args)=>{
|
|
32
|
-
const [varOne, varTwo, varThree, css] = args;
|
|
33
|
-
const { code, exports } = lightningcss.transform({
|
|
34
|
-
...DEFAULT_CONFIG.lightningcss,
|
|
35
|
-
...config.lightningcss,
|
|
36
|
-
filename: id,
|
|
37
|
-
code: new TextEncoder().encode(css)
|
|
38
|
-
});
|
|
39
|
-
const href = cyrb53([
|
|
40
|
-
...Object.keys(exports ?? {}),
|
|
41
|
-
id
|
|
42
|
-
].join(''));
|
|
43
|
-
const classes = exports ? Object.fromEntries(Object.entries(exports).map(([key, value])=>[
|
|
44
|
-
key,
|
|
45
|
-
value.name
|
|
46
|
-
])) : {};
|
|
47
|
-
return [
|
|
48
|
-
varOne && `const ${varOne} = \`${code}\``,
|
|
49
|
-
varTwo && `const ${varTwo} = ${JSON.stringify(classes)}`,
|
|
50
|
-
varThree && `const ${varThree} = \`${href}\``
|
|
51
|
-
].filter(Boolean).join('\n');
|
|
52
|
-
});
|
|
53
|
-
return tmpl;
|
|
54
|
-
} catch (err) {
|
|
55
|
-
console.error('cxx error :(', err);
|
|
56
|
-
return source;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
exports.inject = inject;
|
package/dist/inject/index.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { CustomAtRules, TransformOptions } from 'lightningcss';
|
|
2
|
-
|
|
3
|
-
type Config<C extends CustomAtRules = CustomAtRules> = {
|
|
4
|
-
lightningcss?: Partial<TransformOptions<C>>;
|
|
5
|
-
};
|
|
6
|
-
declare function inject<C extends CustomAtRules = CustomAtRules>(source: string, id: string, config?: Config<C>): string;
|
|
7
|
-
|
|
8
|
-
export { type Config, inject };
|
package/dist/inject/index.js
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { transform } from 'lightningcss';
|
|
2
|
-
|
|
3
|
-
// cyrb53 (c) 2018 bryc (github.com/bryc)
|
|
4
|
-
// https://github.com/bryc/code/blob/master/jshash/experimental/cyrb53.js
|
|
5
|
-
function cyrb53(str, seed = 0) {
|
|
6
|
-
let h1 = 0xdeadbeef ^ seed;
|
|
7
|
-
let h2 = 0x41c6ce57 ^ seed;
|
|
8
|
-
for(let i = 0, ch; i < str.length; i++){
|
|
9
|
-
ch = str.charCodeAt(i);
|
|
10
|
-
h1 = Math.imul(h1 ^ ch, 2654435761);
|
|
11
|
-
h2 = Math.imul(h2 ^ ch, 1597334677);
|
|
12
|
-
}
|
|
13
|
-
h1 = Math.imul(h1 ^ h1 >>> 16, 2246822507);
|
|
14
|
-
h1 ^= Math.imul(h2 ^ h2 >>> 13, 3266489909);
|
|
15
|
-
h2 = Math.imul(h2 ^ h2 >>> 16, 2246822507);
|
|
16
|
-
h2 ^= Math.imul(h1 ^ h1 >>> 13, 3266489909);
|
|
17
|
-
return 4294967296 * (2097151 & h2) + (h1 >>> 0);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const varMatch = /(?:const|var|let)\s*\[(\w+|)\s*,?\s*(\w+|)\s*,?\s*(\w+|)\s*\]\s*=\s*cxx\s*`([\s\S]*?)`/gm;
|
|
21
|
-
const DEFAULT_CONFIG = {
|
|
22
|
-
lightningcss: {
|
|
23
|
-
minify: true,
|
|
24
|
-
cssModules: true
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
function inject(source, id, config = {}) {
|
|
28
|
-
try {
|
|
29
|
-
const tmpl = source.replace(varMatch, (_, ...args)=>{
|
|
30
|
-
const [varOne, varTwo, varThree, css] = args;
|
|
31
|
-
const { code, exports } = transform({
|
|
32
|
-
...DEFAULT_CONFIG.lightningcss,
|
|
33
|
-
...config.lightningcss,
|
|
34
|
-
filename: id,
|
|
35
|
-
code: new TextEncoder().encode(css)
|
|
36
|
-
});
|
|
37
|
-
const href = cyrb53([
|
|
38
|
-
...Object.keys(exports ?? {}),
|
|
39
|
-
id
|
|
40
|
-
].join(''));
|
|
41
|
-
const classes = exports ? Object.fromEntries(Object.entries(exports).map(([key, value])=>[
|
|
42
|
-
key,
|
|
43
|
-
value.name
|
|
44
|
-
])) : {};
|
|
45
|
-
return [
|
|
46
|
-
varOne && `const ${varOne} = \`${code}\``,
|
|
47
|
-
varTwo && `const ${varTwo} = ${JSON.stringify(classes)}`,
|
|
48
|
-
varThree && `const ${varThree} = \`${href}\``
|
|
49
|
-
].filter(Boolean).join('\n');
|
|
50
|
-
});
|
|
51
|
-
return tmpl;
|
|
52
|
-
} catch (err) {
|
|
53
|
-
console.error('cxx error :(', err);
|
|
54
|
-
return source;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export { inject };
|
package/dist/next/cxx-loader.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { inject } from '../inject/index.js';
|
|
2
|
-
|
|
3
|
-
function vitePluginCxx(config) {
|
|
4
|
-
return {
|
|
5
|
-
name: 'cxx',
|
|
6
|
-
enforce: 'pre',
|
|
7
|
-
transform (code, id) {
|
|
8
|
-
return {
|
|
9
|
-
code: inject(code, id, config),
|
|
10
|
-
map: null
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export { vitePluginCxx as default };
|
package/src/cyrb53.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
// cyrb53 (c) 2018 bryc (github.com/bryc)
|
|
2
|
-
// https://github.com/bryc/code/blob/master/jshash/experimental/cyrb53.js
|
|
3
|
-
|
|
4
|
-
export function cyrb53(str: string, seed = 0) {
|
|
5
|
-
let h1 = 0xdeadbeef ^ seed
|
|
6
|
-
let h2 = 0x41c6ce57 ^ seed
|
|
7
|
-
|
|
8
|
-
for (let i = 0, ch: number; i < str.length; i++) {
|
|
9
|
-
ch = str.charCodeAt(i)
|
|
10
|
-
h1 = Math.imul(h1 ^ ch, 2654435761)
|
|
11
|
-
h2 = Math.imul(h2 ^ ch, 1597334677)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507)
|
|
15
|
-
h1 ^= Math.imul(h2 ^ (h2 >>> 13), 3266489909)
|
|
16
|
-
h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507)
|
|
17
|
-
h2 ^= Math.imul(h1 ^ (h1 >>> 13), 3266489909)
|
|
18
|
-
|
|
19
|
-
return 4294967296 * (2097151 & h2) + (h1 >>> 0)
|
|
20
|
-
}
|
package/src/inject.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { cyrb53 } from './cyrb53'
|
|
2
|
-
|
|
3
|
-
import { type TransformOptions, type CustomAtRules, transform } from 'lightningcss'
|
|
4
|
-
|
|
5
|
-
const varMatch =
|
|
6
|
-
/(?:const|var|let)\s*\[(\w+|)\s*,?\s*(\w+|)\s*,?\s*(\w+|)\s*\]\s*=\s*cxx\s*`([\s\S]*?)`/gm
|
|
7
|
-
|
|
8
|
-
export type Config<C extends CustomAtRules = CustomAtRules> = {
|
|
9
|
-
lightningcss?: Partial<TransformOptions<C>>
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const DEFAULT_CONFIG: Config = {
|
|
13
|
-
lightningcss: {
|
|
14
|
-
minify: true,
|
|
15
|
-
cssModules: true,
|
|
16
|
-
},
|
|
17
|
-
} as const
|
|
18
|
-
|
|
19
|
-
export function inject<C extends CustomAtRules = CustomAtRules>(
|
|
20
|
-
source: string,
|
|
21
|
-
id: string,
|
|
22
|
-
config: Config<C> = {},
|
|
23
|
-
) {
|
|
24
|
-
try {
|
|
25
|
-
const tmpl = source.replace(varMatch, (_: string, ...args: string[]) => {
|
|
26
|
-
const [varOne, varTwo, varThree, css] = args
|
|
27
|
-
|
|
28
|
-
const { code, exports } = transform({
|
|
29
|
-
...DEFAULT_CONFIG.lightningcss,
|
|
30
|
-
...config.lightningcss,
|
|
31
|
-
filename: id,
|
|
32
|
-
code: new TextEncoder().encode(css),
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
const href = cyrb53([...Object.keys(exports ?? {}), id].join(''))
|
|
36
|
-
const classes = exports
|
|
37
|
-
? Object.fromEntries(Object.entries(exports).map(([key, value]) => [key, value.name]))
|
|
38
|
-
: {}
|
|
39
|
-
|
|
40
|
-
return [
|
|
41
|
-
varOne && `const ${varOne} = \`${code}\``,
|
|
42
|
-
varTwo && `const ${varTwo} = ${JSON.stringify(classes)}`,
|
|
43
|
-
varThree && `const ${varThree} = \`${href}\``,
|
|
44
|
-
]
|
|
45
|
-
.filter(Boolean)
|
|
46
|
-
.join('\n')
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
return tmpl
|
|
50
|
-
} catch (err) {
|
|
51
|
-
console.error('cxx error :(', err)
|
|
52
|
-
return source
|
|
53
|
-
}
|
|
54
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { Plugin } from 'vite'
|
|
2
|
-
|
|
3
|
-
import { inject, type Config } from '../inject'
|
|
4
|
-
|
|
5
|
-
export default function vitePluginCxx(config?: Config): Plugin {
|
|
6
|
-
return {
|
|
7
|
-
name: 'cxx',
|
|
8
|
-
enforce: 'pre',
|
|
9
|
-
transform(code, id) {
|
|
10
|
-
return {
|
|
11
|
-
code: inject(code, id, config),
|
|
12
|
-
map: null
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
}
|