tungsten 0.2.16 → 0.2.18
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/_client/cjsHelpers.sxyt.js +8 -6
- package/dist/babelPlugins/BabelTransformPackageImports.d.ts.map +1 -1
- package/dist/babelPlugins/BabelTransformPackageImports.js +18 -9
- package/dist/babelPlugins/BabelTransformRemoveDevBlocks.d.ts +9 -0
- package/dist/babelPlugins/BabelTransformRemoveDevBlocks.d.ts.map +1 -0
- package/dist/babelPlugins/BabelTransformRemoveDevBlocks.js +38 -0
- package/dist/bin/commands/compile.sxyt.js +65 -0
- package/dist/build/rollup.user.prod.config.d.ts.map +1 -1
- package/dist/build/rollup.user.prod.config.js +2 -1
- package/dist/style/styleContentSxy.d.ts.map +1 -1
- package/dist/style/styleContentSxy.js +10 -5
- package/dist/style/unusedStyles.d.ts +11 -0
- package/dist/style/unusedStyles.d.ts.map +1 -0
- package/dist/style/unusedStyles.js +43 -0
- package/package.json +1 -1
|
@@ -22,13 +22,15 @@ describe('_client/cjsHelpers loadDeps()', ({
|
|
|
22
22
|
it(`loads a dependency cycle instead of hanging`, async () => {
|
|
23
23
|
const dir = await mkdtemp(join(tmpdir(), 'tungsten-load-deps-'));
|
|
24
24
|
try {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const
|
|
25
|
+
// .mjs so that node does not have to guess the module type of a file in a
|
|
26
|
+
// temp dir with no package.json
|
|
27
|
+
const a = pathToFileURL(join(dir, 'a.mjs')).href;
|
|
28
|
+
const b = pathToFileURL(join(dir, 'b.mjs')).href;
|
|
29
|
+
const c = pathToFileURL(join(dir, 'c.mjs')).href;
|
|
28
30
|
// a <-> b is circular, and both reach c
|
|
29
|
-
await writeFile(join(dir, 'a.
|
|
30
|
-
await writeFile(join(dir, 'b.
|
|
31
|
-
await writeFile(join(dir, 'c.
|
|
31
|
+
await writeFile(join(dir, 'a.mjs'), moduleSource([b, c]));
|
|
32
|
+
await writeFile(join(dir, 'b.mjs'), moduleSource([a, c]));
|
|
33
|
+
await writeFile(join(dir, 'c.mjs'), moduleSource([]));
|
|
32
34
|
const timeout = new Promise(resolve => setTimeout(() => resolve('timed out'), 5000).unref());
|
|
33
35
|
const loaded = await Promise.race([loadDeps([a]), timeout]);
|
|
34
36
|
expect(loaded).not.to.equal('timed out');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BabelTransformPackageImports.d.ts","sourceRoot":"","sources":["../../src/babelPlugins/BabelTransformPackageImports.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"BabelTransformPackageImports.d.ts","sourceRoot":"","sources":["../../src/babelPlugins/BabelTransformPackageImports.ts"],"names":[],"mappings":"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"}
|
|
@@ -93,7 +93,11 @@ export function MakeBabelTransformPackageImports(opts) {
|
|
|
93
93
|
try {
|
|
94
94
|
const packageName = location.startsWith('@') ? location.split('/').slice(0, 2).join('/') : location.split('/')[0];
|
|
95
95
|
const resolutionPaths = packageName === 'react' || packageName === 'react-dom' ? [opts.projectDir, sourcePackageDir] : [sourcePackageDir];
|
|
96
|
-
|
|
96
|
+
// an import site resolves with the 'import' condition, a require()
|
|
97
|
+
// site with 'require' - see resolvePrecinctDependencies()
|
|
98
|
+
fullLocation = fileType === 'esm' ? resolveBareImport(location, resolutionPaths) ?? require.resolve(location, {
|
|
99
|
+
paths: resolutionPaths
|
|
100
|
+
}) : require.resolve(location, {
|
|
97
101
|
paths: resolutionPaths
|
|
98
102
|
});
|
|
99
103
|
} catch (e) {
|
|
@@ -172,21 +176,24 @@ export function MakeBabelTransformPackageImports(opts) {
|
|
|
172
176
|
history.push(`${error.dependency} (unresolved)`);
|
|
173
177
|
return 'Your code that is compiled may depend on a node module - this is not allowed.' + `\nCould not resolve "${error.dependency}".` + `\nImport history:\n ${history.join('\n -> ')}`;
|
|
174
178
|
}
|
|
175
|
-
function resolvePrecinctDependencies(deps, file, sourceFilename, history) {
|
|
179
|
+
function resolvePrecinctDependencies(deps, file, fileType, sourceFilename, history) {
|
|
180
|
+
// Only a file that will be served as ESM may resolve with the 'import' condition.
|
|
181
|
+
// A converted CJS file's require() shim looks its dependencies up by the location
|
|
182
|
+
// recorded here, and the CJS transform resolves the same specifier with the
|
|
183
|
+
// 'require' condition - resolving the two differently loses the file.
|
|
184
|
+
const esmSource = fileType === 'esm';
|
|
176
185
|
const out = [];
|
|
177
186
|
for (const dep of deps) {
|
|
178
187
|
if (dep.startsWith('node:')) continue;
|
|
179
188
|
try {
|
|
180
189
|
const packageName = dep.startsWith('@') ? dep.split('/').slice(0, 2).join('/') : dep.split('/')[0];
|
|
181
190
|
if (packageName === 'react' || packageName === 'react-dom') {
|
|
182
|
-
out.push(resolveBareImport(dep, [opts.projectDir]) ?? require.resolve(dep, {
|
|
191
|
+
out.push((esmSource ? resolveBareImport(dep, [opts.projectDir]) : undefined) ?? require.resolve(dep, {
|
|
183
192
|
paths: [opts.projectDir]
|
|
184
193
|
}));
|
|
185
194
|
continue;
|
|
186
195
|
}
|
|
187
|
-
|
|
188
|
-
// shipping both builds is taken as ESM rather than through the CJS route
|
|
189
|
-
const f = (isBareImport(dep) ? resolveBareImport(dep, [dirname(file)]) : undefined) ?? getCjsRequire(file).resolve(dep);
|
|
196
|
+
const f = esmSource && isBareImport(dep) ? resolveBareImport(dep, [dirname(file)]) ?? getCjsRequire(file).resolve(dep) : getCjsRequire(file).resolve(dep);
|
|
190
197
|
out.push(f);
|
|
191
198
|
} catch (error) {
|
|
192
199
|
throw new UnsupportedCompiledDependencyError(dep, file, history.length === 0 ? [sourceFilename] : history, {
|
|
@@ -207,7 +214,7 @@ export function MakeBabelTransformPackageImports(opts) {
|
|
|
207
214
|
//console.log('getFileDependencies', 'd', d)
|
|
208
215
|
return isBareImport(d) ? applyImportAliases(d, fileInfo.type) : d;
|
|
209
216
|
});
|
|
210
|
-
const resolved = resolvePrecinctDependencies(deps, file, sourceFilename, history);
|
|
217
|
+
const resolved = resolvePrecinctDependencies(deps, file, fileInfo.type, sourceFilename, history);
|
|
211
218
|
return resolved;
|
|
212
219
|
}
|
|
213
220
|
function getFileEsmGenIntermediateCacheLocation(file, packageInfo) {
|
|
@@ -744,8 +751,10 @@ export function MakeBabelTransformPackageImports(opts) {
|
|
|
744
751
|
//console.log(chalk.orange`We did the hacky jsx runtime alias in BabelTransformPackageImports`)
|
|
745
752
|
location = 'tungsten/jsxRuntime.js';
|
|
746
753
|
}
|
|
747
|
-
// the real file location of the file being imported
|
|
748
|
-
|
|
754
|
+
// the real file location of the file being imported.
|
|
755
|
+
// User code is served as ESM, so it resolves with the 'import'
|
|
756
|
+
// condition - see resolvePrecinctDependencies()
|
|
757
|
+
const importTarget = resolveBareImport(location, [dirname(filename)]) ?? require.resolve(location);
|
|
749
758
|
// Should do some checking here to show helpful errors about bad imports
|
|
750
759
|
if (importTarget === location) {
|
|
751
760
|
//console.log()
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { NodePath } from '@babel/core';
|
|
2
|
+
import type { ConditionalExpression, IfStatement } from '@babel/types';
|
|
3
|
+
export declare function MakeBabelTransformRemoveDevBlocks(): () => {
|
|
4
|
+
visitor: {
|
|
5
|
+
IfStatement(path: NodePath<IfStatement>): void;
|
|
6
|
+
ConditionalExpression(path: NodePath<ConditionalExpression>): void;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=BabelTransformRemoveDevBlocks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BabelTransformRemoveDevBlocks.d.ts","sourceRoot":"","sources":["../../src/babelPlugins/BabelTransformRemoveDevBlocks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,KAAK,EAAE,qBAAqB,EAAc,WAAW,EAAE,MAAM,cAAc,CAAA;AAOlF,wBAAgB,iCAAiC;;0BAef,QAAQ,CAAC,WAAW,CAAC;oCAUX,QAAQ,CAAC,qBAAqB,CAAC;;EAS1E"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Removes dev only branches from the production client bundle.
|
|
2
|
+
// `isDev` is false in production, so `if (isDev) {...}` blocks and `isDev ? a : b`
|
|
3
|
+
// expressions collapse to their alternate (or disappear entirely).
|
|
4
|
+
// This also lets rollup tree shake modules that are only imported by dev branches.
|
|
5
|
+
export function MakeBabelTransformRemoveDevBlocks() {
|
|
6
|
+
return function BabelTransformRemoveDevBlocks(/*babel*/
|
|
7
|
+
) {
|
|
8
|
+
function investigationCondition(test) {
|
|
9
|
+
if (test.type === 'Identifier' && test.name === 'isDev') {
|
|
10
|
+
return true;
|
|
11
|
+
} else if (test.type === 'LogicalExpression' && test.operator === '&&') {
|
|
12
|
+
// false && anything is false
|
|
13
|
+
return investigationCondition(test.left) || investigationCondition(test.right);
|
|
14
|
+
}
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
visitor: {
|
|
19
|
+
IfStatement(path) {
|
|
20
|
+
const test = path.node.test;
|
|
21
|
+
if (investigationCondition(test)) {
|
|
22
|
+
if (path.node.alternate) {
|
|
23
|
+
path.replaceWith(path.node.alternate);
|
|
24
|
+
} else {
|
|
25
|
+
path.remove();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
ConditionalExpression(path) {
|
|
30
|
+
const test = path.node.test;
|
|
31
|
+
if (investigationCondition(test)) {
|
|
32
|
+
path.replaceWith(path.node.alternate);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
}
|
|
@@ -94,6 +94,71 @@ describe('tungsten compile', ({
|
|
|
94
94
|
});
|
|
95
95
|
}
|
|
96
96
|
});
|
|
97
|
+
it('takes the import build of a dual package for an import, and the require build for a require', async () => {
|
|
98
|
+
const projectDir = await mkdtemp(join(tmpdir(), 'tungsten-compile-conditions-test-'));
|
|
99
|
+
const cliLocation = join(findProjectDir(import.meta.url), 'dist', 'bin', 'index.js');
|
|
100
|
+
const sourceDir = join(projectDir, 'src');
|
|
101
|
+
const dualDir = join(projectDir, 'node_modules', 'dual-package');
|
|
102
|
+
const cjsDir = join(projectDir, 'node_modules', 'cjs-package');
|
|
103
|
+
async function copiedToPackages(rel) {
|
|
104
|
+
try {
|
|
105
|
+
await readFile(join(projectDir, '.tungsten/test/.packages', rel), 'utf8');
|
|
106
|
+
return true;
|
|
107
|
+
} catch {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
await mkdir(dualDir, {
|
|
113
|
+
recursive: true
|
|
114
|
+
});
|
|
115
|
+
await mkdir(cjsDir, {
|
|
116
|
+
recursive: true
|
|
117
|
+
});
|
|
118
|
+
await mkdir(sourceDir, {
|
|
119
|
+
recursive: true
|
|
120
|
+
});
|
|
121
|
+
await writeFile(join(projectDir, 'package.json'), '{"type":"module"}');
|
|
122
|
+
await writeFile(join(projectDir, 'tungsten.config.js'), 'export default { codeDir: "src", useRootComponent: false }');
|
|
123
|
+
// ships both builds, as @trpc/server and zod do
|
|
124
|
+
await writeFile(join(dualDir, 'package.json'), JSON.stringify({
|
|
125
|
+
name: 'dual-package',
|
|
126
|
+
version: '1.0.0',
|
|
127
|
+
exports: {
|
|
128
|
+
'.': {
|
|
129
|
+
import: './index.mjs',
|
|
130
|
+
require: './index.cjs'
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}));
|
|
134
|
+
await writeFile(join(dualDir, 'index.mjs'), 'export const dual = "esm"');
|
|
135
|
+
await writeFile(join(dualDir, 'index.cjs'), 'module.exports = { dual: "cjs" }');
|
|
136
|
+
// a CJS package that require()s the dual package
|
|
137
|
+
await writeFile(join(cjsDir, 'package.json'), JSON.stringify({
|
|
138
|
+
name: 'cjs-package',
|
|
139
|
+
version: '1.0.0',
|
|
140
|
+
main: './index.js'
|
|
141
|
+
}));
|
|
142
|
+
await writeFile(join(cjsDir, 'index.js'), 'module.exports = require(\'dual-package\')');
|
|
143
|
+
await writeFile(join(sourceDir, 'entry.js'), 'import { dual } from \'dual-package\'\n' + 'import viaCjs from \'cjs-package\'\n' + 'export { dual, viaCjs }');
|
|
144
|
+
const {
|
|
145
|
+
stdout
|
|
146
|
+
} = await execFileAsync(process.execPath, [cliLocation, 'compile', '--js', '--output', '.tungsten/test', '--quiet'], {
|
|
147
|
+
cwd: projectDir
|
|
148
|
+
});
|
|
149
|
+
expect(stdout).to.contain('Compile complete');
|
|
150
|
+
// the ESM import took ./index.mjs
|
|
151
|
+
expect(await copiedToPackages('dual-package@1.0.0/index.mjs')).to.equal(true);
|
|
152
|
+
// and the require() inside the CJS package took ./index.cjs, so that the
|
|
153
|
+
// converted require() shim can find it in its deps
|
|
154
|
+
expect(await copiedToPackages('dual-package@1.0.0/index.cjs')).to.equal(true);
|
|
155
|
+
} finally {
|
|
156
|
+
await rm(projectDir, {
|
|
157
|
+
recursive: true,
|
|
158
|
+
force: true
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
});
|
|
97
162
|
it('overrides the ignoreDirs and ignorePatterns config entries from the command line', async () => {
|
|
98
163
|
const projectDir = await mkdtemp(join(tmpdir(), 'tungsten-compile-ignore-test-'));
|
|
99
164
|
const cliLocation = join(findProjectDir(import.meta.url), 'dist', 'bin', 'index.js');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rollup.user.prod.config.d.ts","sourceRoot":"","sources":["../../src/build/rollup.user.prod.config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"rollup.user.prod.config.d.ts","sourceRoot":"","sources":["../../src/build/rollup.user.prod.config.ts"],"names":[],"mappings":"AAcA,KAAK,YAAY,GAAG;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CACrB,CAAA;AAeD,QAAA,MAAM,YAAY,EAAE,YAkBnB,CAAA;AAED,eAAe,YAAY,CAAA"}
|
|
@@ -6,6 +6,7 @@ import { terser } from "rollup-plugin-terser";
|
|
|
6
6
|
//import gzip from "rollup-plugin-gzip"
|
|
7
7
|
import jsonModule from "@rollup/plugin-json";
|
|
8
8
|
import { MakeBabelTransformRemoveServerBlocks } from "../babelPlugins/BabelTransformRemoveServerBlocks.js";
|
|
9
|
+
import { MakeBabelTransformRemoveDevBlocks } from "../babelPlugins/BabelTransformRemoveDevBlocks.js";
|
|
9
10
|
const json = typeof jsonModule === "function" ? jsonModule : jsonModule.default;
|
|
10
11
|
function replaceProductionNodeEnv() {
|
|
11
12
|
return {
|
|
@@ -25,7 +26,7 @@ const rollupConfig = {
|
|
|
25
26
|
replaceProductionNodeEnv(), babel({
|
|
26
27
|
babelHelpers: 'bundled',
|
|
27
28
|
exclude: '**/node_modules/**',
|
|
28
|
-
plugins: [MakeBabelTransformRemoveServerBlocks()]
|
|
29
|
+
plugins: [MakeBabelTransformRemoveServerBlocks(), MakeBabelTransformRemoveDevBlocks()]
|
|
29
30
|
}),
|
|
30
31
|
// must be after commonjs
|
|
31
32
|
terser({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"styleContentSxy.d.ts","sourceRoot":"","sources":["../../src/style/styleContentSxy.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,
|
|
1
|
+
{"version":3,"file":"styleContentSxy.d.ts","sourceRoot":"","sources":["../../src/style/styleContentSxy.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,EACH,KAAK,WAAW,EACnB,MAAM,mBAAmB,CAAA;AAa1B,wBAAgB,eAAe,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,eAIrE"}
|
|
@@ -4,15 +4,17 @@ import { warn } from "../output.js";
|
|
|
4
4
|
import { TungstenError } from "../TungstenError.js";
|
|
5
5
|
import { componentBumpClass } from "../componentClassName.js";
|
|
6
6
|
import { $props, $type } from "../contentNodeSymbols.js";
|
|
7
|
+
import { isDev } from "../isDev.js";
|
|
8
|
+
import { getStyleUsage } from "./unusedStyles.js";
|
|
7
9
|
function debug(...texts) {
|
|
8
10
|
//console.log(...texts)
|
|
9
11
|
}
|
|
10
12
|
export function styleContentSxy(content, styles) {
|
|
11
13
|
if (count(styles.tags) === 0 && count(styles.classes) === 0) return content; // optimization short circuit
|
|
12
|
-
processElement(content, styles);
|
|
14
|
+
processElement(content, styles, isDev ? getStyleUsage(styles) : undefined);
|
|
13
15
|
return content;
|
|
14
16
|
}
|
|
15
|
-
function processElement(element, styles) {
|
|
17
|
+
function processElement(element, styles, usage) {
|
|
16
18
|
//console.log('element', element)
|
|
17
19
|
debug('styles', styles);
|
|
18
20
|
//debug(`---- style element ----`)
|
|
@@ -37,14 +39,15 @@ function processElement(element, styles) {
|
|
|
37
39
|
if (Array.isArray(element)) {
|
|
38
40
|
//debug('**** array element ****', element)
|
|
39
41
|
for (const e of element) {
|
|
40
|
-
processElement(e, styles);
|
|
42
|
+
processElement(e, styles, usage);
|
|
41
43
|
}
|
|
42
44
|
return;
|
|
43
45
|
}
|
|
44
46
|
debug('Element must be an element. Type: ', typeof element);
|
|
45
47
|
// element is a ContentNodeElement
|
|
46
48
|
let tagName;
|
|
47
|
-
if (element[$props] !== undefined && element[$props].tagName !== undefined) {
|
|
49
|
+
//if (element[$props] !== undefined && element[$props].tagName !== undefined) {
|
|
50
|
+
if (element[$props].tagName !== undefined) {
|
|
48
51
|
if (typeof element[$props].tagName !== 'string') {
|
|
49
52
|
throw new TungstenError(`styleContentSxy() error: ${ContentNodeElementIsHtml(element) ? element[$type] : getComponentName(element)}` + ` component tagName field should be type string. Received ${typeof element[$props].tagName}`);
|
|
50
53
|
}
|
|
@@ -97,6 +100,7 @@ function processElement(element, styles) {
|
|
|
97
100
|
let newClassName = '';
|
|
98
101
|
if (tagName in styles.tags) {
|
|
99
102
|
newClassName += ' ' + componentBumpClass + ' ' + styles.tags[tagName];
|
|
103
|
+
usage?.usedTags.add(tagName);
|
|
100
104
|
}
|
|
101
105
|
//console.log(element.props.className)
|
|
102
106
|
//if (element.props.className !== undefined) console.log(element.props.className)
|
|
@@ -110,6 +114,7 @@ function processElement(element, styles) {
|
|
|
110
114
|
for (const cn of classNames) {
|
|
111
115
|
if (cn in styles.classes) {
|
|
112
116
|
newClassName += ` ${styles.classes[cn]}`;
|
|
117
|
+
usage?.usedClasses.add(cn);
|
|
113
118
|
}
|
|
114
119
|
}
|
|
115
120
|
}
|
|
@@ -120,7 +125,7 @@ function processElement(element, styles) {
|
|
|
120
125
|
if (element[$props].children !== undefined) {
|
|
121
126
|
//debug(tagName + '^^^^children', element.props.children)
|
|
122
127
|
//element.props.children = element.props.children as ContentNode
|
|
123
|
-
processElement(element[$props].children, styles);
|
|
128
|
+
processElement(element[$props].children, styles, usage);
|
|
124
129
|
}
|
|
125
130
|
//console.log('element after mods', tagName, element)
|
|
126
131
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CssNames } from '../CssNames.js';
|
|
2
|
+
export type StyleUsage = {
|
|
3
|
+
styles: CssNames;
|
|
4
|
+
usedTags: Set<string>;
|
|
5
|
+
usedClasses: Set<string>;
|
|
6
|
+
reportedTags: Set<string>;
|
|
7
|
+
reportedClasses: Set<string>;
|
|
8
|
+
};
|
|
9
|
+
export declare function getStyleUsage(styles: CssNames): StyleUsage;
|
|
10
|
+
export declare function reportUnusedStyles(): void;
|
|
11
|
+
//# sourceMappingURL=unusedStyles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unusedStyles.d.ts","sourceRoot":"","sources":["../../src/style/unusedStyles.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAU9C,MAAM,MAAM,UAAU,GAAG;IACrB,MAAM,EAAE,QAAQ,CAAA;IAChB,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACrB,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACxB,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACzB,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAC/B,CAAA;AAUD,wBAAgB,aAAa,CAAC,MAAM,EAAE,QAAQ,cAc7C;AASD,wBAAgB,kBAAkB,SA0BjC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { warn } from "../output.js";
|
|
2
|
+
// component stylesheets are module level singletons, so holding them here is not a leak
|
|
3
|
+
const usageByStyles = new Map();
|
|
4
|
+
// wait for render activity to settle before reporting, so that content rendered a little
|
|
5
|
+
// later (async components, route changes) doesn't get reported as unused
|
|
6
|
+
const reportDelayMs = 5000;
|
|
7
|
+
let reportHandle;
|
|
8
|
+
export function getStyleUsage(styles) {
|
|
9
|
+
let usage = usageByStyles.get(styles);
|
|
10
|
+
if (usage === undefined) {
|
|
11
|
+
usage = {
|
|
12
|
+
styles,
|
|
13
|
+
usedTags: new Set(),
|
|
14
|
+
usedClasses: new Set(),
|
|
15
|
+
reportedTags: new Set(),
|
|
16
|
+
reportedClasses: new Set()
|
|
17
|
+
};
|
|
18
|
+
usageByStyles.set(styles, usage);
|
|
19
|
+
}
|
|
20
|
+
scheduleUnusedStylesReport();
|
|
21
|
+
return usage;
|
|
22
|
+
}
|
|
23
|
+
function scheduleUnusedStylesReport() {
|
|
24
|
+
if (reportHandle !== undefined) clearTimeout(reportHandle);
|
|
25
|
+
reportHandle = setTimeout(reportUnusedStyles, reportDelayMs);
|
|
26
|
+
// don't hold a node process open just for the report
|
|
27
|
+
if (typeof reportHandle === 'object' && typeof reportHandle.unref === 'function') reportHandle.unref();
|
|
28
|
+
}
|
|
29
|
+
export function reportUnusedStyles() {
|
|
30
|
+
if (reportHandle !== undefined) {
|
|
31
|
+
clearTimeout(reportHandle);
|
|
32
|
+
reportHandle = undefined;
|
|
33
|
+
}
|
|
34
|
+
for (const usage of usageByStyles.values()) {
|
|
35
|
+
const tags = Object.keys(usage.styles.tags).filter(tag => !usage.usedTags.has(tag) && !usage.reportedTags.has(tag));
|
|
36
|
+
const classes = Object.keys(usage.styles.classes).filter(className => !usage.usedClasses.has(className) && !usage.reportedClasses.has(className));
|
|
37
|
+
if (tags.length === 0 && classes.length === 0) continue;
|
|
38
|
+
// only report each selector once, otherwise every later render repeats the warning
|
|
39
|
+
for (const tag of tags) usage.reportedTags.add(tag);
|
|
40
|
+
for (const className of classes) usage.reportedClasses.add(className);
|
|
41
|
+
warn(`Tungsten dev: styles in module "${usage.styles.moduleName}" have not matched any content:` + (tags.length > 0 ? `\n tag/component names: ${tags.join(', ')}` : '') + (classes.length > 0 ? `\n class names: ${classes.join(', ')}` : ''));
|
|
42
|
+
}
|
|
43
|
+
}
|