@knighted/css 1.0.0-rc.12 → 1.0.0-rc.14

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.
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.asKnightedCssCombinedModule = asKnightedCssCombinedModule;
4
+ function asKnightedCssCombinedModule(module) {
5
+ return module;
6
+ }
@@ -0,0 +1,4 @@
1
+ import type { KnightedCssCombinedModule } from './loader.cjs';
2
+ type KnightedCssCombinedExtras = Readonly<Record<string, unknown>>;
3
+ export declare function asKnightedCssCombinedModule<TModule, TExtras extends KnightedCssCombinedExtras = Record<never, never>>(module: unknown): KnightedCssCombinedModule<TModule, TExtras>;
4
+ export {};
@@ -18,6 +18,7 @@ const loader = async function loader(source) {
18
18
  namespace: resolvedNamespace,
19
19
  resourcePath: this.resourcePath,
20
20
  emitWarning: message => emitKnightedWarning(this, message),
21
+ target: 'js',
21
22
  })
22
23
  : undefined;
23
24
  const injection = buildInjection(css, {
@@ -80,6 +81,7 @@ const pitch = function pitch() {
80
81
  namespace: resolvedNamespace,
81
82
  resourcePath: this.resourcePath,
82
83
  emitWarning: message => emitKnightedWarning(this, message),
84
+ target: 'js',
83
85
  })
84
86
  : undefined;
85
87
  return createCombinedModule(request, css, {
@@ -1,6 +1,7 @@
1
1
  import type { LoaderDefinitionFunction, PitchLoaderDefinitionFunction } from 'webpack';
2
2
  import { type CssOptions } from './css.cjs';
3
- export type KnightedCssCombinedModule<TModule> = TModule & {
3
+ type KnightedCssCombinedExtras = Readonly<Record<string, unknown>>;
4
+ export type KnightedCssCombinedModule<TModule, TExtras extends KnightedCssCombinedExtras = Record<never, never>> = TModule & TExtras & {
4
5
  knightedCss: string;
5
6
  };
6
7
  export interface KnightedCssVanillaOptions {
@@ -6,8 +6,10 @@ exports.stableClass = stableClass;
6
6
  exports.stableSelector = stableSelector;
7
7
  exports.createStableClassFactory = createStableClassFactory;
8
8
  exports.stableClassName = stableClassName;
9
+ exports.mergeStableClass = mergeStableClass;
9
10
  const DEFAULT_NAMESPACE = 'knighted';
10
11
  const defaultJoin = (values) => values.filter(Boolean).join(' ');
12
+ const toArray = (value) => Array.isArray(value) ? value : [value];
11
13
  const normalizeToken = (token) => {
12
14
  const sanitized = token
13
15
  .trim()
@@ -42,3 +44,30 @@ function stableClassName(styles, key, options) {
42
44
  return join([hashed, stable]);
43
45
  }
44
46
  exports.stableClassFromModule = stableClassName;
47
+ function mergeStableClass(input) {
48
+ if ('token' in input) {
49
+ return mergeSingle(input);
50
+ }
51
+ return mergeBatch(input);
52
+ }
53
+ function mergeSingle(input) {
54
+ const join = input.join ?? defaultJoin;
55
+ const hashed = toArray(input.hashed);
56
+ const stable = input.selector?.trim().length
57
+ ? input.selector
58
+ : stableClass(input.token, { namespace: input.namespace });
59
+ return join([...hashed, stable]);
60
+ }
61
+ function mergeBatch(input) {
62
+ const join = input.join ?? defaultJoin;
63
+ const output = {};
64
+ for (const key of Object.keys(input.hashed)) {
65
+ const hashedValue = input.hashed[key];
66
+ const selector = input.selectors?.[String(key)];
67
+ const stable = selector?.trim().length
68
+ ? selector
69
+ : stableClass(String(key), { namespace: input.namespace });
70
+ output[key] = join([...toArray(hashedValue), stable]);
71
+ }
72
+ return output;
73
+ }
@@ -5,9 +5,24 @@ export interface StableClassNameOptions extends StableSelectorOptions {
5
5
  token?: string;
6
6
  join?: (values: string[]) => string;
7
7
  }
8
+ export interface MergeStableClassSingleInput extends StableSelectorOptions {
9
+ hashed: string | string[];
10
+ selector?: string;
11
+ token: string;
12
+ join?: (values: string[]) => string;
13
+ }
14
+ export interface MergeStableClassBatchInput<Hashed extends Record<string, string | string[]>, Selectors extends Record<string, string> | undefined = Record<string, string>> extends StableSelectorOptions {
15
+ hashed: Hashed;
16
+ selectors?: Selectors;
17
+ join?: (values: string[]) => string;
18
+ }
8
19
  export declare function stableToken(token: string, options?: StableSelectorOptions): string;
9
20
  export declare function stableClass(token: string, options?: StableSelectorOptions): string;
10
21
  export declare function stableSelector(token: string, options?: StableSelectorOptions): string;
11
22
  export declare function createStableClassFactory(options?: StableSelectorOptions): (token: string) => string;
12
23
  export declare function stableClassName<T extends Record<string, string>>(styles: T, key: keyof T | string, options?: StableClassNameOptions): string;
13
24
  export declare const stableClassFromModule: typeof stableClassName;
25
+ export declare function mergeStableClass(input: MergeStableClassSingleInput): string;
26
+ export declare function mergeStableClass<Hashed extends Record<string, string | string[]>>(input: MergeStableClassBatchInput<Hashed>): {
27
+ [Key in keyof Hashed]: string;
28
+ };
@@ -7,20 +7,23 @@ exports.formatStableSelectorMap = formatStableSelectorMap;
7
7
  const lightningcss_1 = require("lightningcss");
8
8
  const helpers_js_1 = require("./helpers.cjs");
9
9
  function buildStableSelectorsLiteral(options) {
10
+ const target = options.target ?? 'ts';
10
11
  const trimmedNamespace = options.namespace.trim();
11
12
  if (!trimmedNamespace) {
12
13
  options.emitWarning(`stableSelectors requested for ${options.resourcePath} but "stableNamespace" resolved to an empty value.`);
13
- return {
14
- literal: 'export const stableSelectors = {} as const;\n',
15
- selectorMap: new Map(),
16
- };
14
+ return finalizeLiteral(new Map(), target);
17
15
  }
18
16
  const selectorMap = collectStableSelectors(options.css, trimmedNamespace, options.resourcePath);
19
17
  if (selectorMap.size === 0) {
20
18
  options.emitWarning(`stableSelectors requested for ${options.resourcePath} but no selectors matched namespace "${trimmedNamespace}".`);
21
19
  }
20
+ return finalizeLiteral(selectorMap, target);
21
+ }
22
+ function finalizeLiteral(selectorMap, target) {
23
+ const formatted = formatStableSelectorMap(selectorMap);
24
+ const suffix = target === 'ts' ? ' as const' : '';
22
25
  return {
23
- literal: `export const stableSelectors = ${formatStableSelectorMap(selectorMap)} as const;\n`,
26
+ literal: `export const stableSelectors = ${formatted}${suffix};\n`,
24
27
  selectorMap,
25
28
  };
26
29
  }
@@ -2,11 +2,13 @@ export interface StableSelectorsLiteralResult {
2
2
  literal: string;
3
3
  selectorMap: Map<string, string>;
4
4
  }
5
+ type StableSelectorsLiteralTarget = 'ts' | 'js';
5
6
  export declare function buildStableSelectorsLiteral(options: {
6
7
  css: string;
7
8
  namespace: string;
8
9
  resourcePath: string;
9
10
  emitWarning: (message: string) => void;
11
+ target?: StableSelectorsLiteralTarget;
10
12
  }): StableSelectorsLiteralResult;
11
13
  export declare function collectStableSelectors(css: string, namespace: string, filename?: string): Map<string, string>;
12
14
  declare function collectStableSelectorsByRegex(css: string, namespace: string): Map<string, string>;
@@ -0,0 +1,4 @@
1
+ import type { KnightedCssCombinedModule } from './loader.js';
2
+ type KnightedCssCombinedExtras = Readonly<Record<string, unknown>>;
3
+ export declare function asKnightedCssCombinedModule<TModule, TExtras extends KnightedCssCombinedExtras = Record<never, never>>(module: unknown): KnightedCssCombinedModule<TModule, TExtras>;
4
+ export {};
@@ -0,0 +1,3 @@
1
+ export function asKnightedCssCombinedModule(module) {
2
+ return module;
3
+ }
package/dist/loader.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { LoaderDefinitionFunction, PitchLoaderDefinitionFunction } from 'webpack';
2
2
  import { type CssOptions } from './css.js';
3
- export type KnightedCssCombinedModule<TModule> = TModule & {
3
+ type KnightedCssCombinedExtras = Readonly<Record<string, unknown>>;
4
+ export type KnightedCssCombinedModule<TModule, TExtras extends KnightedCssCombinedExtras = Record<never, never>> = TModule & TExtras & {
4
5
  knightedCss: string;
5
6
  };
6
7
  export interface KnightedCssVanillaOptions {
package/dist/loader.js CHANGED
@@ -15,6 +15,7 @@ const loader = async function loader(source) {
15
15
  namespace: resolvedNamespace,
16
16
  resourcePath: this.resourcePath,
17
17
  emitWarning: message => emitKnightedWarning(this, message),
18
+ target: 'js',
18
19
  })
19
20
  : undefined;
20
21
  const injection = buildInjection(css, {
@@ -77,6 +78,7 @@ export const pitch = function pitch() {
77
78
  namespace: resolvedNamespace,
78
79
  resourcePath: this.resourcePath,
79
80
  emitWarning: message => emitKnightedWarning(this, message),
81
+ target: 'js',
80
82
  })
81
83
  : undefined;
82
84
  return createCombinedModule(request, css, {
@@ -5,9 +5,24 @@ export interface StableClassNameOptions extends StableSelectorOptions {
5
5
  token?: string;
6
6
  join?: (values: string[]) => string;
7
7
  }
8
+ export interface MergeStableClassSingleInput extends StableSelectorOptions {
9
+ hashed: string | string[];
10
+ selector?: string;
11
+ token: string;
12
+ join?: (values: string[]) => string;
13
+ }
14
+ export interface MergeStableClassBatchInput<Hashed extends Record<string, string | string[]>, Selectors extends Record<string, string> | undefined = Record<string, string>> extends StableSelectorOptions {
15
+ hashed: Hashed;
16
+ selectors?: Selectors;
17
+ join?: (values: string[]) => string;
18
+ }
8
19
  export declare function stableToken(token: string, options?: StableSelectorOptions): string;
9
20
  export declare function stableClass(token: string, options?: StableSelectorOptions): string;
10
21
  export declare function stableSelector(token: string, options?: StableSelectorOptions): string;
11
22
  export declare function createStableClassFactory(options?: StableSelectorOptions): (token: string) => string;
12
23
  export declare function stableClassName<T extends Record<string, string>>(styles: T, key: keyof T | string, options?: StableClassNameOptions): string;
13
24
  export declare const stableClassFromModule: typeof stableClassName;
25
+ export declare function mergeStableClass(input: MergeStableClassSingleInput): string;
26
+ export declare function mergeStableClass<Hashed extends Record<string, string | string[]>>(input: MergeStableClassBatchInput<Hashed>): {
27
+ [Key in keyof Hashed]: string;
28
+ };
@@ -1,5 +1,6 @@
1
1
  const DEFAULT_NAMESPACE = 'knighted';
2
2
  const defaultJoin = (values) => values.filter(Boolean).join(' ');
3
+ const toArray = (value) => Array.isArray(value) ? value : [value];
3
4
  const normalizeToken = (token) => {
4
5
  const sanitized = token
5
6
  .trim()
@@ -34,3 +35,30 @@ export function stableClassName(styles, key, options) {
34
35
  return join([hashed, stable]);
35
36
  }
36
37
  export const stableClassFromModule = stableClassName;
38
+ export function mergeStableClass(input) {
39
+ if ('token' in input) {
40
+ return mergeSingle(input);
41
+ }
42
+ return mergeBatch(input);
43
+ }
44
+ function mergeSingle(input) {
45
+ const join = input.join ?? defaultJoin;
46
+ const hashed = toArray(input.hashed);
47
+ const stable = input.selector?.trim().length
48
+ ? input.selector
49
+ : stableClass(input.token, { namespace: input.namespace });
50
+ return join([...hashed, stable]);
51
+ }
52
+ function mergeBatch(input) {
53
+ const join = input.join ?? defaultJoin;
54
+ const output = {};
55
+ for (const key of Object.keys(input.hashed)) {
56
+ const hashedValue = input.hashed[key];
57
+ const selector = input.selectors?.[String(key)];
58
+ const stable = selector?.trim().length
59
+ ? selector
60
+ : stableClass(String(key), { namespace: input.namespace });
61
+ output[key] = join([...toArray(hashedValue), stable]);
62
+ }
63
+ return output;
64
+ }
@@ -2,11 +2,13 @@ export interface StableSelectorsLiteralResult {
2
2
  literal: string;
3
3
  selectorMap: Map<string, string>;
4
4
  }
5
+ type StableSelectorsLiteralTarget = 'ts' | 'js';
5
6
  export declare function buildStableSelectorsLiteral(options: {
6
7
  css: string;
7
8
  namespace: string;
8
9
  resourcePath: string;
9
10
  emitWarning: (message: string) => void;
11
+ target?: StableSelectorsLiteralTarget;
10
12
  }): StableSelectorsLiteralResult;
11
13
  export declare function collectStableSelectors(css: string, namespace: string, filename?: string): Map<string, string>;
12
14
  declare function collectStableSelectorsByRegex(css: string, namespace: string): Map<string, string>;
@@ -1,20 +1,23 @@
1
1
  import { transform as lightningTransform } from 'lightningcss';
2
2
  import { escapeRegex, serializeSelector } from './helpers.js';
3
3
  export function buildStableSelectorsLiteral(options) {
4
+ const target = options.target ?? 'ts';
4
5
  const trimmedNamespace = options.namespace.trim();
5
6
  if (!trimmedNamespace) {
6
7
  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
- };
8
+ return finalizeLiteral(new Map(), target);
11
9
  }
12
10
  const selectorMap = collectStableSelectors(options.css, trimmedNamespace, options.resourcePath);
13
11
  if (selectorMap.size === 0) {
14
12
  options.emitWarning(`stableSelectors requested for ${options.resourcePath} but no selectors matched namespace "${trimmedNamespace}".`);
15
13
  }
14
+ return finalizeLiteral(selectorMap, target);
15
+ }
16
+ function finalizeLiteral(selectorMap, target) {
17
+ const formatted = formatStableSelectorMap(selectorMap);
18
+ const suffix = target === 'ts' ? ' as const' : '';
16
19
  return {
17
- literal: `export const stableSelectors = ${formatStableSelectorMap(selectorMap)} as const;\n`,
20
+ literal: `export const stableSelectors = ${formatted}${suffix};\n`,
18
21
  selectorMap,
19
22
  };
20
23
  }
@@ -19,7 +19,12 @@ declare module '*?knighted-css&types' {
19
19
  * TypeScript cannot infer the underlying module automatically, so consumers can
20
20
  * import the default export and narrow it with `KnightedCssCombinedModule<typeof import('./file')>`.
21
21
  */
22
- type KnightedCssCombinedModule<TModule> = TModule & { knightedCss: string }
22
+ type KnightedCssCombinedExtras = Readonly<Record<string, unknown>>
23
+
24
+ type KnightedCssCombinedModule<
25
+ TModule,
26
+ TExtras extends KnightedCssCombinedExtras = Record<never, never>,
27
+ > = TModule & TExtras & { knightedCss: string }
23
28
 
24
29
  declare module '*?knighted-css&combined' {
25
30
  const combined: KnightedCssCombinedModule<Record<string, unknown>>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knighted/css",
3
- "version": "1.0.0-rc.12",
3
+ "version": "1.0.0-rc.14",
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",
@@ -10,6 +10,9 @@
10
10
  "loader": [
11
11
  "./dist/loader.d.ts"
12
12
  ],
13
+ "loader-helpers": [
14
+ "./dist/loader-helpers.d.ts"
15
+ ],
13
16
  "loader-queries": [
14
17
  "./loader-queries.d.ts"
15
18
  ],
@@ -32,6 +35,11 @@
32
35
  "import": "./dist/loader.js",
33
36
  "require": "./dist/cjs/loader.cjs"
34
37
  },
38
+ "./loader-helpers": {
39
+ "types": "./dist/loader-helpers.d.ts",
40
+ "import": "./dist/loader-helpers.js",
41
+ "require": "./dist/cjs/loader-helpers.cjs"
42
+ },
35
43
  "./loader-queries": {
36
44
  "types": "./loader-queries.d.ts",
37
45
  "default": "./loader-queries.d.ts"