@pikacss/core 0.0.8 → 0.0.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/dist/index.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- const ATOMIC_STYLE_NAME_PLACEHOLDER = "$$";
4
- const ATOMIC_STYLE_NAME_PLACEHOLDER_RE_GLOBAL = /\$\$/g;
3
+ const ATOMIC_STYLE_ID_PLACEHOLDER = "$$";
4
+ const ATOMIC_STYLE_ID_PLACEHOLDER_RE_GLOBAL = /\$\$/g;
5
5
 
6
6
  const chars = [..."abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"];
7
7
  const numOfChars = chars.length;
@@ -61,6 +61,25 @@ function appendAutocompleteCssPropertyValues(config, property, ...values) {
61
61
  const current = config.autocomplete.cssProperties.get(property) || [];
62
62
  config.autocomplete.cssProperties.set(property, [...current, ...values]);
63
63
  }
64
+ function renderCSSStyleBlocks(blocks, isFormatted, depth = 0) {
65
+ const blockIndent = isFormatted ? " ".repeat(depth) : "";
66
+ const blockBodyIndent = isFormatted ? " ".repeat(depth + 1) : "";
67
+ const selectorEnd = isFormatted ? " " : "";
68
+ const propertySpace = isFormatted ? " " : "";
69
+ const lineEnd = isFormatted ? "\n" : "";
70
+ const lines = [];
71
+ blocks.forEach(({ properties, children }, selector) => {
72
+ if (properties.length === 0 && children == null)
73
+ return;
74
+ lines.push(...[
75
+ `${blockIndent}${selector}${selectorEnd}{`,
76
+ ...properties.map(({ property, value }) => `${blockBodyIndent}${property}:${propertySpace}${value};`),
77
+ ...children != null ? [renderCSSStyleBlocks(children, isFormatted, depth + 1)] : [],
78
+ `${blockIndent}}`
79
+ ]);
80
+ });
81
+ return lines.join(lineEnd);
82
+ }
64
83
 
65
84
  function replaceBySplitAndJoin(str, split, mapFn, join) {
66
85
  let splitted = str.split(split);
@@ -81,13 +100,13 @@ function normalizeSelectors({
81
100
  return [defaultSelector];
82
101
  const normalized = selectors.map((s) => s.replace(RE_SPLIT, ","));
83
102
  const lastSelector = selectors[selectors.length - 1];
84
- if (lastSelector.includes(ATOMIC_STYLE_NAME_PLACEHOLDER) === false && lastSelector.includes(DEFAULT_SELECTOR_PLACEHOLDER) === false) {
103
+ if (lastSelector.includes(ATOMIC_STYLE_ID_PLACEHOLDER) === false && lastSelector.includes(DEFAULT_SELECTOR_PLACEHOLDER) === false) {
85
104
  normalized.push(DEFAULT_SELECTOR_PLACEHOLDER);
86
105
  }
87
106
  return normalized.map(
88
107
  (s) => replaceBySplitAndJoin(
89
108
  s,
90
- ATOMIC_STYLE_NAME_PLACEHOLDER_RE_GLOBAL,
109
+ ATOMIC_STYLE_ID_PLACEHOLDER_RE_GLOBAL,
91
110
  (a) => replaceBySplitAndJoin(
92
111
  a,
93
112
  ATTRIBUTE_SUFFIX_MATCH_RE_GLOBAL,
@@ -99,7 +118,7 @@ function normalizeSelectors({
99
118
  ),
100
119
  ATTRIBUTE_SUFFIX_MATCH
101
120
  ),
102
- ATOMIC_STYLE_NAME_PLACEHOLDER
121
+ ATOMIC_STYLE_ID_PLACEHOLDER
103
122
  )
104
123
  );
105
124
  }
@@ -196,7 +215,7 @@ const hooks = {
196
215
  transformStyleItems: (plugins, styleItems) => execAsyncHook(plugins, "transformStyleItems", styleItems),
197
216
  transformStyleDefinitions: (plugins, styleDefinitions) => execAsyncHook(plugins, "transformStyleDefinitions", styleDefinitions),
198
217
  preflightUpdated: (plugins) => execSyncHook(plugins, "preflightUpdated", void 0),
199
- atomicRuleAdded: (plugins) => execSyncHook(plugins, "atomicRuleAdded", void 0),
218
+ atomicStyleAdded: (plugins) => execSyncHook(plugins, "atomicStyleAdded", void 0),
200
219
  autocompleteConfigUpdated: (plugins) => execSyncHook(plugins, "autocompleteConfigUpdated", void 0)
201
220
  };
202
221
  const orderMap = /* @__PURE__ */ new Map([
@@ -268,15 +287,7 @@ function keyframes() {
268
287
  configList.forEach((config) => {
269
288
  const { name, frames, autocomplete: autocompleteAnimation } = resolveKeyframesConfig(config);
270
289
  if (frames != null) {
271
- const css = [
272
- `@keyframes ${name}{`,
273
- ...Object.entries(frames).map(([frame, properties]) => (
274
- // eslint-disable-next-line style/newline-per-chained-call
275
- `${frame}{${Object.entries(properties).map(([property, value]) => `${property}:${value}`).join(";")}}`
276
- )),
277
- "}"
278
- ].join("");
279
- allKeyframes.set(name, css);
290
+ allKeyframes.set(name, frames);
280
291
  }
281
292
  autocomplete.animationName.push(name);
282
293
  autocomplete.animation.push(`${name} `);
@@ -285,9 +296,9 @@ function keyframes() {
285
296
  });
286
297
  appendAutocompleteCssPropertyValues(resolvedConfig, "animationName", ...autocomplete.animationName);
287
298
  appendAutocompleteCssPropertyValues(resolvedConfig, "animation", ...autocomplete.animation);
288
- resolvedConfig.preflights.push((engine) => {
299
+ resolvedConfig.preflights.push((engine, isFormatted) => {
289
300
  const used = /* @__PURE__ */ new Set();
290
- engine.store.atomicRules.forEach(({ content: { property, value } }) => {
301
+ engine.store.atomicStyles.forEach(({ content: { property, value } }) => {
291
302
  if (property === "animationName") {
292
303
  value.forEach((name) => used.add(name));
293
304
  } else if (property === "animation") {
@@ -301,8 +312,25 @@ function keyframes() {
301
312
  });
302
313
  }
303
314
  });
304
- const content = Array.from(allKeyframes.entries()).filter(([name]) => used.has(name)).map(([, css]) => css).join("");
305
- return content;
315
+ return renderCSSStyleBlocks(
316
+ new Map(Array.from(allKeyframes.entries()).filter(([name]) => used.has(name)).map(([name, frames]) => [
317
+ `@keyframes ${name}`,
318
+ {
319
+ properties: [],
320
+ children: new Map(Object.entries(frames).map(([frame, properties]) => [
321
+ frame,
322
+ {
323
+ properties: Object.entries(properties).filter(([_, value]) => isNotNullish(value)).flatMap(([property, value]) => {
324
+ if (Array.isArray(value))
325
+ return value.map((v) => ({ property, value: String(v) }));
326
+ return { property, value: String(value) };
327
+ })
328
+ }
329
+ ]))
330
+ }
331
+ ])),
332
+ isFormatted
333
+ );
306
334
  });
307
335
  }
308
336
  });
@@ -664,15 +692,22 @@ function variables() {
664
692
  if (asProperty)
665
693
  appendAutocompleteExtraCssProperties(resolvedConfig, name);
666
694
  if (value != null)
667
- allVariables.set(name, `${name}:${value}`);
695
+ allVariables.set(name, value);
668
696
  });
669
- resolvedConfig.preflights.push((engine) => {
697
+ resolvedConfig.preflights.push((engine, isFormatted) => {
670
698
  const used = /* @__PURE__ */ new Set();
671
- engine.store.atomicRules.forEach(({ content: { value } }) => {
699
+ engine.store.atomicStyles.forEach(({ content: { value } }) => {
672
700
  value.flatMap(extractUsedVarNames).forEach((name) => used.add(normalizeVariableName(name)));
673
701
  });
674
- const content = Array.from(allVariables.entries()).filter(([name]) => used.has(name)).map(([, css]) => css).join(";");
675
- return content === "" ? "" : `:root{${content}}`;
702
+ return renderCSSStyleBlocks(
703
+ /* @__PURE__ */ new Map([[
704
+ ":root",
705
+ {
706
+ properties: Array.from(allVariables.entries()).filter(([name]) => used.has(name)).map(([name, value]) => ({ property: name, value }))
707
+ }
708
+ ]]),
709
+ isFormatted
710
+ );
676
711
  });
677
712
  }
678
713
  });
@@ -707,8 +742,8 @@ class Engine {
707
742
  config;
708
743
  extract;
709
744
  store = {
710
- atomicNames: /* @__PURE__ */ new Map(),
711
- atomicRules: /* @__PURE__ */ new Map()
745
+ atomicStyleIds: /* @__PURE__ */ new Map(),
746
+ atomicStyles: /* @__PURE__ */ new Map()
712
747
  };
713
748
  constructor(config) {
714
749
  this.config = config;
@@ -723,8 +758,8 @@ class Engine {
723
758
  notifyPreflightUpdated() {
724
759
  hooks.preflightUpdated(this.config.plugins);
725
760
  }
726
- notifyAtomicRuleAdded() {
727
- hooks.atomicRuleAdded(this.config.plugins);
761
+ notifyAtomicStyleAdded() {
762
+ hooks.atomicStyleAdded(this.config.plugins);
728
763
  }
729
764
  notifyAutocompleteConfigUpdated() {
730
765
  hooks.autocompleteConfigUpdated(this.config.plugins);
@@ -762,53 +797,39 @@ class Engine {
762
797
  transformStyleItems: (styleItems) => hooks.transformStyleItems(this.config.plugins, styleItems),
763
798
  extractStyleDefinition: (styleDefinition) => this.extract(styleDefinition)
764
799
  });
765
- const resolvedNames = [];
800
+ const resolvedIds = [];
766
801
  contents.forEach((content) => {
767
- const name = getAtomicStyleName({
802
+ const id = getAtomicStyleId({
768
803
  content,
769
804
  prefix: this.config.prefix,
770
- stored: this.store.atomicNames
805
+ stored: this.store.atomicStyleIds
771
806
  });
772
- resolvedNames.push(name);
773
- if (!this.store.atomicRules.has(name)) {
774
- const added = {
775
- name,
776
- content
777
- };
778
- this.store.atomicRules.set(name, added);
779
- this.notifyAtomicRuleAdded();
807
+ resolvedIds.push(id);
808
+ if (!this.store.atomicStyles.has(id)) {
809
+ this.store.atomicStyles.set(id, { id, content });
810
+ this.notifyAtomicStyleAdded();
780
811
  }
781
812
  });
782
- return [...unknown, ...resolvedNames];
783
- }
784
- async renderPreviewStyles(...itemList) {
785
- const nameList = await this.use(...itemList);
786
- const targets = nameList.map((name) => this.store.atomicRules.get(name)).filter(isNotNullish);
787
- return renderAtomicStyles({
788
- atomicRules: targets,
789
- isPreview: true
790
- });
791
- }
792
- renderStyles() {
793
- return [
794
- this.renderPreflights(),
795
- this.renderAtomicStyles()
796
- ].join("");
813
+ return [...unknown, ...resolvedIds];
797
814
  }
798
- renderPreflights() {
799
- return this.config.preflights.map((p) => p(this)).join("");
815
+ renderPreflights(isFormatted) {
816
+ const lineEnd = isFormatted ? "\n" : "";
817
+ return this.config.preflights.map((p) => p(this, isFormatted)).join(lineEnd);
800
818
  }
801
- renderAtomicStyles() {
819
+ renderAtomicStyles(isFormatted, options = {}) {
820
+ const { atomicStyleIds = null, isPreview = false } = options;
821
+ const atomicStyles = atomicStyleIds == null ? [...this.store.atomicStyles.values()] : atomicStyleIds.map((id) => this.store.atomicStyles.get(id)).filter(isNotNullish);
802
822
  return renderAtomicStyles({
803
- atomicRules: [...this.store.atomicRules.values()],
804
- isPreview: false
823
+ atomicStyles,
824
+ isPreview,
825
+ isFormatted
805
826
  });
806
827
  }
807
828
  }
808
829
  async function resolveEngineConfig(config) {
809
830
  const {
810
831
  prefix = "",
811
- defaultSelector = `.${ATOMIC_STYLE_NAME_PLACEHOLDER}`,
832
+ defaultSelector = `.${ATOMIC_STYLE_ID_PLACEHOLDER}`,
812
833
  plugins = [],
813
834
  preflights = [],
814
835
  autocomplete = {}
@@ -838,7 +859,7 @@ async function resolveEngineConfig(config) {
838
859
  autocomplete.cssProperties?.forEach(([property, value]) => appendAutocompleteCssPropertyValues(resolvedConfig, property, ...[value].flat()));
839
860
  return resolvedConfig;
840
861
  }
841
- function getAtomicStyleName({
862
+ function getAtomicStyleId({
842
863
  content,
843
864
  prefix,
844
865
  stored
@@ -848,9 +869,9 @@ function getAtomicStyleName({
848
869
  if (cached != null)
849
870
  return cached;
850
871
  const num = stored.size;
851
- const name = `${prefix}${numberToChars(num)}`;
852
- stored.set(key, name);
853
- return name;
872
+ const id = `${prefix}${numberToChars(num)}`;
873
+ stored.set(key, id);
874
+ return id;
854
875
  }
855
876
  function optimizeAtomicStyleContents(list) {
856
877
  const map = /* @__PURE__ */ new Map();
@@ -881,49 +902,32 @@ async function resolveStyleItemList({
881
902
  contents: optimizeAtomicStyleContents(list)
882
903
  };
883
904
  }
884
- function prepareAtomicStyleBlocks({
885
- atomicRules,
886
- isPreview
887
- }) {
905
+ function renderAtomicStyles(payload) {
906
+ const { atomicStyles, isPreview, isFormatted } = payload;
888
907
  const blocks = /* @__PURE__ */ new Map();
889
- atomicRules.forEach(({ name, content: { selector, property, value } }) => {
890
- const isValidSelector = selector.some((s) => s.includes(ATOMIC_STYLE_NAME_PLACEHOLDER));
908
+ atomicStyles.forEach(({ id, content: { selector, property, value } }) => {
909
+ const isValidSelector = selector.some((s) => s.includes(ATOMIC_STYLE_ID_PLACEHOLDER));
891
910
  if (isValidSelector === false || value == null)
892
911
  return;
893
912
  const renderObject = {
894
- selector: isPreview ? selector : selector.map((s) => s.replace(ATOMIC_STYLE_NAME_PLACEHOLDER_RE_GLOBAL, name)),
895
- content: Array.isArray(value) ? value.map((v) => `${property}:${v}`).join(";") : `${property}:${value}`
913
+ selector: isPreview ? selector : selector.map((s) => s.replace(ATOMIC_STYLE_ID_PLACEHOLDER_RE_GLOBAL, id)),
914
+ properties: value.map((v) => ({ property, value: v }))
896
915
  };
897
916
  let currentBlocks = blocks;
898
917
  for (let i = 0; i < renderObject.selector.length; i++) {
899
918
  const s = renderObject.selector[i];
900
- const block = currentBlocks.get(s) || { content: [] };
901
- const isLast = i === renderObject.selector.length - 1;
902
- if (isLast) {
903
- block.content.push(renderObject.content);
904
- } else {
905
- block.children ||= /* @__PURE__ */ new Map();
906
- }
907
- currentBlocks.set(s, block);
908
- if (isLast === false)
909
- currentBlocks = block.children;
919
+ const blockBody = currentBlocks.get(s) || { properties: [] };
920
+ const isLastSelector = i === renderObject.selector.length - 1;
921
+ if (isLastSelector)
922
+ blockBody.properties.push(...renderObject.properties);
923
+ else
924
+ blockBody.children ||= /* @__PURE__ */ new Map();
925
+ currentBlocks.set(s, blockBody);
926
+ if (isLastSelector === false)
927
+ currentBlocks = blockBody.children;
910
928
  }
911
929
  });
912
- return blocks;
913
- }
914
- function renderAtomicStyleBlocks(blocks) {
915
- let rendered = "";
916
- blocks.forEach((block, selector) => {
917
- rendered += `${selector}{${block.content.join(";")}`;
918
- if (block.children != null)
919
- rendered += renderAtomicStyleBlocks(block.children);
920
- rendered += "}";
921
- });
922
- return rendered;
923
- }
924
- function renderAtomicStyles(payload) {
925
- const blocks = prepareAtomicStyleBlocks(payload);
926
- return renderAtomicStyleBlocks(blocks);
930
+ return renderCSSStyleBlocks(blocks, isFormatted);
927
931
  }
928
932
 
929
933
  function createDefineEnginePluginFn() {
@@ -950,3 +954,4 @@ exports.createDefineEnginePluginFn = createDefineEnginePluginFn;
950
954
  exports.createEngine = createEngine;
951
955
  exports.defineEngineConfig = defineEngineConfig;
952
956
  exports.defineEnginePlugin = defineEnginePlugin;
957
+ exports.renderCSSStyleBlocks = renderCSSStyleBlocks;
package/dist/index.d.cts CHANGED
@@ -7,12 +7,12 @@ declare class Engine {
7
7
  config: ResolvedEngineConfig;
8
8
  extract: ExtractFn;
9
9
  store: {
10
- atomicNames: Map<string, string>;
11
- atomicRules: Map<string, AtomicStyle>;
10
+ atomicStyleIds: Map<string, string>;
11
+ atomicStyles: Map<string, AtomicStyle>;
12
12
  };
13
13
  constructor(config: ResolvedEngineConfig);
14
14
  notifyPreflightUpdated(): void;
15
- notifyAtomicRuleAdded(): void;
15
+ notifyAtomicStyleAdded(): void;
16
16
  notifyAutocompleteConfigUpdated(): void;
17
17
  appendAutocompleteSelectors(...selectors: string[]): void;
18
18
  appendAutocompleteStyleItemStrings(...styleItemStrings: string[]): void;
@@ -21,10 +21,11 @@ declare class Engine {
21
21
  appendAutocompletePropertyValues(property: string, ...tsTypes: string[]): void;
22
22
  appendAutocompleteCssPropertyValues(property: string, ...values: (string | number)[]): void;
23
23
  use(...itemList: StyleItem$1[]): Promise<string[]>;
24
- renderPreviewStyles(...itemList: StyleItem$1[]): Promise<string>;
25
- renderStyles(): string;
26
- renderPreflights(): string;
27
- renderAtomicStyles(): string;
24
+ renderPreflights(isFormatted: boolean): string;
25
+ renderAtomicStyles(isFormatted: boolean, options?: {
26
+ atomicStyleIds?: string[];
27
+ isPreview?: boolean;
28
+ }): string;
28
29
  }
29
30
 
30
31
  type DefineHooks<Hooks extends Record<string, [type: 'sync' | 'async', payload: any, returnValue?: any]>> = Hooks;
@@ -37,7 +38,7 @@ type EngineHooksDefinition<_CustomConfig, _Selector extends string, _CSSProperty
37
38
  transformStyleItems: ['async', styleItems: _StyleItem[]];
38
39
  transformStyleDefinitions: ['async', styleDefinitions: _StyleDefinition[]];
39
40
  preflightUpdated: ['sync', void];
40
- atomicRuleAdded: ['sync', void];
41
+ atomicStyleAdded: ['sync', void];
41
42
  autocompleteConfigUpdated: ['sync', void];
42
43
  }>;
43
44
  type EnginePluginHooksOptions<_CustomConfig, _Selector extends string, _CSSProperty extends string, _Properties, _StyleDefinition, _StyleItem> = {
@@ -100,9 +101,17 @@ interface AtomicStyleContent {
100
101
  value: string[];
101
102
  }
102
103
  interface AtomicStyle {
103
- name: string;
104
+ id: string;
104
105
  content: AtomicStyleContent;
105
106
  }
107
+ interface CSSStyleBlockBody {
108
+ properties: {
109
+ property: string;
110
+ value: string;
111
+ }[];
112
+ children?: CSSStyleBlocks;
113
+ }
114
+ type CSSStyleBlocks = Map<string, CSSStyleBlockBody>;
106
115
 
107
116
  interface Frames<_Properties = Properties$1> {
108
117
  from: _Properties;
@@ -115,7 +124,7 @@ type KeyframesConfig<_Properties = Properties$1> = string | [name: string, frame
115
124
  autocomplete?: string[];
116
125
  };
117
126
 
118
- type PreflightFn = (engine: Engine) => string;
127
+ type PreflightFn = (engine: Engine, isFormatted: boolean) => string;
119
128
  /**
120
129
  * PreflightConfig can be a string or a function that returns a string.
121
130
  *
@@ -178,27 +187,27 @@ interface EngineConfig<_Plugins extends EnginePlugin[] = EnginePlugin[], _Select
178
187
  */
179
188
  plugins?: [..._Plugins];
180
189
  /**
181
- * Set the prefix for generated atomic class names.
190
+ * Set the prefix for generated atomic style id.
182
191
  *
183
192
  * @default ''
184
193
  * @example
185
194
  * ```ts
186
195
  * {
187
- * prefix: 'pika-' // Generated class names will be like 'pika-xxx'
196
+ * prefix: 'pika-' // Generated atomic id will be 'pika-xxx'
188
197
  * }
189
198
  * ```
190
199
  */
191
200
  prefix?: string;
192
201
  /**
193
- * Set the default selector format. '$$' will be replaced with the atomic style name.
202
+ * Set the default selector format. '$$' will be replaced with the atomic style id.
194
203
  *
195
204
  * @default '.$$'
196
205
  * @example
197
206
  * ```ts
198
207
  * {
199
- * defaultSelector: '.$$' // Use class attribute: <div class="a b c">
208
+ * defaultSelector: '.$$' // Use with class attribute: <div class="a b c">
200
209
  * // or
201
- * defaultSelector: '[data-pika~="$$"]' // Use attribute selector: <div data-pika="a b c">
210
+ * defaultSelector: '[data-pika~="$$"]' // Use with attribute selector: <div data-pika="a b c">
202
211
  * }
203
212
  * ```
204
213
  */
@@ -401,10 +410,11 @@ declare function appendAutocompleteExtraProperties(config: Pick<ResolvedEngineCo
401
410
  declare function appendAutocompleteExtraCssProperties(config: Pick<ResolvedEngineConfig, 'autocomplete'>, ...properties: string[]): void;
402
411
  declare function appendAutocompletePropertyValues(config: Pick<ResolvedEngineConfig, 'autocomplete'>, property: string, ...tsTypes: string[]): void;
403
412
  declare function appendAutocompleteCssPropertyValues(config: Pick<ResolvedEngineConfig, 'autocomplete'>, property: string, ...values: (string | number)[]): void;
413
+ declare function renderCSSStyleBlocks(blocks: CSSStyleBlocks, isFormatted: boolean, depth?: number): string;
404
414
 
405
415
  declare function createDefineEnginePluginFn<A extends Autocomplete = EmptyAutocomplete>(): <C extends Record<string, any>>(plugin: EnginePlugin<C, A["Selector"] | CSSSelectors, A["ExtraCssProperty"] | CSSProperty, Properties<A>, StyleDefinition<A>, StyleItem<A>>) => EnginePlugin<C>;
406
416
  declare const defineEnginePlugin: <C extends Record<string, any>>(plugin: EnginePlugin<C, CSSSelectors, keyof CSSProperties, Properties<EmptyAutocomplete>, StyleDefinition<EmptyAutocomplete>, StyleItem<EmptyAutocomplete>>) => EnginePlugin<C, string, string, Properties$1, StyleDefinition$1, StyleItem$1>;
407
417
  declare function createDefineEngineConfigFn<A extends Autocomplete = EmptyAutocomplete>(): <P extends EnginePlugin[] = []>(config: EngineConfig<P, A["Selector"] | CSSSelectors, A["ExtraCssProperty"] | CSSProperty, Properties<A>, StyleDefinition<A>, StyleItem<A>> & PluginsCustomConfig<P>) => EngineConfig<P> & PluginsCustomConfig<P>;
408
418
  declare const defineEngineConfig: <P extends EnginePlugin[] = []>(config: EngineConfig<P, CSSSelectors, keyof CSSProperties, Properties<EmptyAutocomplete>, StyleDefinition<EmptyAutocomplete>, StyleItem<EmptyAutocomplete>> & PluginsCustomConfig<P, {}>) => EngineConfig<P, string, string, Properties$1, StyleDefinition$1, StyleItem$1> & PluginsCustomConfig<P, {}>;
409
419
 
410
- export { type Arrayable, type Autocomplete, type Awaitable, type EmptyAutocomplete, Engine, type EngineConfig, type EnginePlugin, type FromKebab, type GetValue, type IsEqual, type PluginsCustomConfig, type Properties, type Simplify, type StyleDefinition, type StyleItem, type ToKebab, type UnionNumber, type UnionString, type UnionToIntersection, appendAutocompleteCssPropertyValues, appendAutocompleteExtraCssProperties, appendAutocompleteExtraProperties, appendAutocompletePropertyValues, appendAutocompleteSelectors, appendAutocompleteStyleItemStrings, createDefineEngineConfigFn, createDefineEnginePluginFn, createEngine, defineEngineConfig, defineEnginePlugin };
420
+ export { type Arrayable, type Autocomplete, type Awaitable, type CSSStyleBlockBody, type CSSStyleBlocks, type EmptyAutocomplete, Engine, type EngineConfig, type EnginePlugin, type FromKebab, type GetValue, type IsEqual, type PluginsCustomConfig, type Properties, type Simplify, type StyleDefinition, type StyleItem, type ToKebab, type UnionNumber, type UnionString, type UnionToIntersection, appendAutocompleteCssPropertyValues, appendAutocompleteExtraCssProperties, appendAutocompleteExtraProperties, appendAutocompletePropertyValues, appendAutocompleteSelectors, appendAutocompleteStyleItemStrings, createDefineEngineConfigFn, createDefineEnginePluginFn, createEngine, defineEngineConfig, defineEnginePlugin, renderCSSStyleBlocks };
package/dist/index.d.mts CHANGED
@@ -7,12 +7,12 @@ declare class Engine {
7
7
  config: ResolvedEngineConfig;
8
8
  extract: ExtractFn;
9
9
  store: {
10
- atomicNames: Map<string, string>;
11
- atomicRules: Map<string, AtomicStyle>;
10
+ atomicStyleIds: Map<string, string>;
11
+ atomicStyles: Map<string, AtomicStyle>;
12
12
  };
13
13
  constructor(config: ResolvedEngineConfig);
14
14
  notifyPreflightUpdated(): void;
15
- notifyAtomicRuleAdded(): void;
15
+ notifyAtomicStyleAdded(): void;
16
16
  notifyAutocompleteConfigUpdated(): void;
17
17
  appendAutocompleteSelectors(...selectors: string[]): void;
18
18
  appendAutocompleteStyleItemStrings(...styleItemStrings: string[]): void;
@@ -21,10 +21,11 @@ declare class Engine {
21
21
  appendAutocompletePropertyValues(property: string, ...tsTypes: string[]): void;
22
22
  appendAutocompleteCssPropertyValues(property: string, ...values: (string | number)[]): void;
23
23
  use(...itemList: StyleItem$1[]): Promise<string[]>;
24
- renderPreviewStyles(...itemList: StyleItem$1[]): Promise<string>;
25
- renderStyles(): string;
26
- renderPreflights(): string;
27
- renderAtomicStyles(): string;
24
+ renderPreflights(isFormatted: boolean): string;
25
+ renderAtomicStyles(isFormatted: boolean, options?: {
26
+ atomicStyleIds?: string[];
27
+ isPreview?: boolean;
28
+ }): string;
28
29
  }
29
30
 
30
31
  type DefineHooks<Hooks extends Record<string, [type: 'sync' | 'async', payload: any, returnValue?: any]>> = Hooks;
@@ -37,7 +38,7 @@ type EngineHooksDefinition<_CustomConfig, _Selector extends string, _CSSProperty
37
38
  transformStyleItems: ['async', styleItems: _StyleItem[]];
38
39
  transformStyleDefinitions: ['async', styleDefinitions: _StyleDefinition[]];
39
40
  preflightUpdated: ['sync', void];
40
- atomicRuleAdded: ['sync', void];
41
+ atomicStyleAdded: ['sync', void];
41
42
  autocompleteConfigUpdated: ['sync', void];
42
43
  }>;
43
44
  type EnginePluginHooksOptions<_CustomConfig, _Selector extends string, _CSSProperty extends string, _Properties, _StyleDefinition, _StyleItem> = {
@@ -100,9 +101,17 @@ interface AtomicStyleContent {
100
101
  value: string[];
101
102
  }
102
103
  interface AtomicStyle {
103
- name: string;
104
+ id: string;
104
105
  content: AtomicStyleContent;
105
106
  }
107
+ interface CSSStyleBlockBody {
108
+ properties: {
109
+ property: string;
110
+ value: string;
111
+ }[];
112
+ children?: CSSStyleBlocks;
113
+ }
114
+ type CSSStyleBlocks = Map<string, CSSStyleBlockBody>;
106
115
 
107
116
  interface Frames<_Properties = Properties$1> {
108
117
  from: _Properties;
@@ -115,7 +124,7 @@ type KeyframesConfig<_Properties = Properties$1> = string | [name: string, frame
115
124
  autocomplete?: string[];
116
125
  };
117
126
 
118
- type PreflightFn = (engine: Engine) => string;
127
+ type PreflightFn = (engine: Engine, isFormatted: boolean) => string;
119
128
  /**
120
129
  * PreflightConfig can be a string or a function that returns a string.
121
130
  *
@@ -178,27 +187,27 @@ interface EngineConfig<_Plugins extends EnginePlugin[] = EnginePlugin[], _Select
178
187
  */
179
188
  plugins?: [..._Plugins];
180
189
  /**
181
- * Set the prefix for generated atomic class names.
190
+ * Set the prefix for generated atomic style id.
182
191
  *
183
192
  * @default ''
184
193
  * @example
185
194
  * ```ts
186
195
  * {
187
- * prefix: 'pika-' // Generated class names will be like 'pika-xxx'
196
+ * prefix: 'pika-' // Generated atomic id will be 'pika-xxx'
188
197
  * }
189
198
  * ```
190
199
  */
191
200
  prefix?: string;
192
201
  /**
193
- * Set the default selector format. '$$' will be replaced with the atomic style name.
202
+ * Set the default selector format. '$$' will be replaced with the atomic style id.
194
203
  *
195
204
  * @default '.$$'
196
205
  * @example
197
206
  * ```ts
198
207
  * {
199
- * defaultSelector: '.$$' // Use class attribute: <div class="a b c">
208
+ * defaultSelector: '.$$' // Use with class attribute: <div class="a b c">
200
209
  * // or
201
- * defaultSelector: '[data-pika~="$$"]' // Use attribute selector: <div data-pika="a b c">
210
+ * defaultSelector: '[data-pika~="$$"]' // Use with attribute selector: <div data-pika="a b c">
202
211
  * }
203
212
  * ```
204
213
  */
@@ -401,10 +410,11 @@ declare function appendAutocompleteExtraProperties(config: Pick<ResolvedEngineCo
401
410
  declare function appendAutocompleteExtraCssProperties(config: Pick<ResolvedEngineConfig, 'autocomplete'>, ...properties: string[]): void;
402
411
  declare function appendAutocompletePropertyValues(config: Pick<ResolvedEngineConfig, 'autocomplete'>, property: string, ...tsTypes: string[]): void;
403
412
  declare function appendAutocompleteCssPropertyValues(config: Pick<ResolvedEngineConfig, 'autocomplete'>, property: string, ...values: (string | number)[]): void;
413
+ declare function renderCSSStyleBlocks(blocks: CSSStyleBlocks, isFormatted: boolean, depth?: number): string;
404
414
 
405
415
  declare function createDefineEnginePluginFn<A extends Autocomplete = EmptyAutocomplete>(): <C extends Record<string, any>>(plugin: EnginePlugin<C, A["Selector"] | CSSSelectors, A["ExtraCssProperty"] | CSSProperty, Properties<A>, StyleDefinition<A>, StyleItem<A>>) => EnginePlugin<C>;
406
416
  declare const defineEnginePlugin: <C extends Record<string, any>>(plugin: EnginePlugin<C, CSSSelectors, keyof CSSProperties, Properties<EmptyAutocomplete>, StyleDefinition<EmptyAutocomplete>, StyleItem<EmptyAutocomplete>>) => EnginePlugin<C, string, string, Properties$1, StyleDefinition$1, StyleItem$1>;
407
417
  declare function createDefineEngineConfigFn<A extends Autocomplete = EmptyAutocomplete>(): <P extends EnginePlugin[] = []>(config: EngineConfig<P, A["Selector"] | CSSSelectors, A["ExtraCssProperty"] | CSSProperty, Properties<A>, StyleDefinition<A>, StyleItem<A>> & PluginsCustomConfig<P>) => EngineConfig<P> & PluginsCustomConfig<P>;
408
418
  declare const defineEngineConfig: <P extends EnginePlugin[] = []>(config: EngineConfig<P, CSSSelectors, keyof CSSProperties, Properties<EmptyAutocomplete>, StyleDefinition<EmptyAutocomplete>, StyleItem<EmptyAutocomplete>> & PluginsCustomConfig<P, {}>) => EngineConfig<P, string, string, Properties$1, StyleDefinition$1, StyleItem$1> & PluginsCustomConfig<P, {}>;
409
419
 
410
- export { type Arrayable, type Autocomplete, type Awaitable, type EmptyAutocomplete, Engine, type EngineConfig, type EnginePlugin, type FromKebab, type GetValue, type IsEqual, type PluginsCustomConfig, type Properties, type Simplify, type StyleDefinition, type StyleItem, type ToKebab, type UnionNumber, type UnionString, type UnionToIntersection, appendAutocompleteCssPropertyValues, appendAutocompleteExtraCssProperties, appendAutocompleteExtraProperties, appendAutocompletePropertyValues, appendAutocompleteSelectors, appendAutocompleteStyleItemStrings, createDefineEngineConfigFn, createDefineEnginePluginFn, createEngine, defineEngineConfig, defineEnginePlugin };
420
+ export { type Arrayable, type Autocomplete, type Awaitable, type CSSStyleBlockBody, type CSSStyleBlocks, type EmptyAutocomplete, Engine, type EngineConfig, type EnginePlugin, type FromKebab, type GetValue, type IsEqual, type PluginsCustomConfig, type Properties, type Simplify, type StyleDefinition, type StyleItem, type ToKebab, type UnionNumber, type UnionString, type UnionToIntersection, appendAutocompleteCssPropertyValues, appendAutocompleteExtraCssProperties, appendAutocompleteExtraProperties, appendAutocompletePropertyValues, appendAutocompleteSelectors, appendAutocompleteStyleItemStrings, createDefineEngineConfigFn, createDefineEnginePluginFn, createEngine, defineEngineConfig, defineEnginePlugin, renderCSSStyleBlocks };
package/dist/index.d.ts CHANGED
@@ -7,12 +7,12 @@ declare class Engine {
7
7
  config: ResolvedEngineConfig;
8
8
  extract: ExtractFn;
9
9
  store: {
10
- atomicNames: Map<string, string>;
11
- atomicRules: Map<string, AtomicStyle>;
10
+ atomicStyleIds: Map<string, string>;
11
+ atomicStyles: Map<string, AtomicStyle>;
12
12
  };
13
13
  constructor(config: ResolvedEngineConfig);
14
14
  notifyPreflightUpdated(): void;
15
- notifyAtomicRuleAdded(): void;
15
+ notifyAtomicStyleAdded(): void;
16
16
  notifyAutocompleteConfigUpdated(): void;
17
17
  appendAutocompleteSelectors(...selectors: string[]): void;
18
18
  appendAutocompleteStyleItemStrings(...styleItemStrings: string[]): void;
@@ -21,10 +21,11 @@ declare class Engine {
21
21
  appendAutocompletePropertyValues(property: string, ...tsTypes: string[]): void;
22
22
  appendAutocompleteCssPropertyValues(property: string, ...values: (string | number)[]): void;
23
23
  use(...itemList: StyleItem$1[]): Promise<string[]>;
24
- renderPreviewStyles(...itemList: StyleItem$1[]): Promise<string>;
25
- renderStyles(): string;
26
- renderPreflights(): string;
27
- renderAtomicStyles(): string;
24
+ renderPreflights(isFormatted: boolean): string;
25
+ renderAtomicStyles(isFormatted: boolean, options?: {
26
+ atomicStyleIds?: string[];
27
+ isPreview?: boolean;
28
+ }): string;
28
29
  }
29
30
 
30
31
  type DefineHooks<Hooks extends Record<string, [type: 'sync' | 'async', payload: any, returnValue?: any]>> = Hooks;
@@ -37,7 +38,7 @@ type EngineHooksDefinition<_CustomConfig, _Selector extends string, _CSSProperty
37
38
  transformStyleItems: ['async', styleItems: _StyleItem[]];
38
39
  transformStyleDefinitions: ['async', styleDefinitions: _StyleDefinition[]];
39
40
  preflightUpdated: ['sync', void];
40
- atomicRuleAdded: ['sync', void];
41
+ atomicStyleAdded: ['sync', void];
41
42
  autocompleteConfigUpdated: ['sync', void];
42
43
  }>;
43
44
  type EnginePluginHooksOptions<_CustomConfig, _Selector extends string, _CSSProperty extends string, _Properties, _StyleDefinition, _StyleItem> = {
@@ -100,9 +101,17 @@ interface AtomicStyleContent {
100
101
  value: string[];
101
102
  }
102
103
  interface AtomicStyle {
103
- name: string;
104
+ id: string;
104
105
  content: AtomicStyleContent;
105
106
  }
107
+ interface CSSStyleBlockBody {
108
+ properties: {
109
+ property: string;
110
+ value: string;
111
+ }[];
112
+ children?: CSSStyleBlocks;
113
+ }
114
+ type CSSStyleBlocks = Map<string, CSSStyleBlockBody>;
106
115
 
107
116
  interface Frames<_Properties = Properties$1> {
108
117
  from: _Properties;
@@ -115,7 +124,7 @@ type KeyframesConfig<_Properties = Properties$1> = string | [name: string, frame
115
124
  autocomplete?: string[];
116
125
  };
117
126
 
118
- type PreflightFn = (engine: Engine) => string;
127
+ type PreflightFn = (engine: Engine, isFormatted: boolean) => string;
119
128
  /**
120
129
  * PreflightConfig can be a string or a function that returns a string.
121
130
  *
@@ -178,27 +187,27 @@ interface EngineConfig<_Plugins extends EnginePlugin[] = EnginePlugin[], _Select
178
187
  */
179
188
  plugins?: [..._Plugins];
180
189
  /**
181
- * Set the prefix for generated atomic class names.
190
+ * Set the prefix for generated atomic style id.
182
191
  *
183
192
  * @default ''
184
193
  * @example
185
194
  * ```ts
186
195
  * {
187
- * prefix: 'pika-' // Generated class names will be like 'pika-xxx'
196
+ * prefix: 'pika-' // Generated atomic id will be 'pika-xxx'
188
197
  * }
189
198
  * ```
190
199
  */
191
200
  prefix?: string;
192
201
  /**
193
- * Set the default selector format. '$$' will be replaced with the atomic style name.
202
+ * Set the default selector format. '$$' will be replaced with the atomic style id.
194
203
  *
195
204
  * @default '.$$'
196
205
  * @example
197
206
  * ```ts
198
207
  * {
199
- * defaultSelector: '.$$' // Use class attribute: <div class="a b c">
208
+ * defaultSelector: '.$$' // Use with class attribute: <div class="a b c">
200
209
  * // or
201
- * defaultSelector: '[data-pika~="$$"]' // Use attribute selector: <div data-pika="a b c">
210
+ * defaultSelector: '[data-pika~="$$"]' // Use with attribute selector: <div data-pika="a b c">
202
211
  * }
203
212
  * ```
204
213
  */
@@ -401,10 +410,11 @@ declare function appendAutocompleteExtraProperties(config: Pick<ResolvedEngineCo
401
410
  declare function appendAutocompleteExtraCssProperties(config: Pick<ResolvedEngineConfig, 'autocomplete'>, ...properties: string[]): void;
402
411
  declare function appendAutocompletePropertyValues(config: Pick<ResolvedEngineConfig, 'autocomplete'>, property: string, ...tsTypes: string[]): void;
403
412
  declare function appendAutocompleteCssPropertyValues(config: Pick<ResolvedEngineConfig, 'autocomplete'>, property: string, ...values: (string | number)[]): void;
413
+ declare function renderCSSStyleBlocks(blocks: CSSStyleBlocks, isFormatted: boolean, depth?: number): string;
404
414
 
405
415
  declare function createDefineEnginePluginFn<A extends Autocomplete = EmptyAutocomplete>(): <C extends Record<string, any>>(plugin: EnginePlugin<C, A["Selector"] | CSSSelectors, A["ExtraCssProperty"] | CSSProperty, Properties<A>, StyleDefinition<A>, StyleItem<A>>) => EnginePlugin<C>;
406
416
  declare const defineEnginePlugin: <C extends Record<string, any>>(plugin: EnginePlugin<C, CSSSelectors, keyof CSSProperties, Properties<EmptyAutocomplete>, StyleDefinition<EmptyAutocomplete>, StyleItem<EmptyAutocomplete>>) => EnginePlugin<C, string, string, Properties$1, StyleDefinition$1, StyleItem$1>;
407
417
  declare function createDefineEngineConfigFn<A extends Autocomplete = EmptyAutocomplete>(): <P extends EnginePlugin[] = []>(config: EngineConfig<P, A["Selector"] | CSSSelectors, A["ExtraCssProperty"] | CSSProperty, Properties<A>, StyleDefinition<A>, StyleItem<A>> & PluginsCustomConfig<P>) => EngineConfig<P> & PluginsCustomConfig<P>;
408
418
  declare const defineEngineConfig: <P extends EnginePlugin[] = []>(config: EngineConfig<P, CSSSelectors, keyof CSSProperties, Properties<EmptyAutocomplete>, StyleDefinition<EmptyAutocomplete>, StyleItem<EmptyAutocomplete>> & PluginsCustomConfig<P, {}>) => EngineConfig<P, string, string, Properties$1, StyleDefinition$1, StyleItem$1> & PluginsCustomConfig<P, {}>;
409
419
 
410
- export { type Arrayable, type Autocomplete, type Awaitable, type EmptyAutocomplete, Engine, type EngineConfig, type EnginePlugin, type FromKebab, type GetValue, type IsEqual, type PluginsCustomConfig, type Properties, type Simplify, type StyleDefinition, type StyleItem, type ToKebab, type UnionNumber, type UnionString, type UnionToIntersection, appendAutocompleteCssPropertyValues, appendAutocompleteExtraCssProperties, appendAutocompleteExtraProperties, appendAutocompletePropertyValues, appendAutocompleteSelectors, appendAutocompleteStyleItemStrings, createDefineEngineConfigFn, createDefineEnginePluginFn, createEngine, defineEngineConfig, defineEnginePlugin };
420
+ export { type Arrayable, type Autocomplete, type Awaitable, type CSSStyleBlockBody, type CSSStyleBlocks, type EmptyAutocomplete, Engine, type EngineConfig, type EnginePlugin, type FromKebab, type GetValue, type IsEqual, type PluginsCustomConfig, type Properties, type Simplify, type StyleDefinition, type StyleItem, type ToKebab, type UnionNumber, type UnionString, type UnionToIntersection, appendAutocompleteCssPropertyValues, appendAutocompleteExtraCssProperties, appendAutocompleteExtraProperties, appendAutocompletePropertyValues, appendAutocompleteSelectors, appendAutocompleteStyleItemStrings, createDefineEngineConfigFn, createDefineEnginePluginFn, createEngine, defineEngineConfig, defineEnginePlugin, renderCSSStyleBlocks };
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- const ATOMIC_STYLE_NAME_PLACEHOLDER = "$$";
2
- const ATOMIC_STYLE_NAME_PLACEHOLDER_RE_GLOBAL = /\$\$/g;
1
+ const ATOMIC_STYLE_ID_PLACEHOLDER = "$$";
2
+ const ATOMIC_STYLE_ID_PLACEHOLDER_RE_GLOBAL = /\$\$/g;
3
3
 
4
4
  const chars = [..."abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"];
5
5
  const numOfChars = chars.length;
@@ -59,6 +59,25 @@ function appendAutocompleteCssPropertyValues(config, property, ...values) {
59
59
  const current = config.autocomplete.cssProperties.get(property) || [];
60
60
  config.autocomplete.cssProperties.set(property, [...current, ...values]);
61
61
  }
62
+ function renderCSSStyleBlocks(blocks, isFormatted, depth = 0) {
63
+ const blockIndent = isFormatted ? " ".repeat(depth) : "";
64
+ const blockBodyIndent = isFormatted ? " ".repeat(depth + 1) : "";
65
+ const selectorEnd = isFormatted ? " " : "";
66
+ const propertySpace = isFormatted ? " " : "";
67
+ const lineEnd = isFormatted ? "\n" : "";
68
+ const lines = [];
69
+ blocks.forEach(({ properties, children }, selector) => {
70
+ if (properties.length === 0 && children == null)
71
+ return;
72
+ lines.push(...[
73
+ `${blockIndent}${selector}${selectorEnd}{`,
74
+ ...properties.map(({ property, value }) => `${blockBodyIndent}${property}:${propertySpace}${value};`),
75
+ ...children != null ? [renderCSSStyleBlocks(children, isFormatted, depth + 1)] : [],
76
+ `${blockIndent}}`
77
+ ]);
78
+ });
79
+ return lines.join(lineEnd);
80
+ }
62
81
 
63
82
  function replaceBySplitAndJoin(str, split, mapFn, join) {
64
83
  let splitted = str.split(split);
@@ -79,13 +98,13 @@ function normalizeSelectors({
79
98
  return [defaultSelector];
80
99
  const normalized = selectors.map((s) => s.replace(RE_SPLIT, ","));
81
100
  const lastSelector = selectors[selectors.length - 1];
82
- if (lastSelector.includes(ATOMIC_STYLE_NAME_PLACEHOLDER) === false && lastSelector.includes(DEFAULT_SELECTOR_PLACEHOLDER) === false) {
101
+ if (lastSelector.includes(ATOMIC_STYLE_ID_PLACEHOLDER) === false && lastSelector.includes(DEFAULT_SELECTOR_PLACEHOLDER) === false) {
83
102
  normalized.push(DEFAULT_SELECTOR_PLACEHOLDER);
84
103
  }
85
104
  return normalized.map(
86
105
  (s) => replaceBySplitAndJoin(
87
106
  s,
88
- ATOMIC_STYLE_NAME_PLACEHOLDER_RE_GLOBAL,
107
+ ATOMIC_STYLE_ID_PLACEHOLDER_RE_GLOBAL,
89
108
  (a) => replaceBySplitAndJoin(
90
109
  a,
91
110
  ATTRIBUTE_SUFFIX_MATCH_RE_GLOBAL,
@@ -97,7 +116,7 @@ function normalizeSelectors({
97
116
  ),
98
117
  ATTRIBUTE_SUFFIX_MATCH
99
118
  ),
100
- ATOMIC_STYLE_NAME_PLACEHOLDER
119
+ ATOMIC_STYLE_ID_PLACEHOLDER
101
120
  )
102
121
  );
103
122
  }
@@ -194,7 +213,7 @@ const hooks = {
194
213
  transformStyleItems: (plugins, styleItems) => execAsyncHook(plugins, "transformStyleItems", styleItems),
195
214
  transformStyleDefinitions: (plugins, styleDefinitions) => execAsyncHook(plugins, "transformStyleDefinitions", styleDefinitions),
196
215
  preflightUpdated: (plugins) => execSyncHook(plugins, "preflightUpdated", void 0),
197
- atomicRuleAdded: (plugins) => execSyncHook(plugins, "atomicRuleAdded", void 0),
216
+ atomicStyleAdded: (plugins) => execSyncHook(plugins, "atomicStyleAdded", void 0),
198
217
  autocompleteConfigUpdated: (plugins) => execSyncHook(plugins, "autocompleteConfigUpdated", void 0)
199
218
  };
200
219
  const orderMap = /* @__PURE__ */ new Map([
@@ -266,15 +285,7 @@ function keyframes() {
266
285
  configList.forEach((config) => {
267
286
  const { name, frames, autocomplete: autocompleteAnimation } = resolveKeyframesConfig(config);
268
287
  if (frames != null) {
269
- const css = [
270
- `@keyframes ${name}{`,
271
- ...Object.entries(frames).map(([frame, properties]) => (
272
- // eslint-disable-next-line style/newline-per-chained-call
273
- `${frame}{${Object.entries(properties).map(([property, value]) => `${property}:${value}`).join(";")}}`
274
- )),
275
- "}"
276
- ].join("");
277
- allKeyframes.set(name, css);
288
+ allKeyframes.set(name, frames);
278
289
  }
279
290
  autocomplete.animationName.push(name);
280
291
  autocomplete.animation.push(`${name} `);
@@ -283,9 +294,9 @@ function keyframes() {
283
294
  });
284
295
  appendAutocompleteCssPropertyValues(resolvedConfig, "animationName", ...autocomplete.animationName);
285
296
  appendAutocompleteCssPropertyValues(resolvedConfig, "animation", ...autocomplete.animation);
286
- resolvedConfig.preflights.push((engine) => {
297
+ resolvedConfig.preflights.push((engine, isFormatted) => {
287
298
  const used = /* @__PURE__ */ new Set();
288
- engine.store.atomicRules.forEach(({ content: { property, value } }) => {
299
+ engine.store.atomicStyles.forEach(({ content: { property, value } }) => {
289
300
  if (property === "animationName") {
290
301
  value.forEach((name) => used.add(name));
291
302
  } else if (property === "animation") {
@@ -299,8 +310,25 @@ function keyframes() {
299
310
  });
300
311
  }
301
312
  });
302
- const content = Array.from(allKeyframes.entries()).filter(([name]) => used.has(name)).map(([, css]) => css).join("");
303
- return content;
313
+ return renderCSSStyleBlocks(
314
+ new Map(Array.from(allKeyframes.entries()).filter(([name]) => used.has(name)).map(([name, frames]) => [
315
+ `@keyframes ${name}`,
316
+ {
317
+ properties: [],
318
+ children: new Map(Object.entries(frames).map(([frame, properties]) => [
319
+ frame,
320
+ {
321
+ properties: Object.entries(properties).filter(([_, value]) => isNotNullish(value)).flatMap(([property, value]) => {
322
+ if (Array.isArray(value))
323
+ return value.map((v) => ({ property, value: String(v) }));
324
+ return { property, value: String(value) };
325
+ })
326
+ }
327
+ ]))
328
+ }
329
+ ])),
330
+ isFormatted
331
+ );
304
332
  });
305
333
  }
306
334
  });
@@ -662,15 +690,22 @@ function variables() {
662
690
  if (asProperty)
663
691
  appendAutocompleteExtraCssProperties(resolvedConfig, name);
664
692
  if (value != null)
665
- allVariables.set(name, `${name}:${value}`);
693
+ allVariables.set(name, value);
666
694
  });
667
- resolvedConfig.preflights.push((engine) => {
695
+ resolvedConfig.preflights.push((engine, isFormatted) => {
668
696
  const used = /* @__PURE__ */ new Set();
669
- engine.store.atomicRules.forEach(({ content: { value } }) => {
697
+ engine.store.atomicStyles.forEach(({ content: { value } }) => {
670
698
  value.flatMap(extractUsedVarNames).forEach((name) => used.add(normalizeVariableName(name)));
671
699
  });
672
- const content = Array.from(allVariables.entries()).filter(([name]) => used.has(name)).map(([, css]) => css).join(";");
673
- return content === "" ? "" : `:root{${content}}`;
700
+ return renderCSSStyleBlocks(
701
+ /* @__PURE__ */ new Map([[
702
+ ":root",
703
+ {
704
+ properties: Array.from(allVariables.entries()).filter(([name]) => used.has(name)).map(([name, value]) => ({ property: name, value }))
705
+ }
706
+ ]]),
707
+ isFormatted
708
+ );
674
709
  });
675
710
  }
676
711
  });
@@ -705,8 +740,8 @@ class Engine {
705
740
  config;
706
741
  extract;
707
742
  store = {
708
- atomicNames: /* @__PURE__ */ new Map(),
709
- atomicRules: /* @__PURE__ */ new Map()
743
+ atomicStyleIds: /* @__PURE__ */ new Map(),
744
+ atomicStyles: /* @__PURE__ */ new Map()
710
745
  };
711
746
  constructor(config) {
712
747
  this.config = config;
@@ -721,8 +756,8 @@ class Engine {
721
756
  notifyPreflightUpdated() {
722
757
  hooks.preflightUpdated(this.config.plugins);
723
758
  }
724
- notifyAtomicRuleAdded() {
725
- hooks.atomicRuleAdded(this.config.plugins);
759
+ notifyAtomicStyleAdded() {
760
+ hooks.atomicStyleAdded(this.config.plugins);
726
761
  }
727
762
  notifyAutocompleteConfigUpdated() {
728
763
  hooks.autocompleteConfigUpdated(this.config.plugins);
@@ -760,53 +795,39 @@ class Engine {
760
795
  transformStyleItems: (styleItems) => hooks.transformStyleItems(this.config.plugins, styleItems),
761
796
  extractStyleDefinition: (styleDefinition) => this.extract(styleDefinition)
762
797
  });
763
- const resolvedNames = [];
798
+ const resolvedIds = [];
764
799
  contents.forEach((content) => {
765
- const name = getAtomicStyleName({
800
+ const id = getAtomicStyleId({
766
801
  content,
767
802
  prefix: this.config.prefix,
768
- stored: this.store.atomicNames
803
+ stored: this.store.atomicStyleIds
769
804
  });
770
- resolvedNames.push(name);
771
- if (!this.store.atomicRules.has(name)) {
772
- const added = {
773
- name,
774
- content
775
- };
776
- this.store.atomicRules.set(name, added);
777
- this.notifyAtomicRuleAdded();
805
+ resolvedIds.push(id);
806
+ if (!this.store.atomicStyles.has(id)) {
807
+ this.store.atomicStyles.set(id, { id, content });
808
+ this.notifyAtomicStyleAdded();
778
809
  }
779
810
  });
780
- return [...unknown, ...resolvedNames];
781
- }
782
- async renderPreviewStyles(...itemList) {
783
- const nameList = await this.use(...itemList);
784
- const targets = nameList.map((name) => this.store.atomicRules.get(name)).filter(isNotNullish);
785
- return renderAtomicStyles({
786
- atomicRules: targets,
787
- isPreview: true
788
- });
789
- }
790
- renderStyles() {
791
- return [
792
- this.renderPreflights(),
793
- this.renderAtomicStyles()
794
- ].join("");
811
+ return [...unknown, ...resolvedIds];
795
812
  }
796
- renderPreflights() {
797
- return this.config.preflights.map((p) => p(this)).join("");
813
+ renderPreflights(isFormatted) {
814
+ const lineEnd = isFormatted ? "\n" : "";
815
+ return this.config.preflights.map((p) => p(this, isFormatted)).join(lineEnd);
798
816
  }
799
- renderAtomicStyles() {
817
+ renderAtomicStyles(isFormatted, options = {}) {
818
+ const { atomicStyleIds = null, isPreview = false } = options;
819
+ const atomicStyles = atomicStyleIds == null ? [...this.store.atomicStyles.values()] : atomicStyleIds.map((id) => this.store.atomicStyles.get(id)).filter(isNotNullish);
800
820
  return renderAtomicStyles({
801
- atomicRules: [...this.store.atomicRules.values()],
802
- isPreview: false
821
+ atomicStyles,
822
+ isPreview,
823
+ isFormatted
803
824
  });
804
825
  }
805
826
  }
806
827
  async function resolveEngineConfig(config) {
807
828
  const {
808
829
  prefix = "",
809
- defaultSelector = `.${ATOMIC_STYLE_NAME_PLACEHOLDER}`,
830
+ defaultSelector = `.${ATOMIC_STYLE_ID_PLACEHOLDER}`,
810
831
  plugins = [],
811
832
  preflights = [],
812
833
  autocomplete = {}
@@ -836,7 +857,7 @@ async function resolveEngineConfig(config) {
836
857
  autocomplete.cssProperties?.forEach(([property, value]) => appendAutocompleteCssPropertyValues(resolvedConfig, property, ...[value].flat()));
837
858
  return resolvedConfig;
838
859
  }
839
- function getAtomicStyleName({
860
+ function getAtomicStyleId({
840
861
  content,
841
862
  prefix,
842
863
  stored
@@ -846,9 +867,9 @@ function getAtomicStyleName({
846
867
  if (cached != null)
847
868
  return cached;
848
869
  const num = stored.size;
849
- const name = `${prefix}${numberToChars(num)}`;
850
- stored.set(key, name);
851
- return name;
870
+ const id = `${prefix}${numberToChars(num)}`;
871
+ stored.set(key, id);
872
+ return id;
852
873
  }
853
874
  function optimizeAtomicStyleContents(list) {
854
875
  const map = /* @__PURE__ */ new Map();
@@ -879,49 +900,32 @@ async function resolveStyleItemList({
879
900
  contents: optimizeAtomicStyleContents(list)
880
901
  };
881
902
  }
882
- function prepareAtomicStyleBlocks({
883
- atomicRules,
884
- isPreview
885
- }) {
903
+ function renderAtomicStyles(payload) {
904
+ const { atomicStyles, isPreview, isFormatted } = payload;
886
905
  const blocks = /* @__PURE__ */ new Map();
887
- atomicRules.forEach(({ name, content: { selector, property, value } }) => {
888
- const isValidSelector = selector.some((s) => s.includes(ATOMIC_STYLE_NAME_PLACEHOLDER));
906
+ atomicStyles.forEach(({ id, content: { selector, property, value } }) => {
907
+ const isValidSelector = selector.some((s) => s.includes(ATOMIC_STYLE_ID_PLACEHOLDER));
889
908
  if (isValidSelector === false || value == null)
890
909
  return;
891
910
  const renderObject = {
892
- selector: isPreview ? selector : selector.map((s) => s.replace(ATOMIC_STYLE_NAME_PLACEHOLDER_RE_GLOBAL, name)),
893
- content: Array.isArray(value) ? value.map((v) => `${property}:${v}`).join(";") : `${property}:${value}`
911
+ selector: isPreview ? selector : selector.map((s) => s.replace(ATOMIC_STYLE_ID_PLACEHOLDER_RE_GLOBAL, id)),
912
+ properties: value.map((v) => ({ property, value: v }))
894
913
  };
895
914
  let currentBlocks = blocks;
896
915
  for (let i = 0; i < renderObject.selector.length; i++) {
897
916
  const s = renderObject.selector[i];
898
- const block = currentBlocks.get(s) || { content: [] };
899
- const isLast = i === renderObject.selector.length - 1;
900
- if (isLast) {
901
- block.content.push(renderObject.content);
902
- } else {
903
- block.children ||= /* @__PURE__ */ new Map();
904
- }
905
- currentBlocks.set(s, block);
906
- if (isLast === false)
907
- currentBlocks = block.children;
917
+ const blockBody = currentBlocks.get(s) || { properties: [] };
918
+ const isLastSelector = i === renderObject.selector.length - 1;
919
+ if (isLastSelector)
920
+ blockBody.properties.push(...renderObject.properties);
921
+ else
922
+ blockBody.children ||= /* @__PURE__ */ new Map();
923
+ currentBlocks.set(s, blockBody);
924
+ if (isLastSelector === false)
925
+ currentBlocks = blockBody.children;
908
926
  }
909
927
  });
910
- return blocks;
911
- }
912
- function renderAtomicStyleBlocks(blocks) {
913
- let rendered = "";
914
- blocks.forEach((block, selector) => {
915
- rendered += `${selector}{${block.content.join(";")}`;
916
- if (block.children != null)
917
- rendered += renderAtomicStyleBlocks(block.children);
918
- rendered += "}";
919
- });
920
- return rendered;
921
- }
922
- function renderAtomicStyles(payload) {
923
- const blocks = prepareAtomicStyleBlocks(payload);
924
- return renderAtomicStyleBlocks(blocks);
928
+ return renderCSSStyleBlocks(blocks, isFormatted);
925
929
  }
926
930
 
927
931
  function createDefineEnginePluginFn() {
@@ -937,4 +941,4 @@ function createDefineEngineConfigFn() {
937
941
  }
938
942
  const defineEngineConfig = createDefineEngineConfigFn();
939
943
 
940
- export { appendAutocompleteCssPropertyValues, appendAutocompleteExtraCssProperties, appendAutocompleteExtraProperties, appendAutocompletePropertyValues, appendAutocompleteSelectors, appendAutocompleteStyleItemStrings, createDefineEngineConfigFn, createDefineEnginePluginFn, createEngine, defineEngineConfig, defineEnginePlugin };
944
+ export { appendAutocompleteCssPropertyValues, appendAutocompleteExtraCssProperties, appendAutocompleteExtraProperties, appendAutocompletePropertyValues, appendAutocompleteSelectors, appendAutocompleteStyleItemStrings, createDefineEngineConfigFn, createDefineEnginePluginFn, createEngine, defineEngineConfig, defineEnginePlugin, renderCSSStyleBlocks };
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
- "version": "0.0.8",
7
+ "version": "0.0.10",
8
8
  "author": "DevilTea <ch19980814@gmail.com>",
9
9
  "license": "MIT",
10
10
  "repository": {