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

Spitballing: @import (preprocess) 'file.less'; #3045

Closed
calvinjuarez opened this issue Apr 6, 2017 · 23 comments
Closed

Spitballing: @import (preprocess) 'file.less'; #3045

calvinjuarez opened this issue Apr 6, 2017 · 23 comments

Comments

@calvinjuarez
Copy link
Member

calvinjuarez commented Apr 6, 2017

In my development, I've occasionally wanted to import some chunk of Less that I've got, but scoped under some selector, like this:

.scope {
  @import 'some-bit-of-some-library-i-want.less';
}

This can cause problems if that library ever uses .grandpa &; in cases like #3032 (or #1850, #2052, #2534, etc.) where scoped extends are desired; or for a more modular, requirejs-inspired component authoring style (as mentioned in #3040).

I currently work around this by creating a separate Less file containing all the bits I need for the think I want, pre-compiling that some-bit-of-some-library-i-want.less to CSS, then @import-ing that. It works fine, but adds another weird CSS file to my code, and setting that up can take some time.

Now, I'm just spitballing, and looking for a discussion, not immediate action, but adding (yes, yet another) @import flag to specify the imported file should be processed to CSS before importing it could make that workflow much easier.

.scope {
  @import (preprocess) 'some-bit-of-some-library-i-want.less';
}

Bottom line: It would afford library & "module" authors access to more of the features of Less.


Flag name options:

  • preprocess – It's explicit about the behavior.
  • precompile – Like preprocess, but, I don't know, different.
  • component – Self-contained, "requirejs-ish" components/modules might be a compelling use case.
  • module – Same reasons as component (though it feels weird to me, as "module" means something else in the CSS world, already).
  • scopable – Describes the capabilities of the feature, in a more use-case-agnostic way (though it seems conspicuously silent on the limitations the feature would have).
  • flat or flatten – Seems clear about the behavior and limitations.
@calvinjuarez
Copy link
Member Author

calvinjuarez commented Apr 6, 2017

P.S. (To clarify how this would be useful for #3040): This flag should probably keep imports in the imported files from affecting the compiling of the parent file. In fact I imagine it'd block access to the imported file's Less stuff entirely, essentially compiling the primary imported file all the way to CSS, and importing it inline as such.

P.P.S.: The result of this import could probably be entirely cached and re-used, since the result would be static. At least, my initial concept is that this kind of import would essentially behave just like @import (less) 'some-css-file.css'; does (except it compiles the imported file to CSS first, obviously).

@matthew-dean
Copy link
Member

Maybe my head is a bit foggy today, but I really don't understand the problem that's being addressed, how this addresses that problem, and the way it solves it. I don't understand wanting to "scope" under a selector but not wanting it to inherit the selector. Couldn't you just import as a sibling of the selector?

& {
  @import 'some-bit-of-some-library-i-want.less';
  .scope { }
}

It would be "local" to .scope without inheriting any parent selectors. Is there something I'm missing?

@calvinjuarez
Copy link
Member Author

calvinjuarez commented Apr 7, 2017

library/component-one.less

.component-one {
  ...

  ol& {
    ...
  }
}

library/component-two.less

.component-two {
  ...
}
.component-two-alias {
  &:extend(.component-two all);
}

master.less

.scope {
  @import 'library/component-one.less';
  @import 'library/component-two.less';
}

currently results in:

master.css

.scope .component-one {
  ...
}
ol.scope .component-one { /* [1] */
  ...
}
.scope .component-two,
.scope .scope .component-two-alias { /* [2] */
  ...
}

This feature would change the ouput to:

master.css

.scope .component-one {
  ...
}
.scope ol.component-one { /* [1] */
  ...
}
.scope .component-two,
.scope .component-two-alias { /* [2] */
  ...
}

@matthew-dean
Copy link
Member

Ohh I see, so it processes the import as a kind of "flat" import, as if it was a root.

@calvinjuarez
Copy link
Member Author

calvinjuarez commented Apr 7, 2017

Exactly. It'd make components written in Less more portable, as they could be reliably imported the same anywhere, while not keeping their authors from employing Less features like internal extends or .granparent &-type selectors.

@calvinjuarez
Copy link
Member Author

calvinjuarez commented Apr 7, 2017

Other questions I'm having:

  1. Would the importer file's variables/mixins be available to the imported file, like a standard import, even if that compiling happens in isolation? If so, it'd be essentially as if the importer file was reference-imported into the imported file.

  2. Likewise, would the imported file's variables/mixins be exportable somehow to the importer file? Without this, the workaround would just be @import (reference) 'file.less'; @import (flat) 'file.less';, I guess (assuming flat would be implicitly like multiple).

Essentially, the question is how isolated would an @import (flat) import be?

@matthew-dean
Copy link
Member

The evaluation of imports is one of the most complicated things in Less. I'm not sure this is necessarily the right approach. Imports should have nothing to do with it. That is: it seems like the same feature should be available here:

.scope {
	.mixin();
}

.mixin() {
  .component {
    prop: 1;

    ol& {
      prop: 2;
    }
  }
}

You're talking about imports, but it what those import changes do is change the effect of scope on collapsing behavior. It's the second part that's being changed, and such a change should probably (maybe) be more generic than import-specific. But there's a larger problem...

That is: the list of Ready to Implement features for Less.js is already incredibly long, and the number of contributions in terms of code has gone down. There are a number of code & feature improvements ready to be started today.

So, I'm a) skeptical of this feature, b) even if it will/should go in, it feels like a lower priority than other ready-to-implement, c) it's unlikely it would ever happen in a reasonable timeframe unless you are going to write the code changes yourself, d) if you are going to do that work (which is great), there are other areas of Less.js which could use your help in a much greater way to impact many more people.

