来自https://github.com/less/less.js/issues/2541,但是我已经在项目中看到了
// mixins.less
.background(@image) {
background-image: data-uri(@image);
}
// app/content/button.less
button {
.background("images/btn.jpg");
}
我希望从app/content/images/btn.jpg
中获取图像,但从images/btn.jpg
。
我欢迎您提供有关这是一个重大更改(保证重大更新)还是一个错误修复的反馈。
我欢迎您提供有关这是一个重大更改(保证重大更新)还是一个错误修复的反馈。
仅供参考:您可以轻松实现此目标,而不会以非常简单的方式破坏向后兼容性。
当前, data-uri()
函数接受包含字符串的Quoted
树节点作为文件路径,并在内部将其作为URL解析为包含函数调用的文件的位置。 您可以重载data-uri
函数,以接受包含实际URL的Url
树节点。 这样,URL应针对调用url()
CSS函数的位置进行规范化,而不再应在data-uri()
Less函数内部进行规范化。
例如
// app/content/button.less
button {
.background(url("images/btn.jpg"));
}
@rjgotten
对我来说,它更像是一种解决方法,而不是解决方法。 在进一步的迭代中,他们将通过将url
移到mixin来避免冗长,然后问题再次出现。 另一个问题是,以原始问题为例(#2541),通常按以下方式使用:
// mixins.less
.background(@image) {
background-image: data-uri("@{image}.jpg");
}
// app/content/button.less
button {
.background("images/btn");
}
(例如,以一个字体混合的示例为例,它通常是多个woff
, ttf
, eot
, eot?#iefix
等。扩展名附加到同一文件名)。 这样,较早的url
也是不可能的。
@ seven-phases-max
然后,我真的认为没有合适的解决方案期限。 您需要某种方法来确定上下文,相对URL应针对该上下文进行解析。 您可以从定义了字符串值的文件的文件信息中获取该上下文,该字符串值将进入data-uri()
函数,或者通过url()
函数和Url
使截止点更加明确
如果要支持路径变量替换,那么事情很快就会变得棘手,因为您需要弄清楚如何对路径的各个部分进行标准化。
例如,您如何将类似以下内容标准化:
// mixins.less
.background(@image) {
background-image: data-uri("../../@{image}.jpg");
}
// app/content/button.less
button {
.background("../images/btn");
}
您如何将这两个路径的相对URL解析度和令牌替换驱动的组合方式结合起来?
我想一个选择是仅当替换标记位于最终URL值的开头并进入url()
或data-uri()
时,才对定义替换替换标记的字符串的文件进行解析。
另一个解决方案可能是引入一些路径处理功能来加入路径或添加/删除/编辑文件扩展名(类似于unit()
函数如何处理尺寸),使事情更加明确。
例如
// mixins.less
.background(@image) {
background-image: data-uri(extension(<strong i="21">@image</strong>, "jpg"));
}
// app/content/button.less
button {
.background(url("./images/btn"));
}
对于第一个示例,它不需要任何特殊的规范化, "../../@{image}.jpg"
在编写时会扩展为"../../../images/btn.jpg"
(然后由data-uri
处理路径)。
第二个示例只是...堆叠要解决的功能一个要解决与...的向后兼容性的功能...究竟是什么? 调用其他文件中定义的混入时,__错误_文件路径?
毕竟,如果使用.background(url("images/btn.jpg"));
只能按预期工作_only_,那么与直接编写.background(data-uri("images/btn.jpg"));
而不进行任何更改有何不同? :)
换句话说,我的意思是,如果要修复此问题,则无论其破坏程度如何,都应使用data-uri
修复该问题。 (老实说,我不知道什么是更好的策略:a。等待更多报告/请求,然后(如果有足够的话)进行更改,或b。尽早对其进行修改以最大程度地减少可能的破坏性影响)。
换句话说,假设url
和data-uri
最初设计为可互换的(即data-uri
只是url
的特殊版本(并编译为CSS url
最后)),要描述为什么确切地ulr
表现为“像这样”(带有这样的选项)而data-uri
表现为“像那样”(带有这样的选项),并且要获得某些行为,您将需要data-uri(url())
组合,仅限于mixin中的“ data-uri
,其中url
_out_与--relative-urls: on
“ <-Bhrrrr ... :)
对我来说,它更像是一种解决方法,而不是解决方法。 在进一步的迭代中,他们将尝试通过将url移至mixin来避免冗长,然后问题再次出现。
是的,我同意。
我正在慢慢尝试建立更多的精力以减少对v3发行版的投入,并解决此问题。
我正在考虑找出所有可能的文件路径,然后逐个尝试-尽管如果在不同位置有多个文件,这有点令人讨厌...我想我同意不可能永久性地完全解决此问题,但至少我们可以解决正常情况。
可能resolve()
函数可能有助于将解析的url传递给函数(但是如果它不是无法使用的完整路径,而在解决此问题后将使用完整路径...)
抱歉,只是迅速记下了想法。
这只是一个速记,但使用变量插值进行导入时,我们将遇到同样的问题。
使用变量插值导入。
这既有趣又令人不安。
它是实际支持的用例还是巧合?
@rjgotten支持,但是支持有限。 在#410中被追踪
这有效:
<strong i="8">@variable</strong>: "path.less";
<strong i="9">@import</strong> "@{variable}";
这不是:
.mixin(@variable) {
<strong i="13">@import</strong> "@{variable}";
}
编辑:修改以使链接起作用。
我不确定我是否要在mixins中支持变量@import
。
整个变量导入有点不可思议,并且可以创建一些违反直觉的代码..因此,我不建议这样做。
有关变通办法的大量讨论,也许只是解决了实际问题? 还不清楚data-uri应该相对于正在处理的文件。
现在我有从另一个路径导入_a reference_的文件,它仍然抱怨data-uri。 至少那一定是一个错误吗? 我的意思是,如果我通过引用导入,则不应尝试重写相对于当前文件的路径。
@Ciantic
我的意思是,如果我通过引用导入,则不应尝试重写相对于当前文件的路径。
究竟基于什么? 它与reference
什么关系?
现在,我有从另一个路径导入引用的文件,但它仍然抱怨data-uri。
听起来与上述问题相反。 您能否提供更多详细信息? (例如,导入,导入和数据文件的路径等)。
无样式
.something {
background: data-uri("some.svg");
}
sub / test.less
<strong i="11">@import</strong> (reference) "../style.less";
.test {
color: green;
}
它编译style.less,而不是test.less,因为它尝试使用与test.less相关的data-uri。
为什么引用导入会尝试重写路径,我认为使用引用时没有必要。
我希望data-uri遵循选项中的url重写规则。 当然....很难说出data-uri的实际含义。
通常,data-uri应该相对于“调用.less文件”来解析。 因此,在mixin的情况下,它应相对于mixin的调用位置而不是mixin的位置进行解析。 mixin“混合”这些语句,然后解析它们。 所以@lukeapage我认为您的解释是正确的:
// app/content/button.less
button {
.background("images/btn.jpg");
}
它应该在app/content/images/
寻找btn.jpg。 如果不是,那是一个错误,因为它不是mixins应该如何工作的。 我认为这不是“重大更改”,而是错误修复。
就是说...我认为解决这样的问题不会有问题:
Node.js尝试使用多个路径进行解析。 只要清楚地记录了解决顺序,您就可以管理期望。 那样做意味着如果有人以.less为根据执行行为#2,那么即使在并非所有情况下,它仍然可以在几乎所有情况下工作。
@马修院长
通常,data-uri应该相对于“调用.less文件”来解析。 因此,在mixin的情况下,它应相对于mixin的调用位置而不是mixin的位置进行解析。 mixin“混合”这些语句,然后解析它们。
您永远不可能以一种适用于所有用例的正确方式进行这项工作。
例如,您将如何支持参数化的url,即带有替换标记的url,这些URL应该在仅填充替换标记的某些已知基础文件夹中解析? 在这种情况下,需要对被呼叫者的文件而不是对呼叫者的文件进行重新整理。
我对如何透明地解决此问题而没有在呼叫站点上显式使用url()
有一个突然的认识,@ seven-phases-max正确地称为一个坏主意(因为有人最终会_will_试图将其重构为mixin调用并中断操作):
创建文字Quoted
节点后,请保留其文件信息。 通过变量分配,混入调用等传播该信息。源自Quoted
调用者文件的任何url()
或data-uri()
,都将针对该调用者文件进行解析。 但是,作为混入某些内部逻辑的一部分的Quoted
值仍会针对混入的本地文件进行解析。
这样可以确保一切正常运行,除了方案中的替换字符串外,例如:
// mixins.less
.background(@image) {
background-image: data-uri("@{image}.jpg");
}
// app/content/button.less
button {
.background("images/btn");
}
您还可以使用一种技巧来解决这些问题:填写替换令牌时,如果令牌位于替换字符串的开头,则生成的字符串应该继承填充令牌中的文件信息,而不是替换字符串。
如果mixin自己的作者的意图是使此类路径针对mixin文件进行解析,则他们仍然可以通过使用例如"./@{image}.jpg"
作为模式来完成这项工作。 这样可以有效地将责任负担从呼叫者那里转移出去,而这正是您想要的。
// _mixins.less
.sprite(@image) {
background: data-uri("../images/sprites/@{image}.png") no-repeat;
}
// main.less
div {
.sprite('logo');
}
输出:
div {
background: url(data:image/png;base64,...) no-repeat;
}
哇,这是一个非常古老的...。我的两分钱也是这个问题,也影响了我。
将选项添加到url函数或创建一个新函数,将url解析为绝对值,该怎么办? 这样,无论在何处设置mixin,它都将在绝对路径下工作,并且没有错误的余地。
将选项添加到url函数或创建一个新函数,将url解析为绝对值,该怎么办? 这样,无论在何处设置mixin,它都将在绝对路径下工作,并且没有错误的余地。
这里的问题不是绝对路径还是相对路径。 它是关于相对于呼叫站点的相对于相对于声明站点的相对的。 完全不同的问题。
也许问题已经发展了,但是最初的注释和标题是关于data-uri解析与被调用文件有关的路径的问题,当与放置在其他地方的mixin结合使用时,可能会错误地解析该路径。 好吧,这就是我遇到的问题。
那么,绝对路径在哪里作为解决方案呢?
假设data-uri接受绝对路径,并且有一个比较老套的absolute-url
函数,那么无论将mixin放在何处,以下代码都将起作用。
// mixins.less
.background(@image) {
background-image: data-uri(@image);
}
// app/content/button.less
button {
.background(absolute-url("images/btn.jpg"));
}
@ miljan-aleksic“绝对”是指相对于data-uri
位置的文件吗? 如果这样,“绝对”可能是错误的术语。
不过,似乎将URL用作任何相对于URL文件的功能性包装是一个好方法。 或url()的附加参数。
@ matthew-dean,绝对是指文件的完整路径,例如: /users/myuser/projects/lessproject/icon.svg
。
我不了解您的方法,因为我看不到url()如何在不知道泛型的情况下如何建立data-uri位置文件的相对路径。
不过,似乎将URL用作任何相对于URL文件的功能性包装是一个好方法。 或url()的附加参数。
很有趣; 这几乎是我几年前的建议。 ;-)
绝对地,我的意思是文件的完整路径,例如:/users/myuser/projects/lessproject/icon.svg。
看起来绝对是指这个absolute-url
函数_pre-resolves_根据调用absolute-url
函数的文件的位置,传递给它的相对路径到完整的输出路径,相对于编译后的输出CSS文件将到达的位置。
也就是说,你们两个都是同一件事。 当时我和我一样。
根据调用绝对URL函数的文件的位置(相对于编译后的输出CSS文件将到达的位置),将其转换为完整的输出路径。
与之类似,重写URL或rootpath仍然适用,但是基于定义位置吗? 这似乎与@lukeapage的原始示例稍有不同,该示例不是在谈论相对于输出的URL,而是在compile_期间的URL。 例如data-uri()
位置。
因此,此问题有点难以跟踪,因为人们发布了有关相似但不完全相同的问题。 也就是说,更改相对的_source_可能需要与更改相对的_output_完全不同的解决方案。 也许不是; 它取决于路径逻辑; 但我们应该清楚,data-uri不会产生任何路径作为输出。
也许我们需要像resolve()
这样的东西? 我不知道,只是吐口水,但是url(resolve(file(), "my/path"))
吗? 我想这就是@ miljan-aleksic由absolute()
表示的含义,因为它将解析为一个绝对URL。 但是它仍然需要输入(例如file()
来解决)。 否则,您可以执行类似file-resolve()
在一个函数中指定该逻辑,但是将resolve()
和file()
作为两个函数可能分别有用。
所有这些棘手的部分是所有的重写URL选项,从PR合并开始,其中的更多选项都增加了模块支持。 (https://github.com/less/less.js/pull/3248)。 因此,如果返回的是文件相对URL,是否仍可以重写? 我想是的,但是我们需要弄清楚。
是的,resolve()和file()完全定义了我要解释的内容。 我希望我们可以在不久的将来看到这一点。
@ miljan-aleksic好吧,那很有意义。
实际上, file()
不太正确,因为那样会返回我假定的文件名,就更像dir()
。 而且它可能应该是每个文件的变量常量。
关于什么:
data-uri(resolve(<strong i="10">@DIR</strong>, "my/path"))
因此,增加了两件事:1)合并路径的resolve()函数,2)在评估时将@DIR
(和@FILE
?)常量注入到每个文件中。 唯一棘手的事情是测试那些注入的var不覆盖或与根中的其他var合并,但是测试起来应该相当简单。 还是应该使用小写字母,例如@arguments
? 在这种情况下,我建议使用@directory
和@filename
以避免冲突。 什么是Less-y选项?
也许我们需要像
resolve()
这样的东西?
^宾果。 就是这样
什么是Less-y选项?
我会选择Node.js-y选项: __dirname
它已经存在了很长时间并且是众所周知的。 在Less中为相同的概念使用相同的名称可能是一个好主意。
我会选择Node.js-y选项:__dirname
错误...不会匹配Less / CSS关键字,Less变量或函数语义。 我们必须做得更好。 @__dirname
也许,但是下划线对于语言还是有点奇怪。 它根本不适合。
下划线对于该语言仍然有些奇怪。 它根本不适合。
双引号下划线用于以多种语言表示“系统提供的内容”,尤其是涉及诸如内在变量之类的东西时。 因此,不合时宜是这里的重点。
当然; 如果您不喜欢它,可以始终使用@dirname
或@dir-name
类的派生类。
但是,经过更多考虑之后,为什么我们甚至需要将当前文件路径公开为变量? 不能将其编入概念性的resolve()
函数本身吗?
不能将其编织到概念的resolve()函数本身中吗?
我们回到了我的建议中,只是使用了不同的函数名称。 我仍然最喜欢它,甚至更喜欢resolve()。
我们回到了我的建议中,只是使用了不同的函数名称。
有点。
我要说的是afaik不需要传递对resolve()
函数进行调用的文件的URL /路径,因为该位置应为函数的_known_。
函数中的this
引用FunctionCaller
实例,该实例具有currentFileInfo
属性。
该属性被初始化为与该函数调用相对应的Call
AST节点的文件信息。
IE
如果我正确地读取了代码,则那里的文件信息对应于函数调用为_declared_的位置的文件信息-而不是评估函数调用的文件的位置。
这意味着可以将此文件信息用于“渴望的” URL解析器。 即使将函数调用放在在另一个文件的上下文中导入和评估的mixin内,它也将按预期方式工作。 即:将分辨率固定到定义了混合的文件上。
但是,经过更多考虑之后,为什么我们甚至需要将当前文件路径公开为变量? 不能将其编织到概念的resolve()函数本身中吗?
如果我们确定没有人需要当前文件或通用的解析器函数……也许……这是一个显式的本地变量,则表明它不是通用函数,并且该函数不会像任何其他功能。 我真正关心的是语义。 不管您用什么名称,如果您没有“当前文件”的特殊“标记”,那么就不会像其他任何基于输入来解析相同功能的函数一样。 换句话说,它是一个根据看不见的输入解析的函数,与我有关。 但是,如果函数像current-file-resolve()
这样非常明确的东西,也许就足够清楚了。 否则,您只会使人们感到困惑,为什么mixin调用不能根据调用的文件而不是mixin定义的文件来解析specialfunction()
。
因此,不,从技术上讲,不需要本地变量,但是需要从语义上清楚其含义/输出/行为。
唔...
好的。 然后我们有一个resolve-url(url, [base])
函数-一个可选的base
; 默认为写入/声明/定义函数调用的文件目录。 然后有一个declared-dir()
函数,如果作者想显式地拉路径,它会拉this.fileInfo
并抓住路径。 想要从其他文件获取路径; 或需要将其用作与URL解析无关的其他功能的一部分。
即,完整的表单调用(不包含隐式基数)将类似于:
resolve-url("../foo", declared-dir())
...相当于只做
resolve-url("../foo")
...这相当于懒惰的渴望
url("../foo")
不需要那种“自动”注入的变量。 我认为,这可以纯粹作为一组插件函数来实现。 我们唯一需要的核心机制是将URL标记为“已经解析”的方法,这样就可以阻止默认解析器逻辑在resolve-url
函数产生的URL上运行。
语义应在课程记录中明确说明。 并且该文档可以将url
与resolve-url
进行显式比较,以说明急切和懒惰的评估/解决方案。
万一“注入变量”的想法由于导入的文件具有相同的作用域而无法正常工作(无其他黑客)。
<strong i="7">@__dir</strong>: "whatever";
// *everywhere* it's the only <strong i="8">@__dir</strong> value = the path of "c"
<strong i="9">@import</strong> "a";
<strong i="10">@import</strong> "b";
<strong i="11">@import</strong> "c";
说到基于函数的实现,我认为(但不能确定)仍然可以获得在this.context.?
或this.context.frames[?]
调用函数的文件的路径。或者。
嗯,所以我们没有更好的方法来解决它?
@heynext
嗯,所以我们没有更好的方法来解决它?
恐怕懒惰的评估使这很难正确解决。
@ seven-phases-max
说到基于函数的实现,我认为(但不能确定)仍然可以获得在this.context.?
或this.context.frames[?]
调用函数的文件的路径或者。
您应该能够在其层次结构中找到Call
节点,是的。
最有用的评论
唔...
好的。 然后我们有一个
resolve-url(url, [base])
函数-一个可选的base
; 默认为写入/声明/定义函数调用的文件目录。 然后有一个declared-dir()
函数,如果作者想显式地拉路径,它会拉this.fileInfo
并抓住路径。 想要从其他文件获取路径; 或需要将其用作与URL解析无关的其他功能的一部分。即,完整的表单调用(不包含隐式基数)将类似于:
...相当于只做
...这相当于懒惰的渴望
不需要那种“自动”注入的变量。 我认为,这可以纯粹作为一组插件函数来实现。 我们唯一需要的核心机制是将URL标记为“已经解析”的方法,这样就可以阻止默认解析器逻辑在
resolve-url
函数产生的URL上运行。语义应在课程记录中明确说明。 并且该文档可以将
url
与resolve-url
进行显式比较,以说明急切和懒惰的评估/解决方案。