@surplus/esbuild 1.2.1 → 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.
- package/index.mjs +2 -60
- package/lib/css.mjs +177 -0
- package/lib/surplus.mjs +64 -0
- package/package.json +10 -3
package/index.mjs
CHANGED
|
@@ -1,60 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { compile } from "@surplus/compiler";
|
|
4
|
-
|
|
5
|
-
const BASE_RESULT = {
|
|
6
|
-
pluginName: "Surplus Compiler",
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export default (opts) => ({
|
|
10
|
-
name: "surplus",
|
|
11
|
-
setup(build) {
|
|
12
|
-
const jsFileExtensions = [".js", ".jsx", ".mjs", ".cjs"];
|
|
13
|
-
const tsFileExtensions = [".ts", ".tsx"];
|
|
14
|
-
|
|
15
|
-
const fileExtensions = [
|
|
16
|
-
...jsFileExtensions.map((e) => [e, false]),
|
|
17
|
-
...tsFileExtensions.map((e) => [e, true]),
|
|
18
|
-
];
|
|
19
|
-
|
|
20
|
-
for (const [ext, ts] of fileExtensions) {
|
|
21
|
-
build.onLoad({ filter: new RegExp(`\\${ext}$`) }, async (args) => {
|
|
22
|
-
try {
|
|
23
|
-
const source = await fsp.readFile(args.path, "utf8");
|
|
24
|
-
|
|
25
|
-
const result = compile({
|
|
26
|
-
source,
|
|
27
|
-
minify: false,
|
|
28
|
-
sourcemapFilename: args.path,
|
|
29
|
-
typescript: ts,
|
|
30
|
-
...opts,
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
if (result.errors.length > 0) {
|
|
34
|
-
return {
|
|
35
|
-
...BASE_RESULT,
|
|
36
|
-
errors: result.errors?.map((err) => ({
|
|
37
|
-
text: err,
|
|
38
|
-
})),
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return {
|
|
43
|
-
...BASE_RESULT,
|
|
44
|
-
contents: result.code,
|
|
45
|
-
warnings: result.warnings?.map((err) => ({
|
|
46
|
-
text: err,
|
|
47
|
-
})),
|
|
48
|
-
loader: "default",
|
|
49
|
-
};
|
|
50
|
-
} catch (err) {
|
|
51
|
-
// Handle any errors from the transpiler
|
|
52
|
-
return {
|
|
53
|
-
...BASE_RESULT,
|
|
54
|
-
errors: [{ text: err.message }],
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
},
|
|
60
|
-
});
|
|
1
|
+
export { default as surplus } from "./lib/surplus.mjs";
|
|
2
|
+
export { default as surplusCss } from "./lib/css.mjs";
|
package/lib/css.mjs
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { promises as fsp } from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
|
|
4
|
+
import css from "css";
|
|
5
|
+
import * as cssWhat from "css-what";
|
|
6
|
+
import { camelCase } from "change-case";
|
|
7
|
+
|
|
8
|
+
const toArrayBuffer = (text) => new TextEncoder("utf-8").encode(text);
|
|
9
|
+
|
|
10
|
+
const camelize = (str) => camelCase(str, { transform: camelCase });
|
|
11
|
+
|
|
12
|
+
async function processCSS(contents, uid, mappings) {
|
|
13
|
+
const ast = css.parse(contents);
|
|
14
|
+
|
|
15
|
+
let priority = 0;
|
|
16
|
+
|
|
17
|
+
ast.stylesheet.rules = ast.stylesheet.rules
|
|
18
|
+
.map((rule) => {
|
|
19
|
+
switch (rule.type) {
|
|
20
|
+
case "rule":
|
|
21
|
+
const { selectors, ...rest } = rule;
|
|
22
|
+
|
|
23
|
+
let globalize = false;
|
|
24
|
+
let ignore = false;
|
|
25
|
+
|
|
26
|
+
const result = {
|
|
27
|
+
selectors: selectors.map((selector) =>
|
|
28
|
+
cssWhat.stringify(
|
|
29
|
+
cssWhat.parse(selector).map((tokens) =>
|
|
30
|
+
tokens
|
|
31
|
+
.map((t) => {
|
|
32
|
+
if (
|
|
33
|
+
t.type === "tag" &&
|
|
34
|
+
t.name === "@global"
|
|
35
|
+
) {
|
|
36
|
+
globalize = true;
|
|
37
|
+
return false;
|
|
38
|
+
} else if (
|
|
39
|
+
t.type === "attribute" &&
|
|
40
|
+
t.name === "class"
|
|
41
|
+
) {
|
|
42
|
+
const newValue = globalize
|
|
43
|
+
? t.value
|
|
44
|
+
: `${t.value}-${uid}`;
|
|
45
|
+
mappings[camelize(t.value)] =
|
|
46
|
+
newValue;
|
|
47
|
+
return {
|
|
48
|
+
...t,
|
|
49
|
+
value: newValue,
|
|
50
|
+
};
|
|
51
|
+
} else if (
|
|
52
|
+
t.type === "tag" &&
|
|
53
|
+
t.name === "@meta"
|
|
54
|
+
) {
|
|
55
|
+
// Don't emit it in the resulting CSS.
|
|
56
|
+
ignore = true;
|
|
57
|
+
|
|
58
|
+
for (const decl of rule.declarations) {
|
|
59
|
+
switch (decl.property) {
|
|
60
|
+
case "priority":
|
|
61
|
+
priority =
|
|
62
|
+
parseFloat(
|
|
63
|
+
decl.value,
|
|
64
|
+
10,
|
|
65
|
+
);
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return t;
|
|
72
|
+
})
|
|
73
|
+
.filter(Boolean),
|
|
74
|
+
),
|
|
75
|
+
),
|
|
76
|
+
),
|
|
77
|
+
...rest,
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
return ignore ? null : result;
|
|
81
|
+
default:
|
|
82
|
+
return rule;
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
.filter(Boolean);
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
content: css.stringify(ast),
|
|
89
|
+
priority,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export default ({ outfile } = {}) => {
|
|
94
|
+
return {
|
|
95
|
+
name: "Surplus CSS Modules",
|
|
96
|
+
setup(build) {
|
|
97
|
+
const cssFiles = new Map();
|
|
98
|
+
const cssFilesList = [];
|
|
99
|
+
|
|
100
|
+
build.onLoad({ filter: /\.css$/ }, async (args) => {
|
|
101
|
+
const contents = await fsp.readFile(args.path, "utf-8");
|
|
102
|
+
|
|
103
|
+
let mappings = {};
|
|
104
|
+
|
|
105
|
+
if (cssFiles.has(args.path)) {
|
|
106
|
+
({ mappings } = cssFiles.get(args.path));
|
|
107
|
+
} else {
|
|
108
|
+
const { content, priority } = await processCSS(
|
|
109
|
+
contents,
|
|
110
|
+
cssFiles.size,
|
|
111
|
+
mappings,
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
cssFiles.set(args.path, {
|
|
115
|
+
content,
|
|
116
|
+
mappings,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
cssFilesList.push({ pathname: args.path, priority });
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
contents: Object.entries(mappings)
|
|
124
|
+
.map(
|
|
125
|
+
(e) =>
|
|
126
|
+
`export const ${e[0]} = ${JSON.stringify(e[1])};`,
|
|
127
|
+
)
|
|
128
|
+
.join("\n"),
|
|
129
|
+
loader: "js",
|
|
130
|
+
};
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
build.onEnd(async (result) => {
|
|
134
|
+
const outPath = outfile || build.initialOptions.outfile;
|
|
135
|
+
if (!outPath) {
|
|
136
|
+
// We need to know where to put it based on its sibling output files.
|
|
137
|
+
return {
|
|
138
|
+
warnings: [
|
|
139
|
+
{
|
|
140
|
+
text: "not emitting a .css file because it appears there are no other output files (or an error occurred somewhere else in the build)",
|
|
141
|
+
},
|
|
142
|
+
],
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const buildDir = path.dirname(outPath);
|
|
147
|
+
|
|
148
|
+
cssFilesList.sort((a, b) => a.priority - b.priority);
|
|
149
|
+
|
|
150
|
+
const chunks = [];
|
|
151
|
+
|
|
152
|
+
for (const { pathname } of cssFilesList) {
|
|
153
|
+
const cssFile = cssFiles.get(pathname);
|
|
154
|
+
chunks.push(`/* ${path.relative(buildDir, pathname)} */`);
|
|
155
|
+
chunks.push(cssFile.content);
|
|
156
|
+
chunks.push("");
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
let outText = chunks.join("\n");
|
|
160
|
+
|
|
161
|
+
if (build.initialOptions.minify) {
|
|
162
|
+
outText = css.stringify(css.parse(outText), {
|
|
163
|
+
compress: true,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
await fsp.writeFile(
|
|
168
|
+
path.join(
|
|
169
|
+
buildDir,
|
|
170
|
+
path.basename(outPath, path.extname(outPath)) + ".css",
|
|
171
|
+
),
|
|
172
|
+
outText,
|
|
173
|
+
);
|
|
174
|
+
});
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
};
|
package/lib/surplus.mjs
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import fsp from "node:fs/promises";
|
|
2
|
+
|
|
3
|
+
import { compile } from "@surplus/compiler";
|
|
4
|
+
|
|
5
|
+
const BASE_RESULT = {
|
|
6
|
+
pluginName: "Surplus Compiler",
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export default (opts) => ({
|
|
10
|
+
name: "Surplus Compiler",
|
|
11
|
+
setup(build) {
|
|
12
|
+
const jsFileExtensions = [".js", ".jsx", ".mjs", ".cjs"];
|
|
13
|
+
const tsFileExtensions = [".ts", ".tsx"];
|
|
14
|
+
|
|
15
|
+
const fileExtensions = [
|
|
16
|
+
...jsFileExtensions.map((e) => [e, false]),
|
|
17
|
+
...tsFileExtensions.map((e) => [e, true]),
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
for (const [ext, ts] of fileExtensions) {
|
|
21
|
+
build.onLoad({ filter: new RegExp(`\\${ext}$`) }, async (args) => {
|
|
22
|
+
try {
|
|
23
|
+
const source = await fsp.readFile(args.path, "utf8");
|
|
24
|
+
|
|
25
|
+
const result = compile({
|
|
26
|
+
source,
|
|
27
|
+
minify: false,
|
|
28
|
+
sourcemapFilename: args.path,
|
|
29
|
+
typescript: ts,
|
|
30
|
+
...opts,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
if (result.errors.length > 0) {
|
|
34
|
+
return {
|
|
35
|
+
...BASE_RESULT,
|
|
36
|
+
errors: result.errors?.map((err) => ({
|
|
37
|
+
text: err,
|
|
38
|
+
})),
|
|
39
|
+
warnings: result.warnings?.map((err) => ({
|
|
40
|
+
text: err,
|
|
41
|
+
})),
|
|
42
|
+
loader: "default",
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
...BASE_RESULT,
|
|
48
|
+
contents: result.code,
|
|
49
|
+
warnings: result.warnings?.map((err) => ({
|
|
50
|
+
text: err,
|
|
51
|
+
})),
|
|
52
|
+
loader: "default",
|
|
53
|
+
};
|
|
54
|
+
} catch (err) {
|
|
55
|
+
// Handle any errors from the transpiler
|
|
56
|
+
return {
|
|
57
|
+
...BASE_RESULT,
|
|
58
|
+
errors: [{ text: err.message }],
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@surplus/esbuild",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Surplus framework ESBuild plugin",
|
|
5
5
|
"author": "Josh Junon (https://github.com/qix-)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -20,15 +20,20 @@
|
|
|
20
20
|
],
|
|
21
21
|
"scripts": {
|
|
22
22
|
"format": "prettier -w .",
|
|
23
|
-
"lint": "prettier -c ."
|
|
23
|
+
"lint": "prettier -c .",
|
|
24
|
+
"test": "cd test && node esbuild.mjs"
|
|
24
25
|
},
|
|
25
26
|
"files": [
|
|
27
|
+
"lib/",
|
|
26
28
|
"index.mjs",
|
|
27
29
|
"LICENSE",
|
|
28
30
|
"README.md"
|
|
29
31
|
],
|
|
30
32
|
"dependencies": {
|
|
31
|
-
"@surplus/compiler": "^1.3.0"
|
|
33
|
+
"@surplus/compiler": "^1.3.0",
|
|
34
|
+
"change-case": "^5.4.4",
|
|
35
|
+
"css": "^3.0.0",
|
|
36
|
+
"css-what": "^7.0.0"
|
|
32
37
|
},
|
|
33
38
|
"engines": {
|
|
34
39
|
"node": "^12.17.0 || ^14.13 || >=16.0.0"
|
|
@@ -37,6 +42,8 @@
|
|
|
37
42
|
"access": "public"
|
|
38
43
|
},
|
|
39
44
|
"devDependencies": {
|
|
45
|
+
"@surplus/s": "^1.2.0",
|
|
46
|
+
"esbuild": "^0.27.2",
|
|
40
47
|
"prettier": "^3.6.2"
|
|
41
48
|
}
|
|
42
49
|
}
|