Less.js: data-uri函数使用data-uri调用的路径,而不是包含文件路径的字符串。

创建于 2015-07-08  ·  37评论  ·  资料来源: less/less.js

来自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

我欢迎您提供有关这是一个重大更改(保证重大更新)还是一个错误修复的反馈。

最有用的评论

唔...

好的。 然后我们有一个resolve-url(url, [base])函数-一个可选的base ; 默认为写入/声明/定义函数调用的文件目录。 然后有一个declared-dir()函数,如果作者想显式地拉路径,它会拉this.fileInfo并抓住路径。 想要从其他文件获取路径; 或需要将其用作与URL解析无关的其他功能的一部分。

即,完整的表单调用(不包含隐式基数)将类似于:

resolve-url("../foo", declared-dir())

...相当于只做

resolve-url("../foo")

...这相当于懒惰的渴望

url("../foo")

不需要那种“自动”注入的变量。 我认为,这可以纯粹作为一组插件函数来实现。 我们唯一需要的核心机制是将URL标记为“已经解析”的方法,这样就可以阻止默认解析器逻辑在resolve-url函数产生的URL上运行。

语义应在课程记录中明确说明。 并且该文档可以将urlresolve-url进行显式比较,以说明急切和懒惰的评估/解决方案。

所有37条评论

我欢迎您提供有关这是一个重大更改(保证重大更新)还是一个错误修复的反馈。

仅供参考:您可以轻松实现此目标,而不会以非常简单的方式破坏向后兼容性。

当前, 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");
}

(例如,以一个字体混合的示例为例,它通常是多个woffttfeoteot?#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。尽早对其进行修改以最大程度地减少可能的破坏性影响)。



换句话说,假设urldata-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应该如何工作的。 我认为这不是“重大更改”,而是错误修复。

就是说...我认为解决这样的问题不会有问题:

  1. 尝试解决相对于呼叫者的问题。
  2. 尝试解决相对于mixin的问题。

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

https://github.com/less/less.js/blob/4e903e8254cc20fec80fccd35794fb797949e653/lib/less/tree/call.js#L47

如果我正确地读取了代码,则那里的文件信息对应于函数调用为_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上运行。

语义应在课程记录中明确说明。 并且该文档可以将urlresolve-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节点,是的。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

matthew-dean picture matthew-dean  ·  6评论

papandreou picture papandreou  ·  7评论

seven-phases-max picture seven-phases-max  ·  6评论

xblakestone picture xblakestone  ·  3评论

vecerek picture vecerek  ·  5评论