commit
6e6daf9511
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,4 @@
|
||||
node_modules
|
||||
dist
|
||||
build
|
||||
yarn-error.log
|
||||
test/dist
|
||||
|
||||
125
dist/index.esm.js
vendored
Normal file
125
dist/index.esm.js
vendored
Normal file
@ -0,0 +1,125 @@
|
||||
import {ensureDir, readFile, writeFile} from "fs-extra";
|
||||
import {TextDecoder} from "util";
|
||||
import path from "path";
|
||||
import tmp from "tmp";
|
||||
import postcss from "postcss";
|
||||
import postcssModules from "postcss-modules";
|
||||
import less from "less";
|
||||
import stylus from "stylus";
|
||||
import resolveFile from "resolve-file";
|
||||
const postCSSPlugin = ({
|
||||
plugins = [],
|
||||
modules = true,
|
||||
rootDir = process.cwd()
|
||||
}) => ({
|
||||
name: "postcss2",
|
||||
setup(build) {
|
||||
const tmpDirPath = tmp.dirSync().name, modulesMap = [];
|
||||
const modulesPlugin = postcssModules({
|
||||
generateScopedName: "[name]__[local]___[hash:base64:5]",
|
||||
...typeof modules !== "boolean" ? modules : {},
|
||||
getJSON(filepath, json, outpath) {
|
||||
const mapIndex = modulesMap.findIndex((m) => m.path === filepath);
|
||||
if (mapIndex !== -1) {
|
||||
modulesMap[mapIndex].map = json;
|
||||
} else {
|
||||
modulesMap.push({
|
||||
path: filepath,
|
||||
map: json
|
||||
});
|
||||
}
|
||||
if (typeof modules !== "boolean" && typeof modules.getJSON === "function")
|
||||
return modules.getJSON(filepath, json, outpath);
|
||||
}
|
||||
});
|
||||
build.onResolve({filter: /.\.(css|sass|scss|less|styl)$/}, async (args) => {
|
||||
if (args.namespace !== "file" && args.namespace !== "")
|
||||
return;
|
||||
let sourceFullPath = resolveFile(args.path);
|
||||
if (!sourceFullPath)
|
||||
sourceFullPath = path.resolve(args.resolveDir, args.path);
|
||||
const sourceExt = path.extname(sourceFullPath);
|
||||
const sourceBaseName = path.basename(sourceFullPath, sourceExt);
|
||||
const sourceDir = path.dirname(sourceFullPath);
|
||||
const sourceRelDir = path.relative(path.dirname(rootDir), sourceDir);
|
||||
const isModule = sourceBaseName.match(/\.module$/);
|
||||
const tmpDir = path.resolve(tmpDirPath, sourceRelDir);
|
||||
let tmpFilePath = path.resolve(tmpDir, `${Date.now()}-${sourceBaseName}.css`);
|
||||
if (args.kind === "entry-point")
|
||||
tmpFilePath = path.resolve(tmpDir, `${sourceBaseName}.css`);
|
||||
await ensureDir(tmpDir);
|
||||
const fileContent = await readFile(sourceFullPath);
|
||||
let css = sourceExt === ".css" ? fileContent : "";
|
||||
if (sourceExt === ".sass" || sourceExt === ".scss")
|
||||
css = (await renderSass({file: sourceFullPath})).css.toString();
|
||||
if (sourceExt === ".styl")
|
||||
css = await renderStylus(new TextDecoder().decode(fileContent), {
|
||||
filename: sourceFullPath
|
||||
});
|
||||
if (sourceExt === ".less")
|
||||
css = (await less.render(new TextDecoder().decode(fileContent), {
|
||||
filename: sourceFullPath,
|
||||
rootpath: path.dirname(args.path)
|
||||
})).css;
|
||||
const result = await postcss(isModule ? [modulesPlugin, ...plugins] : plugins).process(css, {
|
||||
from: sourceFullPath,
|
||||
to: tmpFilePath
|
||||
});
|
||||
await writeFile(tmpFilePath, result.css);
|
||||
return {
|
||||
namespace: isModule ? "postcss-module" : "file",
|
||||
path: tmpFilePath,
|
||||
watchFiles: [sourceFullPath],
|
||||
pluginData: {
|
||||
originalPath: sourceFullPath
|
||||
}
|
||||
};
|
||||
});
|
||||
build.onLoad({filter: /.*/, namespace: "postcss-module"}, async (args) => {
|
||||
const mod = modulesMap.find(({path: path2}) => path2 === args?.pluginData?.originalPath), resolveDir = path.dirname(args.path);
|
||||
return {
|
||||
resolveDir,
|
||||
contents: `import ${JSON.stringify(args.path)};
|
||||
export default ${JSON.stringify(mod && mod.map ? mod.map : {})};`
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
function renderSass(options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
getSassImpl().render(options, (e, res) => {
|
||||
if (e)
|
||||
reject(e);
|
||||
else
|
||||
resolve(res);
|
||||
});
|
||||
});
|
||||
}
|
||||
function renderStylus(str, options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
stylus.render(str, options, (e, res) => {
|
||||
if (e)
|
||||
reject(e);
|
||||
else
|
||||
resolve(res);
|
||||
});
|
||||
});
|
||||
}
|
||||
function getSassImpl() {
|
||||
let impl = "sass";
|
||||
try {
|
||||
require.resolve("sass");
|
||||
} catch {
|
||||
try {
|
||||
require.resolve("node-sass");
|
||||
impl = "node-sass";
|
||||
} catch {
|
||||
throw new Error('Please install "sass" or "node-sass" package');
|
||||
}
|
||||
}
|
||||
return require(impl);
|
||||
}
|
||||
var src_default = postCSSPlugin;
|
||||
export {
|
||||
src_default as default
|
||||
};
|
||||
148
dist/index.js
vendored
Normal file
148
dist/index.js
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
var __create = Object.create;
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getProtoOf = Object.getPrototypeOf;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __markAsModule = (target) => __defProp(target, "__esModule", {value: true});
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, {get: all[name], enumerable: true});
|
||||
};
|
||||
var __exportStar = (target, module2, desc) => {
|
||||
if (module2 && typeof module2 === "object" || typeof module2 === "function") {
|
||||
for (let key of __getOwnPropNames(module2))
|
||||
if (!__hasOwnProp.call(target, key) && key !== "default")
|
||||
__defProp(target, key, {get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable});
|
||||
}
|
||||
return target;
|
||||
};
|
||||
var __toModule = (module2) => {
|
||||
return __exportStar(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? {get: () => module2.default, enumerable: true} : {value: module2, enumerable: true})), module2);
|
||||
};
|
||||
__markAsModule(exports);
|
||||
__export(exports, {
|
||||
default: () => src_default
|
||||
});
|
||||
var import_fs_extra = __toModule(require("fs-extra"));
|
||||
var import_util = __toModule(require("util"));
|
||||
var import_path = __toModule(require("path"));
|
||||
var import_tmp = __toModule(require("tmp"));
|
||||
var import_postcss2 = __toModule(require("postcss"));
|
||||
var import_postcss_modules = __toModule(require("postcss-modules"));
|
||||
var import_less = __toModule(require("less"));
|
||||
var import_stylus = __toModule(require("stylus"));
|
||||
var import_resolve_file = __toModule(require("resolve-file"));
|
||||
const postCSSPlugin = ({
|
||||
plugins = [],
|
||||
modules = true,
|
||||
rootDir = process.cwd()
|
||||
}) => ({
|
||||
name: "postcss2",
|
||||
setup(build) {
|
||||
const tmpDirPath = import_tmp.default.dirSync().name, modulesMap = [];
|
||||
const modulesPlugin = (0, import_postcss_modules.default)({
|
||||
generateScopedName: "[name]__[local]___[hash:base64:5]",
|
||||
...typeof modules !== "boolean" ? modules : {},
|
||||
getJSON(filepath, json, outpath) {
|
||||
const mapIndex = modulesMap.findIndex((m) => m.path === filepath);
|
||||
if (mapIndex !== -1) {
|
||||
modulesMap[mapIndex].map = json;
|
||||
} else {
|
||||
modulesMap.push({
|
||||
path: filepath,
|
||||
map: json
|
||||
});
|
||||
}
|
||||
if (typeof modules !== "boolean" && typeof modules.getJSON === "function")
|
||||
return modules.getJSON(filepath, json, outpath);
|
||||
}
|
||||
});
|
||||
build.onResolve({filter: /.\.(css|sass|scss|less|styl)$/}, async (args) => {
|
||||
if (args.namespace !== "file" && args.namespace !== "")
|
||||
return;
|
||||
let sourceFullPath = (0, import_resolve_file.default)(args.path);
|
||||
if (!sourceFullPath)
|
||||
sourceFullPath = import_path.default.resolve(args.resolveDir, args.path);
|
||||
const sourceExt = import_path.default.extname(sourceFullPath);
|
||||
const sourceBaseName = import_path.default.basename(sourceFullPath, sourceExt);
|
||||
const sourceDir = import_path.default.dirname(sourceFullPath);
|
||||
const sourceRelDir = import_path.default.relative(import_path.default.dirname(rootDir), sourceDir);
|
||||
const isModule = sourceBaseName.match(/\.module$/);
|
||||
const tmpDir = import_path.default.resolve(tmpDirPath, sourceRelDir);
|
||||
let tmpFilePath = import_path.default.resolve(tmpDir, `${Date.now()}-${sourceBaseName}.css`);
|
||||
if (args.kind === "entry-point")
|
||||
tmpFilePath = import_path.default.resolve(tmpDir, `${sourceBaseName}.css`);
|
||||
await (0, import_fs_extra.ensureDir)(tmpDir);
|
||||
const fileContent = await (0, import_fs_extra.readFile)(sourceFullPath);
|
||||
let css = sourceExt === ".css" ? fileContent : "";
|
||||
if (sourceExt === ".sass" || sourceExt === ".scss")
|
||||
css = (await renderSass({file: sourceFullPath})).css.toString();
|
||||
if (sourceExt === ".styl")
|
||||
css = await renderStylus(new import_util.TextDecoder().decode(fileContent), {
|
||||
filename: sourceFullPath
|
||||
});
|
||||
if (sourceExt === ".less")
|
||||
css = (await import_less.default.render(new import_util.TextDecoder().decode(fileContent), {
|
||||
filename: sourceFullPath,
|
||||
rootpath: import_path.default.dirname(args.path)
|
||||
})).css;
|
||||
const result = await (0, import_postcss2.default)(isModule ? [modulesPlugin, ...plugins] : plugins).process(css, {
|
||||
from: sourceFullPath,
|
||||
to: tmpFilePath
|
||||
});
|
||||
await (0, import_fs_extra.writeFile)(tmpFilePath, result.css);
|
||||
return {
|
||||
namespace: isModule ? "postcss-module" : "file",
|
||||
path: tmpFilePath,
|
||||
watchFiles: [sourceFullPath],
|
||||
pluginData: {
|
||||
originalPath: sourceFullPath
|
||||
}
|
||||
};
|
||||
});
|
||||
build.onLoad({filter: /.*/, namespace: "postcss-module"}, async (args) => {
|
||||
const mod = modulesMap.find(({path: path2}) => path2 === args?.pluginData?.originalPath), resolveDir = import_path.default.dirname(args.path);
|
||||
return {
|
||||
resolveDir,
|
||||
contents: `import ${JSON.stringify(args.path)};
|
||||
export default ${JSON.stringify(mod && mod.map ? mod.map : {})};`
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
function renderSass(options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
getSassImpl().render(options, (e, res) => {
|
||||
if (e)
|
||||
reject(e);
|
||||
else
|
||||
resolve(res);
|
||||
});
|
||||
});
|
||||
}
|
||||
function renderStylus(str, options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
import_stylus.default.render(str, options, (e, res) => {
|
||||
if (e)
|
||||
reject(e);
|
||||
else
|
||||
resolve(res);
|
||||
});
|
||||
});
|
||||
}
|
||||
function getSassImpl() {
|
||||
let impl = "sass";
|
||||
try {
|
||||
require.resolve("sass");
|
||||
} catch {
|
||||
try {
|
||||
require.resolve("node-sass");
|
||||
impl = "node-sass";
|
||||
} catch {
|
||||
throw new Error('Please install "sass" or "node-sass" package');
|
||||
}
|
||||
}
|
||||
return require(impl);
|
||||
}
|
||||
var src_default = postCSSPlugin;
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "esbuild-plugin-postcss2",
|
||||
"version": "0.0.7",
|
||||
"version": "0.0.8",
|
||||
"description": "Use postcss with esbuild",
|
||||
"repository": "https://github.com/martonlederer/esbuild-plugin-postcss2",
|
||||
"author": "Marton Lederer <marton@lederer.hu>",
|
||||
@ -39,16 +39,16 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.2.15",
|
||||
"@types/fs-extra": "^9.0.8",
|
||||
"@types/fs-extra": "^9.0.9",
|
||||
"@types/less": "^3.0.2",
|
||||
"@types/mocha": "^8.2.2",
|
||||
"@types/node": "^14.14.35",
|
||||
"@types/node": "^14.14.37",
|
||||
"@types/sass": "^1.16.0",
|
||||
"@types/stylus": "^0.48.33",
|
||||
"@types/tmp": "^0.2.0",
|
||||
"chai": "^4.3.4",
|
||||
"cross-env": "^7.0.3",
|
||||
"esbuild": "^0.9.6",
|
||||
"esbuild": "^0.11.2",
|
||||
"mocha": "^8.3.2",
|
||||
"normalize.css": "^8.0.1",
|
||||
"prettier": "^2.2.1",
|
||||
|
||||
17
src/index.ts
17
src/index.ts
@ -43,10 +43,16 @@ const postCSSPlugin = ({
|
||||
generateScopedName: "[name]__[local]___[hash:base64:5]",
|
||||
...(typeof modules !== "boolean" ? modules : {}),
|
||||
getJSON(filepath, json, outpath) {
|
||||
modulesMap.push({
|
||||
path: filepath,
|
||||
map: json
|
||||
});
|
||||
// Make sure to replace json map instead of pushing new map everytime with edit file on watch
|
||||
const mapIndex = modulesMap.findIndex((m) => m.path === filepath);
|
||||
if (mapIndex !== -1) {
|
||||
modulesMap[mapIndex].map = json;
|
||||
} else {
|
||||
modulesMap.push({
|
||||
path: filepath,
|
||||
map: json
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
typeof modules !== "boolean" &&
|
||||
@ -62,7 +68,7 @@ const postCSSPlugin = ({
|
||||
// Namespace is empty when using CSS as an entrypoint
|
||||
if (args.namespace !== "file" && args.namespace !== "") return;
|
||||
|
||||
// Resolve files also from node_modules (ex: npm normalize.css)
|
||||
// Resolve files from node_modules (ex: npm install normalize.css)
|
||||
let sourceFullPath = resolveFile(args.path);
|
||||
if (!sourceFullPath)
|
||||
sourceFullPath = path.resolve(args.resolveDir, args.path);
|
||||
@ -117,6 +123,7 @@ const postCSSPlugin = ({
|
||||
return {
|
||||
namespace: isModule ? "postcss-module" : "file",
|
||||
path: tmpFilePath,
|
||||
watchFiles: [sourceFullPath],
|
||||
pluginData: {
|
||||
originalPath: sourceFullPath
|
||||
}
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
const autoprefixer = require("autoprefixer"),
|
||||
{ build } = require("esbuild"),
|
||||
postCSS = require("../dist"),
|
||||
{ assert } = require("chai");
|
||||
{ assert } = require("chai"),
|
||||
fs = require("fs");
|
||||
|
||||
describe("PostCSS esbuild tests", () => {
|
||||
it("Works with basic CSS imports", (done) => {
|
||||
@ -44,6 +45,38 @@ describe("PostCSS esbuild tests", () => {
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
it("Works while waching css files", (done) => {
|
||||
let notTriggerTimeout = null;
|
||||
build({
|
||||
entryPoints: ["tests/watch.ts"],
|
||||
bundle: true,
|
||||
outdir: "dist",
|
||||
watch: {
|
||||
onRebuild: (error, result) => {
|
||||
notTriggerTimeout = null;
|
||||
if (error) return done(error);
|
||||
assert(result);
|
||||
done();
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
postCSS.default({
|
||||
plugins: [autoprefixer]
|
||||
})
|
||||
]
|
||||
})
|
||||
.then(() => {
|
||||
// test if modifying the css actually triggers the onRebuild event
|
||||
const data = `.Test { display: block; }`;
|
||||
fs.writeFile("./styles/watch.css", data, (err) => {
|
||||
if (err) return done(err);
|
||||
notTriggerTimeout = setTimeout(() => {
|
||||
done("Watch file not triggered!");
|
||||
}, 1000);
|
||||
});
|
||||
})
|
||||
.catch(() => process.exit(1));
|
||||
});
|
||||
});
|
||||
|
||||
function test(entryPoint) {
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
@test: 2em;
|
||||
|
||||
.LessClass {
|
||||
height: @test;
|
||||
.Test {
|
||||
display: block;
|
||||
}
|
||||
|
||||
3
test/styles/watch.css
Normal file
3
test/styles/watch.css
Normal file
@ -0,0 +1,3 @@
|
||||
.Test {
|
||||
display: block;
|
||||
}
|
||||
1
test/tests/watch.ts
Normal file
1
test/tests/watch.ts
Normal file
@ -0,0 +1 @@
|
||||
import "../styles/watch.css";
|
||||
24
yarn.lock
24
yarn.lock
@ -7,10 +7,10 @@
|
||||
"resolved" "https://registry.npmjs.org/@types/chai/-/chai-4.2.15.tgz"
|
||||
"version" "4.2.15"
|
||||
|
||||
"@types/fs-extra@^9.0.8":
|
||||
"integrity" "sha512-bnlTVTwq03Na7DpWxFJ1dvnORob+Otb8xHyUqUWhqvz/Ksg8+JXPlR52oeMSZ37YEOa5PyccbgUNutiQdi13TA=="
|
||||
"resolved" "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.8.tgz"
|
||||
"version" "9.0.8"
|
||||
"@types/fs-extra@^9.0.9":
|
||||
"integrity" "sha512-5TqDycCl0oMzwzd1cIjSJWMKMvLCDVErle4ZTjU4EmHDURR/+yZghe6GDHMCpHtcVfq0x0gMoOM546/5TbYHrg=="
|
||||
"resolved" "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.9.tgz"
|
||||
"version" "9.0.9"
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
@ -24,10 +24,10 @@
|
||||
"resolved" "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.2.tgz"
|
||||
"version" "8.2.2"
|
||||
|
||||
"@types/node@*", "@types/node@^14.14.35":
|
||||
"integrity" "sha512-Lt+wj8NVPx0zUmUwumiVXapmaLUcAk3yPuHCFVXras9k5VT9TdhJqKqGVUQCD60OTMCl0qxJ57OiTL0Mic3Iag=="
|
||||
"resolved" "https://registry.npmjs.org/@types/node/-/node-14.14.35.tgz"
|
||||
"version" "14.14.35"
|
||||
"@types/node@*", "@types/node@^14.14.37":
|
||||
"integrity" "sha512-XYmBiy+ohOR4Lh5jE379fV2IU+6Jn4g5qASinhitfyO71b/sCo6MKsMLF5tc7Zf2CE8hViVQyYSobJNke8OvUw=="
|
||||
"resolved" "https://registry.npmjs.org/@types/node/-/node-14.14.37.tgz"
|
||||
"version" "14.14.37"
|
||||
|
||||
"@types/sass@^1.16.0":
|
||||
"integrity" "sha512-2XZovu4NwcqmtZtsBR5XYLw18T8cBCnU2USFHTnYLLHz9fkhnoEMoDsqShJIOFsFhn5aJHjweiUUdTrDGujegA=="
|
||||
@ -374,10 +374,10 @@
|
||||
dependencies:
|
||||
"prr" "~1.0.1"
|
||||
|
||||
"esbuild@^0.9.6":
|
||||
"integrity" "sha512-F6vASxU0wT/Davt9aj2qtDwDNSkQxh9VbyO56M7PDWD+D/Vgq/rmUDGDQo7te76W5auauVojjnQr/wTu3vpaUA=="
|
||||
"resolved" "https://registry.npmjs.org/esbuild/-/esbuild-0.9.6.tgz"
|
||||
"version" "0.9.6"
|
||||
"esbuild@^0.11.2":
|
||||
"integrity" "sha512-8d5FCQrR+juXC2u9zjTQ3+IYiuFuaWyKYwmApFJLquTrYNbk36H/+MkRQeTuOJg7IjUchRX2Ulwo1zRYXZ1pUg=="
|
||||
"resolved" "https://registry.npmjs.org/esbuild/-/esbuild-0.11.2.tgz"
|
||||
"version" "0.11.2"
|
||||
|
||||
"escalade@^3.1.1":
|
||||
"integrity" "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user