@projectwallace/css-layer-tree 2.1.0 → 2.1.2

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,21 @@
1
+ import { CSSNode } from "@projectwallace/css-parser";
2
+
3
+ //#region src/TreeNode.d.ts
4
+ type Location = {
5
+ line: number;
6
+ column: number;
7
+ start: number;
8
+ end: number;
9
+ };
10
+ type TreeNode = {
11
+ name: string;
12
+ is_anonymous: boolean;
13
+ locations: Location[];
14
+ children: TreeNode[];
15
+ };
16
+ //#endregion
17
+ //#region src/index.d.ts
18
+ declare function layer_tree_from_ast(ast: CSSNode): TreeNode[];
19
+ declare function layer_tree(css: string): TreeNode[];
20
+ //#endregion
21
+ export { type Location, type TreeNode, layer_tree, layer_tree_from_ast };
package/dist/index.mjs ADDED
@@ -0,0 +1,124 @@
1
+ import { AT_RULE, LAYER_NAME, parse, traverse } from "@projectwallace/css-parser";
2
+ //#region src/TreeNode.ts
3
+ var LayerTreeNode = class LayerTreeNode {
4
+ name;
5
+ is_anonymous;
6
+ children;
7
+ locations;
8
+ constructor(name) {
9
+ this.name = name;
10
+ this.is_anonymous = false;
11
+ this.children = /* @__PURE__ */ new Map();
12
+ this.locations = [];
13
+ }
14
+ add_child(path, name, location) {
15
+ let current = this;
16
+ path.forEach((segment) => {
17
+ current = current.children.get(segment);
18
+ });
19
+ if (current.children.has(name)) {
20
+ if (location !== void 0) current.children.get(name).locations.push(location);
21
+ } else {
22
+ const new_node = new LayerTreeNode(name);
23
+ if (location !== void 0) new_node.locations.push(location);
24
+ new_node.is_anonymous = name.startsWith("__anonymous");
25
+ current.children.set(name, new_node);
26
+ }
27
+ }
28
+ to_plain_object() {
29
+ return {
30
+ name: this.name,
31
+ is_anonymous: this.is_anonymous,
32
+ locations: this.locations,
33
+ children: Array.from(this.children.values(), (child) => child.to_plain_object())
34
+ };
35
+ }
36
+ };
37
+ //#endregion
38
+ //#region src/index.ts
39
+ function get_layer_names(name) {
40
+ return name.split(".").map((s) => s.trim());
41
+ }
42
+ function create_location(node) {
43
+ return {
44
+ line: node.line,
45
+ column: node.column,
46
+ start: node.start,
47
+ end: node.end
48
+ };
49
+ }
50
+ function layer_tree_from_ast(ast) {
51
+ let current_stack = [];
52
+ let root = new LayerTreeNode("root");
53
+ let anonymous_counter = 0;
54
+ function get_anonymous_id() {
55
+ anonymous_counter++;
56
+ return `__anonymous-${anonymous_counter}__`;
57
+ }
58
+ traverse(ast, {
59
+ enter(node) {
60
+ if (node.type !== AT_RULE) return;
61
+ if (node.name === "layer") if (node.prelude) {
62
+ let groups = node.prelude.text.split(",").map((s) => s.trim());
63
+ if (!node.has_block) for (let name of groups) {
64
+ let parts = get_layer_names(name);
65
+ for (let i = 0; i < parts.length; i++) {
66
+ let path = parts.slice(0, i);
67
+ let layer_name = parts[i];
68
+ if (layer_name) {
69
+ let loc = i === parts.length - 1 ? create_location(node) : void 0;
70
+ root.add_child(path, layer_name, loc);
71
+ }
72
+ }
73
+ }
74
+ else {
75
+ let layer_names = [];
76
+ for (let child of node.prelude.children) if (child.type === LAYER_NAME) layer_names.push(child.text);
77
+ for (let i = 0; i < layer_names.length; i++) {
78
+ let layer_name = layer_names[i];
79
+ if (!layer_name) continue;
80
+ let path = layer_names.slice(0, i);
81
+ let loc = i === layer_names.length - 1 ? create_location(node) : void 0;
82
+ root.add_child(current_stack.concat(path), layer_name, loc);
83
+ }
84
+ current_stack.push(...layer_names);
85
+ }
86
+ } else {
87
+ let name = get_anonymous_id();
88
+ root.add_child(current_stack, name, create_location(node));
89
+ current_stack.push(name);
90
+ }
91
+ else if (node.name === "import" && node.prelude) {
92
+ for (let child of node.prelude.children) if (child.type === LAYER_NAME) {
93
+ if (child.name?.trim()) for (let layer_name of get_layer_names(child.name)) {
94
+ root.add_child(current_stack, layer_name, create_location(node));
95
+ current_stack.push(layer_name);
96
+ }
97
+ else {
98
+ let name = get_anonymous_id();
99
+ root.add_child([], name, create_location(node));
100
+ }
101
+ break;
102
+ }
103
+ }
104
+ },
105
+ leave(node) {
106
+ if (node.type !== AT_RULE) return;
107
+ if (node.name === "layer") if (node.prelude && node.has_block) {
108
+ let layer_count = 0;
109
+ for (let child of node.prelude.children) if (child.type === LAYER_NAME) layer_count++;
110
+ for (let i = 0; i < layer_count; i++) current_stack.pop();
111
+ } else current_stack.pop();
112
+ else if (node.name === "import") current_stack.length = 0;
113
+ }
114
+ });
115
+ return root.to_plain_object().children;
116
+ }
117
+ function layer_tree(css) {
118
+ return layer_tree_from_ast(parse(css, {
119
+ parse_selectors: false,
120
+ parse_values: false
121
+ }));
122
+ }
123
+ //#endregion
124
+ export { layer_tree, layer_tree_from_ast };
package/package.json CHANGED
@@ -1,61 +1,61 @@
1
1
  {
2
- "name": "@projectwallace/css-layer-tree",
3
- "version": "2.1.0",
4
- "description": "Discover the composition of your CSS @layers in a tree-based format.",
5
- "repository": {
6
- "type": "git",
7
- "url": "git+https://github.com/projectwallace/css-layer-tree.git"
8
- },
9
- "author": {
10
- "name": "Bart Veneman"
11
- },
12
- "homepage": "https://github.com/projectwallace/css-layer-tree",
13
- "issues": "https://github.com/projectwallace/css-layer-tree/issues",
14
- "license": "MIT",
15
- "engines": {
16
- "node": ">=18.0.0"
17
- },
18
- "type": "module",
19
- "main": "./dist/css-layer-tree.js",
20
- "types": "./index.d.ts",
21
- "exports": {
22
- "types": "./index.d.ts",
23
- "default": "./dist/css-layer-tree.js"
24
- },
25
- "scripts": {
26
- "build": "vite build",
27
- "test": "c8 --reporter=lcov uvu",
28
- "check": "tsc --noEmit",
29
- "prettier": "prettier --check src/**/*.js test/**/*.js"
30
- },
31
- "devDependencies": {
32
- "@codecov/vite-plugin": "^1.2.1",
33
- "c8": "^10.1.2",
34
- "prettier": "^3.3.3",
35
- "typescript": "5.4.2",
36
- "uvu": "^0.5.6",
37
- "vite": "^5.4.10"
38
- },
39
- "files": [
40
- "dist",
41
- "index.d.ts"
42
- ],
43
- "keywords": [
44
- "css",
45
- "stylesheet",
46
- "layer",
47
- "layers",
48
- "composition",
49
- "architecture",
50
- "tree"
51
- ],
52
- "prettier": {
53
- "semi": false,
54
- "useTabs": true,
55
- "printWidth": 140,
56
- "singleQuote": true
57
- },
58
- "dependencies": {
59
- "@projectwallace/css-parser": "^0.12.2"
60
- }
2
+ "name": "@projectwallace/css-layer-tree",
3
+ "version": "2.1.2",
4
+ "description": "Discover the composition of your CSS @layers in a tree-based format.",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/projectwallace/css-layer-tree.git"
8
+ },
9
+ "author": {
10
+ "name": "Bart Veneman"
11
+ },
12
+ "homepage": "https://github.com/projectwallace/css-layer-tree",
13
+ "issues": "https://github.com/projectwallace/css-layer-tree/issues",
14
+ "license": "MIT",
15
+ "engines": {
16
+ "node": ">=18.0.0"
17
+ },
18
+ "type": "module",
19
+ "main": "./dist/index.mjs",
20
+ "types": "./dist/index.d.mts",
21
+ "exports": {
22
+ "types": "./dist/index.d.mts",
23
+ "default": "./dist/index.mjs"
24
+ },
25
+ "scripts": {
26
+ "build": "tsdown",
27
+ "test": "vitest",
28
+ "check": "tsc --noEmit",
29
+ "lint": "oxlint"
30
+ },
31
+ "devDependencies": {
32
+ "@codecov/rollup-plugin": "^1.9.1",
33
+ "oxlint": "^1.51.0",
34
+ "prettier": "^3.3.3",
35
+ "publint": "^0.3.18",
36
+ "tsdown": "^0.21.0",
37
+ "typescript": "5.9.3",
38
+ "vitest": "^4.0.0"
39
+ },
40
+ "files": [
41
+ "dist"
42
+ ],
43
+ "keywords": [
44
+ "css",
45
+ "stylesheet",
46
+ "layer",
47
+ "layers",
48
+ "composition",
49
+ "architecture",
50
+ "tree"
51
+ ],
52
+ "prettier": {
53
+ "semi": false,
54
+ "useTabs": true,
55
+ "printWidth": 140,
56
+ "singleQuote": true
57
+ },
58
+ "dependencies": {
59
+ "@projectwallace/css-parser": "^0.13.5"
60
+ }
61
61
  }
