@mlut/core 1.0.0 → 2.0.1

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.
@@ -1,18 +1,19 @@
1
1
  export declare class JitEngine {
2
2
  private utils;
3
- private inputFilePath;
4
3
  private inputFileDir;
5
4
  private sassModuleName;
6
5
  private inputFileCache;
7
- private generationDebounce;
8
6
  private readonly defaultSassConfig;
9
7
  private readonly utilsByFile;
10
8
  private readonly utilsRegexps;
11
9
  private readonly configRegexps;
12
10
  init([inputPath, inputContent]?: [string | undefined, string | undefined]): Promise<void>;
13
- putAndGenerateCss(id: string, content: string): Promise<string | undefined>;
11
+ putContent(id: string, content: string | undefined): void;
12
+ deleteContent(id: string): boolean;
13
+ updateSassConfig(content: string): Promise<void>;
14
+ generateCss(): Promise<string>;
14
15
  private extractUtils;
15
- private normalizeClassNameStr;
16
+ private filterAndProcessClassStr;
16
17
  private extractUserSassConfig;
17
18
  private loadUtils;
18
19
  }
@@ -8,82 +8,78 @@ const sass = await import('sass-embedded')
8
8
  const __dirname = new URL('.', import.meta.url).pathname;
9
9
  export class JitEngine {
10
10
  utils = new Set();
11
- inputFilePath = '';
12
11
  inputFileDir = __dirname;
13
12
  sassModuleName = 'tools';
14
13
  inputFileCache = '@use "../sass/tools";';
15
- generationDebounce;
16
14
  defaultSassConfig = '@use "sass:map";\n @use "../sass/tools/settings" as ml;';
17
15
  utilsByFile = new Map();
18
16
  utilsRegexps = {
19
- quotedContent: /"\n?[^"]*?[A-Z][^"\n]*\n?"/g,
20
- singleQuotedContent: /'\n?[^']*?[A-Z][^'\n]*\n?'/g,
17
+ quotedContent: /"\n?[^"]*[^"\n]*\n?"/g,
18
+ singleQuotedContent: /'\n?[^']*[^'\n]*\n?'/g,
19
+ backtickQuotedContent: /`\n?[^`]*[^`\n]*\n?`/g,
21
20
  tooMoreSpaces: /\s{2,}|\n/g,
21
+ escapedQuotes: /\\['"`]/g,
22
22
  utilName: /^-?[A-Z]{1}[a-zA-Z]*/,
23
+ uppercaseLetter: /[A-Z]/,
23
24
  };
24
25
  configRegexps = {
25
26
  userSettings: /@use ['"][^'"]*(tools|mlut|core)['"](\s*as\s+[\w]+)?\s+with\s*\(([^;]+)\);/s,
26
27
  sassModuleName: /@use ['"][^'"]*(tools|mlut|core)['"]\s*;/s,
27
28
  };
28
29
  async init([inputPath, inputContent] = ['', '']) {
30
+ if (this.utils.size) {
31
+ return;
32
+ }
29
33
  let sassConfig = this.defaultSassConfig;
30
34
  if (inputPath && inputContent) {
31
- this.inputFilePath = path.join(process.cwd(), inputPath);
32
- this.inputFileDir = path.dirname(this.inputFilePath);
35
+ this.inputFileDir = path.dirname(path.resolve(process.cwd(), inputPath));
33
36
  this.inputFileCache = inputContent;
34
37
  sassConfig = this.extractUserSassConfig(inputContent);
35
38
  }
36
39
  await this.loadUtils(sassConfig);
37
40
  }
38
- async putAndGenerateCss(id, content) {
41
+ putContent(id, content) {
42
+ if (!content) {
43
+ return;
44
+ }
45
+ this.utilsByFile.set(id, this.extractUtils(content));
46
+ }
47
+ deleteContent(id) {
48
+ return this.utilsByFile.delete(id);
49
+ }
50
+ async updateSassConfig(content) {
51
+ this.inputFileCache = content;
52
+ const sassConfig = this.extractUserSassConfig(content);
53
+ if (sassConfig) {
54
+ await this.loadUtils(sassConfig);
55
+ }
56
+ }
57
+ async generateCss() {
39
58
  if (this.utils.size === 0) {
40
59
  logger.warn('Config with utilities is not loaded!');
41
60
  return '';
42
61
  }
43
- if (id === this.inputFilePath) {
44
- this.inputFileCache = content;
45
- const sassConfig = this.extractUserSassConfig(content);
46
- if (sassConfig) {
47
- await this.loadUtils(sassConfig);
48
- }
49
- }
50
- else if (content) {
51
- this.utilsByFile.set(id, this.extractUtils(content));
52
- }
53
- else {
54
- this.utilsByFile.delete(id);
62
+ if (this.utilsByFile.size === 0) {
63
+ logger.warn('No content to generate CSS was found!');
64
+ return '';
55
65
  }
56
- return new Promise((resolve) => {
57
- //eslint-disable-next-line
58
- let timeout;
59
- clearTimeout(this.generationDebounce);
60
- this.generationDebounce = setTimeout(async () => {
61
- clearTimeout(timeout);
62
- const allUniqueUtils = [...new Set([...this.utilsByFile.values()].flat())];
63
- const applyStr = `\n@include ${this.sassModuleName}.apply(${JSON.stringify(allUniqueUtils)},(),true);`;
64
- // `compileStringAsync` is almost always faster than `compile` in sass-embedded
65
- const css = await sass.compileStringAsync(this.inputFileCache + applyStr, { loadPaths: [this.inputFileDir, 'node_modules'] }).then(({ css }) => css, (e) => (logger.error('Sass compilation error.', e), undefined));
66
- resolve(css);
67
- }, 100);
68
- timeout = setTimeout(() => resolve(undefined), 300);
69
- });
66
+ const allUniqueUtils = [...new Set([...this.utilsByFile.values()].flat())];
67
+ const applyStr = `\n@include ${this.sassModuleName}.apply(${JSON.stringify(allUniqueUtils)},(),true);`;
68
+ return sass.compileStringAsync(this.inputFileCache + applyStr, { loadPaths: [this.inputFileDir, 'node_modules'] }).then(({ css }) => css, (e) => (logger.error('Sass compilation error.', e), ''));
70
69
  }
71
70
  extractUtils(content) {
72
- const allClassNames = [];
73
- const quotedClassNames = content
71
+ let fixedContent = content.replace(this.utilsRegexps.escapedQuotes, '');
72
+ const allClassNames = fixedContent
74
73
  .match(this.utilsRegexps.quotedContent)
75
- //eslint-disable-next-line
76
- ?.map(this.normalizeClassNameStr, this);
77
- const singleQuotedClassNames = content
78
- .replace(this.utilsRegexps.quotedContent, '')
74
+ ?.reduce(this.filterAndProcessClassStr, []) ?? [];
75
+ fixedContent = fixedContent.replace(this.utilsRegexps.quotedContent, '');
76
+ fixedContent
79
77
  .match(this.utilsRegexps.singleQuotedContent)
80
- //eslint-disable-next-line
81
- ?.map(this.normalizeClassNameStr, this);
82
- for (const item of [quotedClassNames, singleQuotedClassNames]) {
83
- if (item instanceof Array) {
84
- allClassNames.push(...item);
85
- }
86
- }
78
+ ?.reduce(this.filterAndProcessClassStr, allClassNames);
79
+ fixedContent
80
+ .replace(this.utilsRegexps.singleQuotedContent, '')
81
+ .match(this.utilsRegexps.backtickQuotedContent)
82
+ ?.reduce(this.filterAndProcessClassStr, allClassNames);
87
83
  return [...allClassNames.join(' ').split(' ').reduce((acc, cssClass) => {
88
84
  const utility = cssClass.split('_').find((str) => (this.utilsRegexps.utilName.test(str)));
89
85
  if (utility) {
@@ -95,9 +91,12 @@ export class JitEngine {
95
91
  return acc;
96
92
  }, new Set())];
97
93
  }
98
- normalizeClassNameStr(str) {
99
- return str.replace(this.utilsRegexps.tooMoreSpaces, ' ').slice(1, -1);
100
- }
94
+ filterAndProcessClassStr = (acc, str) => {
95
+ if (this.utilsRegexps.uppercaseLetter.test(str)) {
96
+ acc.push(str.replace(this.utilsRegexps.tooMoreSpaces, ' ').slice(1, -1));
97
+ }
98
+ return acc;
99
+ };
101
100
  extractUserSassConfig(content) {
102
101
  let matchResult = content.match(this.configRegexps.userSettings);
103
102
  if (matchResult != null) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mlut/core",
3
- "version": "1.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "Atomic CSS toolkit with Sass and ergonomics for creating styles of any complexity",
5
5
  "author": "mr150",
6
6
  "type": "module",
@@ -27,10 +27,10 @@
27
27
  "url": "https://github.com/mr150/mlut/issues"
28
28
  },
29
29
  "exports": {
30
- ".": {
31
- "default": "./dist/index.js"
32
- }
33
- },
30
+ ".": {
31
+ "default": "./dist/index.js"
32
+ }
33
+ },
34
34
  "scripts": {
35
35
  "build": "rm -rf dist && tsc && cp src/sass dist/ -r"
36
36
  },
@@ -43,6 +43,6 @@
43
43
  "@types/node": "^20.10.5",
44
44
  "sass-embedded": "^1.71.0",
45
45
  "sass": "^1.71.0",
46
- "typescript": "^5.3.3"
46
+ "typescript": "^4.8.0"
47
47
  }
48
48
  }