@zslabs/atomic-css-modules 0.1.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/CHANGELOG.md +10 -0
- package/GUIDE.md +32 -0
- package/LICENSE +21 -0
- package/README.md +121 -0
- package/dist/atom-key.d.ts +19 -0
- package/dist/atom-key.js +72 -0
- package/dist/atom-key.js.map +1 -0
- package/dist/atoms.d.ts +8 -0
- package/dist/atoms.js +33 -0
- package/dist/atoms.js.map +1 -0
- package/dist/declaration-utils.d.ts +37 -0
- package/dist/declaration-utils.js +99 -0
- package/dist/declaration-utils.js.map +1 -0
- package/dist/file-scan-cache.d.ts +21 -0
- package/dist/file-scan-cache.js +122 -0
- package/dist/file-scan-cache.js.map +1 -0
- package/dist/hash.d.ts +15 -0
- package/dist/hash.js +38 -0
- package/dist/hash.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/process.d.ts +2 -0
- package/dist/process.js +19 -0
- package/dist/process.js.map +1 -0
- package/dist/registry.d.ts +3 -0
- package/dist/registry.js +107 -0
- package/dist/registry.js.map +1 -0
- package/dist/report.d.ts +7 -0
- package/dist/report.js +67 -0
- package/dist/report.js.map +1 -0
- package/dist/rewrite.d.ts +2 -0
- package/dist/rewrite.js +482 -0
- package/dist/rewrite.js.map +1 -0
- package/dist/rule-context.d.ts +35 -0
- package/dist/rule-context.js +86 -0
- package/dist/rule-context.js.map +1 -0
- package/dist/scan.d.ts +2 -0
- package/dist/scan.js +177 -0
- package/dist/scan.js.map +1 -0
- package/dist/selector-utils.d.ts +34 -0
- package/dist/selector-utils.js +156 -0
- package/dist/selector-utils.js.map +1 -0
- package/dist/shorthand-groups.d.ts +7 -0
- package/dist/shorthand-groups.js +85 -0
- package/dist/shorthand-groups.js.map +1 -0
- package/dist/skip-comment.d.ts +6 -0
- package/dist/skip-comment.js +48 -0
- package/dist/skip-comment.js.map +1 -0
- package/dist/types.d.ts +152 -0
- package/dist/types.js +14 -0
- package/dist/types.js.map +1 -0
- package/dist/vite-plugin.d.ts +27 -0
- package/dist/vite-plugin.js +231 -0
- package/dist/vite-plugin.js.map +1 -0
- package/package.json +75 -0
package/dist/hash.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic, dependency-free string hashing (FNV-1a) used to derive
|
|
3
|
+
* short, stable atomic class names from declaration fingerprints.
|
|
4
|
+
*/
|
|
5
|
+
export function fnv1a(input) {
|
|
6
|
+
let hash = 0x811c9dc5;
|
|
7
|
+
for (let i = 0; i < input.length; i++) {
|
|
8
|
+
hash ^= input.charCodeAt(i);
|
|
9
|
+
hash = Math.imul(hash, 0x01000193);
|
|
10
|
+
}
|
|
11
|
+
// Unsigned 32-bit hex, zero-padded.
|
|
12
|
+
return (hash >>> 0).toString(16).padStart(8, '0');
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* FNV-1a encoded as base36, with a leading digit remapped to a letter
|
|
16
|
+
* so the name is a valid CSS class without a reserved prefix.
|
|
17
|
+
*/
|
|
18
|
+
export function atomClassName(fingerprint) {
|
|
19
|
+
const encoded = Number.parseInt(fnv1a(fingerprint), 16).toString(36);
|
|
20
|
+
const lead = encoded.charCodeAt(0);
|
|
21
|
+
if (lead >= 48 && lead <= 57) {
|
|
22
|
+
return String.fromCharCode(lead + 49) + encoded.slice(1);
|
|
23
|
+
}
|
|
24
|
+
return encoded;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Picks `desired` when free, otherwise appends `-2`, `-3`, … until unique.
|
|
28
|
+
* Used so class-name collisions never silently share a registry rule.
|
|
29
|
+
*/
|
|
30
|
+
export function allocateUniqueClassName(taken, desired) {
|
|
31
|
+
if (!taken.has(desired))
|
|
32
|
+
return desired;
|
|
33
|
+
let suffix = 2;
|
|
34
|
+
while (taken.has(`${desired}-${suffix}`))
|
|
35
|
+
suffix += 1;
|
|
36
|
+
return `${desired}-${suffix}`;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=hash.js.map
|
package/dist/hash.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.js","sourceRoot":"","sources":["../src/hash.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,UAAU,KAAK,CAAC,KAAa;IACjC,IAAI,IAAI,GAAG,UAAU,CAAA;IACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;QAC3B,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;IACpC,CAAC;IACD,oCAAoC;IACpC,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;AACnD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,WAAmB;IAC/C,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;IACpE,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;IAClC,IAAI,IAAI,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,EAAE,CAAC;QAC7B,OAAO,MAAM,CAAC,YAAY,CAAC,IAAI,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAC1D,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CACrC,KAA0B,EAC1B,OAAe;IAEf,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAA;IACvC,IAAI,MAAM,GAAG,CAAC,CAAA;IACd,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,IAAI,MAAM,EAAE,CAAC;QAAE,MAAM,IAAI,CAAC,CAAA;IACrD,OAAO,GAAG,OAAO,IAAI,MAAM,EAAE,CAAA;AAC/B,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { FileScanCache } from './file-scan-cache.js';
|
|
2
|
+
export { ensureUniqueAtomNames, syncScanAtomHashes } from './atoms.js';
|
|
3
|
+
export { processCssModules } from './process.js';
|
|
4
|
+
export { buildRegistryCss } from './registry.js';
|
|
5
|
+
export { SKIP_REASON_LEGEND, formatAtomizationReport, summarizeAtomization, } from './report.js';
|
|
6
|
+
export { rewriteFiles } from './rewrite.js';
|
|
7
|
+
export { scanFiles } from './scan.js';
|
|
8
|
+
export type { Atom, AtomCondition, AtomKey, AtomPseudo, AtomizationReport, AtomizationSkip, DeclDecision, ProcessOptions, ProcessResult, RewrittenFile, ScanFileResult, ScanResult, ScanRuleInfo, SkipReason, SourceFile, } from './types.js';
|
|
9
|
+
export { SKIP_REASONS } from './types.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { FileScanCache } from './file-scan-cache.js';
|
|
2
|
+
export { ensureUniqueAtomNames, syncScanAtomHashes } from './atoms.js';
|
|
3
|
+
export { processCssModules } from './process.js';
|
|
4
|
+
export { buildRegistryCss } from './registry.js';
|
|
5
|
+
export { SKIP_REASON_LEGEND, formatAtomizationReport, summarizeAtomization, } from './report.js';
|
|
6
|
+
export { rewriteFiles } from './rewrite.js';
|
|
7
|
+
export { scanFiles } from './scan.js';
|
|
8
|
+
export { SKIP_REASONS } from './types.js';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAkBrC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA"}
|
package/dist/process.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public orchestration entry point: scan a set of CSS Modules files, then
|
|
3
|
+
* rewrite them and build the shared atomic registry.
|
|
4
|
+
*/
|
|
5
|
+
import { buildRegistryCss } from './registry.js';
|
|
6
|
+
import { summarizeAtomization } from './report.js';
|
|
7
|
+
import { rewriteFiles } from './rewrite.js';
|
|
8
|
+
import { scanFiles } from './scan.js';
|
|
9
|
+
export function processCssModules(files, options) {
|
|
10
|
+
const scanResult = scanFiles(files, options);
|
|
11
|
+
const rewrittenFiles = rewriteFiles(files, scanResult.files, options, scanResult.atoms);
|
|
12
|
+
const registryCss = buildRegistryCss(scanResult.atoms.values());
|
|
13
|
+
return {
|
|
14
|
+
files: rewrittenFiles,
|
|
15
|
+
registryCss,
|
|
16
|
+
report: summarizeAtomization(files, scanResult, registryCss),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=process.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process.js","sourceRoot":"","sources":["../src/process.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAGrC,MAAM,UAAU,iBAAiB,CAC/B,KAA4B,EAC5B,OAAuB;IAEvB,MAAM,UAAU,GAAG,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;IAC5C,MAAM,cAAc,GAAG,YAAY,CACjC,KAAK,EACL,UAAU,CAAC,KAAK,EAChB,OAAO,EACP,UAAU,CAAC,KAAK,CACjB,CAAA;IACD,MAAM,WAAW,GAAG,gBAAgB,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAA;IAC/D,OAAO;QACL,KAAK,EAAE,cAAc;QACrB,WAAW;QACX,MAAM,EAAE,oBAAoB,CAAC,KAAK,EAAE,UAAU,EAAE,WAAW,CAAC;KAC7D,CAAA;AACH,CAAC"}
|
package/dist/registry.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { transform } from 'lightningcss';
|
|
2
|
+
function locationStub() {
|
|
3
|
+
return { source_index: 0, line: 0, column: 1 };
|
|
4
|
+
}
|
|
5
|
+
function atomSelector(atom) {
|
|
6
|
+
const selector = [
|
|
7
|
+
{ type: 'class', name: atom.className },
|
|
8
|
+
];
|
|
9
|
+
if (atom.key.pseudo)
|
|
10
|
+
selector.push(atom.key.pseudo);
|
|
11
|
+
return selector;
|
|
12
|
+
}
|
|
13
|
+
function atomStyleRule(atom) {
|
|
14
|
+
const declarations = atom.key.important
|
|
15
|
+
? { importantDeclarations: [atom.declaration] }
|
|
16
|
+
: { declarations: [atom.declaration] };
|
|
17
|
+
return {
|
|
18
|
+
type: 'style',
|
|
19
|
+
value: {
|
|
20
|
+
loc: locationStub(),
|
|
21
|
+
selectors: [atomSelector(atom)],
|
|
22
|
+
declarations,
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function wrapOne(wrapper, inner) {
|
|
27
|
+
if (wrapper.kind === 'media') {
|
|
28
|
+
return {
|
|
29
|
+
type: 'media',
|
|
30
|
+
value: {
|
|
31
|
+
loc: locationStub(),
|
|
32
|
+
query: wrapper.query,
|
|
33
|
+
rules: [inner],
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
if (wrapper.kind === 'container') {
|
|
38
|
+
return {
|
|
39
|
+
type: 'container',
|
|
40
|
+
value: {
|
|
41
|
+
loc: locationStub(),
|
|
42
|
+
rules: [inner],
|
|
43
|
+
...(wrapper.name ? { name: wrapper.name } : {}),
|
|
44
|
+
...(wrapper.condition ? { condition: wrapper.condition } : {}),
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
if (wrapper.kind === 'supports') {
|
|
49
|
+
return {
|
|
50
|
+
type: 'supports',
|
|
51
|
+
value: {
|
|
52
|
+
loc: locationStub(),
|
|
53
|
+
condition: wrapper.condition,
|
|
54
|
+
rules: [inner],
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
if (wrapper.kind === 'layer') {
|
|
59
|
+
return {
|
|
60
|
+
type: 'layer-block',
|
|
61
|
+
value: {
|
|
62
|
+
loc: locationStub(),
|
|
63
|
+
rules: [inner],
|
|
64
|
+
...(wrapper.name ? { name: wrapper.name } : {}),
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
if (wrapper.kind === 'starting-style') {
|
|
69
|
+
return {
|
|
70
|
+
type: 'starting-style',
|
|
71
|
+
value: {
|
|
72
|
+
loc: locationStub(),
|
|
73
|
+
rules: [inner],
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
type: 'scope',
|
|
79
|
+
value: {
|
|
80
|
+
loc: locationStub(),
|
|
81
|
+
rules: [inner],
|
|
82
|
+
...(wrapper.scopeStart ? { scopeStart: wrapper.scopeStart } : {}),
|
|
83
|
+
...(wrapper.scopeEnd ? { scopeEnd: wrapper.scopeEnd } : {}),
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function wrapInCondition(atom, styleRule) {
|
|
88
|
+
return atom.key.condition.reduceRight((inner, wrapper) => wrapOne(wrapper, inner), styleRule);
|
|
89
|
+
}
|
|
90
|
+
/** Builds the atomic registry CSS text for a set of collected atoms. Returns an empty string if there are none. */
|
|
91
|
+
export function buildRegistryCss(atoms) {
|
|
92
|
+
const atomList = [...atoms];
|
|
93
|
+
if (atomList.length === 0)
|
|
94
|
+
return '';
|
|
95
|
+
const result = transform({
|
|
96
|
+
filename: 'atomic-registry.css',
|
|
97
|
+
code: Buffer.from(''),
|
|
98
|
+
visitor: {
|
|
99
|
+
StyleSheetExit(sheet) {
|
|
100
|
+
sheet.rules = atomList.map((atom) => wrapInCondition(atom, atomStyleRule(atom)));
|
|
101
|
+
return sheet;
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
return Buffer.from(result.code).toString('utf8');
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
|
package/dist/report.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type AtomizationReport, type ScanResult, type SkipReason, type SourceFile } from './types.js';
|
|
2
|
+
export declare const SKIP_REASON_LEGEND: Record<SkipReason, string>;
|
|
3
|
+
export declare function summarizeAtomization(files: readonly SourceFile[], scan: Pick<ScanResult, 'atoms' | 'skips'>, registryCss: string): AtomizationReport;
|
|
4
|
+
export declare function formatAtomizationReport(report: AtomizationReport, options?: {
|
|
5
|
+
verbose?: boolean;
|
|
6
|
+
root?: string;
|
|
7
|
+
}): string;
|
package/dist/report.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Summarize one scan + registry pass for logs and ProcessResult.report.
|
|
3
|
+
*/
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { SKIP_REASONS, } from './types.js';
|
|
6
|
+
export const SKIP_REASON_LEGEND = {
|
|
7
|
+
combinator: 'descendant or sibling selector (.a .b)',
|
|
8
|
+
compound: 'extra class on the same element (.a.b)',
|
|
9
|
+
element: 'element, id, attribute, or :root',
|
|
10
|
+
'mixed-group': 'grouped list with an ineligible member (.a, div)',
|
|
11
|
+
'functional-pseudo': 'functional pseudo (.a:not(.b))',
|
|
12
|
+
'chained-pseudo': 'more than one trailing pseudo (.a:hover:focus)',
|
|
13
|
+
'shorthand-conflict': 'shorthand plus an overlapping longhand',
|
|
14
|
+
'skip-comment': '/* atomic: skip */ on the rule',
|
|
15
|
+
};
|
|
16
|
+
export function summarizeAtomization(files, scan, registryCss) {
|
|
17
|
+
let bytesIn = 0;
|
|
18
|
+
for (const file of files) {
|
|
19
|
+
bytesIn += Buffer.byteLength(file.code, 'utf8');
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
files: files.length,
|
|
23
|
+
atoms: scan.atoms.size,
|
|
24
|
+
skippedRules: scan.skips.length,
|
|
25
|
+
bytesIn,
|
|
26
|
+
registryBytes: Buffer.byteLength(registryCss, 'utf8'),
|
|
27
|
+
skips: scan.skips,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function plural(count, singular, pluralForm) {
|
|
31
|
+
return `${count} ${count === 1 ? singular : pluralForm}`;
|
|
32
|
+
}
|
|
33
|
+
function skipBuckets(skips) {
|
|
34
|
+
if (skips.length === 0)
|
|
35
|
+
return '';
|
|
36
|
+
const counts = new Map();
|
|
37
|
+
for (const skip of skips) {
|
|
38
|
+
counts.set(skip.reason, (counts.get(skip.reason) ?? 0) + 1);
|
|
39
|
+
}
|
|
40
|
+
const parts = SKIP_REASONS.filter((reason) => counts.has(reason)).map((reason) => `${counts.get(reason)} ${reason}`);
|
|
41
|
+
return ` (${parts.join(', ')})`;
|
|
42
|
+
}
|
|
43
|
+
function skipLegend(skips) {
|
|
44
|
+
if (skips.length === 0)
|
|
45
|
+
return '';
|
|
46
|
+
const seen = new Set(skips.map((skip) => skip.reason));
|
|
47
|
+
return SKIP_REASONS.filter((reason) => seen.has(reason))
|
|
48
|
+
.map((reason) => ` ${reason}: ${SKIP_REASON_LEGEND[reason]}`)
|
|
49
|
+
.join('\n');
|
|
50
|
+
}
|
|
51
|
+
export function formatAtomizationReport(report, options = {}) {
|
|
52
|
+
const summary = `atomic-css-modules: ${plural(report.atoms, 'atom', 'atoms')}, ${plural(report.skippedRules, 'skipped rule', 'skipped rules')}${skipBuckets(report.skips)}, ${report.bytesIn}B in → ${report.registryBytes}B registry`;
|
|
53
|
+
const parts = [summary];
|
|
54
|
+
if (options.verbose) {
|
|
55
|
+
for (const skip of report.skips) {
|
|
56
|
+
const filePath = options.root
|
|
57
|
+
? path.relative(options.root, skip.filePath)
|
|
58
|
+
: skip.filePath;
|
|
59
|
+
parts.push(` ${filePath} ${skip.selector} ${skip.reason}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const legend = skipLegend(report.skips);
|
|
63
|
+
if (legend)
|
|
64
|
+
parts.push(legend);
|
|
65
|
+
return parts.join('\n');
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { type Atom, type ProcessOptions, type RewrittenFile, type ScanFileResult, type SourceFile } from './types.js';
|
|
2
|
+
export declare function rewriteFiles(files: readonly SourceFile[], scanFiles: readonly ScanFileResult[], options: ProcessOptions, atoms: Map<string, Atom>): RewrittenFile[];
|