@knighted/css 1.0.0-rc.1 → 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 +100 -22
- package/dist/cjs/css.d.cts +5 -6
- package/dist/cjs/generateTypes.cjs +636 -0
- package/dist/cjs/generateTypes.d.cts +104 -0
- package/dist/cjs/loader.cjs +65 -55
- package/dist/cjs/loader.d.cts +1 -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 +5 -6
- package/dist/css.js +101 -23
- package/dist/generateTypes.d.ts +104 -0
- package/dist/generateTypes.js +628 -0
- package/dist/loader.d.ts +1 -0
- package/dist/loader.js +63 -53
- 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
package/dist/loader.js
CHANGED
|
@@ -1,10 +1,25 @@
|
|
|
1
1
|
import { cssWithMeta, compileVanillaModule } from './css.js';
|
|
2
|
+
import { detectModuleDefaultExport } from './moduleInfo.js';
|
|
3
|
+
import { buildSanitizedQuery, hasCombinedQuery, hasNamedOnlyQueryFlag, hasQueryFlag, shouldEmitCombinedDefault, shouldForwardDefaultExport, TYPES_QUERY_FLAG, } from './loaderInternals.js';
|
|
4
|
+
import { buildStableSelectorsLiteral } from './stableSelectorsLiteral.js';
|
|
5
|
+
import { resolveStableNamespace } from './stableNamespace.js';
|
|
2
6
|
const DEFAULT_EXPORT_NAME = 'knightedCss';
|
|
3
|
-
const COMBINED_QUERY_FLAG = 'combined';
|
|
4
7
|
const loader = async function loader(source) {
|
|
5
|
-
const { cssOptions, vanillaOptions } = resolveLoaderOptions(this);
|
|
8
|
+
const { cssOptions, vanillaOptions, stableNamespace: optionNamespace, } = resolveLoaderOptions(this);
|
|
9
|
+
const resolvedNamespace = resolveStableNamespace(optionNamespace);
|
|
10
|
+
const typesRequested = hasQueryFlag(this.resourceQuery, TYPES_QUERY_FLAG);
|
|
6
11
|
const css = await extractCss(this, cssOptions);
|
|
7
|
-
const
|
|
12
|
+
const stableSelectorsLiteral = typesRequested
|
|
13
|
+
? buildStableSelectorsLiteral({
|
|
14
|
+
css,
|
|
15
|
+
namespace: resolvedNamespace,
|
|
16
|
+
resourcePath: this.resourcePath,
|
|
17
|
+
emitWarning: message => emitKnightedWarning(this, message),
|
|
18
|
+
})
|
|
19
|
+
: undefined;
|
|
20
|
+
const injection = buildInjection(css, {
|
|
21
|
+
stableSelectorsLiteral: stableSelectorsLiteral?.literal,
|
|
22
|
+
});
|
|
8
23
|
const isStyleModule = this.resourcePath.endsWith('.css.ts');
|
|
9
24
|
if (isStyleModule) {
|
|
10
25
|
const { source: compiledSource } = await compileVanillaModule(this.resourcePath, cssOptions.cwd ?? this.rootContext ?? process.cwd(), cssOptions.peerResolver);
|
|
@@ -43,14 +58,38 @@ export const pitch = function pitch() {
|
|
|
43
58
|
return;
|
|
44
59
|
}
|
|
45
60
|
const request = buildProxyRequest(this);
|
|
46
|
-
const { cssOptions } = resolveLoaderOptions(this);
|
|
47
|
-
|
|
61
|
+
const { cssOptions, stableNamespace: optionNamespace } = resolveLoaderOptions(this);
|
|
62
|
+
const typesRequested = hasQueryFlag(this.resourceQuery, TYPES_QUERY_FLAG);
|
|
63
|
+
const resolvedNamespace = resolveStableNamespace(optionNamespace);
|
|
64
|
+
const skipSyntheticDefault = hasNamedOnlyQueryFlag(this.resourceQuery);
|
|
65
|
+
const defaultSignalPromise = skipSyntheticDefault
|
|
66
|
+
? Promise.resolve('unknown')
|
|
67
|
+
: detectModuleDefaultExport(this.resourcePath);
|
|
68
|
+
return Promise.all([extractCss(this, cssOptions), defaultSignalPromise]).then(([css, defaultSignal]) => {
|
|
69
|
+
const emitDefault = shouldEmitCombinedDefault({
|
|
70
|
+
request,
|
|
71
|
+
skipSyntheticDefault,
|
|
72
|
+
detection: defaultSignal,
|
|
73
|
+
});
|
|
74
|
+
const stableSelectorsLiteral = typesRequested
|
|
75
|
+
? buildStableSelectorsLiteral({
|
|
76
|
+
css,
|
|
77
|
+
namespace: resolvedNamespace,
|
|
78
|
+
resourcePath: this.resourcePath,
|
|
79
|
+
emitWarning: message => emitKnightedWarning(this, message),
|
|
80
|
+
})
|
|
81
|
+
: undefined;
|
|
82
|
+
return createCombinedModule(request, css, {
|
|
83
|
+
emitDefault,
|
|
84
|
+
stableSelectorsLiteral: stableSelectorsLiteral?.literal,
|
|
85
|
+
});
|
|
86
|
+
});
|
|
48
87
|
};
|
|
49
88
|
loader.pitch = pitch;
|
|
50
89
|
export default loader;
|
|
51
90
|
function resolveLoaderOptions(ctx) {
|
|
52
91
|
const rawOptions = (typeof ctx.getOptions === 'function' ? ctx.getOptions() : {});
|
|
53
|
-
const { vanilla, ...rest } = rawOptions;
|
|
92
|
+
const { vanilla, stableNamespace, ...rest } = rawOptions;
|
|
54
93
|
const cssOptions = {
|
|
55
94
|
...rest,
|
|
56
95
|
cwd: rest.cwd ?? ctx.rootContext ?? process.cwd(),
|
|
@@ -58,6 +97,7 @@ function resolveLoaderOptions(ctx) {
|
|
|
58
97
|
return {
|
|
59
98
|
cssOptions,
|
|
60
99
|
vanillaOptions: vanilla,
|
|
100
|
+
stableNamespace,
|
|
61
101
|
};
|
|
62
102
|
}
|
|
63
103
|
async function extractCss(ctx, options) {
|
|
@@ -71,19 +111,12 @@ async function extractCss(ctx, options) {
|
|
|
71
111
|
function toSourceString(source) {
|
|
72
112
|
return typeof source === 'string' ? source : source.toString('utf8');
|
|
73
113
|
}
|
|
74
|
-
function buildInjection(css) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const trimmed = query.startsWith('?') ? query.slice(1) : query;
|
|
81
|
-
if (!trimmed)
|
|
82
|
-
return false;
|
|
83
|
-
return trimmed
|
|
84
|
-
.split('&')
|
|
85
|
-
.filter(Boolean)
|
|
86
|
-
.some(part => isQueryFlag(part, COMBINED_QUERY_FLAG));
|
|
114
|
+
function buildInjection(css, extras) {
|
|
115
|
+
const lines = [`\n\nexport const ${DEFAULT_EXPORT_NAME} = ${JSON.stringify(css)};\n`];
|
|
116
|
+
if (extras?.stableSelectorsLiteral) {
|
|
117
|
+
lines.push(extras.stableSelectorsLiteral);
|
|
118
|
+
}
|
|
119
|
+
return lines.join('');
|
|
87
120
|
}
|
|
88
121
|
function buildProxyRequest(ctx) {
|
|
89
122
|
const sanitizedQuery = buildSanitizedQuery(ctx.resourceQuery);
|
|
@@ -111,51 +144,28 @@ function stripResourceQuery(request) {
|
|
|
111
144
|
const idx = request.indexOf('?');
|
|
112
145
|
return idx >= 0 ? request.slice(0, idx) : request;
|
|
113
146
|
}
|
|
114
|
-
function
|
|
115
|
-
|
|
116
|
-
return '';
|
|
117
|
-
const entries = splitQuery(query).filter(part => {
|
|
118
|
-
return !isQueryFlag(part, COMBINED_QUERY_FLAG) && !isQueryFlag(part, 'knighted-css');
|
|
119
|
-
});
|
|
120
|
-
return entries.length > 0 ? `?${entries.join('&')}` : '';
|
|
121
|
-
}
|
|
122
|
-
function splitQuery(query) {
|
|
123
|
-
const trimmed = query.startsWith('?') ? query.slice(1) : query;
|
|
124
|
-
if (!trimmed)
|
|
125
|
-
return [];
|
|
126
|
-
return trimmed.split('&').filter(Boolean);
|
|
127
|
-
}
|
|
128
|
-
function isQueryFlag(entry, flag) {
|
|
129
|
-
const [rawKey] = entry.split('=');
|
|
130
|
-
try {
|
|
131
|
-
return decodeURIComponent(rawKey) === flag;
|
|
132
|
-
}
|
|
133
|
-
catch {
|
|
134
|
-
return rawKey === flag;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
function createCombinedModule(request, css) {
|
|
147
|
+
function createCombinedModule(request, css, options) {
|
|
148
|
+
const shouldEmitDefault = options?.emitDefault ?? shouldForwardDefaultExport(request);
|
|
138
149
|
const requestLiteral = JSON.stringify(request);
|
|
139
150
|
const lines = [
|
|
140
151
|
`import * as __knightedModule from ${requestLiteral};`,
|
|
141
152
|
`export * from ${requestLiteral};`,
|
|
142
153
|
];
|
|
143
|
-
if (
|
|
154
|
+
if (shouldEmitDefault) {
|
|
144
155
|
lines.push(`const __knightedDefault =
|
|
145
156
|
typeof __knightedModule.default !== 'undefined'
|
|
146
157
|
? __knightedModule.default
|
|
147
158
|
: __knightedModule;`, 'export default __knightedDefault;');
|
|
148
159
|
}
|
|
149
|
-
lines.push(buildInjection(css));
|
|
160
|
+
lines.push(buildInjection(css, { stableSelectorsLiteral: options?.stableSelectorsLiteral }));
|
|
150
161
|
return lines.join('\n');
|
|
151
162
|
}
|
|
152
|
-
function
|
|
153
|
-
const
|
|
154
|
-
if (
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
if (lower.endsWith('.css.ts') || lower.endsWith('.css.js')) {
|
|
158
|
-
return false;
|
|
163
|
+
function emitKnightedWarning(ctx, message) {
|
|
164
|
+
const formatted = `\x1b[33m@knighted/css warning\x1b[0m ${message}`;
|
|
165
|
+
if (typeof ctx.emitWarning === 'function') {
|
|
166
|
+
ctx.emitWarning(new Error(formatted));
|
|
167
|
+
return;
|
|
159
168
|
}
|
|
160
|
-
|
|
169
|
+
// eslint-disable-next-line no-console
|
|
170
|
+
console.warn(formatted);
|
|
161
171
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ModuleDefaultSignal } from './moduleInfo.js';
|
|
2
|
+
export declare const COMBINED_QUERY_FLAG = "combined";
|
|
3
|
+
export declare const TYPES_QUERY_FLAG = "types";
|
|
4
|
+
export declare const NAMED_ONLY_QUERY_FLAGS: readonly ["named-only", "no-default"];
|
|
5
|
+
export type SelectorTypeVariant = 'types' | 'combined' | 'combinedWithoutDefault';
|
|
6
|
+
export declare function splitQuery(query: string): string[];
|
|
7
|
+
export declare function isQueryFlag(entry: string, flag: string): boolean;
|
|
8
|
+
export declare function buildSanitizedQuery(query?: string | null): string;
|
|
9
|
+
export declare function hasQueryFlag(query: string | null | undefined, flag: string): boolean;
|
|
10
|
+
export declare function shouldForwardDefaultExport(request: string): boolean;
|
|
11
|
+
export declare function hasCombinedQuery(query?: string | null): boolean;
|
|
12
|
+
export declare function hasNamedOnlyQueryFlag(query?: string | null): boolean;
|
|
13
|
+
export declare function determineSelectorVariant(query?: string | null): SelectorTypeVariant;
|
|
14
|
+
export declare function shouldEmitCombinedDefault(options: {
|
|
15
|
+
detection: ModuleDefaultSignal;
|
|
16
|
+
request: string;
|
|
17
|
+
skipSyntheticDefault: boolean;
|
|
18
|
+
}): boolean;
|
|
19
|
+
export declare const __loaderInternals: {
|
|
20
|
+
buildSanitizedQuery: typeof buildSanitizedQuery;
|
|
21
|
+
shouldEmitCombinedDefault: typeof shouldEmitCombinedDefault;
|
|
22
|
+
determineSelectorVariant: typeof determineSelectorVariant;
|
|
23
|
+
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
export const COMBINED_QUERY_FLAG = 'combined';
|
|
2
|
+
export const TYPES_QUERY_FLAG = 'types';
|
|
3
|
+
export const NAMED_ONLY_QUERY_FLAGS = ['named-only', 'no-default'];
|
|
4
|
+
export function splitQuery(query) {
|
|
5
|
+
const trimmed = query.startsWith('?') ? query.slice(1) : query;
|
|
6
|
+
if (!trimmed)
|
|
7
|
+
return [];
|
|
8
|
+
return trimmed.split('&').filter(Boolean);
|
|
9
|
+
}
|
|
10
|
+
export function isQueryFlag(entry, flag) {
|
|
11
|
+
const [rawKey] = entry.split('=');
|
|
12
|
+
try {
|
|
13
|
+
return decodeURIComponent(rawKey) === flag;
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return rawKey === flag;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export function buildSanitizedQuery(query) {
|
|
20
|
+
if (!query)
|
|
21
|
+
return '';
|
|
22
|
+
const entries = splitQuery(query).filter(part => {
|
|
23
|
+
if (isQueryFlag(part, COMBINED_QUERY_FLAG)) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
if (isQueryFlag(part, 'knighted-css')) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
if (isQueryFlag(part, TYPES_QUERY_FLAG)) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
if (NAMED_ONLY_QUERY_FLAGS.some(flag => isQueryFlag(part, flag))) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
});
|
|
37
|
+
return entries.length > 0 ? `?${entries.join('&')}` : '';
|
|
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
|
+
}
|
|
55
|
+
export function shouldForwardDefaultExport(request) {
|
|
56
|
+
const [pathPart] = request.split('?');
|
|
57
|
+
if (!pathPart)
|
|
58
|
+
return true;
|
|
59
|
+
const lower = pathPart.toLowerCase();
|
|
60
|
+
if (lower.endsWith('.css.ts') || lower.endsWith('.css.js')) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
return true;
|
|
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
|
+
}
|
|
77
|
+
export function shouldEmitCombinedDefault(options) {
|
|
78
|
+
if (options.skipSyntheticDefault) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
if (!shouldForwardDefaultExport(options.request)) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
if (options.detection === 'has-default') {
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
if (options.detection === 'no-default') {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
export const __loaderInternals = {
|
|
93
|
+
buildSanitizedQuery,
|
|
94
|
+
shouldEmitCombinedDefault,
|
|
95
|
+
determineSelectorVariant,
|
|
96
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { CssResolver } from './types.js';
|
|
2
|
+
export interface ModuleGraphOptions {
|
|
3
|
+
tsConfig?: string | Record<string, unknown>;
|
|
4
|
+
extensions?: string[];
|
|
5
|
+
conditions?: string[];
|
|
6
|
+
}
|
|
7
|
+
interface CollectOptions {
|
|
8
|
+
cwd: string;
|
|
9
|
+
styleExtensions: string[];
|
|
10
|
+
filter: (filePath: string) => boolean;
|
|
11
|
+
resolver?: CssResolver;
|
|
12
|
+
graphOptions?: ModuleGraphOptions;
|
|
13
|
+
}
|
|
14
|
+
export declare function collectStyleImports(entryPath: string, options: CollectOptions): Promise<string[]>;
|
|
15
|
+
export {};
|