@@ -1,125 +0,0 @@
1
- import { traverse as g, AT_RULE as m, LAYER_NAME as f, parse as b } from "@projectwallace/css-parser";
2
- class _ {
3
- /** @param {string} name */
4
- constructor(t) {
5
- this.name = t, this.is_anonymous = !1, this.children = /* @__PURE__ */ new Map(), this.locations = [];
6
- }
7
- /**
8
- * @param {string[]} path
9
- * @param {string} name
10
- * @param {T} location
11
- */
12
- add_child(t, r, n) {
13
- let a = this;
14
- if (t.forEach((e) => {
15
- a = a.children.get(e);
16
- }), a.children.has(r))
17
- n !== void 0 && a.children.get(r).locations.push(n);
18
- else {
19
- const e = new _(r);
20
- n !== void 0 && e.locations.push(n), e.is_anonymous = r.startsWith("__anonymous"), a.children.set(r, e);
21
- }
22
- }
23
- /**
24
- * @typedef PlainObject
25
- * @property {string} name
26
- * @property {boolean} is_anonymous
27
- * @property {T[]} locations
28
- * @property {PlainObject[]} children
29
- */
30
- /**
31
- * Convert the tree to a plain object for easy testing
32
- * @returns {PlainObject}
33
- */
34
- to_plain_object() {
35
- return {
36
- name: this.name,
37
- is_anonymous: this.is_anonymous,
38
- locations: this.locations,
39
- children: Array.from(this.children.values(), (t) => t.to_plain_object())
40
- };
41
- }
42
- }
43
- function h(s) {
44
- return s.split(".").map((t) => t.trim());
45
- }
46
- function u(s) {
47
- return {
48
- line: s.line,
49
- column: s.column,
50
- start: s.start,
51
- end: s.end
52
- };
53
- }
54
- function k(s) {
55
- let t = [], r = new _("root"), n = 0;
56
- function a() {
57
- return n++, `__anonymous-${n}__`;
58
- }
59
- return g(s, {
60
- enter(e) {
61
- if (e.type === m) {
62
- if (e.name === "layer")
63
- if (e.prelude) {
64
- let i = e.prelude.text.split(",").map((l) => l.trim());
65
- if (e.has_block)
66
- for (let l of e.prelude.children)
67
- l.type === f && (r.add_child(t, l.text, u(e)), t.push(l.text));
68
- else
69
- for (let l of i) {
70
- let o = h(l);
71
- for (let c = 0; c < o.length; c++) {
72
- let d = o.slice(0, c), p = o[c];
73
- if (p) {
74
- let y = c === o.length - 1 ? u(e) : void 0;
75
- r.add_child(d, p, y);
76
- }
77
- }
78
- }
79
- } else {
80
- let i = a();
81
- r.add_child(t, i, u(e)), t.push(i);
82
- }
83
- else if (e.name === "import" && e.prelude) {
84
- for (let i of e.prelude.children)
85
- if (i.type === f) {
86
- if (i.name.trim())
87
- for (let l of h(i.name))
88
- r.add_child(t, l, u(e)), t.push(l);
89
- else {
90
- let l = a();
91
- r.add_child([], l, u(e));
92
- }
93
- break;
94
- }
95
- }
96
- }
97
- },
98
- leave(e) {
99
- if (e.type === m)
100
- if (e.name === "layer")
101
- if (e.prelude && e.has_block) {
102
- for (let i of e.prelude.children)
103
- if (i.type === f) {
104
- let l = h(i.text);
105
- for (let o = 0; o < l.length; o++)
106
- t.pop();
107
- break;
108
- }
109
- } else
110
- t.pop();
111
- else e.name === "import" && (t.length = 0);
112
- }
113
- }), r.to_plain_object().children;
114
- }
115
- function v(s) {
116
- let t = b(s, {
117
- parse_selectors: !1,
118
- parse_values: !1
119
- });
120
- return k(t);
121
- }
122
- export {
123
- v as layer_tree,
124
- k as layer_tree_from_ast
125
- };
package/index.d.ts DELETED
@@ -1,18 +0,0 @@
1
- import { type CssNode } from "css-tree";
2
-
3
- export type Location = {
4
- line: number;
5
- column: number;
6
- start: number;
7
- end: number;
8
- }
9
-
10
- export type TreeNode = {
11
- name: string;
12
- is_anonymous: boolean;
13
- children: TreeNode[];
14
- locations: Location[];
15
- }
16
-
17
- export function layer_tree_from_ast(ast: CssNode): TreeNode[];
18
- export function layer_tree(css: string): TreeNode[];