Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Relative data-uri option #2560

Closed
JedWatson opened this issue Apr 20, 2015 · 12 comments
Closed

Relative data-uri option #2560

JedWatson opened this issue Apr 20, 2015 · 12 comments

Comments

@JedWatson
Copy link

Apologies if I've missed the mark with this one - the documentation doesn't actually explain the path resolution behaviour so I'm guessing a bit.

From what I can tell, the data-uri(...) function will find files relative to the entry less file's location on disk. This makes sense, it's similar to how url(...) will point to a location relative to the css file that ends up being loaded in the browser, regardless of whether the less code was in another directory (e.g an include).

I'm developing a component that can be used across multiple projects, published on npm + bower. Providing assets in components is tricky, so I am hoping to use the data-uri feature to inline image resources (i.e icons) for the component.

Anyone using the component can include my component's less file in their project's stylesheet like this:

@import "../node_modules/react-select/less/component.less";

This has a lot of other benefits (developers can override the theme variables, etc.)

However, in this scenario data-uri breaks because I can't know the relative path from their LESS file to my bundled static images (which are provided in node_modules/react-select/images).

If there were a way to use a relative data-uri function (where the path is relative to the less file being processed and not the entry point) then bundling the component would be as simple as adding the line above, and my component's less could inline the images like

background-image: data-uri("../images/dropdown.png");

So it could either be a function that lets me access the current directory of the less file and build the URL from that (like node's __dirname variable) or it could more simply be an argument / different function name. some examples:

background-image: data-uri(current-path() + "../images/dropdown.png");
// or
background-image: data-uri("!../images/dropdown.png");
// or
background-image: data-uri("../images/dropdown.png", true);
// or
background-image: relative-data-uri("../images/dropdown.png");

I personally think that the relative-data-uri function name is clearest, but really anything that lets me achieve this would be brilliant!

@seven-phases-max
Copy link
Member

What about just providing a path variable so that a library user could adjust the path on his own when necessary? E.g.:

// user code

@react-select-path: "../node_modules/react-select";
@import "@{react-select-path}/less/component.less";

// ...................................
// your code (i.e. the component.less)

@react-select-path: ".."; // default value

something {
    background-image: data-uri("@{react-select-path}/images/dropdown.png");
}

This is common approach to handle such things (for example 1, 2 etc.)

Also see --relative-urls (currenty this option applies to data-uri as well).


As for things like current-path(), probably it will do the trick for a static CSS rulesets, but becomes sort of useless for a more generic libraries (e.g. within a mixin such function will return a path of the file where the mixin is invoked instead of where it's defined).

jossmac added a commit to JedWatson/react-date-select that referenced this issue Apr 20, 2015
@seven-phases-max
Copy link
Member

And another reason to make the path customizable via variables. What if I need to replace your images with my own? Obviously I won't want to do this by replacing files in the installed node module... But if you have hardcoded data-uri path, there will be no other way.

@dcousens
Copy link

@react-select-path: "../node_modules/react-select";

And what if we have multiple versions of said package?
This breaks SEMVER.

I guess https://github.com/less/less-plugin-npm-import might work, but it'd be nice for this to be core IMHO.
The above solution will end up building a broken ecosystem for those of us that want composable drop-in components.

@JedWatson
Copy link
Author

@dcousens I've expanded that line of thinking into #2618, which is related but about a separate feature.

@seven-phases-max
Copy link
Member

@react-select-path: "../node_modules/react-select";
And what if we have multiple versions of said package?
This breaks SEMVER.

breaks SEMVER?
Where exactly version number is used for paths, especially in npm "ecosystem" you mentioned?
(not counting that @react-select-path: "../node_modules/react-select"; is just an example and it actually means @react-select-path: "whatever/anything/react-select";). See also --relative-urls.

@dcousens
Copy link

Where exactly version number is used for paths, especially in npm "ecosystem" you mentioned?

@react-select-path: "../node_modules/react-select"; implies a global react-select-path.

I understand --relative-urls was the potential solution to the above problem, but it doesn't really help here:

What if I use a component that uses version 1.0.0 of react-select, and my project also uses version 1.0.0. Something as simple as npm dedupe can completely blast away all of these path-based assumptions in a second.

@seven-phases-max
Copy link
Member

@react-select-path: "../node_modules/react-select"; implies a global react-select-path .

In what way? Yet again please understand that @react-select-path: "../node_modules/react-select"; was just an example for @import "../node_modules/react-select/less/component.less"; of the original post. You're free to set whatever path there.

@dcousens
Copy link

@seven-phases-max having just re-read that, you are right, the [wrong] impression given to me was that @react-select-path was changing that variable across all the compilation units (that is, a global).

However (I believe), the remainder of my points remain relevant (AFAIK). Please see above post, I've since amended it.

@dcousens
Copy link

@seven-phases-max in terms of the issue (our discussion is slightly different), doesn't the ability to use --relative-urls effectively close this issue?

We could continue our discussion in #2618?

@seven-phases-max
Copy link
Member

@dcousens

I understand --relative-urls as the potential solution to the above problem, but it doesn't really help here, since something as simple as npm dedupe can completely blast away

Notice that here we are talking about image files shipped with the library itself, thus whereever the package is put by the npm, the relative path of images from the corresponding less code is always the same (they all are in the same package). So npm is too weak to break --relative-urls in this particular case.

There're other more generic --relative-urls (either on or off) issues like for example those I mentioned in #2615 (and those may actually benefit from some hardcoded-reative-url/data-uri function), but that's a bit out of this particular issue scope.

P.S. Ah sorry, I have not see your last posts yet.

We could continue our discussion in #2618?

I'd rather prefer #1972, just to not repeat all those arguments stated there once more. But well, it does not really matter.

@dcousens
Copy link

@seven-phases-max see my continued comments in #2618.
I think this issue is good to close.

@lukeapage
Copy link
Member

I would advise relative urls for any non simple project.. The only advantage of non relative is when your file is included from a mixin in a different file - less then works out the path relative to the mixin, not the source of the string.
It would get pretty confusing to have some paths relative and some not, controlled by a function name - unless i am missing the point?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants