forked from guybedford/require-inline
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrequire-inline.js
More file actions
154 lines (123 loc) · 4.9 KB
/
require-inline.js
File metadata and controls
154 lines (123 loc) · 4.9 KB
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
/*
* Require-inline
*
* Used for sync inline requires while the document is being written only.
*
* For example, useful for loading jquery inline.
*
* There is no good use case to use a sync require after the document is closed,
* and if this was implemented it would have to use eval, which is not worthwhile.
*
* Usage:
*
* <script>require.inline('dep');</script>
*
* OR for CSP compatibility:
*
* <script src="require-inline.js" data-context="_" data-require="depId"></script>
* <script>
* //dep is now defined along with all subdependencies
* var dep = require('depId');
* </script>
*
* - Loads the dep synchronously at that point in the document.
* - A subsequent inline script can rely on the fact that dep and all its
* sub-dependencies will have been loaded already
* - If the dependency maps to a layer, the entire layer will be downloaded and defined synchronously.
* - If the dependency or a subdependency uses a loader plugin, it can check require.inlineRequire
* to tell if it should be sync.
* If a loader plugin doesn't run the callback synchronously the dependency won't be defined
* - By default, the context is '_'
*
* To load multiple dependencies, use:
*
* <script src="require-inline.js" data-require="depId,depId2"></script>
*
* If you have any dependencies that actually need commas, simply escape the comma with a '\,'.
*
*/
/*
var config = context.config.config;
var _textXhr = config.text.createXhr;
var _csXhr = config.cs.createXhr;
config.text.createXhr = createXhr;
config.cs.createXhr = createXhr;
//do stuff
config.text.createXhr = _textXhr;
config.cs.createXhr = _csXhr;
*/
//make volo think this is an amd module
if (false) define(null);
(function() {
//get the script tag for this script
var scripts = document.getElementsByTagName('script');
var scriptTag = scripts[scripts.length - 1];
// override the load and nextTick methods for the context
// we temporarily change to a sync load putting it back after
// - the beauty of sync is that we can do things like this without conflict
// (as long as we put them back in the same process)
var enableSyncLoad = function(contextName) {
var context = requirejs.s.contexts[contextName]
// marker to check if this is an inline require
requirejs.inlineRequire = contextName;
var _contextLoad = context.load;
var _contextTick = context.nextTick;
context.nextTick = function(callback) { callback(); }
var lt = '<';
context.load = function(id, url) {
//two scripts - first is loading script, second is this script again, but with data attributes for callback triggering
document.write(lt + 'script type="text/javascript" src="' + url + '">' + lt + '/script>');
document.write(lt + 'script type="text/javascript" src="' + scriptTag.src + '" ' +
'data-requiremodule="' + id + '" data-requirecontext="' + contextName + '">' + lt + '/script>');
}
// immediately return the disable function
// must be run in the same cycle to revert the load and tick apis
return function() {
delete requirejs.inlineRequire;
context.nextTick = _contextTick;
context.load = _contextLoad;
}
}
// add a require.inline function call
if (!requirejs.inline) {
requirejs.inline = function(deps, context) {
if (typeof deps == 'string')
deps = [deps];
context = context || '_';
var disableSyncLoad = enableSyncLoad(context);
requirejs.s.contexts[context].require(deps);
disableSyncLoad();
}
}
// check for data-attribute indicating to do a load
var requireDep = scriptTag.getAttribute('data-require');
// do a load
if (requireDep) {
// split with a comma for multiple dependencies
var deps = requireDep.split(',');
// join back any items that were actually escaped (\,)
for (var i = 0; i < deps.length; i++)
if (deps[i].substr(deps[i].length - 1) == '\\') {
deps[i] = deps[i] + ',' + deps[i + 1];
deps.splice(i + 1, 1);
}
requirejs.inline(deps, scriptTag.getAttribute('data-context'));
//remove this script tag
scriptTag.parentNode.removeChild(scriptTag);
}
else {
// check for data-attributes indicating a load callback
var requireModule = scriptTag.getAttribute('data-requiremodule');
var requireContext = scriptTag.getAttribute('data-requirecontext');
//if so - this load is a loaded callback -> trigger
if (requireModule && requireContext) {
var disableSyncLoad = enableSyncLoad(requireContext);
requirejs.s.contexts[requireContext].completeLoad(requireModule);
disableSyncLoad();
//remove this script tag and the one before it used for the load
var prevScript = scriptTag.previousSibling;
prevScript.parentNode.removeChild(prevScript);
scriptTag.parentNode.removeChild(scriptTag);
}
}
})();