mirror of
https://github.com/YunoHost-Apps/rocketchat_ynh.git
synced 2024-09-03 20:16:25 +02:00
278 lines
26 KiB
JavaScript
278 lines
26 KiB
JavaScript
(function () {
|
|
|
|
/* Imports */
|
|
var Meteor = Package.meteor.Meteor;
|
|
var RoutePolicy = Package.routepolicy.RoutePolicy;
|
|
var WebApp = Package.webapp.WebApp;
|
|
var main = Package.webapp.main;
|
|
var WebAppInternals = Package.webapp.WebAppInternals;
|
|
var EJSON = Package.ejson.EJSON;
|
|
var _ = Package.underscore._;
|
|
|
|
/* Package-scope variables */
|
|
var Inject, id;
|
|
|
|
(function(){
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// packages/meteorhacks_inject-initial/lib/inject-server.js //
|
|
// //
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
function escapeReplaceString(str) { // 1
|
|
/* // 2
|
|
* When using string.replace(str, newSubStr), the dollar sign ("$") is // 3
|
|
* considered a special character in newSubStr, and needs to be escaped // 4
|
|
* as "$$". We have to do this twice, for escaping the newSubStr in // 5
|
|
* this function, and for the resulting string which is passed back. // 6
|
|
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace
|
|
*/ // 8
|
|
return str.replace(/\$/g, '$$$$'); // 9
|
|
} // 10
|
|
// 11
|
|
Inject = { // 12
|
|
// stores in a script type=application/ejson tag, accessed with Injected.obj('id') // 13
|
|
obj: function(id, data, res) { // 14
|
|
this._checkForObjOrFunction(data, // 15
|
|
'Inject.obj(id, data [,res]) expects `data` to be an Object or Function'); // 16
|
|
// 17
|
|
if (res) { // 18
|
|
this._resAssign(res, 'objList', id, data); // 19
|
|
} else { // 20
|
|
this.objList[id] = data; // 21
|
|
} // 22
|
|
}, // 23
|
|
objList: {}, // 24
|
|
// 25
|
|
// Inserts a META called `id`, whose `content` can be accessed with Injected.meta() // 26
|
|
meta: function(id, data, res) { // 27
|
|
this._checkForTextOrFunction(data, // 28
|
|
'Inject.meta(id, data [,res]) expects `data` to be an String or Function'); // 29
|
|
// 30
|
|
if (res) { // 31
|
|
this._resAssign(res, 'metaList', id, data); // 32
|
|
} else { // 33
|
|
this.metaList[id] = data; // 34
|
|
} // 35
|
|
}, // 36
|
|
metaList: {}, // 37
|
|
// 38
|
|
rawHead: function(id, textOrFunc, res) { // 39
|
|
this._checkForTextOrFunction(textOrFunc, // 40
|
|
'Inject.rawHead(id, content [,res]) expects `content` to be an String or Function'); // 41
|
|
// 42
|
|
if (res) { // 43
|
|
this._resAssign(res, 'rawHeads', id, textOrFunc); // 44
|
|
} else { // 45
|
|
this.rawHeads[id] = textOrFunc; // 46
|
|
} // 47
|
|
}, // 48
|
|
rawHeads: {}, // 49
|
|
// 50
|
|
rawBody: function(id, textOrFunc, res) { // 51
|
|
this._checkForTextOrFunction(textOrFunc, // 52
|
|
'Inject.rawBody(id, content [,res]) expects `content` to be an String or Function'); // 53
|
|
// 54
|
|
if (res) { // 55
|
|
this._resAssign(res, 'rawBodies', id, textOrFunc); // 56
|
|
} else { // 57
|
|
this.rawBodies[id] = textOrFunc; // 58
|
|
} // 59
|
|
}, // 60
|
|
rawBodies: {}, // 61
|
|
// 62
|
|
// The callback receives the entire HTML page and must return a modified version // 63
|
|
rawModHtml: function(id, func) { // 64
|
|
if (!_.isFunction(func)) { // 65
|
|
var message = 'Inject func id "' + id + '" should be a function, not ' + typeof(func); // 66
|
|
throw new Error(message); // 67
|
|
} // 68
|
|
// 69
|
|
this.rawModHtmlFuncs[id] = func; // 70
|
|
}, // 71
|
|
rawModHtmlFuncs: {}, // 72
|
|
// 73
|
|
_injectObjects: function(html, res) { // 74
|
|
var objs = _.extend({}, Inject.objList, res.Inject && res.Inject.objList); // 75
|
|
if (_.isEmpty(objs)) { // 76
|
|
return html; // 77
|
|
} // 78
|
|
// 79
|
|
var obj, injectHtml = ''; // 80
|
|
for (id in objs) { // 81
|
|
obj = _.isFunction(objs[id]) ? objs[id](res) : objs[id]; // 82
|
|
injectHtml += " <script id='" + id.replace("'", ''') // 83
|
|
+ "' type='application/ejson'>" + EJSON.stringify(obj) // 84
|
|
+ "</script>\n"; // 85
|
|
} // 86
|
|
// 87
|
|
return html.replace('<head>', '<head>\n' + escapeReplaceString(injectHtml)); // 88
|
|
}, // 89
|
|
// 90
|
|
_injectMeta: function(html, res) { // 91
|
|
var metas = _.extend({}, Inject.metaList, res.Inject && res.Inject.metaList); // 92
|
|
if (_.isEmpty(metas)) // 93
|
|
return html; // 94
|
|
// 95
|
|
var injectHtml = ''; // 96
|
|
for (id in metas) { // 97
|
|
var meta = this._evalToText(metas[id], res, html); // 98
|
|
injectHtml += " <meta id='" + id.replace("'", ''') // 99
|
|
+ "' content='" + meta.replace("'", ''') + "'>\n", res; // 100
|
|
} // 101
|
|
// 102
|
|
return html.replace('<head>', '<head>\n' + escapeReplaceString(injectHtml)); // 103
|
|
}, // 104
|
|
// 105
|
|
_injectHeads: function(html, res) { // 106
|
|
var heads = _.extend({}, Inject.rawHeads, res.Inject && res.Inject.rawHeads); // 107
|
|
if (_.isEmpty(heads)) // 108
|
|
return html; // 109
|
|
// 110
|
|
var injectHtml = ''; // 111
|
|
for (id in heads) { // 112
|
|
var head = this._evalToText(heads[id], res, html); // 113
|
|
injectHtml += head + '\n'; // 114
|
|
} // 115
|
|
// 116
|
|
return html.replace('<head>', '<head>\n' + escapeReplaceString(injectHtml)); // 117
|
|
}, // 118
|
|
// 119
|
|
_injectBodies: function(html, res) { // 120
|
|
var bodies = _.extend({}, Inject.rawBodies, res.Inject && res.Inject.rawBodies); // 121
|
|
if (_.isEmpty(bodies)) // 122
|
|
return html; // 123
|
|
// 124
|
|
var injectHtml = ''; // 125
|
|
for (id in bodies) { // 126
|
|
var body = this._evalToText(bodies[id], res, html); // 127
|
|
injectHtml += body + '\n'; // 128
|
|
} // 129
|
|
// 130
|
|
return html.replace('<body>', '<body>\n' + escapeReplaceString(injectHtml)); // 131
|
|
}, // 132
|
|
// 133
|
|
// ensure object exists and store there // 134
|
|
_resAssign: function(res, key, id, value) { // 135
|
|
if (!res.Inject) // 136
|
|
res.Inject = {}; // 137
|
|
if (!res.Inject[key]) // 138
|
|
res.Inject[key] = {}; // 139
|
|
res.Inject[key][id] = value; // 140
|
|
}, // 141
|
|
// 142
|
|
_checkForTextOrFunction: function (arg, message) { // 143
|
|
if(!(_.isString(arg) || _.isFunction(arg))) { // 144
|
|
throw new Error(message); // 145
|
|
} // 146
|
|
}, // 147
|
|
// 148
|
|
_checkForObjOrFunction: function (arg, message) { // 149
|
|
if(!(_.isObject(arg) || _.isFunction(arg))) { // 150
|
|
throw new Error(message); // 151
|
|
} // 152
|
|
}, // 153
|
|
// 154
|
|
// we don't handle errors here. Let them to handle in a higher level // 155
|
|
_evalToText: function(textOrFunc, res, html) { // 156
|
|
if(_.isFunction(textOrFunc)) { // 157
|
|
return textOrFunc(res, html); // 158
|
|
} else { // 159
|
|
return textOrFunc; // 160
|
|
} // 161
|
|
} // 162
|
|
}; // 163
|
|
// 164
|
|
Inject.rawModHtml('injectHeads', Inject._injectHeads.bind(Inject)); // 165
|
|
Inject.rawModHtml('injectMeta', Inject._injectMeta.bind(Inject)); // 166
|
|
Inject.rawModHtml('injectBodies', Inject._injectBodies.bind(Inject)); // 167
|
|
Inject.rawModHtml('injectObjects', Inject._injectObjects.bind(Inject)); // 168
|
|
// 169
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
}).call(this);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(function(){
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// packages/meteorhacks_inject-initial/lib/inject-core.js //
|
|
// //
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Hijack core node API and attach data to the response dynamically // 1
|
|
// We are simply using this hack because, there is no way to alter // 2
|
|
// Meteor's html content on the server side // 3
|
|
// 4
|
|
Inject._hijackWrite = function(res) { // 5
|
|
var originalWrite = res.write; // 6
|
|
res.write = function(chunk, encoding) { // 7
|
|
//prevent hijacking other http requests // 8
|
|
if(!res.iInjected && // 9
|
|
encoding === undefined && /^<!DOCTYPE html>/.test(chunk)) { // 10
|
|
chunk = chunk.toString(); // 11
|
|
// 12
|
|
for (id in Inject.rawModHtmlFuncs) { // 13
|
|
chunk = Inject.rawModHtmlFuncs[id](chunk, res); // 14
|
|
if (!_.isString(chunk)) { // 15
|
|
throw new Error('Inject func id "' + id + '" must return HTML, not ' // 16
|
|
+ typeof(chunk) + '\n' + JSON.stringify(chunk, null, 2)); // 17
|
|
} // 18
|
|
} // 19
|
|
// 20
|
|
res.iInjected = true; // 21
|
|
} // 22
|
|
// 23
|
|
originalWrite.call(res, chunk, encoding); // 24
|
|
}; // 25
|
|
} // 26
|
|
// 27
|
|
WebApp.connectHandlers.use(function(req, res, next) { // 28
|
|
// We only separate this to make testing easier // 29
|
|
Inject._hijackWrite(res); // 30
|
|
// 31
|
|
next(); // 32
|
|
}); // 33
|
|
// 34
|
|
//meteor algorithm to check if this is a meteor serving http request or not // 35
|
|
Inject.appUrl = function(url) { // 36
|
|
if (url === '/favicon.ico' || url === '/robots.txt') // 37
|
|
return false; // 38
|
|
// 39
|
|
// NOTE: app.manifest is not a web standard like favicon.ico and // 40
|
|
// robots.txt. It is a file id we have chosen to use for HTML5 // 41
|
|
// appcache URLs. It is included here to prevent using an appcache // 42
|
|
// then removing it from poisoning an app permanently. Eventually, // 43
|
|
// once we have server side routing, this won't be needed as // 44
|
|
// unknown URLs with return a 404 automatically. // 45
|
|
if (url === '/app.manifest') // 46
|
|
return false; // 47
|
|
// 48
|
|
// Avoid serving app HTML for declared routes such as /sockjs/. // 49
|
|
if (typeof(RoutePolicy) != 'undefined' && RoutePolicy.classify(url)) // 50
|
|
return false; // 51
|
|
// 52
|
|
// we currently return app HTML on all URLs by default // 53
|
|
return true; // 54
|
|
}; // 55
|
|
// 56
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
}).call(this);
|
|
|
|
|
|
/* Exports */
|
|
if (typeof Package === 'undefined') Package = {};
|
|
Package['meteorhacks:inject-initial'] = {
|
|
Inject: Inject
|
|
};
|
|
|
|
})();
|
|
|
|
//# sourceMappingURL=meteorhacks_inject-initial.js.map
|