-
Notifications
You must be signed in to change notification settings - Fork 12k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(@angular-devkit/build-angular): add Less stylesheet support to e…
…xperimental esbuild-based builder When using the experimental esbuild-based browser application builder, stylesheets written in the Less stylesheet language can now be used throughout an application. The support allows Less stylesheets to be used in all locations where CSS and/or Sass can be used. This includes global stylesheets and both inline and external component styles. When using inline component styles, the `inlineLanguageStyle` build option must be set to `less`. Currently, import resolution within a Less stylesheet is limited to default Less behavior which does not include full node package resolution. Full resolution behavior will be added in a future change.
- Loading branch information
1 parent
c07fbf6
commit 01b3bcf
Showing
6 changed files
with
124 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
105 changes: 105 additions & 0 deletions
105
packages/angular_devkit/build_angular/src/builders/browser-esbuild/less-plugin.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
/** | ||
* @license | ||
* Copyright Google LLC All Rights Reserved. | ||
* | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://angular.io/license | ||
*/ | ||
|
||
import type { OnLoadResult, Plugin, PluginBuild } from 'esbuild'; | ||
import assert from 'node:assert'; | ||
import { readFile } from 'node:fs/promises'; | ||
|
||
/** | ||
* The lazy-loaded instance of the less stylesheet preprocessor. | ||
* It is only imported and initialized if a less stylesheet is used. | ||
*/ | ||
let lessPreprocessor: typeof import('less') | undefined; | ||
|
||
export interface LessPluginOptions { | ||
sourcemap: boolean; | ||
includePaths?: string[]; | ||
inlineComponentData?: Record<string, string>; | ||
} | ||
|
||
interface LessException extends Error { | ||
filename: string; | ||
line: number; | ||
column: number; | ||
extract?: string[]; | ||
} | ||
|
||
function isLessException(error: unknown): error is LessException { | ||
return !!error && typeof error === 'object' && 'column' in error; | ||
} | ||
|
||
export function createLessPlugin(options: LessPluginOptions): Plugin { | ||
return { | ||
name: 'angular-less', | ||
setup(build: PluginBuild): void { | ||
// Add a load callback to support inline Component styles | ||
build.onLoad({ filter: /^less;/, namespace: 'angular:styles/component' }, async (args) => { | ||
const data = options.inlineComponentData?.[args.path]; | ||
assert(data, `component style name should always be found [${args.path}]`); | ||
|
||
const [, , filePath] = args.path.split(';', 3); | ||
|
||
return compileString(data, filePath, options); | ||
}); | ||
|
||
// Add a load callback to support files from disk | ||
build.onLoad({ filter: /\.less$/ }, async (args) => { | ||
const data = await readFile(args.path, 'utf-8'); | ||
|
||
return compileString(data, args.path, options); | ||
}); | ||
}, | ||
}; | ||
} | ||
|
||
async function compileString( | ||
data: string, | ||
filename: string, | ||
options: LessPluginOptions, | ||
): Promise<OnLoadResult> { | ||
const less = (lessPreprocessor ??= (await import('less')).default); | ||
|
||
try { | ||
const result = await less.render(data, { | ||
filename, | ||
paths: options.includePaths, | ||
rewriteUrls: 'all', | ||
sourceMap: options.sourcemap | ||
? { | ||
sourceMapFileInline: true, | ||
outputSourceFiles: true, | ||
} | ||
: undefined, | ||
} as Less.Options); | ||
|
||
return { | ||
contents: result.css, | ||
loader: 'css', | ||
}; | ||
} catch (error) { | ||
if (isLessException(error)) { | ||
return { | ||
errors: [ | ||
{ | ||
text: error.message, | ||
location: { | ||
file: error.filename, | ||
line: error.line, | ||
column: error.column, | ||
// Middle element represents the line containing the error | ||
lineText: error.extract && error.extract[Math.trunc(error.extract.length / 2)], | ||
}, | ||
}, | ||
], | ||
loader: 'css', | ||
}; | ||
} | ||
|
||
throw error; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -121,7 +121,6 @@ | |
|
||
"@angular/build-tooling@https://github.com/angular/dev-infra-private-build-tooling-builds.git#ffd5dec0bf78a2c8ff068482ad3c8434c21b54c7": | ||
version "0.0.0-fb077c1937f280aac6327969fa3ab50f98b4d25a" | ||
uid ffd5dec0bf78a2c8ff068482ad3c8434c21b54c7 | ||
resolved "https://github.com/angular/dev-infra-private-build-tooling-builds.git#ffd5dec0bf78a2c8ff068482ad3c8434c21b54c7" | ||
dependencies: | ||
"@angular-devkit/build-angular" "15.2.0-next.3" | ||
|
@@ -307,7 +306,6 @@ | |
|
||
"@angular/ng-dev@https://github.com/angular/dev-infra-private-ng-dev-builds.git#f4601b680d6d0017880115cc8ee99249c34f0c12": | ||
version "0.0.0-fb077c1937f280aac6327969fa3ab50f98b4d25a" | ||
uid f4601b680d6d0017880115cc8ee99249c34f0c12 | ||
resolved "https://github.com/angular/dev-infra-private-ng-dev-builds.git#f4601b680d6d0017880115cc8ee99249c34f0c12" | ||
dependencies: | ||
"@yarnpkg/lockfile" "^1.1.0" | ||
|
@@ -3170,6 +3168,11 @@ | |
"@types/node" "*" | ||
log4js "^6.4.1" | ||
|
||
"@types/less@^3.0.3": | ||
version "3.0.3" | ||
resolved "https://registry.yarnpkg.com/@types/less/-/less-3.0.3.tgz#f9451dbb9548d25391107d65d6401a0cfb15db92" | ||
integrity sha512-1YXyYH83h6We1djyoUEqTlVyQtCfJAFXELSKW2ZRtjHD4hQ82CC4lvrv5D0l0FLcKBaiPbXyi3MpMsI9ZRgKsw== | ||
|
||
"@types/loader-utils@^2.0.0": | ||
version "2.0.3" | ||
resolved "https://registry.yarnpkg.com/@types/loader-utils/-/loader-utils-2.0.3.tgz#fbc2337358f8f4a7dc532ac0a3646c74275edf2d" | ||
|
@@ -10107,7 +10110,6 @@ [email protected]: | |
|
||
"sauce-connect-proxy@https://saucelabs.com/downloads/sc-4.8.1-linux.tar.gz": | ||
version "0.0.0" | ||
uid "9c16682e4c9716734432789884f868212f95f563" | ||
resolved "https://saucelabs.com/downloads/sc-4.8.1-linux.tar.gz#9c16682e4c9716734432789884f868212f95f563" | ||
|
||
saucelabs@^1.5.0: | ||
|