Blame view

node_modules/stylus-loader/lib/listimports.js 2.43 KB
ce4c83ff   wxy   初始提交
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
  var Parser = require('stylus/lib/parser');
  var Visitor = require('stylus/lib/visitor');
  var nodes = require('stylus/lib/nodes');
  
  module.exports = listImports;
  
  // ImportVisitor is a simple stylus ast visitor that navigates the graph
  // building a list of imports in it.
  function ImportVisitor() {
    Visitor.apply(this, arguments);
    this.importPaths = [];
  }
  
  ImportVisitor.prototype = Object.create(Visitor.prototype);
  ImportVisitor.prototype.constructor = ImportVisitor;
  
  ImportVisitor.prototype.visitImport = function(node) {
    this.importPaths.push(node.path.first.string);
    return node;
  };
  
  ImportVisitor.prototype.visitRoot = function(block){
    for (var i = 0; i < block.nodes.length; ++i) {
      this.visit(block.nodes[i]);
    }
    return block;
  };
  
  ImportVisitor.prototype.visitExpression = function(expr) {
    for (var i = 0; i < expr.nodes.length; ++i) {
      this.visit(expr.nodes[i]);
    }
    return expr;
  };
  
  ImportVisitor.prototype.visitCall = function(fn) {
    if (fn.name === 'use' || fn.name === 'json') {
      this.importPaths.push(fn.args.first.string);
    }
    return fn;
  };
  
  ImportVisitor.prototype.visitSelector = function(sel) {
    for (var i = 0; i < sel.block.nodes.length; i++) {
      this.visit(sel.block.nodes[i]);
    }
    return sel;
  }
  
  ImportVisitor.prototype.visitBlock = ImportVisitor.prototype.visitRoot;
  ImportVisitor.prototype.visitGroup = ImportVisitor.prototype.visitRoot;
  
  // Returns a list of paths that given source imports.
  function listImports(source, options) {
    // Store source -> imports work in a cache. The Parser is the most expensive
    // part of stylus and we can't use their cache without creating undesired side
    // effects later during the actual render. In single run builds this will
    // benefit repeated files imported like common styling. In multiple run builds
    // this will help stylus import trees when a dependency changes, the higher up
    // files won't need to be parsed again.
    var cache = options.cache;
    if (cache && cache[source]) { return cache[source]; }
  
    // Current idea here is to silence errors and let them rise in stylus's
    // renderer which has more handling so that the error message is more
    // meaningful and easy to understand.
    try {
      var ast = new Parser(source, { cache: false }).parse();
    } catch (e) {
      return [];
    }
    var importVisitor = new ImportVisitor(ast, {});
    importVisitor.visit(ast);
  
    if (cache) {
      cache[source] = importVisitor.importPaths;
    }
  
    return importVisitor.importPaths;
  }