Skip to content

Commit a798de1

Browse files
Ngo Doan SangSang Ngo
andauthored
add resolver to resolve absolute path in @import (#20)
Co-authored-by: Sang Ngo <sngo@axon.com>
1 parent ccd4cbf commit a798de1

File tree

8 files changed

+89
-12
lines changed

8 files changed

+89
-12
lines changed

.tape.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,20 @@ test(rule, {
105105
accept,
106106
reject
107107
});
108+
109+
accept = [
110+
{ code: '@import "import-custom-properties-absolute.css"; body { background-color: var(--brand-red); background: var(--brand-green); }' }
111+
];
112+
reject = [];
113+
114+
test(rule, {
115+
ruleName,
116+
config: [true, {
117+
resolver: {
118+
paths: './test'
119+
}
120+
}],
121+
skipBasicChecks,
122+
accept,
123+
reject
124+
});

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,28 @@ objects.
110110
}
111111
```
112112

113+
### resolver
114+
115+
Use this option to configure how the rule solve paths of `@import` rules.
116+
117+
```js
118+
// .stylelintrc
119+
{
120+
"plugins": [
121+
"stylelint-value-no-unknown-custom-properties"
122+
],
123+
"rules": {
124+
"csstools/value-no-unknown-custom-properties": [true, {
125+
"resolver": {
126+
"extensions": [".css"], // => default to [".css"]
127+
"paths": ["./assets/css", "./static/css"] // => paths to look for files, default to []
128+
"moduleDirectories": ["node_modules"] // => modules folder to look for files, default to ["node_modules"]
129+
}
130+
}]
131+
}
132+
}
133+
```
134+
113135
[cli-img]: https://img.shields.io/travis/csstools/stylelint-value-no-unknown-custom-properties.svg
114136
[cli-url]: https://travis-ci.org/csstools/stylelint-value-no-unknown-custom-properties
115137
[git-img]: https://img.shields.io/badge/support-chat-blue.svg

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
"node": ">=10.0.0"
2727
},
2828
"dependencies": {
29-
"postcss-values-parser": "^3.2.1"
29+
"postcss-values-parser": "^3.2.1",
30+
"resolve": "^1.20.0"
3031
},
3132
"devDependencies": {
3233
"@babel/core": "^7.9.6",

src/index.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ import ruleName from './lib/rule-name';
77
export default stylelint.createPlugin(ruleName, (method, opts) => {
88
// sources to import custom selectors from
99
const importFrom = [].concat(Object(opts).importFrom || []);
10+
const resolver = Object(opts).resolver || {};
1011

1112
// promise any custom selectors are imported
1213
const customPropertiesPromise = isMethodEnabled(method)
13-
? getCustomPropertiesFromImports(importFrom)
14+
? getCustomPropertiesFromImports(importFrom, resolver)
1415
: {};
1516

1617
return async (root, result) => {
@@ -26,7 +27,7 @@ export default stylelint.createPlugin(ruleName, (method, opts) => {
2627
// all custom properties from the file and imports
2728
const customProperties = Object.assign(
2829
await customPropertiesPromise,
29-
await getCustomPropertiesFromRoot(root)
30+
await getCustomPropertiesFromRoot(root, resolver)
3031
);
3132

3233
// validate the css root

src/lib/get-custom-properties-from-imports.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ import getCustomPropertiesFromRoot from './get-custom-properties-from-root';
66
/* Get Custom Properties from CSS File
77
/* ========================================================================== */
88

9-
async function getCustomPropertiesFromCSSFile(from) {
9+
async function getCustomPropertiesFromCSSFile(from, resolver) {
1010
const css = await readFile(from);
1111
const root = postcss.parse(css, { from });
1212

13-
return await getCustomPropertiesFromRoot(root);
13+
return await getCustomPropertiesFromRoot(root, resolver);
1414
}
1515

1616
/* Get Custom Properties from Object
@@ -47,7 +47,7 @@ async function getCustomPropertiesFromJSFile(from) {
4747
/* Get Custom Properties from Sources
4848
/* ========================================================================== */
4949

50-
export default function getCustomPropertiesFromSources(sources) {
50+
export default function getCustomPropertiesFromSources(sources, resolver) {
5151
return sources.map(source => {
5252
if (source instanceof Promise) {
5353
return source;
@@ -74,7 +74,7 @@ export default function getCustomPropertiesFromSources(sources) {
7474
const { type, from } = await source;
7575

7676
if (type === 'css') {
77-
return Object.assign(await customProperties, await getCustomPropertiesFromCSSFile(from));
77+
return Object.assign(await customProperties, await getCustomPropertiesFromCSSFile(from, resolver));
7878
}
7979

8080
if (type === 'js') {

src/lib/get-custom-properties-from-root.js

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { promises as fs } from 'fs';
22
import path from 'path';
33
import postcss from 'postcss';
4+
import { resolveId } from './resolve-id'
45

56
// return custom selectors from the css root, conditionally removing them
6-
export default async function getCustomPropertiesFromRoot(root) {
7+
export default async function getCustomPropertiesFromRoot(root, resolver) {
78
// initialize custom selectors
89
let customProperties = {};
910

@@ -17,8 +18,19 @@ export default async function getCustomPropertiesFromRoot(root) {
1718
const importPromises = [];
1819
root.walkAtRules('import', atRule => {
1920
const fileName = atRule.params.replace(/['|"]/g, '');
20-
const resolvedFileName = path.resolve(sourceDir, fileName);
21-
importPromises.push(getCustomPropertiesFromCSSFile(resolvedFileName));
21+
22+
if (path.isAbsolute(fileName)) {
23+
importPromises.push(getCustomPropertiesFromCSSFile(fileName, resolver));
24+
} else {
25+
const promise = resolveId(fileName, sourceDir, {
26+
paths: resolver.paths,
27+
extensions: resolver.extensions,
28+
moduleDirectories: resolver.moduleDirectories
29+
})
30+
.then((filePath) => getCustomPropertiesFromCSSFile(filePath, resolver))
31+
.catch(() => {})
32+
importPromises.push(promise)
33+
}
2234
});
2335

2436
(await Promise.all(importPromises)).forEach(propertiesFromImport => {
@@ -41,12 +53,12 @@ export default async function getCustomPropertiesFromRoot(root) {
4153
const customPropertyRegExp = /^--[A-z][\w-]*$/;
4254

4355

44-
async function getCustomPropertiesFromCSSFile(from) {
56+
async function getCustomPropertiesFromCSSFile(from, resolver) {
4557
try {
4658
const css = await fs.readFile(from, 'utf8');
4759
const root = postcss.parse(css, { from });
4860

49-
return await getCustomPropertiesFromRoot(root);
61+
return await getCustomPropertiesFromRoot(root, resolver);
5062
} catch (e) {
5163
return {};
5264
}

src/lib/resolve-id.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import resolve from 'resolve'
2+
3+
export function resolveId(id, basedir, {
4+
paths = [],
5+
moduleDirectories = ['node_modules'],
6+
extensions = ['.css']
7+
} = {}
8+
) {
9+
const resolveOpts = {
10+
basedir,
11+
moduleDirectory: moduleDirectories,
12+
paths,
13+
extensions,
14+
preserveSymlinks: false,
15+
}
16+
return new Promise((res, rej) => {
17+
resolve(id, resolveOpts, (err, resolvedPath) => err ? rej(err) : res(resolvedPath))
18+
})
19+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@import 'import-custom-properties-2.css';
2+
3+
:root {
4+
--brand-red: red;
5+
}

0 commit comments

Comments
 (0)