gpt4 book ai didi

sass - Sass 用来解析@import 语句的算法是什么?

转载 作者:行者123 更新时间:2023-12-04 15:09:32 25 4
gpt4 key购买 nike

Node.js 用于解析 require() 的算法通话很清楚documented in pseudocode .

我需要同样的东西给 Sass 的 @import陈述。

我知道@import 'foo'将尝试基本名称的各种组合 foo_foo , 带扩展名 .scss.sass , 在与导入文件相同的目录中以及相对于任何配置的“加载路径”...但是这些尝试的顺序是什么,即如果有多个文件可以满足 @import 的优先顺序?是否以 ./ 开头或 ../影响它是否尝试加载路径?它还会尝试我没有涵盖的其他任何事情吗?怎么样.css文件?

guide除了“Sass 很聪明,会为你解决”之外,并没有说太多。 reference docs进入更多细节,但仍然没有说明解决步骤。

任何人都可以用伪代码提供它使用的确切算法吗?

最佳答案

这是 @import <import_arg>; 的简化算法.
这是从阅读 SASS 的源代码和运行我自己的测试中得出的。

def main(import_arg)
let dirname = File.dirname(import_arg)
let basename = File.basename(import_arg)
if import_arg is absolute ... # omitted as this is a rare case
else return search(dirname, basename)
end

# try resolving import argument relative to each path in load_paths
# 1. If we encounter an unambiguous match, we finish
# 2. If we encounter an ambiguous match, we give up
# see: https://stackoverflow.com/a/33588202/3649209
def search(dirname, basename)
let cwd = operating system current working directory
let load_paths = paths specified via SASS_PATH env variable and via --load-path options
let search_paths = [cwd].concat(load_paths)
for path in search_paths
let file = find_match(File.expand_path(basename, path), basename)
if (file != false) return file
end
throw "File to import not found or unreadable"
end

def find_match(directory, basename)
let candidates = possible_files(directory, basename)
if candiates.length == 0
# not a single match found ... don't give up yet
return false
else if candidates.length > 1
# several matching files, ambiguity! ... give up
# throw ambiguity error
throw "It's not clear which file to import"
else
# success! exactly one match found
return candidates[0]
end
end

# NB: this is a bit tricky to express in code
# which is why I settled for a high-level description
def possible_files(directory, basename)
# if `basename` is of the form shown on the LHS
# then check the filesystem for existence of
# any of the files shown on the RHS within
# directory `directory`. Return the list all the files
# which do indeed exist (or [] if none exist).
# LHS RHS
# x.sass -> _x.sass, x.sass
# x.scss -> _x.scss, x.scss
# x -> x.scss, _x.scss, x.sass, _x.sass
# _x -> _x.scss, _x.sass
end

为简洁起见,我使用的是 Ruby 的 File#dirname , File#basename 以及 File#expand 这就像 Node.js 的 path.resolve .我正在使用类似 Ruby 的伪代码,但它仍然是伪代码。

关键点:
  • 没有优先顺序。当有多个可能的候选者时,SASS 不会执行优先顺序,而是放弃。例如,如果您写了 @import "x"并同时说 x.scss_x.scss存在,那么 sass 会抛出一个歧义错误。同样,如果两个 x.scssx.sass存在则抛出歧义错误。
  • 从“从左到右”的顺序尝试加载路径。它们提供了一个根或基来解析导入(类似于 UNIX 使用 $PATH 查找可执行文件的方式)。始终首先尝试当前工作目录。 (尽管此行为 will change 从 3.2 到 3.4)
  • 无论您是否使用 ./ 都会尝试加载路径或 ../
  • 在 sass 文件中,常规 .css 文件 cannot be imported

  • 如果您想了解更多详细信息,我建议您阅读 SASS 的源代码:
  • import sass/lib/sass/tree/import_node.rb 的方法.在第 53-56 行,您可以看到与 search 中的循环相同的 for 循环。函数在我们的伪代码中。
  • Importers::Base抽象类 sass/lib/sass/importors/base.rb .这个文件的注释非常方便。
  • find_real_file sass/lib/sass/importors/filesystem.rb 的方法.第 112-126 行实现了我们的 possible_files功能。第 156 行检查只有一个匹配项。如果没有,那么第 167 行会抛出一个歧义错误,否则第 183 行会选择一个匹配的文件。

  • 编辑 : 我对我之前的回答不满意,所以我重写了它,使其更清晰一些。算法现在可以正确处理文件名中的下划线(以前的算法没有)。我还添加了一些关键点来解决 OP 提出的其他问题。

    关于sass - Sass 用来解析@import 语句的算法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34334555/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com