@joneff/sass-import-resolver v1.0.0
sass-import-resolver
sass-import-resolver resolves the path of sass imports, following a heavily opinionated and probably very shady algorithm, which I will get to in a bit.
Purpose
The purpose of the package is to be used for sass importers or similar scripts. The API has similar signature to a sass importer.
Installation
npm install @joneff/sass-import-resolver --save-devBasic Usage
It's probably not a good idea to use in any production code, without rigorous testing. Usage may feel a bit like a Kübler-Ross -- denial, anger, barganing, depression, acceptance -- but it's the only sane solution I was able to come up with.
-- me
Something like this will yield results:
const resolver = require('@joneff/sass-import-resolver');
// assuming @import "../some/dependency.scss" in ./my/overly/nested/framework.scss
const file = ...;
const options = ...;
const result = resolver.resolve({ file, ...options });
console.log(result);
// if the file exists => ./my/overly/some/dependecy.scss
// if not => ../some/dependency.scssAPI
The api has only two methods with both using the same params.
resolve()
- Signature:
function resolve( options: { file: String, prev?: String, includePaths?: Array<String>, nodeModules?: String } ) : String
Just a facade -- passes everything down to _resove and waits for results.
_resolve()
- Signature:
function _resolve( options: { file: String, prev?: String, includePaths?: Array<String>, nodeModules?: String } ) : Array<String>
Does the actual work, collects unique matches and returns them.
options
options.file-- Path to a fileoptions.prev(Optional) -- Path to file (or dir) to be used for resolvingurl. Ideally, it should not be empty and should be the previously resolved path.options.includePaths(Optional) -- An array of paths that the script can look in when attempting to resolve@importdeclarations. When resolving node_module (~), absolute (/) or parent (../) imports, this has no effect.options.nodeModules(Optional) -- Location ofnode_moduleswhen resolving. Defaults to./node_modules.
Heavily Opinionated and Probably Very Shady Algorithm
The algorithm is based on Sass @import documentation, and should work as follows, assuming atleast options.file param is passed:
1) if file starts with http://, https://, //, \\\\ or url(, it's not proccessed at all and returned as is;
2) if prev is file, set cwd to the directory that file is in;
3) if prev is directory, set cwd to that directory;
4) if prev is not passed, set cwd to proccess.cwd();
5) if includePaths is not passed, assume it's an empty array;
6) if file is absolute path, clear cwd and includePaths;
7) if file starts with ~, assume nodemodules import, set cwd to node_modules and clear includePaths;
8) if file starts with ., clear includePaths;
9) assuming there are any includePaths left, unique them with cwd and loop them:
1) if the file portion of file has .css, .scss, or .sass extension, resolve tha path and return it;
2) if the file portion file starts with `, resolve and return the following 7 variants in that order:
1)_file.css2)_file.scss3)_file.sass4)file/index.scss(that's an exception from sass @import)
5)file/index.sass(that's an exception from sass @import)
6)file/_index.scss7)file/_index.sass3) resolve and return the following 9 variants in that order:
1)file.css2)file.scss3)file.sass4)_file.scss5)_file.sass6)file/index.scss(that's an exception from sass @import)
7)file/index.sass(that's an exception from sass @import)
8)file/_index.scss9)file/_index.sass10) assuming there is an array of matches, loop over:
1) return the resolved path of the first file that exists on the file system
2) otherwise return the originalfile`
Surely, the algorithm can be extended in various directions like scraping the package.json of resolved modules and looking for entry points, which is not a bad idea at all. However, if you are a sass package creator and you rely on such custom logic, things will not go well for consumers of said packages.
Contributing?
Sure.