As it stands, I think I'm going to recommend to @less/core that all new feature requests are rejected until such time as there's a healthy base of core maintainers to manage even basic things like bug reports. If you know how to help out Less.js, ideas are welcome. But with where things are at at the moment, I'm going to mark this as "Consider Closing".

@calvinjuarez
Copy link
Member Author

calvinjuarez commented Apr 7, 2017

As to the objections to the feature itself, I don't think that the issues I mentioned are actually, like, bugs; Rather, I think they're how Less works, and I love how Less works. I occasionally find I want to include little self-contained bits, but there are ways around it (compile the bit to CSS, then import the CSS w/ (less)).

So, while I think the feature is best on the @import feature level, I agree that it's little more than a quality of life feature.

But there's a larger problem...

I hear that. As I mentioned in the title, I was just spitballing, but you're right that Less isn't in a position for free-form spitballing rn. I love Less, so I'll try to make time soon to contribute more meaningfully to the code itself. Maybe I'll try to tackle extending mixins or something...

As I'm fairly new to the code, to whom should I direct questions about where to look in the code?

@matthew-dean
Copy link
Member

Maybe I'll try to tackle extending mixins or something

I'm sure that would be welcome!

@matthew-dean
Copy link
Member

As I'm fairly new to the code, to whom should I direct questions about where to look in the code?

That would be either myself, @seven-phases-max, or @lukeapage would be your best bet. I saw you added me on Twitter (I think?), so you can always shoot me questions there.

If you want to start diving into the code base, would you be interested in joining the Less core team (help with planning / organizing these issues, as you have time, of course)? You don't have to contribute any more than you do, just wondering if you might be interested in higher-level stuff as well.

@seven-phases-max
Copy link
Member

For the feature, I think it's possible to be done via plugin. And a plugin implementation is preferred since the feature itself is nothing but a workaround for various scoped import issues (primarily foo & and scope-unaware extend).

@calvinjuarez
Copy link
Member Author

@matthew-dean

I saw you added me on Twitter

Yup that was me. Sorry if that was creepy. haha

If you want to start diving into the code base, would you be interested in joining the Less core team (help with planning / organizing these issues, as you have time, of course)?

I don't mind helping out in any way, I can. Let me know what you'd like me to do.

@matthew-dean
Copy link
Member

@calvinjuarez Can't believe I didn't notice you answered this question back in April about helping out. Oops. Sorry about that. At least I got you set up today! Welcome to the team!

@stale
Copy link

stale bot commented Feb 7, 2018

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Feb 7, 2018
@stale stale bot removed the stale label Feb 7, 2018
@stale
Copy link

stale bot commented Jun 7, 2018

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Jun 7, 2018
@gibbsfromncis
Copy link

Is there any solution to handle cases like this?

@stale stale bot removed the stale label Jun 26, 2018
@rjgotten
Copy link
Contributor

rjgotten commented Jun 27, 2018

What you're really looking for here, is a way to reduce the selector captured in & to the right-hand key; process a set of rules using that right-hand key only, and then prepend the remainder of the original selector to the output rules.

I think the most transparent way to do it without language modifications, would be via a custom rhk-only at-rule. E.g.

// block.less
.block {
  background : red;
  @rhk-only {
    & > &-item {
      background : blue;
    }
  }
}

// main.less
.top {
  @import "block.less";
}
/* main.css */
.top .block {
  background : red;
}
.top .block > .block-item {
  background : blue;
}

Alternatively -- or if you're in need of more control over the selector -- you can have a plugin function that captures the current selector as a (list of) string(s) and then manipulate that further, as per #3053.


@matthew-dean
Did the custom at-rule functionality that was talked about before in meta, ever land in stable 3.x builds?

@matthew-dean
Copy link
Member

@rjgotten

Did the custom at-rule functionality that was talked about before in meta, ever land in stable 3.x builds?

Can you be more specific?

@gibbsfromncis
Copy link

@rjgotten what is rhk-only ?

@rjgotten
Copy link
Contributor

rjgotten commented Jun 28, 2018

Can you be more specific?

There was some discussion in less-meta over being able to register custom at-rules with Less, like you can register custom functions, and iirc even some prototyping. Just wondering if that feature found its way into 3.x

what is rhk-only ?

Just a name for a potential custom at-rule that could be used to implement the desired behavior here. It's not something that ships built-in to Less.

@matthew-dean
Copy link
Member

matthew-dean commented Jun 29, 2018

@rjgotten

There was some discussion in less-meta over being able to register custom at-rules with Less, like you can register custom functions, and iirc even some prototyping. Just wondering if that feature found its way into 3.x

Oh, that. Yes, I did prototype and have it working, but ultimately @seven-phases-max gave a good argument to not auto-magically call functions from nodes that don't look like functions. And he gave the argument that one could easily make a plugin with a visitor for specific at-rules that returned different nodes, which I ultimately agreed with. If you're already registering custom functions, making a replacing visitor is not necessarily a hard step.

So, no, it didn't go into 3.x, to answer your question. Although maybe at some point I could convert it into a simple plugin?

@stale
Copy link

stale bot commented Oct 27, 2018

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Oct 27, 2018
@stale stale bot closed this as completed Nov 26, 2018
@kpaxqin
Copy link

kpaxqin commented May 27, 2022

Is there any solution now ? We still meet this problem and have no idea how to handle this case.

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

6 participants