@zealamic/css-doctor-binding 0.0.0-stage → 1.0.0-beta.1

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 CHANGED
@@ -1,3 +1,48 @@
1
- # Temporary Holding Version
1
+ <div align="center">
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ # @zealamic/css-doctor-binding
4
+
5
+ **Native NAPI-RS bridge for the css-doctor LightningCSS engine.**
6
+
7
+ Version 1.0.0-beta.1
8
+
9
+ [English](./README.md) | [Tiếng Việt](./README_VI.md) | [简体中文](./README_CN.md)
10
+
11
+ </div>
12
+
13
+ ---
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ pnpm add @zealamic/css-doctor-binding
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ```ts
24
+ import { analyzeCss, optimizeCss } from "@zealamic/css-doctor-binding";
25
+
26
+ const analysis = analyzeCss(".card { color: red; }");
27
+
28
+ const result = optimizeCss({
29
+ cssContent: ".card { color: red; } :root { --brand: red; }",
30
+ pageUsage: { home: ["card"] },
31
+ pageCoverage: { enabled: true, minPageRatio: 0.5 },
32
+ sizeBudget: { enabled: true, maxChunkSize: 40 * 1024, isolateVariables: true },
33
+ minify: true,
34
+ });
35
+
36
+ console.log(analysis.stats.selectorCount);
37
+ console.log(result.chunks);
38
+ ```
39
+
40
+ ## Safety and limitations
41
+
42
+ - Prebuilt binaries cover darwin-arm64, darwin-x64, linux-x64-gnu, linux-x64-musl, and win32-x64-msvc.
43
+ - The native API is low-level; prefer @zealamic/css-doctor-vite, next, rsbuild, nuxt, or remix for application builds.
44
+ - Never edit generated index.js, index.d.ts, index.d.cts, or *.node files by hand.
45
+
46
+ ## Full documentation
47
+
48
+ Project README: [English](../../README.md) | [Tiếng Việt](../../README_VI.md) | [简体中文](../../README_CN.md)
package/index.d.ts ADDED
@@ -0,0 +1,298 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ /* auto-generated by NAPI-RS */
5
+
6
+ /** The kind of a simple selector. */
7
+ export const enum JsSelectorKind {
8
+ /** A class selector such as `.button`. */
9
+ Class = 'class',
10
+ /** An ID selector such as `#app`. */
11
+ Id = 'id',
12
+ /** A type/tag selector such as `section`. */
13
+ Tag = 'tag',
14
+ /** An attribute selector such as `[data-state="open"]`. */
15
+ Attribute = 'attribute',
16
+ /** A pseudo-class such as `:hover`. */
17
+ PseudoClass = 'pseudo_class',
18
+ /** A pseudo-element such as `::before`. */
19
+ PseudoElement = 'pseudo_element',
20
+ /** The universal selector `*`. */
21
+ Universal = 'universal',
22
+ /** The CSS nesting selector `&`. */
23
+ Nesting = 'nesting'
24
+ }
25
+ /** Decoded CSS specificity. */
26
+ export interface JsSpecificity {
27
+ /** Number of ID selectors. */
28
+ ids: number
29
+ /** Number of class, attribute and pseudo-class selectors. */
30
+ classes: number
31
+ /** Number of type and pseudo-element selectors. */
32
+ types: number
33
+ }
34
+ /** A 1-based source location. */
35
+ export interface JsSourceLocation {
36
+ /** 1-based line number. */
37
+ line: number
38
+ /** 1-based column number. */
39
+ column: number
40
+ }
41
+ /** A non-fatal parser warning. */
42
+ export interface JsAnalysisWarning {
43
+ /** Human-readable description of the problem. */
44
+ message: string
45
+ /** Location of the problem, when known. */
46
+ location?: JsSourceLocation
47
+ }
48
+ /** A selector extracted from a style rule. */
49
+ export interface JsSelectorInfo {
50
+ /** Normalized selector text. */
51
+ raw: string
52
+ /** Simple-selector kinds present in the selector. */
53
+ kinds: Array<JsSelectorKind>
54
+ /** Class names without the leading dot. */
55
+ classes: Array<string>
56
+ /** ID names without the leading hash. */
57
+ ids: Array<string>
58
+ /** Local type/tag names. */
59
+ tags: Array<string>
60
+ /** Local attribute names. */
61
+ attributes: Array<string>
62
+ /** Pseudo-class names without the leading colon or arguments. */
63
+ pseudoClasses: Array<string>
64
+ /** Pseudo-element names without the leading `::` or arguments. */
65
+ pseudoElements: Array<string>
66
+ /** Tree combinators present (`" "`, `">"`, `"+"`, `"~"`). */
67
+ combinators: Array<string>
68
+ /** Decoded specificity. */
69
+ specificity: JsSpecificity
70
+ /** Index into `CssAnalysisResult.rules`. */
71
+ ruleIndex: number
72
+ /** Number of enclosing style rules. */
73
+ nestingDepth: number
74
+ }
75
+ /** A style rule and its selectors. */
76
+ export interface JsStyleRuleInfo {
77
+ /** Index of the rule in `CssAnalysisResult.rules`. */
78
+ index: number
79
+ /** Index of the enclosing style rule, when nested. */
80
+ parentRuleIndex?: number
81
+ /** Indices into `CssAnalysisResult.selectors`. */
82
+ selectorIndices: Array<number>
83
+ /** Number of normal declarations. */
84
+ declarationCount: number
85
+ /** Number of `!important` declarations. */
86
+ importantDeclarationCount: number
87
+ /** Number of enclosing style rules. */
88
+ nestingDepth: number
89
+ /** Location of the rule in the source. */
90
+ location: JsSourceLocation
91
+ }
92
+ /** Aggregate counters for an analysis run. */
93
+ export interface JsAnalysisStats {
94
+ /** Number of style rules. */
95
+ ruleCount: number
96
+ /** Number of selectors. */
97
+ selectorCount: number
98
+ /** Total number of normal declarations. */
99
+ declarationCount: number
100
+ /** Total number of `!important` declarations. */
101
+ importantDeclarationCount: number
102
+ /** Number of distinct class names. */
103
+ uniqueClassCount: number
104
+ /** Number of distinct ID names. */
105
+ uniqueIdCount: number
106
+ /** Number of distinct type/tag names. */
107
+ uniqueTagCount: number
108
+ /** Number of distinct attribute names. */
109
+ uniqueAttributeCount: number
110
+ /** Deepest style-rule nesting observed. */
111
+ maxNestingDepth: number
112
+ /** Number of parser warnings. */
113
+ warningCount: number
114
+ }
115
+ /** The complete result of analyzing a stylesheet. */
116
+ export interface JsCssAnalysisResult {
117
+ /** All selectors in document order. */
118
+ selectors: Array<JsSelectorInfo>
119
+ /** All style rules in document order. */
120
+ rules: Array<JsStyleRuleInfo>
121
+ /** Aggregate counters. */
122
+ stats: JsAnalysisStats
123
+ /** Recoverable parser warnings. */
124
+ warnings: Array<JsAnalysisWarning>
125
+ }
126
+ /**
127
+ * Analyzes a CSS string synchronously.
128
+ *
129
+ * # Errors
130
+ *
131
+ * Rejects with a JavaScript `Error` when the stylesheet cannot be parsed at
132
+ * all. Recoverable syntax errors are returned as `warnings` instead.
133
+ */
134
+ export declare function analyzeCss(cssContent: string): JsCssAnalysisResult
135
+ /**
136
+ * Analyzes a CSS string on the libuv thread pool and returns a `Promise`.
137
+ *
138
+ * This is the preferred entry point for large stylesheets because it does not
139
+ * block the Node.js event loop.
140
+ *
141
+ * # Errors
142
+ *
143
+ * Rejects with a JavaScript `Error` when the stylesheet cannot be parsed.
144
+ */
145
+ export declare function analyzeCssAsync(cssContent: string): Promise<JsCssAnalysisResult>
146
+ /**
147
+ * Analyzes a CSS string and returns the result as a JSON string.
148
+ *
149
+ * The JSON shape is identical to the object returned by `analyzeCss`.
150
+ *
151
+ * # Errors
152
+ *
153
+ * Rejects with a JavaScript `Error` when parsing or serialization fails.
154
+ */
155
+ export declare function analyzeCssJson(cssContent: string): string
156
+ /** Configuration for page-coverage chunk splitting. */
157
+ export interface JsChunkConfig {
158
+ /**
159
+ * Minimum share of pages that must use a rule before it is considered
160
+ * common. Range: 0.0..=1.0.
161
+ */
162
+ minPageRatio: number
163
+ /** Selectors or class names that should always stay in the common chunk. */
164
+ forceCommonSelectors: Array<string>
165
+ /** Minify serialized CSS. Defaults to `true`. */
166
+ minify?: boolean
167
+ }
168
+ /** Input for [`split_css_by_pages`]. */
169
+ export interface JsSplitInput {
170
+ /** Original CSS source. */
171
+ cssContent: string
172
+ /** Page/route name to class names used by that page. */
173
+ pageUsage: Record<string, Array<string>>
174
+ /** Splitting configuration. */
175
+ config: JsChunkConfig
176
+ }
177
+ /** Usage information for one selector. */
178
+ export interface JsSelectorStat {
179
+ /** Original selector text. */
180
+ selector: string
181
+ /** Matched class occurrences across pages. */
182
+ totalOccurrences: number
183
+ /** Number of pages using the selector. */
184
+ pageCount: number
185
+ /** Fraction of pages using the selector (0..1). */
186
+ coverageRatio: number
187
+ /** `common`, `dead`, or `page:<name>[,<name>...]`. */
188
+ targetChunk: string
189
+ }
190
+ /** Result of page-coverage chunk splitting. */
191
+ export interface JsSplitOutput {
192
+ /** CSS shared by pages reaching the coverage threshold, plus global rules. */
193
+ commonCss: string
194
+ /** Page name to page-specific CSS. */
195
+ pageChunks: Record<string, string>
196
+ /** Per-selector usage matrix. */
197
+ stats: Array<JsSelectorStat>
198
+ /** Number of dead selector occurrences removed. */
199
+ deadCodeCount: number
200
+ }
201
+ /**
202
+ * Splits a stylesheet into common and page-specific CSS chunks.
203
+ *
204
+ * # Errors
205
+ *
206
+ * Rejects with a JavaScript `Error` when the configuration is invalid or the
207
+ * stylesheet/AST cannot be processed.
208
+ */
209
+ export declare function splitCssByPages(input: JsSplitInput): JsSplitOutput
210
+ /** Configuration for the semantic page-coverage tier. */
211
+ export interface JsPageCoverageConfig {
212
+ /** Enable page-coverage splitting. Defaults to `true`. */
213
+ enabled?: boolean
214
+ /** Minimum page coverage for common rules. Defaults to `0.5`. */
215
+ minPageRatio?: number
216
+ /** Selectors or classes that always stay in the common chunk. */
217
+ forceCommon?: Array<string>
218
+ }
219
+ /** Configuration for the physical size-budget tier. */
220
+ export interface JsSizeBudgetConfig {
221
+ /** Enable size-budget splitting. Defaults to `true`. */
222
+ enabled?: boolean
223
+ /** Maximum serialized bytes per body chunk. Defaults to 60 KiB. */
224
+ maxChunkSize?: number
225
+ /** Isolate CSS variables before splitting. Defaults to `true`. */
226
+ isolateVariables?: boolean
227
+ }
228
+ /** Input for [`optimize_css`]. */
229
+ export interface JsPipelineInput {
230
+ /** Original CSS source. */
231
+ cssContent: string
232
+ /** Page/route name to class names used by that page. */
233
+ pageUsage: Record<string, Array<string>>
234
+ /** Optional tier 1 configuration. */
235
+ pageCoverage?: JsPageCoverageConfig
236
+ /** Optional tier 2 configuration. */
237
+ sizeBudget?: JsSizeBudgetConfig
238
+ /** Minify serialized CSS. Defaults to `true`. */
239
+ minify?: boolean
240
+ }
241
+ /** The stage that produced a pipeline chunk. */
242
+ export const enum JsPipelineChunkKind {
243
+ /** Shared/common rules. */
244
+ Common = 'common',
245
+ /** Page-specific rules. */
246
+ Page = 'page',
247
+ /** Isolated CSS variables. */
248
+ Variables = 'variables',
249
+ /** A size-budget part. */
250
+ Part = 'part'
251
+ }
252
+ /** One CSS chunk emitted by the pipeline. */
253
+ export interface JsChunkOutput {
254
+ /** Logical file stem, e.g. `common`, `page-home`, `common-vars`. */
255
+ name: string
256
+ /** Base chunk before physical splitting. */
257
+ sourceChunk: string
258
+ /** Serialized CSS. */
259
+ css: string
260
+ /** Stage/kind of this chunk. */
261
+ kind: JsPipelineChunkKind
262
+ /** Page that owns this chunk, when applicable. */
263
+ page?: string
264
+ /** Whether this chunk contains isolated CSS variables. */
265
+ variables: boolean
266
+ /** 1-based part index when produced by size splitting. */
267
+ part?: number
268
+ /** Serialized byte size. */
269
+ sizeBytes: number
270
+ /** True when an indivisible rule exceeds the budget. */
271
+ oversized: boolean
272
+ /** True when this chunk exists because of the size budget. */
273
+ splitDueToSize: boolean
274
+ }
275
+ /** Result of the two-tier optimization pipeline. */
276
+ export interface JsPipelineOutput {
277
+ /** Final chunks in load order. */
278
+ chunks: Array<JsChunkOutput>
279
+ /** Selector usage matrix from tier 1. */
280
+ stats: Array<JsSelectorStat>
281
+ /** Dead selector occurrences removed by tier 1. */
282
+ deadCodeCount: number
283
+ /** Pages discovered from `page_usage`. */
284
+ pages: Array<string>
285
+ /** Whether page-coverage splitting actually ran. */
286
+ pageCoverageApplied: boolean
287
+ /** Whether size-budget processing was enabled. */
288
+ sizeBudgetApplied: boolean
289
+ }
290
+ /**
291
+ * Runs the two-tier CSS optimization pipeline.
292
+ *
293
+ * # Errors
294
+ *
295
+ * Rejects with a JavaScript `Error` when the configuration is invalid or the
296
+ * stylesheet/AST cannot be processed.
297
+ */
298
+ export declare function optimizeCss(input: JsPipelineInput): JsPipelineOutput
package/index.js ADDED
@@ -0,0 +1,321 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+ /* prettier-ignore */
4
+
5
+ /* auto-generated by NAPI-RS */
6
+
7
+ const { existsSync, readFileSync } = require('fs')
8
+ const { join } = require('path')
9
+
10
+ const { platform, arch } = process
11
+
12
+ let nativeBinding = null
13
+ let localFileExisted = false
14
+ let loadError = null
15
+
16
+ function isMusl() {
17
+ // For Node 10
18
+ if (!process.report || typeof process.report.getReport !== 'function') {
19
+ try {
20
+ const lddPath = require('child_process').execSync('which ldd').toString().trim()
21
+ return readFileSync(lddPath, 'utf8').includes('musl')
22
+ } catch (e) {
23
+ return true
24
+ }
25
+ } else {
26
+ const { glibcVersionRuntime } = process.report.getReport().header
27
+ return !glibcVersionRuntime
28
+ }
29
+ }
30
+
31
+ switch (platform) {
32
+ case 'android':
33
+ switch (arch) {
34
+ case 'arm64':
35
+ localFileExisted = existsSync(join(__dirname, 'css-doctor-binding.android-arm64.node'))
36
+ try {
37
+ if (localFileExisted) {
38
+ nativeBinding = require('./css-doctor-binding.android-arm64.node')
39
+ } else {
40
+ nativeBinding = require('@zealamic/css-doctor-binding-android-arm64')
41
+ }
42
+ } catch (e) {
43
+ loadError = e
44
+ }
45
+ break
46
+ case 'arm':
47
+ localFileExisted = existsSync(join(__dirname, 'css-doctor-binding.android-arm-eabi.node'))
48
+ try {
49
+ if (localFileExisted) {
50
+ nativeBinding = require('./css-doctor-binding.android-arm-eabi.node')
51
+ } else {
52
+ nativeBinding = require('@zealamic/css-doctor-binding-android-arm-eabi')
53
+ }
54
+ } catch (e) {
55
+ loadError = e
56
+ }
57
+ break
58
+ default:
59
+ throw new Error(`Unsupported architecture on Android ${arch}`)
60
+ }
61
+ break
62
+ case 'win32':
63
+ switch (arch) {
64
+ case 'x64':
65
+ localFileExisted = existsSync(
66
+ join(__dirname, 'css-doctor-binding.win32-x64-msvc.node')
67
+ )
68
+ try {
69
+ if (localFileExisted) {
70
+ nativeBinding = require('./css-doctor-binding.win32-x64-msvc.node')
71
+ } else {
72
+ nativeBinding = require('@zealamic/css-doctor-binding-win32-x64-msvc')
73
+ }
74
+ } catch (e) {
75
+ loadError = e
76
+ }
77
+ break
78
+ case 'ia32':
79
+ localFileExisted = existsSync(
80
+ join(__dirname, 'css-doctor-binding.win32-ia32-msvc.node')
81
+ )
82
+ try {
83
+ if (localFileExisted) {
84
+ nativeBinding = require('./css-doctor-binding.win32-ia32-msvc.node')
85
+ } else {
86
+ nativeBinding = require('@zealamic/css-doctor-binding-win32-ia32-msvc')
87
+ }
88
+ } catch (e) {
89
+ loadError = e
90
+ }
91
+ break
92
+ case 'arm64':
93
+ localFileExisted = existsSync(
94
+ join(__dirname, 'css-doctor-binding.win32-arm64-msvc.node')
95
+ )
96
+ try {
97
+ if (localFileExisted) {
98
+ nativeBinding = require('./css-doctor-binding.win32-arm64-msvc.node')
99
+ } else {
100
+ nativeBinding = require('@zealamic/css-doctor-binding-win32-arm64-msvc')
101
+ }
102
+ } catch (e) {
103
+ loadError = e
104
+ }
105
+ break
106
+ default:
107
+ throw new Error(`Unsupported architecture on Windows: ${arch}`)
108
+ }
109
+ break
110
+ case 'darwin':
111
+ localFileExisted = existsSync(join(__dirname, 'css-doctor-binding.darwin-universal.node'))
112
+ try {
113
+ if (localFileExisted) {
114
+ nativeBinding = require('./css-doctor-binding.darwin-universal.node')
115
+ } else {
116
+ nativeBinding = require('@zealamic/css-doctor-binding-darwin-universal')
117
+ }
118
+ break
119
+ } catch {}
120
+ switch (arch) {
121
+ case 'x64':
122
+ localFileExisted = existsSync(join(__dirname, 'css-doctor-binding.darwin-x64.node'))
123
+ try {
124
+ if (localFileExisted) {
125
+ nativeBinding = require('./css-doctor-binding.darwin-x64.node')
126
+ } else {
127
+ nativeBinding = require('@zealamic/css-doctor-binding-darwin-x64')
128
+ }
129
+ } catch (e) {
130
+ loadError = e
131
+ }
132
+ break
133
+ case 'arm64':
134
+ localFileExisted = existsSync(
135
+ join(__dirname, 'css-doctor-binding.darwin-arm64.node')
136
+ )
137
+ try {
138
+ if (localFileExisted) {
139
+ nativeBinding = require('./css-doctor-binding.darwin-arm64.node')
140
+ } else {
141
+ nativeBinding = require('@zealamic/css-doctor-binding-darwin-arm64')
142
+ }
143
+ } catch (e) {
144
+ loadError = e
145
+ }
146
+ break
147
+ default:
148
+ throw new Error(`Unsupported architecture on macOS: ${arch}`)
149
+ }
150
+ break
151
+ case 'freebsd':
152
+ if (arch !== 'x64') {
153
+ throw new Error(`Unsupported architecture on FreeBSD: ${arch}`)
154
+ }
155
+ localFileExisted = existsSync(join(__dirname, 'css-doctor-binding.freebsd-x64.node'))
156
+ try {
157
+ if (localFileExisted) {
158
+ nativeBinding = require('./css-doctor-binding.freebsd-x64.node')
159
+ } else {
160
+ nativeBinding = require('@zealamic/css-doctor-binding-freebsd-x64')
161
+ }
162
+ } catch (e) {
163
+ loadError = e
164
+ }
165
+ break
166
+ case 'linux':
167
+ switch (arch) {
168
+ case 'x64':
169
+ if (isMusl()) {
170
+ localFileExisted = existsSync(
171
+ join(__dirname, 'css-doctor-binding.linux-x64-musl.node')
172
+ )
173
+ try {
174
+ if (localFileExisted) {
175
+ nativeBinding = require('./css-doctor-binding.linux-x64-musl.node')
176
+ } else {
177
+ nativeBinding = require('@zealamic/css-doctor-binding-linux-x64-musl')
178
+ }
179
+ } catch (e) {
180
+ loadError = e
181
+ }
182
+ } else {
183
+ localFileExisted = existsSync(
184
+ join(__dirname, 'css-doctor-binding.linux-x64-gnu.node')
185
+ )
186
+ try {
187
+ if (localFileExisted) {
188
+ nativeBinding = require('./css-doctor-binding.linux-x64-gnu.node')
189
+ } else {
190
+ nativeBinding = require('@zealamic/css-doctor-binding-linux-x64-gnu')
191
+ }
192
+ } catch (e) {
193
+ loadError = e
194
+ }
195
+ }
196
+ break
197
+ case 'arm64':
198
+ if (isMusl()) {
199
+ localFileExisted = existsSync(
200
+ join(__dirname, 'css-doctor-binding.linux-arm64-musl.node')
201
+ )
202
+ try {
203
+ if (localFileExisted) {
204
+ nativeBinding = require('./css-doctor-binding.linux-arm64-musl.node')
205
+ } else {
206
+ nativeBinding = require('@zealamic/css-doctor-binding-linux-arm64-musl')
207
+ }
208
+ } catch (e) {
209
+ loadError = e
210
+ }
211
+ } else {
212
+ localFileExisted = existsSync(
213
+ join(__dirname, 'css-doctor-binding.linux-arm64-gnu.node')
214
+ )
215
+ try {
216
+ if (localFileExisted) {
217
+ nativeBinding = require('./css-doctor-binding.linux-arm64-gnu.node')
218
+ } else {
219
+ nativeBinding = require('@zealamic/css-doctor-binding-linux-arm64-gnu')
220
+ }
221
+ } catch (e) {
222
+ loadError = e
223
+ }
224
+ }
225
+ break
226
+ case 'arm':
227
+ if (isMusl()) {
228
+ localFileExisted = existsSync(
229
+ join(__dirname, 'css-doctor-binding.linux-arm-musleabihf.node')
230
+ )
231
+ try {
232
+ if (localFileExisted) {
233
+ nativeBinding = require('./css-doctor-binding.linux-arm-musleabihf.node')
234
+ } else {
235
+ nativeBinding = require('@zealamic/css-doctor-binding-linux-arm-musleabihf')
236
+ }
237
+ } catch (e) {
238
+ loadError = e
239
+ }
240
+ } else {
241
+ localFileExisted = existsSync(
242
+ join(__dirname, 'css-doctor-binding.linux-arm-gnueabihf.node')
243
+ )
244
+ try {
245
+ if (localFileExisted) {
246
+ nativeBinding = require('./css-doctor-binding.linux-arm-gnueabihf.node')
247
+ } else {
248
+ nativeBinding = require('@zealamic/css-doctor-binding-linux-arm-gnueabihf')
249
+ }
250
+ } catch (e) {
251
+ loadError = e
252
+ }
253
+ }
254
+ break
255
+ case 'riscv64':
256
+ if (isMusl()) {
257
+ localFileExisted = existsSync(
258
+ join(__dirname, 'css-doctor-binding.linux-riscv64-musl.node')
259
+ )
260
+ try {
261
+ if (localFileExisted) {
262
+ nativeBinding = require('./css-doctor-binding.linux-riscv64-musl.node')
263
+ } else {
264
+ nativeBinding = require('@zealamic/css-doctor-binding-linux-riscv64-musl')
265
+ }
266
+ } catch (e) {
267
+ loadError = e
268
+ }
269
+ } else {
270
+ localFileExisted = existsSync(
271
+ join(__dirname, 'css-doctor-binding.linux-riscv64-gnu.node')
272
+ )
273
+ try {
274
+ if (localFileExisted) {
275
+ nativeBinding = require('./css-doctor-binding.linux-riscv64-gnu.node')
276
+ } else {
277
+ nativeBinding = require('@zealamic/css-doctor-binding-linux-riscv64-gnu')
278
+ }
279
+ } catch (e) {
280
+ loadError = e
281
+ }
282
+ }
283
+ break
284
+ case 's390x':
285
+ localFileExisted = existsSync(
286
+ join(__dirname, 'css-doctor-binding.linux-s390x-gnu.node')
287
+ )
288
+ try {
289
+ if (localFileExisted) {
290
+ nativeBinding = require('./css-doctor-binding.linux-s390x-gnu.node')
291
+ } else {
292
+ nativeBinding = require('@zealamic/css-doctor-binding-linux-s390x-gnu')
293
+ }
294
+ } catch (e) {
295
+ loadError = e
296
+ }
297
+ break
298
+ default:
299
+ throw new Error(`Unsupported architecture on Linux: ${arch}`)
300
+ }
301
+ break
302
+ default:
303
+ throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
304
+ }
305
+
306
+ if (!nativeBinding) {
307
+ if (loadError) {
308
+ throw loadError
309
+ }
310
+ throw new Error(`Failed to load native binding`)
311
+ }
312
+
313
+ const { JsSelectorKind, analyzeCss, analyzeCssAsync, analyzeCssJson, splitCssByPages, JsPipelineChunkKind, optimizeCss } = nativeBinding
314
+
315
+ module.exports.JsSelectorKind = JsSelectorKind
316
+ module.exports.analyzeCss = analyzeCss
317
+ module.exports.analyzeCssAsync = analyzeCssAsync
318
+ module.exports.analyzeCssJson = analyzeCssJson
319
+ module.exports.splitCssByPages = splitCssByPages
320
+ module.exports.JsPipelineChunkKind = JsPipelineChunkKind
321
+ module.exports.optimizeCss = optimizeCss
package/package.json CHANGED
@@ -1,6 +1,41 @@
1
1
  {
2
2
  "name": "@zealamic/css-doctor-binding",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "1.0.0-beta.1",
4
+ "description": "Native Node.js bindings for the css-doctor CSS analysis engine",
5
+ "license": "MIT",
6
+ "main": "index.js",
7
+ "types": "index.d.ts",
8
+ "files": [
9
+ "index.js",
10
+ "index.d.ts",
11
+ "*.node"
12
+ ],
13
+ "napi": {
14
+ "name": "css-doctor-binding",
15
+ "triples": {
16
+ "defaults": true
17
+ }
18
+ },
19
+ "devDependencies": {
20
+ "@napi-rs/cli": "^2.18.4",
21
+ "@types/node": "^22.20.5",
22
+ "tsx": "^4.23.15",
23
+ "typescript": "^5.9.3"
24
+ },
25
+ "engines": {
26
+ "node": ">=18"
27
+ },
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
31
+ "scripts": {
32
+ "build": "napi build --platform --release",
33
+ "build:debug": "napi build --platform",
34
+ "test": "pnpm build && pnpm typecheck && tsx test.ts",
35
+ "typecheck": "tsc --noEmit -p tsconfig.json",
36
+ "lint": "biome lint src test.ts",
37
+ "format": "biome format --write src test.ts",
38
+ "format:check": "biome format src test.ts",
39
+ "check": "biome check src test.ts"
40
+ }
6
41
  }