@gomeniucivan/ui 1.0.54 → 1.0.55
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.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +95 -95
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +95 -95
- package/dist/index.mjs.map +1 -1
- package/loader.js +16 -115
- package/package.json +3 -2
- package/scripts/stylePathTransform.js +229 -0
package/loader.js
CHANGED
|
@@ -23,13 +23,10 @@
|
|
|
23
23
|
* use: [{ loader: require.resolve('@gomeniucivan/ui/loader'), options: { rootDir: __dirname } }],
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
-
'use strict';
|
|
27
|
-
|
|
28
|
-
const nodePath = require('path');
|
|
29
|
-
|
|
30
|
-
/** Functions whose calls get a `{ path }` second argument injected. */
|
|
31
|
-
const TARGET_FNS = ['createStaticStyles', 'createStyles'];
|
|
32
|
-
const CALL_RE = new RegExp(`(?:${TARGET_FNS.join('|')})\\s*\\(`, 'g');
|
|
26
|
+
'use strict';
|
|
27
|
+
|
|
28
|
+
const nodePath = require('path');
|
|
29
|
+
const { injectStylePath } = require('./scripts/stylePathTransform');
|
|
33
30
|
|
|
34
31
|
/**
|
|
35
32
|
* Resolve the project root directory.
|
|
@@ -56,112 +53,16 @@ function resolveRoot(loaderContext) {
|
|
|
56
53
|
return process.cwd();
|
|
57
54
|
}
|
|
58
55
|
|
|
59
|
-
module.exports = function injectStylePathLoader(source) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
// Skip the factory implementation files themselves
|
|
67
|
-
if (
|
|
68
|
-
(resourcePath.includes('createStaticStyles') || resourcePath.includes('createStyles')) &&
|
|
69
|
-
resourcePath.endsWith('index.ts')
|
|
70
|
-
) {
|
|
71
|
-
return source;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const rootDir = resolveRoot(this);
|
|
75
|
-
|
|
76
|
-
// Relative path from project root, forward slashes, no extension
|
|
77
|
-
const filePath = nodePath
|
|
56
|
+
module.exports = function injectStylePathLoader(source) {
|
|
57
|
+
const resourcePath = this.resourcePath.replace(/\\/g, '/');
|
|
58
|
+
|
|
59
|
+
const rootDir = resolveRoot(this);
|
|
60
|
+
|
|
61
|
+
// Relative path from project root, forward slashes, no extension
|
|
62
|
+
const filePath = nodePath
|
|
78
63
|
.relative(rootDir, this.resourcePath)
|
|
79
|
-
.replace(/\\/g, '/')
|
|
80
|
-
.replace(/\.\w+$/, '');
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
let m;
|
|
85
|
-
while ((m = CALL_RE.exec(source)) !== null) {
|
|
86
|
-
// Skip if inside a comment
|
|
87
|
-
const lineStart = source.lastIndexOf('\n', m.index) + 1;
|
|
88
|
-
const lineText = source.slice(lineStart, m.index).trimStart();
|
|
89
|
-
if (lineText.startsWith('*') || lineText.startsWith('//')) continue;
|
|
90
|
-
positions.push(m.index + m[0].length); // right after opening `(`
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (positions.length === 0) return source;
|
|
94
|
-
|
|
95
|
-
// Process in reverse so indices don't shift
|
|
96
|
-
let result = source;
|
|
97
|
-
for (let ci = positions.length - 1; ci >= 0; ci--) {
|
|
98
|
-
const afterParen = positions[ci];
|
|
99
|
-
|
|
100
|
-
// Count parens to find matching close (skip strings and template literals)
|
|
101
|
-
let depth = 1;
|
|
102
|
-
let closeIdx = -1;
|
|
103
|
-
let inStr = false;
|
|
104
|
-
let strCh = '';
|
|
105
|
-
let inTpl = false;
|
|
106
|
-
let tplDepth = 0;
|
|
107
|
-
|
|
108
|
-
for (let i = afterParen; i < result.length; i++) {
|
|
109
|
-
const ch = result[i];
|
|
110
|
-
const prev = i > 0 ? result[i - 1] : '';
|
|
111
|
-
|
|
112
|
-
if (inStr) {
|
|
113
|
-
if (ch === strCh && prev !== '\\') inStr = false;
|
|
114
|
-
continue;
|
|
115
|
-
}
|
|
116
|
-
if (inTpl) {
|
|
117
|
-
if (ch === '`' && prev !== '\\') {
|
|
118
|
-
inTpl = false;
|
|
119
|
-
continue;
|
|
120
|
-
}
|
|
121
|
-
if (ch === '$' && result[i + 1] === '{') {
|
|
122
|
-
tplDepth++;
|
|
123
|
-
i++;
|
|
124
|
-
continue;
|
|
125
|
-
}
|
|
126
|
-
if (ch === '}' && tplDepth > 0) {
|
|
127
|
-
tplDepth--;
|
|
128
|
-
continue;
|
|
129
|
-
}
|
|
130
|
-
continue;
|
|
131
|
-
}
|
|
132
|
-
if (ch === '"' || ch === "'") {
|
|
133
|
-
inStr = true;
|
|
134
|
-
strCh = ch;
|
|
135
|
-
continue;
|
|
136
|
-
}
|
|
137
|
-
if (ch === '`') {
|
|
138
|
-
inTpl = true;
|
|
139
|
-
tplDepth = 0;
|
|
140
|
-
continue;
|
|
141
|
-
}
|
|
142
|
-
if (ch === '(') depth++;
|
|
143
|
-
if (ch === ')') {
|
|
144
|
-
depth--;
|
|
145
|
-
if (depth === 0) {
|
|
146
|
-
closeIdx = i;
|
|
147
|
-
break;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
if (closeIdx === -1) continue;
|
|
153
|
-
|
|
154
|
-
// Skip if already has a path option
|
|
155
|
-
const inner = result.slice(afterParen, closeIdx);
|
|
156
|
-
if (inner.includes('path:')) continue;
|
|
157
|
-
|
|
158
|
-
const hasTrailingComma = /,\s*$/.test(inner);
|
|
159
|
-
const pathArg = hasTrailingComma
|
|
160
|
-
? ` { path: '${filePath}' }`
|
|
161
|
-
: `, { path: '${filePath}' }`;
|
|
162
|
-
|
|
163
|
-
result = result.slice(0, closeIdx) + pathArg + result.slice(closeIdx);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return result;
|
|
167
|
-
};
|
|
64
|
+
.replace(/\\/g, '/')
|
|
65
|
+
.replace(/\.\w+$/, '');
|
|
66
|
+
|
|
67
|
+
return injectStylePath(source, filePath, resourcePath);
|
|
68
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gomeniucivan/ui",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.55",
|
|
4
4
|
"private": false,
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"**/*.css"
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
"files": [
|
|
22
22
|
"dist",
|
|
23
23
|
"loader.js",
|
|
24
|
-
"next-plugin.js"
|
|
24
|
+
"next-plugin.js",
|
|
25
|
+
"scripts/stylePathTransform.js"
|
|
25
26
|
],
|
|
26
27
|
"scripts": {
|
|
27
28
|
"build": "tsup",
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Functions whose calls get a `{ path }` option injected.
|
|
5
|
+
*/
|
|
6
|
+
const TARGET_FNS = ['createStaticStyles', 'createStyles'];
|
|
7
|
+
const CALL_RE = new RegExp(`(?:${TARGET_FNS.join('|')})\\s*\\(`, 'g');
|
|
8
|
+
|
|
9
|
+
const hasPathProperty = (text) => /\bpath\s*:/.test(text);
|
|
10
|
+
|
|
11
|
+
const escapePathValue = (value) => value.replace(/\\/g, '/').replace(/'/g, "\\'");
|
|
12
|
+
|
|
13
|
+
const injectPathIntoObjectLiteral = (objectText, pathValue) => {
|
|
14
|
+
const trimmed = objectText.trim();
|
|
15
|
+
|
|
16
|
+
if (!trimmed.startsWith('{') || !trimmed.endsWith('}')) return null;
|
|
17
|
+
if (hasPathProperty(trimmed)) return objectText;
|
|
18
|
+
|
|
19
|
+
const body = trimmed.slice(1, -1).trim();
|
|
20
|
+
const injected =
|
|
21
|
+
body.length === 0
|
|
22
|
+
? `{ path: '${escapePathValue(pathValue)}' }`
|
|
23
|
+
: `{ path: '${escapePathValue(pathValue)}', ${body} }`;
|
|
24
|
+
|
|
25
|
+
const leading = objectText.match(/^\s*/)?.[0] ?? '';
|
|
26
|
+
const trailing = objectText.match(/\s*$/)?.[0] ?? '';
|
|
27
|
+
return `${leading}${injected}${trailing}`;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Find the matching `)` for a call starting right after `(` and collect
|
|
32
|
+
* top-level argument commas.
|
|
33
|
+
*/
|
|
34
|
+
const findCallBoundaries = (source, afterParen) => {
|
|
35
|
+
let depth = 1;
|
|
36
|
+
let braceDepth = 0;
|
|
37
|
+
let bracketDepth = 0;
|
|
38
|
+
let closeIdx = -1;
|
|
39
|
+
const topLevelCommas = [];
|
|
40
|
+
|
|
41
|
+
let inStr = false;
|
|
42
|
+
let strCh = '';
|
|
43
|
+
let inTpl = false;
|
|
44
|
+
let inLineComment = false;
|
|
45
|
+
let inBlockComment = false;
|
|
46
|
+
|
|
47
|
+
for (let i = afterParen; i < source.length; i++) {
|
|
48
|
+
const ch = source[i];
|
|
49
|
+
const prev = i > 0 ? source[i - 1] : '';
|
|
50
|
+
const next = i + 1 < source.length ? source[i + 1] : '';
|
|
51
|
+
|
|
52
|
+
if (inLineComment) {
|
|
53
|
+
if (ch === '\n') inLineComment = false;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (inBlockComment) {
|
|
58
|
+
if (ch === '*' && next === '/') {
|
|
59
|
+
inBlockComment = false;
|
|
60
|
+
i++;
|
|
61
|
+
}
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (inStr) {
|
|
66
|
+
if (ch === strCh && prev !== '\\') inStr = false;
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (inTpl) {
|
|
71
|
+
if (ch === '`' && prev !== '\\') {
|
|
72
|
+
inTpl = false;
|
|
73
|
+
}
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (ch === '/' && next === '/') {
|
|
78
|
+
inLineComment = true;
|
|
79
|
+
i++;
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (ch === '/' && next === '*') {
|
|
84
|
+
inBlockComment = true;
|
|
85
|
+
i++;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (ch === '"' || ch === "'") {
|
|
90
|
+
inStr = true;
|
|
91
|
+
strCh = ch;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (ch === '`') {
|
|
96
|
+
inTpl = true;
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (ch === '{') {
|
|
101
|
+
braceDepth++;
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (ch === '}') {
|
|
106
|
+
if (braceDepth > 0) braceDepth--;
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (ch === '[') {
|
|
111
|
+
bracketDepth++;
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (ch === ']') {
|
|
116
|
+
if (bracketDepth > 0) bracketDepth--;
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (ch === '(') {
|
|
121
|
+
depth++;
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (ch === ')') {
|
|
126
|
+
depth--;
|
|
127
|
+
if (depth === 0) {
|
|
128
|
+
closeIdx = i;
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (ch === ',' && depth === 1 && braceDepth === 0 && bracketDepth === 0) {
|
|
135
|
+
topLevelCommas.push(i);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (closeIdx === -1) return null;
|
|
140
|
+
return { closeIdx, topLevelCommas };
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Inject `{ path: '<file-path>' }` into createStyles/createStaticStyles calls.
|
|
145
|
+
*
|
|
146
|
+
* Rules:
|
|
147
|
+
* - One arg call: append second arg `{ path }`
|
|
148
|
+
* - Two+ arg call:
|
|
149
|
+
* - if second arg is object literal and has no `path`, inject into object
|
|
150
|
+
* - otherwise append third arg `{ path }` as a fallback
|
|
151
|
+
*/
|
|
152
|
+
const injectStylePath = (source, filePath, resourcePath = '') => {
|
|
153
|
+
if (!CALL_RE.test(source)) return source;
|
|
154
|
+
CALL_RE.lastIndex = 0;
|
|
155
|
+
|
|
156
|
+
const normalizedResourcePath = resourcePath.replace(/\\/g, '/');
|
|
157
|
+
|
|
158
|
+
// Skip the style factory implementation files themselves.
|
|
159
|
+
if (
|
|
160
|
+
(normalizedResourcePath.includes('createStaticStyles') ||
|
|
161
|
+
normalizedResourcePath.includes('createStyles')) &&
|
|
162
|
+
normalizedResourcePath.endsWith('index.ts')
|
|
163
|
+
) {
|
|
164
|
+
return source;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const positions = [];
|
|
168
|
+
let match;
|
|
169
|
+
while ((match = CALL_RE.exec(source)) !== null) {
|
|
170
|
+
const lineStart = source.lastIndexOf('\n', match.index) + 1;
|
|
171
|
+
const lineText = source.slice(lineStart, match.index).trimStart();
|
|
172
|
+
if (lineText.startsWith('*') || lineText.startsWith('//')) continue;
|
|
173
|
+
positions.push(match.index + match[0].length);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (positions.length === 0) return source;
|
|
177
|
+
|
|
178
|
+
let result = source;
|
|
179
|
+
const escapedPath = escapePathValue(filePath);
|
|
180
|
+
|
|
181
|
+
for (let pi = positions.length - 1; pi >= 0; pi--) {
|
|
182
|
+
const afterParen = positions[pi];
|
|
183
|
+
const callInfo = findCallBoundaries(result, afterParen);
|
|
184
|
+
if (!callInfo) continue;
|
|
185
|
+
|
|
186
|
+
const { closeIdx, topLevelCommas } = callInfo;
|
|
187
|
+
|
|
188
|
+
// Single-arg call: add options as second arg.
|
|
189
|
+
if (topLevelCommas.length === 0) {
|
|
190
|
+
const inner = result.slice(afterParen, closeIdx);
|
|
191
|
+
const hasTrailingComma = /,\s*$/.test(inner);
|
|
192
|
+
result =
|
|
193
|
+
result.slice(0, closeIdx) +
|
|
194
|
+
(hasTrailingComma ? ` { path: '${escapedPath}' }` : `, { path: '${escapedPath}' }`) +
|
|
195
|
+
result.slice(closeIdx);
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Two+ args: patch second arg when it's an object literal.
|
|
200
|
+
const secondStart = topLevelCommas[0] + 1;
|
|
201
|
+
const secondEnd = topLevelCommas[1] ?? closeIdx;
|
|
202
|
+
const secondArgRaw = result.slice(secondStart, secondEnd);
|
|
203
|
+
|
|
204
|
+
if (hasPathProperty(secondArgRaw)) continue;
|
|
205
|
+
|
|
206
|
+
const injectedSecondArg = injectPathIntoObjectLiteral(secondArgRaw, filePath);
|
|
207
|
+
if (injectedSecondArg !== null) {
|
|
208
|
+
result =
|
|
209
|
+
result.slice(0, secondStart) +
|
|
210
|
+
injectedSecondArg +
|
|
211
|
+
result.slice(secondEnd);
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Fallback for non-object second args.
|
|
216
|
+
const inner = result.slice(afterParen, closeIdx);
|
|
217
|
+
const hasTrailingComma = /,\s*$/.test(inner);
|
|
218
|
+
result =
|
|
219
|
+
result.slice(0, closeIdx) +
|
|
220
|
+
(hasTrailingComma ? ` { path: '${escapedPath}' }` : `, { path: '${escapedPath}' }`) +
|
|
221
|
+
result.slice(closeIdx);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return result;
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
module.exports = {
|
|
228
|
+
injectStylePath,
|
|
229
|
+
};
|