Skip to content

Commit

Permalink
refactor: options
Browse files Browse the repository at this point in the history
BREAKING CHANGE: the `resolveUrl` option is `true by default
  • Loading branch information
cap-Bernardito authored Sep 16, 2020
1 parent 9ee6717 commit b723d51
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 22 deletions.
4 changes: 4 additions & 0 deletions src/evaluator.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,13 @@ export default async function createEvaluator(code, options, loaderContext) {

return class CustomEvaluator extends Evaluator {
visitImport(imported) {
this.return += 1;

const node = this.visit(imported.path).first;
const nodePath = node.string;

this.return -= 1;

if (node.name !== 'url' && nodePath && !URL_RE.test(nodePath)) {
const resolved = deps.get(nodePath);

Expand Down
10 changes: 6 additions & 4 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,12 @@ export default async function stylusLoader(source) {
}
}

if (typeof stylusOptions.resolveUrl !== 'undefined') {
stylusOptions.resolveUrl = {};

styl.define('url', resolver(stylusOptions));
if (stylusOptions.resolveUrl !== false) {
stylusOptions.resolveUrl = {
...stylusOptions.resolveUrl,
paths: options.paths,
};
styl.define('url', resolver(stylusOptions.resolveUrl));
}

if (typeof stylusOptions.define !== 'undefined') {
Expand Down
56 changes: 41 additions & 15 deletions src/lib/resolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,55 @@ export default function resolver(options = {}) {
// eslint-disable-next-line no-underscore-dangle
const _paths = options.paths || [];

function url(imported) {
function resolve(url) {
const paths = _paths.concat(this.paths);
const { filename } = this;
const { filename } = url;

// Compile the url
const compiler = new Compiler(imported);
const compiler = new Compiler(url);

compiler.isURL = true;

const query = imported.nodes
const query = url.nodes
.map((node) => {
return compiler.visit(node);
})
.join('');

const components = query.split(/!/g).map((urlSegment) => {
if (!urlSegment) {
return urlSegment;
}
const components = query.split(/!/g);
const resolvedFilePath = resolveUrl(components.pop(), this.filename);

function resolveUrl(urlSegment, name) {
const parsedUrl = parse(urlSegment);

const literal = new nodes.Literal(parsedUrl.href);

// Absolute or hash
if (
parsedUrl.protocol ||
!parsedUrl.pathname ||
parsedUrl.pathname[0] === '/'
) {
return literal;
}

if (parsedUrl.protocol) {
return parsedUrl.href;
}

// Lookup
const found = utils.lookup(parsedUrl.pathname, paths, '', true);
let found;

// Check that file exists
if (!options.noCheck) {
found = utils.lookup(parsedUrl.pathname, paths, '', true);

if (!found) {
return parsedUrl.href;
}
}

if (!found) {
return parsedUrl.href;
found = parsedUrl.href;
}

let tail = '';
Expand All @@ -49,19 +68,26 @@ export default function resolver(options = {}) {
tail += parsedUrl.hash;
}

let res = path.relative(path.dirname(filename), found) + tail;
let res =
path.relative(
path.dirname(name),
options.noCheck ? path.join(path.dirname(filename), found) : found
) + tail;

if (path.sep === '\\') {
res = res.replace(/\\/g, '/');
}

return res;
});
}

components.push(resolvedFilePath);

return new nodes.Literal(`url("${components.join('!')}")`);
}

url.raw = true;
resolve.options = options;
resolve.raw = true;

return url;
return resolve;
}
7 changes: 7 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ function getStylusOptions(loaderContext, loaderOptions) {

stylusOptions.filename = loaderContext.resourcePath;

stylusOptions.resolveUrl =
typeof stylusOptions.resolveUrl === 'boolean' && !stylusOptions.resolveUrl
? false
: typeof stylusOptions.resolveUrl === 'object'
? stylusOptions.resolveUrl
: {};

if (
typeof stylusOptions.use !== 'undefined' &&
stylusOptions.use.length > 0
Expand Down
39 changes: 36 additions & 3 deletions test/__snapshots__/loader.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ exports[`loader should not be resolved when url begin with "#": css 1`] = `
cursor: pointer;
shape-rendering: crispEdges;
fill: url(\\"#MyGradient\\");
background-image: url(\\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M256 40c118.621 0 216 96.075 216 216 0 119.291-96.61 216-216 216-119.244 0-216-96.562-216-216 0-119.203 96.602-216 216-216m0-32C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm-11.49 120h22.979c6.823 0 12.274 5.682 11.99 12.5l-7 168c-.268 6.428-5.556 11.5-11.99 11.5h-8.979c-6.433 0-11.722-5.073-11.99-11.5l-7-168c-.283-6.818 5.167-12.5 11.99-12.5zM256 340c-15.464 0-28 12.536-28 28s12.536 28 28 28 28-12.536 28-28-12.536-28-28-28z'%3E%3C/path%3E%3C/svg%3E\\");
background-image: url(\\"data:image/svg+xml,%3Csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20viewBox=%270%200%20512%20512%27%3E%3Cpath%20d=%27M256%2040c118.621%200%20216%2096.075%20216%20216%200%20119.291-96.61%20216-216%20216-119.244%200-216-96.562-216-216%200-119.203%2096.602-216%20216-216m0-32C119.043%208%208%20119.083%208%20256c0%20136.997%20111.043%20248%20248%20248s248-111.003%20248-248C504%20119.083%20392.957%208%20256%208zm-11.49%20120h22.979c6.823%200%2012.274%205.682%2011.99%2012.5l-7%20168c-.268%206.428-5.556%2011.5-11.99%2011.5h-8.979c-6.433%200-11.722-5.073-11.99-11.5l-7-168c-.283-6.818%205.167-12.5%2011.99-12.5zM256%20340c-15.464%200-28%2012.536-28%2028s12.536%2028%2028%2028%2028-12.536%2028-28-12.536-28-28-28z%27%3E%3C/path%3E%3C/svg%3E\\");
}
"
`;
Expand Down Expand Up @@ -718,8 +718,8 @@ th {
}
@font-face {
font-family: \\"Glyphicons Halflings\\";
src: url(\\"../fonts/glyphicons-halflings-regular.eot\\");
src: url(\\"../fonts/glyphicons-halflings-regular.eot?#iefix\\") format(\\"embedded-opentype\\"), url(\\"../fonts/glyphicons-halflings-regular.woff2\\") format(\\"woff2\\"), url(\\"../fonts/glyphicons-halflings-regular.woff\\") format(\\"woff\\"), url(\\"../fonts/glyphicons-halflings-regular.ttf\\") format(\\"truetype\\"), url(\\"../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular\\") format(\\"svg\\");
src: url(\\"../../node_modules/bootstrap-styl/fonts/glyphicons-halflings-regular.eot\\");
src: url(\\"../../node_modules/bootstrap-styl/fonts/glyphicons-halflings-regular.eot?#iefix\\") format(\\"embedded-opentype\\"), url(\\"../../node_modules/bootstrap-styl/fonts/glyphicons-halflings-regular.woff2\\") format(\\"woff2\\"), url(\\"../../node_modules/bootstrap-styl/fonts/glyphicons-halflings-regular.woff\\") format(\\"woff\\"), url(\\"../../node_modules/bootstrap-styl/fonts/glyphicons-halflings-regular.ttf\\") format(\\"truetype\\"), url(\\"../../node_modules/bootstrap-styl/fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular\\") format(\\"svg\\");
}
.glyphicon {
position: relative;
Expand Down Expand Up @@ -7251,9 +7251,42 @@ exports[`loader stylus can find modules in node_modules: errors 1`] = `Array []`
exports[`loader stylus can find modules in node_modules: warnings 1`] = `Array []`;
exports[`loader with option resolveUrl noCheck, should resolve missing urls relatively: css 1`] = `
".img {
content: url(\\"img.png\\");
content: url(\\"not-exist.png\\");
background: url(\\"deep/deep-img.png\\");
background: url(\\"!!deep/deep-img.png\\");
background: url(\\"file!deep/deep-img.png\\");
background: url(\\"file?foo!deep/deep-img.png\\");
}
"
`;
exports[`loader with option resolveUrl noCheck, should resolve missing urls relatively: errors 1`] = `Array []`;
exports[`loader with option resolveUrl noCheck, should resolve missing urls relatively: warnings 1`] = `Array []`;
exports[`loader with option, should not resolve urls relatively: css 1`] = `
".img {
content: url(\\"../img.png\\");
content: url(\\"../not-exist.png\\");
background: url(\\"deep-img.png\\");
background: url(\\"!!deep-img.png\\");
background: url(\\"file!deep-img.png\\");
background: url(\\"file?foo!deep-img.png\\");
}
"
`;
exports[`loader with option, should not resolve urls relatively: errors 1`] = `Array []`;
exports[`loader with option, should not resolve urls relatively: warnings 1`] = `Array []`;
exports[`loader with option, should resolve urls relatively: css 1`] = `
".img {
content: url(\\"img.png\\");
content: url(\\"../not-exist.png\\");
background: url(\\"deep/deep-img.png\\");
background: url(\\"!!deep/deep-img.png\\");
background: url(\\"file!deep/deep-img.png\\");
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/deep/deep-urls.styl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.img
content url(../img.png)
content url(../not-exist.png)
background url(deep-img.png)
background url(!!deep-img.png)
background url(file!deep-img.png)
Expand Down
32 changes: 32 additions & 0 deletions test/loader.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,38 @@ describe('loader', () => {
expect(getErrors(stats)).toMatchSnapshot('errors');
});

it('with option, should not resolve urls relatively', async () => {
const testId = './shallow.styl';
const compiler = getCompiler(testId, {
stylusOptions: {
resolveUrl: false,
},
});
const stats = await compile(compiler);
const codeFromBundle = getCodeFromBundle(stats, compiler);

expect(codeFromBundle.css).toMatchSnapshot('css');
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});

it('with option resolveUrl noCheck, should resolve missing urls relatively', async () => {
const testId = './shallow.styl';
const compiler = getCompiler(testId, {
stylusOptions: {
resolveUrl: {
noCheck: true,
},
},
});
const stats = await compile(compiler);
const codeFromBundle = getCodeFromBundle(stats, compiler);

expect(codeFromBundle.css).toMatchSnapshot('css');
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});

it('with paths, find deps and load like normal stylus', async () => {
const testId = './import-paths.styl';
const compiler = getCompiler(testId, {
Expand Down

0 comments on commit b723d51

Please sign in to comment.