@knighted/css 1.0.0-rc.0 → 1.0.0-rc.10
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 +107 -25
- package/dist/cjs/css.d.cts +10 -6
- package/dist/cjs/generateTypes.cjs +636 -0
- package/dist/cjs/generateTypes.d.cts +104 -0
- package/dist/cjs/loader.cjs +128 -56
- package/dist/cjs/loader.d.cts +5 -0
- package/dist/cjs/loaderInternals.cjs +108 -0
- package/dist/cjs/loaderInternals.d.cts +23 -0
- package/dist/cjs/moduleGraph.cjs +431 -0
- package/dist/cjs/moduleGraph.d.cts +15 -0
- package/dist/cjs/moduleInfo.cjs +62 -0
- package/dist/cjs/moduleInfo.d.cts +10 -0
- package/dist/cjs/sassInternals.cjs +135 -0
- package/dist/cjs/sassInternals.d.cts +25 -0
- package/dist/cjs/stableNamespace.cjs +12 -0
- package/dist/cjs/stableNamespace.d.cts +3 -0
- package/dist/cjs/stableSelectors.cjs +44 -0
- package/dist/cjs/stableSelectors.d.cts +13 -0
- package/dist/cjs/stableSelectorsLiteral.cjs +104 -0
- package/dist/cjs/stableSelectorsLiteral.d.cts +19 -0
- package/dist/cjs/types.cjs +2 -0
- package/dist/cjs/types.d.cts +4 -0
- package/dist/css.d.ts +10 -6
- package/dist/css.js +107 -26
- package/dist/generateTypes.d.ts +104 -0
- package/dist/generateTypes.js +628 -0
- package/dist/loader.d.ts +5 -0
- package/dist/loader.js +127 -55
- package/dist/loaderInternals.d.ts +23 -0
- package/dist/loaderInternals.js +96 -0
- package/dist/moduleGraph.d.ts +15 -0
- package/dist/moduleGraph.js +425 -0
- package/dist/moduleInfo.d.ts +10 -0
- package/dist/moduleInfo.js +55 -0
- package/dist/sassInternals.d.ts +25 -0
- package/dist/sassInternals.js +124 -0
- package/dist/stableNamespace.d.ts +3 -0
- package/dist/stableNamespace.js +8 -0
- package/dist/stableSelectors.d.ts +13 -0
- package/dist/stableSelectors.js +36 -0
- package/dist/stableSelectorsLiteral.d.ts +19 -0
- package/dist/stableSelectorsLiteral.js +98 -0
- package/dist/types.d.ts +4 -0
- package/dist/types.js +1 -0
- package/loader-queries.d.ts +61 -0
- package/package.json +58 -8
- package/stable/_index.scss +57 -0
- package/stable/stable.css +15 -0
- package/types-stub/index.d.ts +5 -0
- package/types.d.ts +4 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const DEFAULT_NAMESPACE = 'knighted';
|
|
2
|
+
const defaultJoin = (values) => values.filter(Boolean).join(' ');
|
|
3
|
+
const normalizeToken = (token) => {
|
|
4
|
+
const sanitized = token
|
|
5
|
+
.trim()
|
|
6
|
+
.replace(/\s+/g, '-')
|
|
7
|
+
.replace(/[^A-Za-z0-9_-]/g, '-')
|
|
8
|
+
.replace(/-+/g, '-')
|
|
9
|
+
.replace(/^-|-$/g, '');
|
|
10
|
+
return sanitized.length ? sanitized : 'stable';
|
|
11
|
+
};
|
|
12
|
+
export function stableToken(token, options) {
|
|
13
|
+
const normalized = normalizeToken(token);
|
|
14
|
+
const namespace = options?.namespace?.trim() ?? DEFAULT_NAMESPACE;
|
|
15
|
+
if (!namespace) {
|
|
16
|
+
return normalized;
|
|
17
|
+
}
|
|
18
|
+
return `${namespace}-${normalized}`;
|
|
19
|
+
}
|
|
20
|
+
export function stableClass(token, options) {
|
|
21
|
+
return stableToken(token, options);
|
|
22
|
+
}
|
|
23
|
+
export function stableSelector(token, options) {
|
|
24
|
+
return `.${stableToken(token, options)}`;
|
|
25
|
+
}
|
|
26
|
+
export function createStableClassFactory(options) {
|
|
27
|
+
return (token) => stableClass(token, options);
|
|
28
|
+
}
|
|
29
|
+
export function stableClassName(styles, key, options) {
|
|
30
|
+
const hashed = styles[key] ?? '';
|
|
31
|
+
const token = options?.token ?? String(key);
|
|
32
|
+
const stable = stableClass(token, options);
|
|
33
|
+
const join = options?.join ?? defaultJoin;
|
|
34
|
+
return join([hashed, stable]);
|
|
35
|
+
}
|
|
36
|
+
export const stableClassFromModule = stableClassName;
|
|
@@ -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/dist/types.d.ts
ADDED
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ambient declaration for loader query imports like "./file.js?knighted-css".
|
|
3
|
+
* The loader appends a named export `knightedCss` containing the compiled CSS.
|
|
4
|
+
*/
|
|
5
|
+
declare module '*?knighted-css' {
|
|
6
|
+
export const knightedCss: string
|
|
7
|
+
}
|
|
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
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Ambient declaration for combined loader imports (e.g. "./file.tsx?knighted-css&combined").
|
|
18
|
+
* These modules behave like the original module with an additional `knightedCss` export.
|
|
19
|
+
* TypeScript cannot infer the underlying module automatically, so consumers can
|
|
20
|
+
* import the default export and narrow it with `KnightedCssCombinedModule<typeof import('./file')>`.
|
|
21
|
+
*/
|
|
22
|
+
type KnightedCssCombinedModule<TModule> = TModule & { knightedCss: string }
|
|
23
|
+
|
|
24
|
+
declare module '*?knighted-css&combined' {
|
|
25
|
+
const combined: KnightedCssCombinedModule<Record<string, unknown>>
|
|
26
|
+
export default combined
|
|
27
|
+
export const knightedCss: string
|
|
28
|
+
}
|
|
29
|
+
|
|
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
|
|
39
|
+
export const knightedCss: string
|
|
40
|
+
}
|
|
41
|
+
|
|
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
|
|
59
|
+
export const knightedCss: string
|
|
60
|
+
export const stableSelectors: KnightedCssStableSelectorMap
|
|
61
|
+
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@knighted/css",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.10",
|
|
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",
|
|
7
|
-
"types": "./
|
|
7
|
+
"types": "./types.d.ts",
|
|
8
|
+
"typesVersions": {
|
|
9
|
+
"*": {
|
|
10
|
+
"loader": [
|
|
11
|
+
"./dist/loader.d.ts"
|
|
12
|
+
],
|
|
13
|
+
"loader-queries": [
|
|
14
|
+
"./loader-queries.d.ts"
|
|
15
|
+
],
|
|
16
|
+
"generate-types": [
|
|
17
|
+
"./dist/generateTypes.d.ts"
|
|
18
|
+
],
|
|
19
|
+
"*": [
|
|
20
|
+
"./types.d.ts"
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
},
|
|
8
24
|
"exports": {
|
|
9
25
|
".": {
|
|
10
|
-
"types": "./
|
|
26
|
+
"types": "./types.d.ts",
|
|
11
27
|
"import": "./dist/css.js",
|
|
12
28
|
"require": "./dist/cjs/css.cjs"
|
|
13
29
|
},
|
|
@@ -15,6 +31,27 @@
|
|
|
15
31
|
"types": "./dist/loader.d.ts",
|
|
16
32
|
"import": "./dist/loader.js",
|
|
17
33
|
"require": "./dist/cjs/loader.cjs"
|
|
34
|
+
},
|
|
35
|
+
"./loader-queries": {
|
|
36
|
+
"types": "./loader-queries.d.ts",
|
|
37
|
+
"default": "./loader-queries.d.ts"
|
|
38
|
+
},
|
|
39
|
+
"./generate-types": {
|
|
40
|
+
"types": "./dist/generateTypes.d.ts",
|
|
41
|
+
"import": "./dist/generateTypes.js",
|
|
42
|
+
"default": "./dist/generateTypes.js"
|
|
43
|
+
},
|
|
44
|
+
"./stableSelectors": {
|
|
45
|
+
"types": "./dist/stableSelectors.d.ts",
|
|
46
|
+
"import": "./dist/stableSelectors.js",
|
|
47
|
+
"require": "./dist/cjs/stableSelectors.cjs"
|
|
48
|
+
},
|
|
49
|
+
"./stable": {
|
|
50
|
+
"sass": "./stable/_index.scss",
|
|
51
|
+
"default": "./stable/_index.scss"
|
|
52
|
+
},
|
|
53
|
+
"./stable/stable.css": {
|
|
54
|
+
"default": "./stable/stable.css"
|
|
18
55
|
}
|
|
19
56
|
},
|
|
20
57
|
"keywords": [
|
|
@@ -29,15 +66,23 @@
|
|
|
29
66
|
"vanilla-extract",
|
|
30
67
|
"lightningcss"
|
|
31
68
|
],
|
|
69
|
+
"bin": {
|
|
70
|
+
"knighted-css-generate-types": "./bin/generate-types.js"
|
|
71
|
+
},
|
|
32
72
|
"scripts": {
|
|
33
|
-
"build": "duel",
|
|
34
|
-
"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",
|
|
35
75
|
"test": "c8 --reporter=text --reporter=text-summary --reporter=lcov --include \"src/**/*.ts\" tsx --test test/**/*.test.ts",
|
|
36
76
|
"prepack": "npm run build"
|
|
37
77
|
},
|
|
38
78
|
"dependencies": {
|
|
39
|
-
"
|
|
40
|
-
"lightningcss": "^1.30.2"
|
|
79
|
+
"es-module-lexer": "^2.0.0",
|
|
80
|
+
"lightningcss": "^1.30.2",
|
|
81
|
+
"node-module-type": "^1.0.1",
|
|
82
|
+
"get-tsconfig": "^4.13.0",
|
|
83
|
+
"oxc-parser": "^0.104.0",
|
|
84
|
+
"oxc-resolver": "^11.16.0",
|
|
85
|
+
"tsconfig-paths": "^4.2.0"
|
|
41
86
|
},
|
|
42
87
|
"peerDependencies": {
|
|
43
88
|
"@vanilla-extract/integration": "^8.0.0",
|
|
@@ -56,7 +101,12 @@
|
|
|
56
101
|
}
|
|
57
102
|
},
|
|
58
103
|
"files": [
|
|
59
|
-
"dist"
|
|
104
|
+
"dist",
|
|
105
|
+
"loader-queries.d.ts",
|
|
106
|
+
"types.d.ts",
|
|
107
|
+
"stable",
|
|
108
|
+
"bin",
|
|
109
|
+
"types-stub"
|
|
60
110
|
],
|
|
61
111
|
"author": "KCM <knightedcodemonkey@gmail.com>",
|
|
62
112
|
"license": "MIT",
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// Knighted stable selector mixins
|
|
2
|
+
// Usage: @use '@knighted/css/stable' as knighted;
|
|
3
|
+
// .button { @include knighted.stable('button') { ... } }
|
|
4
|
+
|
|
5
|
+
@use 'sass:meta';
|
|
6
|
+
|
|
7
|
+
$knighted-stable-namespace: 'knighted' !default;
|
|
8
|
+
|
|
9
|
+
@function _knighted-normalize-token($token) {
|
|
10
|
+
@if meta.type-of($token) == 'number' {
|
|
11
|
+
@return $token;
|
|
12
|
+
}
|
|
13
|
+
@return $token;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@function stable-token($token, $namespace: $knighted-stable-namespace) {
|
|
17
|
+
$normalized-token: _knighted-normalize-token($token);
|
|
18
|
+
@if $namespace == '' {
|
|
19
|
+
@return $normalized-token;
|
|
20
|
+
}
|
|
21
|
+
@return '#{$namespace}-#{$normalized-token}';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@function stable-class($token, $namespace: $knighted-stable-namespace) {
|
|
25
|
+
$token-value: stable-token($token, $namespace);
|
|
26
|
+
@return '.#{$token-value}';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@mixin stable($token, $namespace: $knighted-stable-namespace) {
|
|
30
|
+
@if not & {
|
|
31
|
+
@error 'The knighted.stable mixin must be used within a selector context so that "&" is defined.';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
$stable-selector: stable-class($token, $namespace);
|
|
35
|
+
@at-root #{&},
|
|
36
|
+
#{$stable-selector} {
|
|
37
|
+
@content;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@mixin stable-at-root($selector, $token, $namespace: $knighted-stable-namespace) {
|
|
42
|
+
$stable-selector: stable-class($token, $namespace);
|
|
43
|
+
@at-root #{$selector},
|
|
44
|
+
#{$stable-selector} {
|
|
45
|
+
@content;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@function stable-class-name($token, $namespace: $knighted-stable-namespace) {
|
|
50
|
+
@return stable-token($token, $namespace);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@mixin stable-only($token, $namespace: $knighted-stable-namespace) {
|
|
54
|
+
@at-root #{stable-class($token, $namespace)} {
|
|
55
|
+
@content;
|
|
56
|
+
}
|
|
57
|
+
}
|
package/types.d.ts
ADDED