Skip to content

Commit

Permalink
feat: modules
Browse files Browse the repository at this point in the history
  • Loading branch information
iam-medvedev committed Sep 15, 2023
1 parent 949864e commit 1d75b35
Show file tree
Hide file tree
Showing 8 changed files with 581 additions and 259 deletions.
10 changes: 3 additions & 7 deletions __tests__/__snapshots__/index.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,7 @@ exports[`less-loader > builds successful with less as entrypoint 1`] = `
"
`;

exports[`less-loader > onResolve with watch mode 1`] = `
{
"path": "/path",
"watchFiles": [
"/path",
],
}
exports[`less-loader > works with module.less 1`] = `
".o{display:block}.o{color:#000}.button{color:gray}.foo .l{color:red}.foo .l{color:green}
"
`;
34 changes: 29 additions & 5 deletions __tests__/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { describe, expect, it, vi } from 'vitest';
import { describe, expect, it } from 'vitest';
import * as path from 'path';
import { build, BuildOptions, PluginBuild } from 'esbuild';
import { build, BuildOptions } from 'esbuild';
import { lessLoader, LoaderOptions } from '../src/index';

const entryPoints = [
path.resolve(__dirname, '../', 'example', 'index.ts'),
path.resolve(__dirname, '../', 'example', 'index-custom-filter.ts'),
path.resolve(__dirname, '../', 'example', 'index.less'),
path.resolve(__dirname, '../', 'example', 'test.module.ts'),
];

const commonOptions: BuildOptions = {
Expand All @@ -21,20 +22,29 @@ const commonOptions: BuildOptions = {
},
};

const buildLess = async ({
type BuildLessProps = {
lessOptions?: Less.Options;
loaderOptions?: LoaderOptions;
entryPoint?: string;
buildOptions?: BuildOptions;
};

async function buildLess({
lessOptions,
loaderOptions,
entryPoint = entryPoints[0],
}: { lessOptions?: Less.Options; loaderOptions?: LoaderOptions; entryPoint?: string } = {}) => {
buildOptions: _buildOptions = {},
}: BuildLessProps = {}) {
const buildOptions: BuildOptions = {
...commonOptions,
entryPoints: [entryPoint],
plugins: [lessLoader(lessOptions, loaderOptions)],
..._buildOptions,
};

const { outputFiles } = await build(buildOptions);
return outputFiles;
};
}

describe('less-loader', () => {
it('exported module', () => {
Expand Down Expand Up @@ -137,4 +147,18 @@ describe('less-loader', () => {
}),
).rejects.toThrow();
});

it('works with module.less', async () => {
const result = await buildLess({
entryPoint: entryPoints[3],
buildOptions: {
format: 'iife',
},
});

expect(result!.length).toEqual(2);

// Result has compiled .less
expect(result![1].text).toMatchSnapshot();
});
});
33 changes: 33 additions & 0 deletions example/styles/style.module.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* This is a local name with the "local-css" loader
* and a global name with the "global-css" loader
*/
.button {
display: block;
}

/* This is a local name with both loaders */
:local(.button) {
color: black;
}

/* This is a global name with both loaders */
:global(.button) {
color: gray;
}

/* "foo" is global and "bar" is local */
:global .foo :local .bar {
color: red;
}

/* "foo" is global and "bar" is local */
:global {
.foo {
:local {
.bar {
color: green;
}
}
}
}
5 changes: 5 additions & 0 deletions example/test.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { button } from './styles/style.module.less';

const div = document.createElement('div');
div.className = button;
document.body.appendChild(div);
36 changes: 18 additions & 18 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
"package.json"
],
"scripts": {
"build": "NODE_ENV=production ts-node ./scripts/build.ts",
"build": "NODE_ENV=production tsx ./scripts/build.ts",
"build:types": "NODE_ENV=production tsc --emitDeclarationOnly --declaration --outDir build",
"dev:example-ts": "ts-node ./example/build.ts --ts",
"build:example-ts": "NODE_ENV=production ts-node ./example/build.ts --ts",
"dev:example-less": "ts-node ./example/build.ts --less",
"build:example-less": "NODE_ENV=production ts-node ./example/build.ts --less",
"dev:example-ts": "tsx ./example/build.ts --ts",
"build:example-ts": "NODE_ENV=production tsx ./example/build.ts --ts",
"dev:example-less": "tsx ./example/build.ts --less",
"build:example-less": "NODE_ENV=production tsx ./example/build.ts --less",
"commit": "yarn git-cz",
"prepare": "husky install",
"types": "tsc --noEmit",
Expand All @@ -44,29 +44,29 @@
},
"devDependencies": {
"@semantic-release/changelog": "6.0.3",
"@semantic-release/commit-analyzer": "10.0.1",
"@semantic-release/github": "9.0.4",
"@semantic-release/npm": "10.0.4",
"@semantic-release/release-notes-generator": "11.0.4",
"@semantic-release/commit-analyzer": "10.0.4",
"@semantic-release/github": "9.0.6",
"@semantic-release/npm": "10.0.6",
"@semantic-release/release-notes-generator": "11.0.7",
"@types/node": "^20.5.0",
"@vitest/coverage-v8": "^0.34.2",
"@vitest/coverage-v8": "^0.34.4",
"cz-conventional-changelog": "3.3.0",
"esbuild": "^0.19.2",
"esbuild": "^0.19.3",
"git-cz": "4.9.0",
"husky": "^8.0.3",
"lint-staged": "14.0.0",
"prettier": "3.0.2",
"semantic-release": "21.0.7",
"ts-node": "10.9.1",
"typescript": "5.1.6",
"lint-staged": "14.0.1",
"prettier": "3.0.3",
"semantic-release": "21.1.1",
"tsx": "3.12.10",
"typescript": "5.2.2",
"vite": "^4.4.9",
"vitest": "^0.34.2"
"vitest": "^0.34.4"
},
"peerDependencies": {
"esbuild": "^0.14.x || ^0.15.0 || ^0.16.0 || ^0.17.0 || ^0.18.0 || ^0.19.0"
},
"dependencies": {
"@types/less": "^3.0.3",
"@types/less": "^3.0.4",
"less": "^4.2.0"
},
"keywords": [
Expand Down
7 changes: 5 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Loader, Plugin } from 'esbuild';
import path from 'path';
import { promises as fs } from 'fs';
import { Plugin } from 'esbuild';
import less from 'less';
import { convertLessError, getLessImports } from './less-utils';

Expand Down Expand Up @@ -36,6 +36,9 @@ export const lessLoader = (options: Less.Options = {}, loaderOptions: LoaderOpti
build.onLoad({ filter: filter || /\.less$/, namespace: 'file' }, async (args) => {
const content = await fs.readFile(args.path, 'utf-8');
const dir = path.dirname(args.path);
const basename = path.basename(args.path);
const isModule = basename.endsWith('.module.less');
const loader: Loader = isModule ? 'local-css' : 'css';

const opts: Less.Options = {
filename: args.path,
Expand All @@ -49,7 +52,7 @@ export const lessLoader = (options: Less.Options = {}, loaderOptions: LoaderOpti

return {
contents: result.css,
loader: 'css',
loader,
resolveDir: dir,
};
} catch (e) {
Expand Down
1 change: 1 addition & 0 deletions src/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
declare module '*.module.less';
Loading

0 comments on commit 1d75b35

Please sign in to comment.