@knighted/css 1.0.0-rc.6 → 1.0.0-rc.8
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/bin/generate-types.js +31 -0
- package/dist/cjs/css.cjs +54 -6
- package/dist/cjs/generateTypes.cjs +529 -0
- package/dist/cjs/generateTypes.d.cts +54 -0
- package/dist/cjs/loader.cjs +51 -27
- package/dist/cjs/loader.d.cts +1 -0
- package/dist/cjs/loaderInternals.cjs +38 -1
- package/dist/cjs/loaderInternals.d.cts +7 -0
- package/dist/cjs/stableNamespace.cjs +12 -0
- package/dist/cjs/stableNamespace.d.cts +3 -0
- package/dist/cjs/stableSelectorsLiteral.cjs +104 -0
- package/dist/cjs/stableSelectorsLiteral.d.cts +19 -0
- package/dist/css.js +54 -6
- package/dist/generateTypes.d.ts +54 -0
- package/dist/generateTypes.js +521 -0
- package/dist/loader.d.ts +1 -0
- package/dist/loader.js +50 -26
- package/dist/loaderInternals.d.ts +7 -0
- package/dist/loaderInternals.js +33 -0
- package/dist/stableNamespace.d.ts +3 -0
- package/dist/stableNamespace.js +8 -0
- package/dist/stableSelectorsLiteral.d.ts +19 -0
- package/dist/stableSelectorsLiteral.js +98 -0
- package/loader-queries.d.ts +34 -2
- package/package.json +19 -5
- package/types-stub/index.d.ts +5 -0
- package/types.d.ts +1 -0
package/dist/loaderInternals.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export const COMBINED_QUERY_FLAG = 'combined';
|
|
2
|
+
export const TYPES_QUERY_FLAG = 'types';
|
|
2
3
|
export const NAMED_ONLY_QUERY_FLAGS = ['named-only', 'no-default'];
|
|
3
4
|
export function splitQuery(query) {
|
|
4
5
|
const trimmed = query.startsWith('?') ? query.slice(1) : query;
|
|
@@ -25,6 +26,9 @@ export function buildSanitizedQuery(query) {
|
|
|
25
26
|
if (isQueryFlag(part, 'knighted-css')) {
|
|
26
27
|
return false;
|
|
27
28
|
}
|
|
29
|
+
if (isQueryFlag(part, TYPES_QUERY_FLAG)) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
28
32
|
if (NAMED_ONLY_QUERY_FLAGS.some(flag => isQueryFlag(part, flag))) {
|
|
29
33
|
return false;
|
|
30
34
|
}
|
|
@@ -32,6 +36,22 @@ export function buildSanitizedQuery(query) {
|
|
|
32
36
|
});
|
|
33
37
|
return entries.length > 0 ? `?${entries.join('&')}` : '';
|
|
34
38
|
}
|
|
39
|
+
export function hasQueryFlag(query, flag) {
|
|
40
|
+
if (!query)
|
|
41
|
+
return false;
|
|
42
|
+
const entries = splitQuery(query);
|
|
43
|
+
if (entries.length === 0)
|
|
44
|
+
return false;
|
|
45
|
+
return entries.some(part => isQueryFlag(part, flag));
|
|
46
|
+
}
|
|
47
|
+
function safeDecode(value) {
|
|
48
|
+
try {
|
|
49
|
+
return decodeURIComponent(value);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return value;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
35
55
|
export function shouldForwardDefaultExport(request) {
|
|
36
56
|
const [pathPart] = request.split('?');
|
|
37
57
|
if (!pathPart)
|
|
@@ -42,6 +62,18 @@ export function shouldForwardDefaultExport(request) {
|
|
|
42
62
|
}
|
|
43
63
|
return true;
|
|
44
64
|
}
|
|
65
|
+
export function hasCombinedQuery(query) {
|
|
66
|
+
return hasQueryFlag(query, COMBINED_QUERY_FLAG);
|
|
67
|
+
}
|
|
68
|
+
export function hasNamedOnlyQueryFlag(query) {
|
|
69
|
+
return NAMED_ONLY_QUERY_FLAGS.some(flag => hasQueryFlag(query, flag));
|
|
70
|
+
}
|
|
71
|
+
export function determineSelectorVariant(query) {
|
|
72
|
+
if (hasCombinedQuery(query)) {
|
|
73
|
+
return hasNamedOnlyQueryFlag(query) ? 'combinedWithoutDefault' : 'combined';
|
|
74
|
+
}
|
|
75
|
+
return 'types';
|
|
76
|
+
}
|
|
45
77
|
export function shouldEmitCombinedDefault(options) {
|
|
46
78
|
if (options.skipSyntheticDefault) {
|
|
47
79
|
return false;
|
|
@@ -60,4 +92,5 @@ export function shouldEmitCombinedDefault(options) {
|
|
|
60
92
|
export const __loaderInternals = {
|
|
61
93
|
buildSanitizedQuery,
|
|
62
94
|
shouldEmitCombinedDefault,
|
|
95
|
+
determineSelectorVariant,
|
|
63
96
|
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface StableSelectorsLiteralResult {
|
|
2
|
+
literal: string;
|
|
3
|
+
selectorMap: Map<string, string>;
|
|
4
|
+
}
|
|
5
|
+
export declare function buildStableSelectorsLiteral(options: {
|
|
6
|
+
css: string;
|
|
7
|
+
namespace: string;
|
|
8
|
+
resourcePath: string;
|
|
9
|
+
emitWarning: (message: string) => void;
|
|
10
|
+
}): StableSelectorsLiteralResult;
|
|
11
|
+
export declare function collectStableSelectors(css: string, namespace: string, filename?: string): Map<string, string>;
|
|
12
|
+
declare function collectStableSelectorsByRegex(css: string, namespace: string): Map<string, string>;
|
|
13
|
+
export declare function formatStableSelectorMap(map: Map<string, string>): string;
|
|
14
|
+
export declare const __stableSelectorsLiteralInternals: {
|
|
15
|
+
collectStableSelectors: typeof collectStableSelectors;
|
|
16
|
+
collectStableSelectorsByRegex: typeof collectStableSelectorsByRegex;
|
|
17
|
+
formatStableSelectorMap: typeof formatStableSelectorMap;
|
|
18
|
+
};
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { transform as lightningTransform } from 'lightningcss';
|
|
2
|
+
import { escapeRegex, serializeSelector } from './helpers.js';
|
|
3
|
+
export function buildStableSelectorsLiteral(options) {
|
|
4
|
+
const trimmedNamespace = options.namespace.trim();
|
|
5
|
+
if (!trimmedNamespace) {
|
|
6
|
+
options.emitWarning(`stableSelectors requested for ${options.resourcePath} but "stableNamespace" resolved to an empty value.`);
|
|
7
|
+
return {
|
|
8
|
+
literal: 'export const stableSelectors = {} as const;\n',
|
|
9
|
+
selectorMap: new Map(),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
const selectorMap = collectStableSelectors(options.css, trimmedNamespace, options.resourcePath);
|
|
13
|
+
if (selectorMap.size === 0) {
|
|
14
|
+
options.emitWarning(`stableSelectors requested for ${options.resourcePath} but no selectors matched namespace "${trimmedNamespace}".`);
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
literal: `export const stableSelectors = ${formatStableSelectorMap(selectorMap)} as const;\n`,
|
|
18
|
+
selectorMap,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export function collectStableSelectors(css, namespace, filename) {
|
|
22
|
+
if (!namespace)
|
|
23
|
+
return new Map();
|
|
24
|
+
const astResult = collectStableSelectorsFromAst(css, namespace, filename);
|
|
25
|
+
if (astResult) {
|
|
26
|
+
return astResult;
|
|
27
|
+
}
|
|
28
|
+
return collectStableSelectorsByRegex(css, namespace);
|
|
29
|
+
}
|
|
30
|
+
function collectStableSelectorsFromAst(css, namespace, filename) {
|
|
31
|
+
try {
|
|
32
|
+
const tokens = new Map();
|
|
33
|
+
const escaped = escapeRegex(namespace);
|
|
34
|
+
const pattern = new RegExp(`\\.${escaped}-([A-Za-z0-9_-]+)`, 'g');
|
|
35
|
+
lightningTransform({
|
|
36
|
+
filename: filename ?? 'knighted-types-probe.css',
|
|
37
|
+
code: Buffer.from(css),
|
|
38
|
+
minify: false,
|
|
39
|
+
visitor: {
|
|
40
|
+
Rule: {
|
|
41
|
+
style(rule) {
|
|
42
|
+
const target = Array.isArray(rule?.selectors)
|
|
43
|
+
? rule
|
|
44
|
+
: rule?.value && Array.isArray(rule.value.selectors)
|
|
45
|
+
? rule.value
|
|
46
|
+
: undefined;
|
|
47
|
+
if (!target)
|
|
48
|
+
return rule;
|
|
49
|
+
for (const selector of target.selectors) {
|
|
50
|
+
const selectorStr = serializeSelector(selector);
|
|
51
|
+
pattern.lastIndex = 0;
|
|
52
|
+
let match;
|
|
53
|
+
while ((match = pattern.exec(selectorStr)) !== null) {
|
|
54
|
+
const token = match[1];
|
|
55
|
+
if (!token)
|
|
56
|
+
continue;
|
|
57
|
+
tokens.set(token, `${namespace}-${token}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return rule;
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
return tokens;
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function collectStableSelectorsByRegex(css, namespace) {
|
|
72
|
+
const escaped = escapeRegex(namespace);
|
|
73
|
+
const pattern = new RegExp(`\\.${escaped}-([A-Za-z0-9_-]+)`, 'g');
|
|
74
|
+
const tokens = new Map();
|
|
75
|
+
let match;
|
|
76
|
+
while ((match = pattern.exec(css)) !== null) {
|
|
77
|
+
const token = match[1];
|
|
78
|
+
if (!token)
|
|
79
|
+
continue;
|
|
80
|
+
tokens.set(token, `${namespace}-${token}`);
|
|
81
|
+
}
|
|
82
|
+
return tokens;
|
|
83
|
+
}
|
|
84
|
+
export function formatStableSelectorMap(map) {
|
|
85
|
+
if (map.size === 0) {
|
|
86
|
+
return 'Object.freeze({})';
|
|
87
|
+
}
|
|
88
|
+
const entries = Array.from(map.entries()).sort(([a], [b]) => a.localeCompare(b));
|
|
89
|
+
const lines = entries.map(([token, selector]) => {
|
|
90
|
+
return ` ${JSON.stringify(token)}: ${JSON.stringify(selector)}`;
|
|
91
|
+
});
|
|
92
|
+
return `Object.freeze({\n${lines.join(',\n')}\n})`;
|
|
93
|
+
}
|
|
94
|
+
export const __stableSelectorsLiteralInternals = {
|
|
95
|
+
collectStableSelectors,
|
|
96
|
+
collectStableSelectorsByRegex,
|
|
97
|
+
formatStableSelectorMap,
|
|
98
|
+
};
|
package/loader-queries.d.ts
CHANGED
|
@@ -6,6 +6,13 @@ declare module '*?knighted-css' {
|
|
|
6
6
|
export const knightedCss: string
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
+
type KnightedCssStableSelectorMap = Readonly<Record<string, string>>
|
|
10
|
+
|
|
11
|
+
declare module '*?knighted-css&types' {
|
|
12
|
+
export const knightedCss: string
|
|
13
|
+
export const stableSelectors: KnightedCssStableSelectorMap
|
|
14
|
+
}
|
|
15
|
+
|
|
9
16
|
/**
|
|
10
17
|
* Ambient declaration for combined loader imports (e.g. "./file.tsx?knighted-css&combined").
|
|
11
18
|
* These modules behave like the original module with an additional `knightedCss` export.
|
|
@@ -20,10 +27,35 @@ declare module '*?knighted-css&combined' {
|
|
|
20
27
|
export const knightedCss: string
|
|
21
28
|
}
|
|
22
29
|
|
|
23
|
-
declare module '*?knighted-css&combined&named-only
|
|
30
|
+
declare module '*?knighted-css&combined&named-only' {
|
|
31
|
+
const combined: KnightedCssCombinedModule<Record<string, unknown>>
|
|
32
|
+
export default combined
|
|
33
|
+
export const knightedCss: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
declare module '*?knighted-css&combined&no-default' {
|
|
37
|
+
const combined: KnightedCssCombinedModule<Record<string, unknown>>
|
|
38
|
+
export default combined
|
|
24
39
|
export const knightedCss: string
|
|
25
40
|
}
|
|
26
41
|
|
|
27
|
-
declare module '*?knighted-css&combined&
|
|
42
|
+
declare module '*?knighted-css&combined&types' {
|
|
43
|
+
const combined: KnightedCssCombinedModule<Record<string, unknown>>
|
|
44
|
+
export default combined
|
|
45
|
+
export const knightedCss: string
|
|
46
|
+
export const stableSelectors: KnightedCssStableSelectorMap
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
declare module '*?knighted-css&combined&named-only&types' {
|
|
50
|
+
const combined: KnightedCssCombinedModule<Record<string, unknown>>
|
|
51
|
+
export default combined
|
|
52
|
+
export const knightedCss: string
|
|
53
|
+
export const stableSelectors: KnightedCssStableSelectorMap
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
declare module '*?knighted-css&combined&no-default&types' {
|
|
57
|
+
const combined: KnightedCssCombinedModule<Record<string, unknown>>
|
|
58
|
+
export default combined
|
|
28
59
|
export const knightedCss: string
|
|
60
|
+
export const stableSelectors: KnightedCssStableSelectorMap
|
|
29
61
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@knighted/css",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.8",
|
|
4
4
|
"description": "A build-time utility that traverses JavaScript/TypeScript module dependency graphs to extract, compile, and optimize all imported CSS into a single, in-memory string.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/css.js",
|
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
"loader-queries": [
|
|
14
14
|
"./loader-queries.d.ts"
|
|
15
15
|
],
|
|
16
|
+
"generate-types": [
|
|
17
|
+
"./dist/generateTypes.d.ts"
|
|
18
|
+
],
|
|
16
19
|
"*": [
|
|
17
20
|
"./types.d.ts"
|
|
18
21
|
]
|
|
@@ -33,6 +36,11 @@
|
|
|
33
36
|
"types": "./loader-queries.d.ts",
|
|
34
37
|
"default": "./loader-queries.d.ts"
|
|
35
38
|
},
|
|
39
|
+
"./generate-types": {
|
|
40
|
+
"types": "./dist/generateTypes.d.ts",
|
|
41
|
+
"import": "./dist/generateTypes.js",
|
|
42
|
+
"default": "./dist/generateTypes.js"
|
|
43
|
+
},
|
|
36
44
|
"./stableSelectors": {
|
|
37
45
|
"types": "./dist/stableSelectors.d.ts",
|
|
38
46
|
"import": "./dist/stableSelectors.js",
|
|
@@ -58,16 +66,20 @@
|
|
|
58
66
|
"vanilla-extract",
|
|
59
67
|
"lightningcss"
|
|
60
68
|
],
|
|
69
|
+
"bin": {
|
|
70
|
+
"knighted-css-generate-types": "./bin/generate-types.js"
|
|
71
|
+
},
|
|
61
72
|
"scripts": {
|
|
62
|
-
"build": "duel",
|
|
63
|
-
"check-types": "tsc --noEmit",
|
|
73
|
+
"build": "duel && node ./scripts/copy-types-stub.js",
|
|
74
|
+
"check-types": "tsc --noEmit --project tsconfig.json && tsc --noEmit --project tsconfig.tests.json",
|
|
64
75
|
"test": "c8 --reporter=text --reporter=text-summary --reporter=lcov --include \"src/**/*.ts\" tsx --test test/**/*.test.ts",
|
|
65
76
|
"prepack": "npm run build"
|
|
66
77
|
},
|
|
67
78
|
"dependencies": {
|
|
68
79
|
"dependency-tree": "^11.2.0",
|
|
69
80
|
"es-module-lexer": "^2.0.0",
|
|
70
|
-
"lightningcss": "^1.30.2"
|
|
81
|
+
"lightningcss": "^1.30.2",
|
|
82
|
+
"node-module-type": "^1.0.1"
|
|
71
83
|
},
|
|
72
84
|
"overrides": {
|
|
73
85
|
"module-lookup-amd": {
|
|
@@ -94,7 +106,9 @@
|
|
|
94
106
|
"dist",
|
|
95
107
|
"loader-queries.d.ts",
|
|
96
108
|
"types.d.ts",
|
|
97
|
-
"stable"
|
|
109
|
+
"stable",
|
|
110
|
+
"bin",
|
|
111
|
+
"types-stub"
|
|
98
112
|
],
|
|
99
113
|
"author": "KCM <knightedcodemonkey@gmail.com>",
|
|
100
114
|
"license": "MIT",
|
package/types.d.ts
CHANGED