Merge pull request #6 from g45t345rt/master

New watch files + fixes
This commit is contained in:
Marton Lederer 2021-04-05 21:09:44 +02:00 committed by GitHub
commit 6e6daf9511
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 341 additions and 27 deletions

1
.gitignore vendored
View File

@ -1,5 +1,4 @@
node_modules
dist
build
yarn-error.log
test/dist

125
dist/index.esm.js vendored Normal file
View 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
View 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;

View File

@ -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",

View File

@ -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
}

View File

@ -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) {

View File

@ -1,5 +1,3 @@
@test: 2em;
.LessClass {
height: @test;
.Test {
display: block;
}

3
test/styles/watch.css Normal file
View File

@ -0,0 +1,3 @@
.Test {
display: block;
}

1
test/tests/watch.ts Normal file
View File

@ -0,0 +1 @@
import "../styles/watch.css";

View File

@ -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=="