-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
102 lines (83 loc) · 2.92 KB
/
index.js
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
'use strict';
var Path = require('path');
var Riot = require('riot');
var fs = require('fs');
var DEFAULTS = { removeCache: process.env.NODE_ENV !== 'production' };
var layoutCache = {};
var tagsLoaded = null; // when null all tags in view directory will be loaded
/*
* Riot does not Automatically resolve and require nested tags.
* so loadTags requires all files in the template's directory
* QUESTION: do we need to require recursively? discuss: https://git.io/viqjY
*/
function loadTags (filename) {
var viewdir;
if (tagsLoaded) {
return; // early return since have already made the requires
}
viewdir = filename.slice(0, filename.lastIndexOf('/'));
tagsLoaded = fs.readdirSync(viewdir).map(function (file) {
var filepath = Path.join(viewdir, file);
if (filepath !== filename && !require.cache[filepath]) {
require(filepath); //eslint-disable-line
}
return filepath;
});
}
function loadLayout (filePath) {
layoutCache[filePath] = layoutCache[filePath]
|| fs.readFileSync(filePath, 'utf8')
;
return layoutCache[filePath];
}
/*
* during development we want to "un-require" tags to ensure
* that changes made in components are re-loaded
*/
function unCache () {
tagsLoaded.forEach(function (file) {
delete require.cache[require.resolve(file)];
});
tagsLoaded = null;
layoutCache = {};
}
/*
* Vision expects this format a compile object that returns a runtime method.
* template is the template name e.g: 'home' or 'dashboard'
* context is the object (2nd argument) passed in to the reply.view method!
*/
function compile (template, compileOpts) {
var baseOpts = Object.assign({}, DEFAULTS, compileOpts);
return function render (context, renderOpts) {
var layoutFilePath, layoutFileName, content, View, compiledFileRoute;
var mergedOpts = Object.assign({}, baseOpts, renderOpts);
var riotTag = template.split('>')[0].slice(1);
loadTags(mergedOpts.filename);
compiledFileRoute = mergedOpts.compiledFileRoute || '/bundle.js';
View = require(mergedOpts.filename); //eslint-disable-line
content = Riot.render(View, context)
+ '\n<script src="https://cdn.jsdelivr.net/riot/2.6/riot.min.js" ></script>'
+ '\n<script src="' + compiledFileRoute + '"></script>'
+ '\n<script>\nriot.mount("'
+ riotTag + '",' + JSON.stringify(context) + ')\n</script>'
;
if (mergedOpts.layout) {
layoutFileName = mergedOpts.layout === true
? 'layout.html'
: mergedOpts.layout
;
layoutFilePath = Path.join(mergedOpts.layoutPath, layoutFileName);
content = loadLayout(layoutFilePath).replace('<<<RIOT>>>', content);
}
/*
* Delete the view and layout html from the require cache
* so we don't need to restart the app to see view changes.
* Skipped By default when NODE_ENV=production`.
*/
if (mergedOpts.removeCache) {
unCache();
}
return content;
};
}
module.exports = { compile: compile };