1 | const
|
2 | path = require('path'),
|
3 | glob = require('glob'),
|
4 | fs = require('fs'),
|
5 | pug = require('pug'),
|
6 |
|
7 | globOptions = {
|
8 | statCache: {},
|
9 | symlinks: {},
|
10 | nodir: true,
|
11 | nocase: true
|
12 | },
|
13 |
|
14 | resolvePathByPattern = function (filename, basedir) {
|
15 | const
|
16 | separator = '-',
|
17 | absoluteBasedir = path.resolve(basedir),
|
18 | ext = path.extname(filename),
|
19 | [section, ...remainingSegments] = path.basename(filename, ext).split(separator),
|
20 | name = remainingSegments.join(separator);
|
21 |
|
22 | if (undefined === name) {
|
23 | return filename;
|
24 | }
|
25 |
|
26 | switch (section) {
|
27 | case 'svg':
|
28 | minimatchString = `${absoluteBasedir}/**/${name}.svg`;
|
29 | break;
|
30 | default:
|
31 | minimatchString = `${absoluteBasedir}/**/${section}/**/${name}${ext || '.pug'}`;
|
32 |
|
33 | }
|
34 | const [matchedFilename, ...other] = glob.sync(minimatchString, globOptions);
|
35 |
|
36 | if (other.length > 0) {
|
37 | throw new Error(`More than one matches for include '${filename}' found: \n\t\t\t\t\t ` +
|
38 | `${[matchedFilename, ...other].join('\n\t\t\t\t\t ')}`);
|
39 | }
|
40 |
|
41 | return matchedFilename;
|
42 | },
|
43 |
|
44 | includeFunction = function (filename, basedir, locals={}) {
|
45 | return pug.renderFile(resolvePathByPattern(filename, basedir), locals);
|
46 | },
|
47 |
|
48 | postLex = function (tokens, options) {
|
49 |
|
50 | return tokens.map((tok, index) => {
|
51 |
|
52 | if (tok === null) {
|
53 | return tok;
|
54 | }
|
55 |
|
56 | const
|
57 | {type} = tok,
|
58 | nextTok = tokens[index + 1];
|
59 |
|
60 | if (type !== 'include' || nextTok === undefined || nextTok.type !== 'path') {
|
61 | return tok;
|
62 | }
|
63 |
|
64 | if (/`[^`]+`|\+?\s*"[^"]+"\s*\+?|\+?\s*'[^']+'\s*\+?|#|\{[^\}]+}/.test(nextTok.val)) {
|
65 |
|
66 | Object.assign(tok, {
|
67 | type: 'code',
|
68 | val: `process.pug.includeFunction(${nextTok.val}, '${options.basedir}', locals)`,
|
69 | mustEscape: false,
|
70 | buffer: true
|
71 | });
|
72 | Object.assign(tokens[index + 1], {
|
73 | type: 'comment',
|
74 | buffer: false
|
75 | });
|
76 | }
|
77 | return tok;
|
78 | }).filter(tok => tok !== null);
|
79 | },
|
80 |
|
81 | preLoad = function (value, options) {
|
82 | if (options.resolve) {
|
83 | const _resolve = options.resolve;
|
84 | options.resolve = resolve(_resolve);
|
85 | }
|
86 | return value;
|
87 | },
|
88 |
|
89 | resolve = function (_resolve) {
|
90 | return function (filename, source, options) {
|
91 | const resolvedFilename = _resolve.apply(this, arguments);
|
92 |
|
93 | return fs.existsSync(resolvedFilename) ? resolvedFilename : resolvePathByPattern(filename, options.basedir);
|
94 | }
|
95 | };
|
96 |
|
97 | process.pug = {
|
98 | includeFunction
|
99 | };
|
100 |
|
101 | module.exports = {
|
102 | postLex,
|
103 | preLoad,
|
104 | includeFunction
|
105 | }; |
\ | No newline at end of file |