Node.js用于解析require()
调用的算法在伪代码中非常清楚地记录.
萨斯的@import
声明我需要同样的事情.
我知道,@import 'foo'
将尝试基本名称的各种组合foo
,并_foo
与扩展.scss
,并.sass
在同一目录中进口文件,以及相对于任何配置的"负载路径"的......但什么样的顺序,这些都试过,即什么如果有多个文件可以满足@import
?以a开头./
还是../
影响它是否尝试加载路径?还有其他事情会尝试我没有涉及吗?.css
文件怎么样?
该指南并未说明"Sass很聪明,并会为您解决问题".该参考文档进入更详细,但还是不拼出来的解决步骤.
任何人都可以在伪代码中提供它使用的确切算法吗?
这是一个简化的算法@import
.这是通过阅读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: /sf/ask/17360801/ 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.scss
和x.sass
再存在时引发的多义性错误.
从"从左到右"顺序尝试加载路径.它们提供了一个根或基础来解析导入(类似于UNIX使用$ PATH来查找可执行文件).始终首先尝试当前工作目录.(虽然此行为将从3.2 更改为3.4)
负载路径总是不管尝试是否使用./
或../
在sass文件中,无法导入常规.css文件
如果您想了解更多细节,我建议您阅读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提出的其他问题.