2015-12-17 12 views
6

Thuật toán mà Node.js sử dụng để giải quyết cuộc gọi require() rất rõ ràng documented in pseudocode.Thuật toán mà Sass sử dụng để giải quyết câu lệnh @import là gì?

Tôi cần điều tương tự cho tuyên bố @import của Sass.

Tôi biết rằng @import 'foo' sẽ cố gắng kết hợp khác nhau của basenames foo_foo, với phần mở rộng .scss.sass, trong cùng thư mục với tập tin nhập khẩu cũng như liên quan đến bất kỳ của các 'con đường tải' cấu hình ... Nhưng những thứ tự này được thử trong, tức là cái gì được ưu tiên nếu có nhiều tệp có thể đáp ứng @import? Bắt đầu với một số ./ hoặc ../ có ảnh hưởng đến việc liệu nó có thử đường dẫn tải không? Có bất kỳ thứ gì khác mà tôi sẽ thử không? Còn các tệp .css thì sao?

guide không nói nhiều hơn "Sass thông minh và sẽ tìm ra cho bạn". Các reference docs đi vào chi tiết hơn, nhưng vẫn không đánh vần các bước độ phân giải.

Có ai có thể cung cấp thuật toán chính xác mà nó sử dụng, trong mã giả không?

+0

Bạn nhận ra rằng Sass là nguồn mở và bạn có thể tự mình tìm ra điều này, đúng không? – cimmanon

+0

@cimmanon yep. Bạn không nghĩ rằng có bất kỳ giá trị trong nó hiện có trong mã giả quá? – callum

Trả lời

5

Đây là thuật toán đơn giản cho @import <import_arg>;. Điều này bắt nguồn từ việc đọc mã nguồn cho SASS và chạy các thử nghiệm của riêng tôi.

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 

Lưu ý cho ngắn gọn, tôi đang sử dụng Ruby File#dirname, File#basename cũng như File#expand mà là giống như Node.js của path.resolve. Tôi đang sử dụng mã giả giống Ruby nhưng nó vẫn có nghĩa là mã giả.

điểm chính:

  • Không có trật tự ưu tiên. Thay vì thực hiện một thứ tự ưu tiên, SASS bỏ cuộc khi có một số ứng cử viên có thể. Ví dụ: nếu bạn đã viết @import "x" và nói cả hai số x.scss_x.scss tồn tại, thì khi đó sass sẽ ném một lỗi mơ hồ. Tương tự, nếu cả hai x.scssx.sass tồn tại thì lỗi mơ hồ được ném.
  • Đường dẫn tải được thử từ thứ tự 'từ trái sang phải'. Chúng cung cấp một root hoặc base để giải quyết các import từ (tương tự như cách UNIX sử dụng $ PATH để tìm các file thực thi). Thư mục làm việc hiện tại luôn được thử trước. (Mặc dù hành vi này will change 3,2-3,4)
  • đường dẫn tải luôn cố gắng bất kể bạn sử dụng ./ hoặc ../
  • Trong một tập tin sass, các file .css thường xuyên cannot be imported

Nếu bạn muốn biết thêm chi tiết , Tôi khuyên bạn nên đọc mã nguồn của SASS:

  • import phương thức sass/lib/sass/tree/import_node.rb. Trên các dòng 53-56, bạn có thể thấy tương tự cho vòng lặp như một bên trong hàm search trong mã giả của chúng ta.
  • Importers::Base lớp trừu tượng sass/lib/sass/importors/base.rb. Các ý kiến ​​của tập tin này khá tiện dụng.
  • phương thức find_real_filesass/lib/sass/importors/filesystem.rb. Dòng 112-126 thực hiện chức năng possible_files của chúng tôi. Dòng 156 kiểm tra chỉ có một kết quả phù hợp. Nếu không có dòng 167 ném một lỗi mơ hồ, dòng khác 183 chọn một tập tin phù hợp.

Chỉnh sửa: Tôi không hài lòng với câu trả lời trước đây của mình vì vậy tôi đã viết lại một chút rõ ràng hơn. Thuật toán bây giờ xử lý một cách chính xác dấu gạch dưới trong tên tệp (thuật toán trước đó không). Tôi cũng đã thêm một số điểm chính để giải quyết các câu hỏi khác mà OP hỏi.

+0

Dòng 'let dirname = File.dirname (import_arg)' gây nhầm lẫn cho tôi. Bạn không muốn tên dir của tệp nhập, không phải tệp đang được nhập? – callum

+0

Ngoài ra, biến 'dirname' dường như không được sử dụng ở bất cứ đâu. Nó được truyền vào 'search()', nhưng hàm đó bỏ qua nó. – callum

Các vấn đề liên quan