Software zum Installieren eines Smart-Mirror Frameworks , zum Nutzen von hochschulrelevanten Informationen, auf einem Raspberry-Pi.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

environment.js 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  1. 'use strict';
  2. function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); }
  3. function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
  4. var asap = require('asap');
  5. var _waterfall = require('a-sync-waterfall');
  6. var lib = require('./lib');
  7. var compiler = require('./compiler');
  8. var filters = require('./filters');
  9. var _require = require('./loaders'),
  10. FileSystemLoader = _require.FileSystemLoader,
  11. WebLoader = _require.WebLoader,
  12. PrecompiledLoader = _require.PrecompiledLoader;
  13. var tests = require('./tests');
  14. var globals = require('./globals');
  15. var _require2 = require('./object'),
  16. Obj = _require2.Obj,
  17. EmitterObj = _require2.EmitterObj;
  18. var globalRuntime = require('./runtime');
  19. var handleError = globalRuntime.handleError,
  20. Frame = globalRuntime.Frame;
  21. var expressApp = require('./express-app'); // If the user is using the async API, *always* call it
  22. // asynchronously even if the template was synchronous.
  23. function callbackAsap(cb, err, res) {
  24. asap(function () {
  25. cb(err, res);
  26. });
  27. }
  28. /**
  29. * A no-op template, for use with {% include ignore missing %}
  30. */
  31. var noopTmplSrc = {
  32. type: 'code',
  33. obj: {
  34. root: function root(env, context, frame, runtime, cb) {
  35. try {
  36. cb(null, '');
  37. } catch (e) {
  38. cb(handleError(e, null, null));
  39. }
  40. }
  41. }
  42. };
  43. var Environment = /*#__PURE__*/function (_EmitterObj) {
  44. _inheritsLoose(Environment, _EmitterObj);
  45. function Environment() {
  46. return _EmitterObj.apply(this, arguments) || this;
  47. }
  48. var _proto = Environment.prototype;
  49. _proto.init = function init(loaders, opts) {
  50. var _this = this;
  51. // The dev flag determines the trace that'll be shown on errors.
  52. // If set to true, returns the full trace from the error point,
  53. // otherwise will return trace starting from Template.render
  54. // (the full trace from within nunjucks may confuse developers using
  55. // the library)
  56. // defaults to false
  57. opts = this.opts = opts || {};
  58. this.opts.dev = !!opts.dev; // The autoescape flag sets global autoescaping. If true,
  59. // every string variable will be escaped by default.
  60. // If false, strings can be manually escaped using the `escape` filter.
  61. // defaults to true
  62. this.opts.autoescape = opts.autoescape != null ? opts.autoescape : true; // If true, this will make the system throw errors if trying
  63. // to output a null or undefined value
  64. this.opts.throwOnUndefined = !!opts.throwOnUndefined;
  65. this.opts.trimBlocks = !!opts.trimBlocks;
  66. this.opts.lstripBlocks = !!opts.lstripBlocks;
  67. this.loaders = [];
  68. if (!loaders) {
  69. // The filesystem loader is only available server-side
  70. if (FileSystemLoader) {
  71. this.loaders = [new FileSystemLoader('views')];
  72. } else if (WebLoader) {
  73. this.loaders = [new WebLoader('/views')];
  74. }
  75. } else {
  76. this.loaders = lib.isArray(loaders) ? loaders : [loaders];
  77. } // It's easy to use precompiled templates: just include them
  78. // before you configure nunjucks and this will automatically
  79. // pick it up and use it
  80. if (typeof window !== 'undefined' && window.nunjucksPrecompiled) {
  81. this.loaders.unshift(new PrecompiledLoader(window.nunjucksPrecompiled));
  82. }
  83. this._initLoaders();
  84. this.globals = globals();
  85. this.filters = {};
  86. this.tests = {};
  87. this.asyncFilters = [];
  88. this.extensions = {};
  89. this.extensionsList = [];
  90. lib._entries(filters).forEach(function (_ref) {
  91. var name = _ref[0],
  92. filter = _ref[1];
  93. return _this.addFilter(name, filter);
  94. });
  95. lib._entries(tests).forEach(function (_ref2) {
  96. var name = _ref2[0],
  97. test = _ref2[1];
  98. return _this.addTest(name, test);
  99. });
  100. };
  101. _proto._initLoaders = function _initLoaders() {
  102. var _this2 = this;
  103. this.loaders.forEach(function (loader) {
  104. // Caching and cache busting
  105. loader.cache = {};
  106. if (typeof loader.on === 'function') {
  107. loader.on('update', function (name, fullname) {
  108. loader.cache[name] = null;
  109. _this2.emit('update', name, fullname, loader);
  110. });
  111. loader.on('load', function (name, source) {
  112. _this2.emit('load', name, source, loader);
  113. });
  114. }
  115. });
  116. };
  117. _proto.invalidateCache = function invalidateCache() {
  118. this.loaders.forEach(function (loader) {
  119. loader.cache = {};
  120. });
  121. };
  122. _proto.addExtension = function addExtension(name, extension) {
  123. extension.__name = name;
  124. this.extensions[name] = extension;
  125. this.extensionsList.push(extension);
  126. return this;
  127. };
  128. _proto.removeExtension = function removeExtension(name) {
  129. var extension = this.getExtension(name);
  130. if (!extension) {
  131. return;
  132. }
  133. this.extensionsList = lib.without(this.extensionsList, extension);
  134. delete this.extensions[name];
  135. };
  136. _proto.getExtension = function getExtension(name) {
  137. return this.extensions[name];
  138. };
  139. _proto.hasExtension = function hasExtension(name) {
  140. return !!this.extensions[name];
  141. };
  142. _proto.addGlobal = function addGlobal(name, value) {
  143. this.globals[name] = value;
  144. return this;
  145. };
  146. _proto.getGlobal = function getGlobal(name) {
  147. if (typeof this.globals[name] === 'undefined') {
  148. throw new Error('global not found: ' + name);
  149. }
  150. return this.globals[name];
  151. };
  152. _proto.addFilter = function addFilter(name, func, async) {
  153. var wrapped = func;
  154. if (async) {
  155. this.asyncFilters.push(name);
  156. }
  157. this.filters[name] = wrapped;
  158. return this;
  159. };
  160. _proto.getFilter = function getFilter(name) {
  161. if (!this.filters[name]) {
  162. throw new Error('filter not found: ' + name);
  163. }
  164. return this.filters[name];
  165. };
  166. _proto.addTest = function addTest(name, func) {
  167. this.tests[name] = func;
  168. return this;
  169. };
  170. _proto.getTest = function getTest(name) {
  171. if (!this.tests[name]) {
  172. throw new Error('test not found: ' + name);
  173. }
  174. return this.tests[name];
  175. };
  176. _proto.resolveTemplate = function resolveTemplate(loader, parentName, filename) {
  177. var isRelative = loader.isRelative && parentName ? loader.isRelative(filename) : false;
  178. return isRelative && loader.resolve ? loader.resolve(parentName, filename) : filename;
  179. };
  180. _proto.getTemplate = function getTemplate(name, eagerCompile, parentName, ignoreMissing, cb) {
  181. var _this3 = this;
  182. var that = this;
  183. var tmpl = null;
  184. if (name && name.raw) {
  185. // this fixes autoescape for templates referenced in symbols
  186. name = name.raw;
  187. }
  188. if (lib.isFunction(parentName)) {
  189. cb = parentName;
  190. parentName = null;
  191. eagerCompile = eagerCompile || false;
  192. }
  193. if (lib.isFunction(eagerCompile)) {
  194. cb = eagerCompile;
  195. eagerCompile = false;
  196. }
  197. if (name instanceof Template) {
  198. tmpl = name;
  199. } else if (typeof name !== 'string') {
  200. throw new Error('template names must be a string: ' + name);
  201. } else {
  202. for (var i = 0; i < this.loaders.length; i++) {
  203. var loader = this.loaders[i];
  204. tmpl = loader.cache[this.resolveTemplate(loader, parentName, name)];
  205. if (tmpl) {
  206. break;
  207. }
  208. }
  209. }
  210. if (tmpl) {
  211. if (eagerCompile) {
  212. tmpl.compile();
  213. }
  214. if (cb) {
  215. cb(null, tmpl);
  216. return undefined;
  217. } else {
  218. return tmpl;
  219. }
  220. }
  221. var syncResult;
  222. var createTemplate = function createTemplate(err, info) {
  223. if (!info && !err && !ignoreMissing) {
  224. err = new Error('template not found: ' + name);
  225. }
  226. if (err) {
  227. if (cb) {
  228. cb(err);
  229. return;
  230. } else {
  231. throw err;
  232. }
  233. }
  234. var newTmpl;
  235. if (!info) {
  236. newTmpl = new Template(noopTmplSrc, _this3, '', eagerCompile);
  237. } else {
  238. newTmpl = new Template(info.src, _this3, info.path, eagerCompile);
  239. if (!info.noCache) {
  240. info.loader.cache[name] = newTmpl;
  241. }
  242. }
  243. if (cb) {
  244. cb(null, newTmpl);
  245. } else {
  246. syncResult = newTmpl;
  247. }
  248. };
  249. lib.asyncIter(this.loaders, function (loader, i, next, done) {
  250. function handle(err, src) {
  251. if (err) {
  252. done(err);
  253. } else if (src) {
  254. src.loader = loader;
  255. done(null, src);
  256. } else {
  257. next();
  258. }
  259. } // Resolve name relative to parentName
  260. name = that.resolveTemplate(loader, parentName, name);
  261. if (loader.async) {
  262. loader.getSource(name, handle);
  263. } else {
  264. handle(null, loader.getSource(name));
  265. }
  266. }, createTemplate);
  267. return syncResult;
  268. };
  269. _proto.express = function express(app) {
  270. return expressApp(this, app);
  271. };
  272. _proto.render = function render(name, ctx, cb) {
  273. if (lib.isFunction(ctx)) {
  274. cb = ctx;
  275. ctx = null;
  276. } // We support a synchronous API to make it easier to migrate
  277. // existing code to async. This works because if you don't do
  278. // anything async work, the whole thing is actually run
  279. // synchronously.
  280. var syncResult = null;
  281. this.getTemplate(name, function (err, tmpl) {
  282. if (err && cb) {
  283. callbackAsap(cb, err);
  284. } else if (err) {
  285. throw err;
  286. } else {
  287. syncResult = tmpl.render(ctx, cb);
  288. }
  289. });
  290. return syncResult;
  291. };
  292. _proto.renderString = function renderString(src, ctx, opts, cb) {
  293. if (lib.isFunction(opts)) {
  294. cb = opts;
  295. opts = {};
  296. }
  297. opts = opts || {};
  298. var tmpl = new Template(src, this, opts.path);
  299. return tmpl.render(ctx, cb);
  300. };
  301. _proto.waterfall = function waterfall(tasks, callback, forceAsync) {
  302. return _waterfall(tasks, callback, forceAsync);
  303. };
  304. return Environment;
  305. }(EmitterObj);
  306. var Context = /*#__PURE__*/function (_Obj) {
  307. _inheritsLoose(Context, _Obj);
  308. function Context() {
  309. return _Obj.apply(this, arguments) || this;
  310. }
  311. var _proto2 = Context.prototype;
  312. _proto2.init = function init(ctx, blocks, env) {
  313. var _this4 = this;
  314. // Has to be tied to an environment so we can tap into its globals.
  315. this.env = env || new Environment(); // Make a duplicate of ctx
  316. this.ctx = lib.extend({}, ctx);
  317. this.blocks = {};
  318. this.exported = [];
  319. lib.keys(blocks).forEach(function (name) {
  320. _this4.addBlock(name, blocks[name]);
  321. });
  322. };
  323. _proto2.lookup = function lookup(name) {
  324. // This is one of the most called functions, so optimize for
  325. // the typical case where the name isn't in the globals
  326. if (name in this.env.globals && !(name in this.ctx)) {
  327. return this.env.globals[name];
  328. } else {
  329. return this.ctx[name];
  330. }
  331. };
  332. _proto2.setVariable = function setVariable(name, val) {
  333. this.ctx[name] = val;
  334. };
  335. _proto2.getVariables = function getVariables() {
  336. return this.ctx;
  337. };
  338. _proto2.addBlock = function addBlock(name, block) {
  339. this.blocks[name] = this.blocks[name] || [];
  340. this.blocks[name].push(block);
  341. return this;
  342. };
  343. _proto2.getBlock = function getBlock(name) {
  344. if (!this.blocks[name]) {
  345. throw new Error('unknown block "' + name + '"');
  346. }
  347. return this.blocks[name][0];
  348. };
  349. _proto2.getSuper = function getSuper(env, name, block, frame, runtime, cb) {
  350. var idx = lib.indexOf(this.blocks[name] || [], block);
  351. var blk = this.blocks[name][idx + 1];
  352. var context = this;
  353. if (idx === -1 || !blk) {
  354. throw new Error('no super block available for "' + name + '"');
  355. }
  356. blk(env, context, frame, runtime, cb);
  357. };
  358. _proto2.addExport = function addExport(name) {
  359. this.exported.push(name);
  360. };
  361. _proto2.getExported = function getExported() {
  362. var _this5 = this;
  363. var exported = {};
  364. this.exported.forEach(function (name) {
  365. exported[name] = _this5.ctx[name];
  366. });
  367. return exported;
  368. };
  369. return Context;
  370. }(Obj);
  371. var Template = /*#__PURE__*/function (_Obj2) {
  372. _inheritsLoose(Template, _Obj2);
  373. function Template() {
  374. return _Obj2.apply(this, arguments) || this;
  375. }
  376. var _proto3 = Template.prototype;
  377. _proto3.init = function init(src, env, path, eagerCompile) {
  378. this.env = env || new Environment();
  379. if (lib.isObject(src)) {
  380. switch (src.type) {
  381. case 'code':
  382. this.tmplProps = src.obj;
  383. break;
  384. case 'string':
  385. this.tmplStr = src.obj;
  386. break;
  387. default:
  388. throw new Error("Unexpected template object type " + src.type + "; expected 'code', or 'string'");
  389. }
  390. } else if (lib.isString(src)) {
  391. this.tmplStr = src;
  392. } else {
  393. throw new Error('src must be a string or an object describing the source');
  394. }
  395. this.path = path;
  396. if (eagerCompile) {
  397. try {
  398. this._compile();
  399. } catch (err) {
  400. throw lib._prettifyError(this.path, this.env.opts.dev, err);
  401. }
  402. } else {
  403. this.compiled = false;
  404. }
  405. };
  406. _proto3.render = function render(ctx, parentFrame, cb) {
  407. var _this6 = this;
  408. if (typeof ctx === 'function') {
  409. cb = ctx;
  410. ctx = {};
  411. } else if (typeof parentFrame === 'function') {
  412. cb = parentFrame;
  413. parentFrame = null;
  414. } // If there is a parent frame, we are being called from internal
  415. // code of another template, and the internal system
  416. // depends on the sync/async nature of the parent template
  417. // to be inherited, so force an async callback
  418. var forceAsync = !parentFrame; // Catch compile errors for async rendering
  419. try {
  420. this.compile();
  421. } catch (e) {
  422. var err = lib._prettifyError(this.path, this.env.opts.dev, e);
  423. if (cb) {
  424. return callbackAsap(cb, err);
  425. } else {
  426. throw err;
  427. }
  428. }
  429. var context = new Context(ctx || {}, this.blocks, this.env);
  430. var frame = parentFrame ? parentFrame.push(true) : new Frame();
  431. frame.topLevel = true;
  432. var syncResult = null;
  433. var didError = false;
  434. this.rootRenderFunc(this.env, context, frame, globalRuntime, function (err, res) {
  435. // TODO: this is actually a bug in the compiled template (because waterfall
  436. // tasks are both not passing errors up the chain of callbacks AND are not
  437. // causing a return from the top-most render function). But fixing that
  438. // will require a more substantial change to the compiler.
  439. if (didError && cb && typeof res !== 'undefined') {
  440. // prevent multiple calls to cb
  441. return;
  442. }
  443. if (err) {
  444. err = lib._prettifyError(_this6.path, _this6.env.opts.dev, err);
  445. didError = true;
  446. }
  447. if (cb) {
  448. if (forceAsync) {
  449. callbackAsap(cb, err, res);
  450. } else {
  451. cb(err, res);
  452. }
  453. } else {
  454. if (err) {
  455. throw err;
  456. }
  457. syncResult = res;
  458. }
  459. });
  460. return syncResult;
  461. };
  462. _proto3.getExported = function getExported(ctx, parentFrame, cb) {
  463. // eslint-disable-line consistent-return
  464. if (typeof ctx === 'function') {
  465. cb = ctx;
  466. ctx = {};
  467. }
  468. if (typeof parentFrame === 'function') {
  469. cb = parentFrame;
  470. parentFrame = null;
  471. } // Catch compile errors for async rendering
  472. try {
  473. this.compile();
  474. } catch (e) {
  475. if (cb) {
  476. return cb(e);
  477. } else {
  478. throw e;
  479. }
  480. }
  481. var frame = parentFrame ? parentFrame.push() : new Frame();
  482. frame.topLevel = true; // Run the rootRenderFunc to populate the context with exported vars
  483. var context = new Context(ctx || {}, this.blocks, this.env);
  484. this.rootRenderFunc(this.env, context, frame, globalRuntime, function (err) {
  485. if (err) {
  486. cb(err, null);
  487. } else {
  488. cb(null, context.getExported());
  489. }
  490. });
  491. };
  492. _proto3.compile = function compile() {
  493. if (!this.compiled) {
  494. this._compile();
  495. }
  496. };
  497. _proto3._compile = function _compile() {
  498. var props;
  499. if (this.tmplProps) {
  500. props = this.tmplProps;
  501. } else {
  502. var source = compiler.compile(this.tmplStr, this.env.asyncFilters, this.env.extensionsList, this.path, this.env.opts);
  503. var func = new Function(source); // eslint-disable-line no-new-func
  504. props = func();
  505. }
  506. this.blocks = this._getBlocks(props);
  507. this.rootRenderFunc = props.root;
  508. this.compiled = true;
  509. };
  510. _proto3._getBlocks = function _getBlocks(props) {
  511. var blocks = {};
  512. lib.keys(props).forEach(function (k) {
  513. if (k.slice(0, 2) === 'b_') {
  514. blocks[k.slice(2)] = props[k];
  515. }
  516. });
  517. return blocks;
  518. };
  519. return Template;
  520. }(Obj);
  521. module.exports = {
  522. Environment: Environment,
  523. Template: Template
  524. };