-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
157 lines (132 loc) · 5.28 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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// TODO
// add require for packger
// watch support
var path = require('path');
var lookup = require('./lib/lookup');
var parse = require('./lib/parse');
var wrap = require('./lib/wrap');
/*
* syntax
* support - like import module
* support main from 'path'
* support * as all from "path"
* support { foo, bar as mainBar } from `path`
*
* enhance
*
* inspire
*/
var R_SUPPORT_SYNTAX = /\bsupport\s+(\w+|\*\s+as\s+\w+|{[^}]+})\s+from\s+("(?:[^\\"\r\n\f]|\\[\s\S])*"|'(?:[^\\'\n\r\f]|\\[\s\S])*'|`(?:[^\\`\n\r\f]|\\[\s\S])*`)\s*|"(?:[^\\"\r\n\f]|\\[\s\S])*"|'(?:[^\\'\n\r\f]|\\[\s\S])*'|`(?:[^\\`]|\\[\s\S])*`|\/\/[^\r\n\f]+|\/\*[\s\S]+?(?:\*\/|$)/g;
var COMPILE_FILE_MAP = {}; // files of compiled
var SUPPORT_FILE_MAP = {}; // enhance names of support file
var SUPPORT_RELATION = {}; // relations of support file
exports = module.exports = function (fis, opts) {
opts = opts || {};
opts.baseUrl = opts.baseUrl || '/';
fis.on('process:start', function(file) {
if (!file.isJsLike) return;
var filePath = file.subpath;
COMPILE_FILE_MAP[file.subpath] = file;
// injected enchance variable
var supportInited = false;
var supportFiles = {};
var content = wrap(
// add import relation
file,
SUPPORT_FILE_MAP,
{ baseUrl: opts.baseUrl }
).replace(R_SUPPORT_SYNTAX, function(match, supportEnhance, supportPath) {
if (!supportEnhance) return match;
supportEnhance = parse.support(supportEnhance);
if (!supportEnhance) {
fis.log.error(`error support syntax: ${match}`);
return match;
}
supportPath = fis.util.stringQuote(supportPath, '\'`"').rest;
supportInfo = lookup.init(fis, opts)(fis.util.pathinfo(supportPath), file);
if (!supportInfo.file || !supportInfo.file.subpath) {
fis.log.error(`unable to find ${supportInfo.rest} in ${filePath}.`);
return match;
}
var supportFile = supportInfo.file;
var supportFilePath = supportFile.subpath;
// support file relation
var relation = supportFiles[supportFilePath] = supportFiles[supportFilePath] || {};
Object.keys(supportEnhance).forEach(key => {
var value = supportEnhance[key];
// same key support multiple enhance
relation[key] = relation[key] || [];
if (relation[key].indexOf(value) < 0) {
relation[key].push(value);
}
});
match = supportInited ? '' : '\nvar enhance = {};\n';
// support * as all from 'path'
// enhance.all = function() {};
match += '\n' + (relation['*'] || []).map(attr => `enhance.${attr} = function() {};`).join('\n') + '\n';
supportInited = true;
return match;
});
var lastSupportRelation = SUPPORT_RELATION[filePath] || [];
var currSupportRelation = SUPPORT_RELATION[filePath] = Object.keys(supportFiles);
// check circular support
var circularSupport = isCircularSupport(filePath, SUPPORT_RELATION);
if (circularSupport) {
return fis.log.error(`circular support in ${filePath}: ${[''].concat(circularSupport).join('\n--> ')}`);
}
// recompile support file
lastSupportRelation.concat(currSupportRelation)
.filter((item, idx, arr) => arr.indexOf(item) === idx)
.forEach(supportFilePath => {
// update relations for old/new support file
var relations = SUPPORT_FILE_MAP[supportFilePath] = SUPPORT_FILE_MAP[supportFilePath] || {};
relations[filePath] = supportFiles[supportFilePath];
var file = COMPILE_FILE_MAP[supportFilePath];
COMPILE_FILE_MAP[supportFilePath] = null;
// file uncompile
if (!file) return;
file.useCache = false;
fis.emit('compile:add', file);
});
// __amd('./uri')
file.setContent(content.replace(/\b__amd\(([^)]+)\)/, function(match, uri) {
return JSON.stringify(
path.relative(
opts.baseUrl,
path.join(file.subdirname, fis.util.stringQuote(uri).rest)
).replace(/\.js$/, '')
);
}));
});
};
exports.defaultOptions = {
extList: ['.js', '.coffee', '.jsx', '.es6']
};
function isCircularSupport(supportPath, supportMap) {
var stacks = [[supportPath]];
var deps;
while (deps = stacks.pop()) {
var supports = supportMap[deps[0]] || [];
for (var i = 0; i < supports.length; i++) {
var dep = supports[i];
if (deps.indexOf(dep) > -1) {
return deps;
} else {
stacks.push([dep].concat(deps));
}
}
}
return false;
}
function isCircularSupportRecursive(supportPath, supportMap, stacks) {
stacks = [supportPath].concat(stacks || []);
var deps = supportMap[supportPath] || [];
for (var i = 0; i < deps.length; i++) {
if (stacks.indexOf(deps[i]) > -1) {
return true;
} else if (isCircularSupportRecursive(deps[i], supportMap, stacks)) {
return true;
}
}
return false;
}