-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathjade.js
102 lines (92 loc) · 2.74 KB
/
jade.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
/*global __moduleName*/
import Jade from 'jade-compiler'
let Builder
export function translate (load) {
// capture builder object
if (this && this.builder) {
Builder = this
}
return Promise.all([
expand_text({source: load.source, address: load.address}),
get_runtime_loc(__moduleName)
])
.then(function (values) {
let [text, runtime_loc] = values
// Note: mask "require" by separating from left parenthesis to prevent
// dependency processing on module load.
//
let jade_fn = Jade.compileClient(text)
let REQ = 'require'
let fn =
`var jade = ${REQ}("${runtime_loc}")
var jade_fn = ${jade_fn}
jade_fn.fn = jade_fn
jade_fn.html = jade_fn()
module.exports = jade_fn`
return fn
})
}
function get_runtime_loc (module_name) {
return System.normalize('jade-compiler/lib/runtime', module_name)
.then((loc) => {
if (Builder) {
loc = Builder.getCanonicalName(loc)
}
return loc
})
}
function expand_text ({source, address}) {
let {ex_includes, includes} = parse_includes(source)
return fetch_includes({includes, parent_address: address})
.then(fetched_includes => assemble({ex_includes, includes, fetched_includes}))
}
function parse_includes (source) {
source = source.replace(/\r\n|\r/g, '\n')
let include_regexp = /^([ \t]*)include[ \t]+(\S+)[ \t]*$/img
let ex_includes = []
let includes = []
let inc_match
let start_index = 0
while ((inc_match = include_regexp.exec(source)) !== null) {
// console.log(start_index, inc_match.index, include_regexp.lastIndex)
ex_includes.push(source.substring(start_index, inc_match.index))
includes.push({
indent_str: inc_match[1],
file_path: inc_match[2]
})
start_index = include_regexp.lastIndex + 1
}
ex_includes.push(source.substring(start_index, source.length))
return {
ex_includes: ex_includes,
includes: includes
}
}
function fetch_includes ({includes, parent_address}) {
let parent_dir = parent_address.replace(/^(.+\/)*(.+)$/, '$1')
return Promise.all(
includes.map(include =>
System.fetch({ name: include.file_path, address: parent_dir + include.file_path, metadata: {} })
.then(text => text.charAt(text.length - 1) === '\n' ? text : text + '\n')
)
)
}
function assemble ({ex_includes, includes, fetched_includes}) {
let res = ''
let i = 0
while (i < includes.length) {
res += ex_includes[i] +
indent({
text: fetched_includes[i],
indent_str: includes[i].indent_str
})
i++
}
return res + ex_includes[i]
}
function indent ({text, indent_str}) {
return text.replace(/\r\n|\r|\n/g, '\n')
.split('\n')
.map(line => indent_str + line)
.join('\n')
}