1/* eslint-disable no-console */
2
3'use strict';
4
5function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); }
6function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
7var fs = require('fs');
8var path = require('path');
9var Loader = require('./loader');
10var _require = require('./precompiled-loader.js'),
11  PrecompiledLoader = _require.PrecompiledLoader;
12var chokidar;
13var FileSystemLoader = /*#__PURE__*/function (_Loader) {
14  _inheritsLoose(FileSystemLoader, _Loader);
15  function FileSystemLoader(searchPaths, opts) {
16    var _this;
17    _this = _Loader.call(this) || this;
18    if (typeof opts === 'boolean') {
19      console.log('[nunjucks] Warning: you passed a boolean as the second ' + 'argument to FileSystemLoader, but it now takes an options ' + 'object. See http://mozilla.github.io/nunjucks/api.html#filesystemloader');
20    }
21    opts = opts || {};
22    _this.pathsToNames = {};
23    _this.noCache = !!opts.noCache;
24    if (searchPaths) {
25      searchPaths = Array.isArray(searchPaths) ? searchPaths : [searchPaths];
26      // For windows, convert to forward slashes
27      _this.searchPaths = searchPaths.map(path.normalize);
28    } else {
29      _this.searchPaths = ['.'];
30    }
31    if (opts.watch) {
32      // Watch all the templates in the paths and fire an event when
33      // they change
34      try {
35        chokidar = require('chokidar'); // eslint-disable-line global-require
36      } catch (e) {
37        throw new Error('watch requires chokidar to be installed');
38      }
39      var paths = _this.searchPaths.filter(fs.existsSync);
40      var watcher = chokidar.watch(paths);
41      watcher.on('all', function (event, fullname) {
42        fullname = path.resolve(fullname);
43        if (event === 'change' && fullname in _this.pathsToNames) {
44          _this.emit('update', _this.pathsToNames[fullname], fullname);
45        }
46      });
47      watcher.on('error', function (error) {
48        console.log('Watcher error: ' + error);
49      });
50    }
51    return _this;
52  }
53  var _proto = FileSystemLoader.prototype;
54  _proto.getSource = function getSource(name) {
55    var fullpath = null;
56    var paths = this.searchPaths;
57    for (var i = 0; i < paths.length; i++) {
58      var basePath = path.resolve(paths[i]);
59      var p = path.resolve(paths[i], name);
60
61      // Only allow the current directory and anything
62      // underneath it to be searched
63      if (p.indexOf(basePath) === 0 && fs.existsSync(p)) {
64        fullpath = p;
65        break;
66      }
67    }
68    if (!fullpath) {
69      return null;
70    }
71    this.pathsToNames[fullpath] = name;
72    var source = {
73      src: fs.readFileSync(fullpath, 'utf-8'),
74      path: fullpath,
75      noCache: this.noCache
76    };
77    this.emit('load', name, source);
78    return source;
79  };
80  return FileSystemLoader;
81}(Loader);
82var NodeResolveLoader = /*#__PURE__*/function (_Loader2) {
83  _inheritsLoose(NodeResolveLoader, _Loader2);
84  function NodeResolveLoader(opts) {
85    var _this2;
86    _this2 = _Loader2.call(this) || this;
87    opts = opts || {};
88    _this2.pathsToNames = {};
89    _this2.noCache = !!opts.noCache;
90    if (opts.watch) {
91      try {
92        chokidar = require('chokidar'); // eslint-disable-line global-require
93      } catch (e) {
94        throw new Error('watch requires chokidar to be installed');
95      }
96      _this2.watcher = chokidar.watch();
97      _this2.watcher.on('change', function (fullname) {
98        _this2.emit('update', _this2.pathsToNames[fullname], fullname);
99      });
100      _this2.watcher.on('error', function (error) {
101        console.log('Watcher error: ' + error);
102      });
103      _this2.on('load', function (name, source) {
104        _this2.watcher.add(source.path);
105      });
106    }
107    return _this2;
108  }
109  var _proto2 = NodeResolveLoader.prototype;
110  _proto2.getSource = function getSource(name) {
111    // Don't allow file-system traversal
112    if (/^\.?\.?(\/|\\)/.test(name)) {
113      return null;
114    }
115    if (/^[A-Z]:/.test(name)) {
116      return null;
117    }
118    var fullpath;
119    try {
120      fullpath = require.resolve(name);
121    } catch (e) {
122      return null;
123    }
124    this.pathsToNames[fullpath] = name;
125    var source = {
126      src: fs.readFileSync(fullpath, 'utf-8'),
127      path: fullpath,
128      noCache: this.noCache
129    };
130    this.emit('load', name, source);
131    return source;
132  };
133  return NodeResolveLoader;
134}(Loader);
135module.exports = {
136  FileSystemLoader: FileSystemLoader,
137  PrecompiledLoader: PrecompiledLoader,
138  NodeResolveLoader: NodeResolveLoader
139};