1 | /*------------------------------------*\
|
2 | RESPONSE
|
3 | \*------------------------------------*/
|
4 | /* jslint node: true */
|
5 |
|
6 | /**
|
7 | * Get all information to prepare the response.
|
8 | * @private
|
9 | * @function prepareResponse
|
10 | * @memberOf NA#
|
11 | * @this NA
|
12 | * @param {string} path The url listening.
|
13 | * @param {Object} options Option associate to this url.
|
14 | * @param {Object} request Initial request.
|
15 | * @param {Object} response Initial response.
|
16 | * @param {NA~callback} next Next step after.
|
17 | */
|
18 | exports.prepareResponse = function (path, options, request, response, next) {
|
19 | var NA = this,
|
20 |
|
21 | /**
|
22 | * All parameters from a specific page.
|
23 | * @namespace routeParameters
|
24 | * @public
|
25 | * @alias routeParameters
|
26 | * @type {Object}
|
27 | * @memberOf NA#locals
|
28 | */
|
29 | routeParameters = options[path],
|
30 |
|
31 | /**
|
32 | * All locals provided for Views Template Engine and Hooks.
|
33 | * @namespace locals
|
34 | * @public
|
35 | * @alias locals
|
36 | * @type {Object}
|
37 | * @memberOf NA#
|
38 | */
|
39 | locals = {
|
40 |
|
41 | /**
|
42 | * Expose route of current page from current webconfig `routes`.
|
43 | * @public
|
44 | * @alias route
|
45 | * @type {string}
|
46 | * @memberOf NA#locals
|
47 | * @example /categories/:category/
|
48 | */
|
49 | route: path
|
50 | };
|
51 |
|
52 | /* path contain `{ view, controller, ... }` because `NA.webconfig.routes` is `[{ view, controller, ... }, ...]` */
|
53 | if (typeof path === "object") {
|
54 | routeParameters = path;
|
55 | }
|
56 |
|
57 | /* routeParameters contain `"index.htm"` because `NA.webconfig.routes["/"]` is `"index.htm"` not `{ view, controller, ... }` */
|
58 | if (typeof routeParameters === 'string') {
|
59 | routeParameters = {
|
60 |
|
61 | /**
|
62 | * This is the file name of view used for render of page behind the route.
|
63 | * @public
|
64 | * @alias view
|
65 | * @type {string}
|
66 | * @memberOf NA#locals.routeParameters
|
67 | */
|
68 | view: routeParameters
|
69 | };
|
70 | }
|
71 |
|
72 | /* Case of `routeParameters.url` replace `path` because `path` is used like a key. */
|
73 | if (routeParameters.url) {
|
74 | locals.route = routeParameters.url;
|
75 | }
|
76 |
|
77 | if (routeParameters.url && typeof path === "string") {
|
78 |
|
79 | /**
|
80 | * Expose the key from `<currentRoute>` object from webconfig.
|
81 | * @public
|
82 | * @alias routeKey
|
83 | * @type {Object}
|
84 | * @memberOf NA#locals
|
85 | */
|
86 | locals.routeKey = path;
|
87 | }
|
88 | if (routeParameters.key) {
|
89 | locals.routeKey = routeParameters.key;
|
90 | }
|
91 |
|
92 | /**
|
93 | * Expose all data from `routes[<currentRoute>]` object from webconfig.
|
94 | * @public
|
95 | * @alias routeParameters
|
96 | * @type {Object}
|
97 | * @memberOf NA#locals
|
98 | */
|
99 | locals.routeParameters = routeParameters;
|
100 |
|
101 | /**
|
102 | * Expose all webconfig values.
|
103 | * @public
|
104 | * @alias webconfig
|
105 | * @type {Object}
|
106 | * @memberOf NA#locals
|
107 | */
|
108 | locals.webconfig = NA.webconfig;
|
109 |
|
110 | /* Add preparation into response. */
|
111 | if (response) {
|
112 | response.locals = locals;
|
113 | }
|
114 |
|
115 | NA.prepareRenderLanguage(locals, request, response, next);
|
116 | };
|
117 |
|
118 | /**
|
119 | * Create some variable for manage path for render.
|
120 | * @private
|
121 | * @function prepareRenderLanguage
|
122 | * @memberOf NA#
|
123 | * @this NA
|
124 | * @param {Object} locals Local variables for the current page.
|
125 | * @param {Object} request Information from request.
|
126 | * @param {Object} response Information from response.
|
127 | * @param {NA~callback} next Next step after.
|
128 | */
|
129 | exports.prepareRenderLanguage = function (locals, request, response, next) {
|
130 | var NA = this;
|
131 |
|
132 | /**
|
133 | * Expose the current language code for the page if setted else expose the global if setted.
|
134 | * @public
|
135 | * @alias languageCode
|
136 | * @type {string}
|
137 | * @memberOf NA#locals
|
138 | * @default undefined
|
139 | */
|
140 | locals.languageCode =
|
141 |
|
142 | /**
|
143 | * Represent the language code for this page.
|
144 | * @public
|
145 | * @alias languageCode
|
146 | * @type {string}
|
147 | * @memberOf NA#locals.routeParameters
|
148 | * @default undefined
|
149 | */
|
150 | locals.routeParameters.languageCode ||
|
151 |
|
152 | /**
|
153 | * Represent the global and main language code for website.
|
154 | * @public
|
155 | * @alias languageCode
|
156 | * @type {string}
|
157 | * @memberOf NA#webconfig
|
158 | * @default undefined.
|
159 | */
|
160 | NA.webconfig.languageCode;
|
161 |
|
162 | /* Next preparation render for variation. */
|
163 | NA.prepareRenderPath(locals, request, response, next);
|
164 | };
|
165 |
|
166 | /**
|
167 | * Create some variable for manage path for render.
|
168 | * @private
|
169 | * @function prepareRenderPath
|
170 | * @memberOf NA#
|
171 | * @this NA
|
172 | * @param {Object} locals Local variables for the current page.
|
173 | * @param {Object} request Information from request.
|
174 | * @param {Object} response Information from response.
|
175 | * @param {NA~callback} next Next step after.
|
176 | */
|
177 | exports.prepareRenderPath = function (locals, request, response, next) {
|
178 | var NA = this,
|
179 | path = NA.modules.path,
|
180 | url = NA.modules.url,
|
181 | query = (request && request.originalUrl && request.originalUrl.split("?"));
|
182 |
|
183 | /**
|
184 | * Idem as `NA#webconfig.urlRoot`.
|
185 | * @public
|
186 | * @alias urlRootPath
|
187 | * @type {string}
|
188 | * @memberOf NA#locals
|
189 | * @example http://localhost:7777
|
190 | * https://www.example.here
|
191 | */
|
192 | locals.urlRootPath = NA.webconfig.urlRoot;
|
193 |
|
194 | /**
|
195 | * Idem as `NA#webconfig.urlRelativeSubPath`.
|
196 | * @public
|
197 | * @alias urlSubPath
|
198 | * @type {string}
|
199 | * @memberOf NA#locals
|
200 | * @example /subpath
|
201 | */
|
202 | locals.urlSubPath = NA.webconfig.urlRelativeSubPath;
|
203 |
|
204 | /**
|
205 | * Expose the current URL of page with `NA#webconfig.urlRoot` and `NA#webconfig.urlRelativeSubPath`.
|
206 | * @public
|
207 | * @alias urlBasePath
|
208 | * @type {string}
|
209 | * @memberOf NA#locals
|
210 | * @example http://localhost:7777/subpath
|
211 | * https://www.example.here
|
212 | */
|
213 | locals.urlBasePath = NA.webconfig.urlRoot + NA.webconfig.urlRelativeSubPath;
|
214 |
|
215 | /**
|
216 | * Url from `url` value for current route.
|
217 | * @public
|
218 | * @alias urlFilePath
|
219 | * @type {string}
|
220 | * @memberOf NA#locals
|
221 | * @example /example.html
|
222 | * /example/this/
|
223 | */
|
224 | locals.urlFilePath = locals.routeParameters.output || locals.routeParameters.url;
|
225 | if (request) {
|
226 | locals.urlFilePath = url.format(path.join("/", request.url.replace(new RegExp("^/?" + locals.urlSubPath), "")));
|
227 | }
|
228 |
|
229 | /**
|
230 | * Query from `url` value for current route.
|
231 | * @public
|
232 | * @alias urlQueryPath
|
233 | * @type {string}
|
234 | * @memberOf NA#locals
|
235 | * @example ?title=Haeresis&description=ok
|
236 | * ?title=Haeresis
|
237 | */
|
238 | locals.urlQueryPath = query && query[1] ? "?" + query[1] : "";
|
239 |
|
240 | /**
|
241 | * Expose the current URL of page with `NA#webconfig.urlBasePath` and the current page route.
|
242 | * @public
|
243 | * @alias urlPath
|
244 | * @type {string}
|
245 | * @memberOf NA#locals
|
246 | * @example http://localhost:7777/subpath/example.html?title=Haeresis&description=ok
|
247 | * https://www.example.here/example/this/?title=Haeresis
|
248 | */
|
249 | locals.urlPath = locals.urlBasePath + locals.route + locals.urlQueryPath;
|
250 | if (request) {
|
251 | locals.urlPath = "http" + ((NA.webconfig.httpSecure) ? "s" : "") + '://' + request.get("host") + request.originalUrl;
|
252 | }
|
253 |
|
254 | /* Next preparation render for variation. */
|
255 | NA.prepareRenderVariation(locals, request, response, next);
|
256 | };
|
257 |
|
258 | /**
|
259 | * Create some variable for manage variation into render.
|
260 | * @private
|
261 | * @function prepareRenderVariation
|
262 | * @memberOf NA#
|
263 | * @this NA
|
264 | * @param {Object} locals Local variables for the current page.
|
265 | * @param {Object} request Information from request.
|
266 | * @param {Object} response Information from response.
|
267 | * @param {NA~callback} next Next step after.
|
268 | */
|
269 | exports.prepareRenderVariation = function (locals, request, response, next) {
|
270 | var NA = this,
|
271 | extend = NA.modules.extend,
|
272 | async = NA.modules.async;
|
273 |
|
274 | if (request) {
|
275 |
|
276 | /**
|
277 | * Expose list of slug parameters used into URL.
|
278 | * @public
|
279 | * @alias params
|
280 | * @type {string}
|
281 | * @memberOf NA#locals
|
282 | * @example If current route is '/example/:selector/'
|
283 | * At http://localhost/example/test/ the value of `NA.locals#params` is
|
284 | * { "selector": "test" }
|
285 | */
|
286 | locals.params = request.params || {};
|
287 |
|
288 | /**
|
289 | * Expose list of query parameters used into URL.
|
290 | * @public
|
291 | * @alias query
|
292 | * @type {string}
|
293 | * @memberOf NA#locals
|
294 | * @example At http://localhost/example/?param=test the value of `NA.locals#query` is
|
295 | * { "param": "test" }
|
296 | */
|
297 | locals.query = request.query || {};
|
298 |
|
299 | /**
|
300 | * Expose list of body parameters used into page.
|
301 | * @public
|
302 | * @alias body
|
303 | * @type {string}
|
304 | * @memberOf NA#locals
|
305 | * @example If the Response body is `test=This+is+a+test` the value of `NA.locals#body` is
|
306 | * { "test": "This is a test" }
|
307 | */
|
308 | locals.body = request.body || {};
|
309 | }
|
310 |
|
311 | async.parallel([
|
312 | function (callback) {
|
313 |
|
314 | /**
|
315 | * Name of file for `common` variation.
|
316 | * @public
|
317 | * @alias variation
|
318 | * @type {string}
|
319 | * @memberOf NA#webconfig
|
320 | */
|
321 | locals.common = NA.openVariation(NA.webconfig.variation, locals.languageCode);
|
322 | if (locals.languageCode) {
|
323 |
|
324 | /**
|
325 | * Expose all JSON data from `variation` file.
|
326 | * @public
|
327 | * @alias common
|
328 | * @type {Object}
|
329 | * @memberOf NA#locals
|
330 | */
|
331 | locals.common = extend(true, NA.openVariation(NA.webconfig.variation, undefined, true), locals.common);
|
332 | }
|
333 |
|
334 | callback();
|
335 | },
|
336 | function (callback) {
|
337 |
|
338 | /**
|
339 | * Name of file for `specific` variation.
|
340 | * @public
|
341 | * @alias variation
|
342 | * @type {string}
|
343 | * @memberOf NA#locals.routeParameters
|
344 | */
|
345 | locals.specific = NA.openVariation(locals.routeParameters.variation, locals.languageCode);
|
346 | if (locals.languageCode) {
|
347 |
|
348 | /**
|
349 | * Expose all JSON data from `routes[<currentRoute>].variation` file.
|
350 | * @public
|
351 | * @alias specific
|
352 | * @type {Object}
|
353 | * @memberOf NA#locals
|
354 | */
|
355 | locals.specific = extend(true, NA.openVariation(locals.routeParameters.variation, undefined, true), locals.specific);
|
356 | }
|
357 |
|
358 | callback();
|
359 | }
|
360 | ], function () {
|
361 |
|
362 | /* Nexts Step for render. */
|
363 | NA.prepareHeaders(locals, request, response, next);
|
364 | });
|
365 | };
|
366 |
|
367 | /**
|
368 | * Add and Remove headers from Webconfig.
|
369 | * @private
|
370 | * @function manageHeaders
|
371 | * @memberOf NA~
|
372 | * @param {NA} NA NodeAtlas instance.
|
373 | * @param {Object} headers All headers from webconfig.
|
374 | * @param {Object} response All stuff for HTTP response.
|
375 | */
|
376 | function manageHeaders(NA, headers, response) {
|
377 | var header;
|
378 |
|
379 | for (header in NA.webconfig.headers) {
|
380 | if (!NA.webconfig.headers.hasOwnProperty(header)) {
|
381 | continue;
|
382 | }
|
383 | if (NA.webconfig.headers[header] === false) {
|
384 | response.removeHeader(header);
|
385 | } else {
|
386 | response.setHeader(header, NA.webconfig.headers[header]);
|
387 | }
|
388 | }
|
389 | for (header in headers) {
|
390 | if (!headers.hasOwnProperty(header)) {
|
391 | continue;
|
392 | }
|
393 | if (headers[header] === false) {
|
394 | response.removeHeader(header);
|
395 | } else {
|
396 | response.setHeader(header, headers[header]);
|
397 | }
|
398 | }
|
399 | }
|
400 |
|
401 | /**
|
402 | * Set all webconfig headers.
|
403 | * @private
|
404 | * @function prepareHeaders
|
405 | * @memberOf NA#
|
406 | * @this NA
|
407 | * @param {Object} locals Local variables for the current page.
|
408 | * @param {Object} request Information from request.
|
409 | * @param {Object} response Information from response.
|
410 | * @param {NA~callback} next Next step after.
|
411 | */
|
412 | exports.prepareHeaders = function (locals, request, response, next) {
|
413 | var NA = this,
|
414 |
|
415 | /**
|
416 | * Charset used for render of this page.
|
417 | * @public
|
418 | * @alias charset
|
419 | * @type {string}
|
420 | * @memberOf NA#locals.routeParameters
|
421 | * @default "utf-8"
|
422 | */
|
423 | charset = locals.routeParameters.charset || NA.webconfig.charset,
|
424 |
|
425 | /**
|
426 | * Content Type used for respond with this page.
|
427 | * @public
|
428 | * @alias mimeType
|
429 | * @type {string}
|
430 | * @memberOf NA#locals.routeParameters
|
431 | * @default "text/html"
|
432 | */
|
433 | mimeType = locals.routeParameters.mimeType || NA.webconfig.mimeType,
|
434 |
|
435 | /**
|
436 | * Status Code used for respond with this page.
|
437 | * @public
|
438 | * @alias statusCode
|
439 | * @type {number}
|
440 | * @memberOf NA#locals.routeParameters
|
441 | * @default 200
|
442 | */
|
443 | statusCode = locals.routeParameters.statusCode || 200,
|
444 |
|
445 | /**
|
446 | * Headers value used for respond with this page.
|
447 | * @public
|
448 | * @alias mimeType
|
449 | * @type {string}
|
450 | * @memberOf NA#locals.routeParameters
|
451 | * @default "text/html"
|
452 | */
|
453 | headers = locals.routeParameters.headers || {};
|
454 |
|
455 | if (response) {
|
456 | /* Set charset and */
|
457 | response.statusCode = statusCode;
|
458 |
|
459 | /* Set headers into response */
|
460 | response.setHeader("Content-Type", mimeType + ";" + " charset=" + charset);
|
461 | manageHeaders(NA, headers, response);
|
462 | }
|
463 |
|
464 | /* Nexts Step for render. */
|
465 | next(locals, request, response);
|
466 | };
|
467 |
|
468 | /**
|
469 | * Intercept Variation from common file.
|
470 | * @private
|
471 | * @function changeVariationsCommon
|
472 | * @memberOf NA#
|
473 | * @this NA
|
474 | * @param {Object} locals Local variables for the current page.
|
475 | * @param {Object} request Information from request.
|
476 | * @param {Object} response Information from response.
|
477 | * @param {NA~callback} next Next step after.
|
478 | */
|
479 | exports.changeVariationsCommon = function (locals, request, response, next) {
|
480 | var NA = this;
|
481 |
|
482 | /* Loading the controller file if `routeParameters.controller` exist. */
|
483 | NA.openController(
|
484 |
|
485 | /**
|
486 | * This is the file name of specific controller used for back-end part of this page.
|
487 | * @public
|
488 | * @alias controller
|
489 | * @type {string}
|
490 | * @memberOf NA#locals.routeParameters
|
491 | */
|
492 | locals.routeParameters.controller);
|
493 |
|
494 | /* Use the `NA.controllers[<controller>].changeVariations(...)` function if set... */
|
495 | if (typeof NA.controllers[NA.webconfig.controller] !== 'undefined' &&
|
496 | typeof NA.controllers[NA.webconfig.controller].changeVariations !== 'undefined') {
|
497 |
|
498 | /**
|
499 | * Define this function for intercept Variation object and modify it. Both `common` and `specific` controller.
|
500 | * @function changeVariations
|
501 | * @memberOf NA#controllers[]
|
502 | * @param {changeVariations~callback} callback Next steps after configuration is done.
|
503 | * @param {Object} locals Local variables object of current page.
|
504 | * @param {Object} response Initial response.
|
505 | * @param {Object} request Initial request.
|
506 | */
|
507 | NA.controllers[NA.webconfig.controller].changeVariations.call(NA,
|
508 |
|
509 | /**
|
510 | * Next steps after changeVariations is done.
|
511 | * @callback changeVariations~callback
|
512 | */
|
513 | function () {
|
514 | NA.changeVariationsSpecific(locals, request, response, next);
|
515 | }, locals, request, response);
|
516 | /* ...else, just continue. */
|
517 | } else {
|
518 | NA.changeVariationsSpecific(locals, request, response, next);
|
519 | }
|
520 | };
|
521 |
|
522 | /**
|
523 | * Intercept Variation from specific file.
|
524 | * @private
|
525 | * @function changeVariationsSpecific
|
526 | * @memberOf NA#
|
527 | * @this NA
|
528 | * @param {Object} locals Local variables for the current page.
|
529 | * @param {Object} request Information from request.
|
530 | * @param {Object} response Information from response.
|
531 | * @param {NA~callback} next Next step after.
|
532 | */
|
533 | exports.changeVariationsSpecific = function (locals, request, response, next) {
|
534 | var NA = this;
|
535 |
|
536 | if (typeof NA.controllers[locals.routeParameters.controller] !== 'undefined' &&
|
537 | typeof NA.controllers[locals.routeParameters.controller].changeVariations !== 'undefined') {
|
538 | /* Use the `NA.controllers[<controller>].changeVariations(...)` function if set... */
|
539 | NA.controllers[locals.routeParameters.controller].changeVariations.call(NA, function () {
|
540 | NA.changeDomCommon(locals, request, response, next);
|
541 | }, locals, request, response);
|
542 | } else {
|
543 | /* ...else, just continue. */
|
544 | NA.changeDomCommon(locals, request, response, next);
|
545 | }
|
546 | };
|
547 |
|
548 | /**
|
549 | * Prepare the choosen engine to parse view.
|
550 | * @private
|
551 | * @function prepareEngineProcess
|
552 | * @memberOf NA~
|
553 | * @param {NA} NA NodeAtlas instance.
|
554 | * @param {Object} locals Local variables for the current page.
|
555 | * @param {Object} response Information from response.
|
556 | * @param {NA~callback} next Next step after.
|
557 | */
|
558 | function prepareEngineProcess(NA, locals, response, next) {
|
559 | var ejs = NA.modules.ejs,
|
560 | pug = NA.modules.pug,
|
561 | pathM = NA.modules.path,
|
562 | engine = NA.webconfig.pug ? pug : ejs,
|
563 | path = NA.modules.path,
|
564 | view = path.join(NA.serverPath, NA.webconfig.viewsRelativePath, (
|
565 |
|
566 | /**
|
567 | * Name of file for `common` view.
|
568 | * @public
|
569 | * @alias view
|
570 | * @type {string}
|
571 | * @memberOf NA#webconfig
|
572 | */
|
573 | NA.webconfig.view) ? NA.webconfig.view : (locals.routeParameters.view || ""));
|
574 |
|
575 | if (typeof locals.routeParameters.pug === "boolean") {
|
576 |
|
577 | /**
|
578 | * Allow you to enable Pug only for a page.
|
579 | * @public
|
580 | * @alias pug
|
581 | * @type {boolean}
|
582 | * @memberOf NA#locals.routeParameters
|
583 | * @default undefined
|
584 | */
|
585 | engine = locals.routeParameters.pug ? pug : ejs;
|
586 | }
|
587 |
|
588 | /* Without view, no data. */
|
589 | if (!locals.routeParameters.view) {
|
590 | return next("");
|
591 | }
|
592 |
|
593 | /**
|
594 | * Allow template engine know which file is currently in use.
|
595 | * @public
|
596 | * @alias filename
|
597 | * @type {string}
|
598 | * @memberOf NA#locals
|
599 | */
|
600 | locals.filename = pathM.join(NA.serverPath, NA.webconfig.viewsRelativePath, NA.webconfig.view || locals.routeParameters.view);
|
601 |
|
602 | engineProcess(NA, view, engine, locals, response, next);
|
603 | }
|
604 |
|
605 | /**
|
606 | * Choose an engine to parse view.
|
607 | * @private
|
608 | * @function engineProcess
|
609 | * @memberOf NA~
|
610 | * @param {NA} NA NodeAtlas instance.
|
611 | * @param {string} view View to parse.
|
612 | * @param {string} engine Engine to parse.
|
613 | * @param {Object} locals Local variables for the current page.
|
614 | * @param {Object} response Information from response.
|
615 | * @param {NA~callback} next Next step after.
|
616 | */
|
617 | function engineProcess(NA, view, engine, locals, response, next) {
|
618 | if (NA.webconfig.engine) {
|
619 |
|
620 | /* Transform from any engine but globaly. */
|
621 | response.render(view, locals, function (err, data) {
|
622 | if (err) {
|
623 | data = err.toString();
|
624 | }
|
625 |
|
626 | next(data);
|
627 | });
|
628 | } else {
|
629 | /* Open the template file */
|
630 | NA.openView(locals.routeParameters, view, function (data) {
|
631 |
|
632 | /* Transform ejs/pug data and inject incduded file. */
|
633 | try {
|
634 | data = engine.render(data, locals);
|
635 | } catch (err) {
|
636 | /* Make error more readable. */
|
637 | data = err.toString()
|
638 | .replace(/</g, "<")
|
639 | .replace(/[\n]/g, "<br>")
|
640 | .replace(/\t/g, "<span style='display:inline-block;width:32px'></span>")
|
641 | .replace(/ /g, "<span style='display:inline-block;width:32px'></span>")
|
642 | .replace(/ /g, "<span style='display:inline-block;width:32px'></span>")
|
643 | .replace(/ /g, "<span style='display:inline-block;width:32px'></span>")
|
644 | .replace(/ >> /g, "<span style='display:inline-block;width:32px'>>></span>")
|
645 | .replace(/> ([0-9])+\|/g, "<span style='display:inline-block;margin-left:-13px'>> $1|</span>")
|
646 | .replace(/^([a-zA-Z]+):/g, "$1:<br><br>");
|
647 | }
|
648 |
|
649 | next(data);
|
650 | });
|
651 | }
|
652 | }
|
653 |
|
654 | /**
|
655 | * Intercept DOM from common file.
|
656 | * @private
|
657 | * @function changeDomCommon
|
658 | * @memberOf NA#
|
659 | * @param {Object} locals Local variables for the current page.
|
660 | * @param {Object} request Information from request.
|
661 | * @param {Object} response Information from response.
|
662 | * @param {NA~callback} next Next step after.
|
663 | */
|
664 | exports.changeDomCommon = function (locals, request, response, next) {
|
665 | var NA = this;
|
666 |
|
667 | // Transform into HTML
|
668 | prepareEngineProcess(NA, locals, response, function (data) {
|
669 |
|
670 | /**
|
671 | * The compiled HTML of view + locals provided by response.
|
672 | * @public
|
673 | * @alias dom
|
674 | * @type {string}
|
675 | * @memberOf NA#locals
|
676 | */
|
677 | locals.dom = data;
|
678 |
|
679 | /* Use the `NA.controllers[<controller>].changeDom(...)` function if set... */
|
680 | if (typeof NA.controllers[NA.webconfig.controller] !== 'undefined' &&
|
681 | typeof NA.controllers[NA.webconfig.controller].changeDom !== 'undefined') {
|
682 |
|
683 | /**
|
684 | * Generate a virtual DOM to use jQuery on it.
|
685 | * @function virtualDom
|
686 | * @memberOf NA#locals
|
687 | * @returns {Object} The $ object to manipulate the virtual DOM.
|
688 | */
|
689 | locals.virtualDom = function () {
|
690 | var jsdom = NA.modules.jsdom;
|
691 | return new jsdom.JSDOM(data);
|
692 | };
|
693 |
|
694 | /**
|
695 | * Define this function for intercept DOM and modify it with jQuery for example. Both `common` and `specific` controller.
|
696 | * @function changeDom
|
697 | * @memberOf NA#controllers[]
|
698 | * @param {changeDom~callback} callback Next steps after configuration is done.
|
699 | * @param {Object} locals Local variables for the current page.
|
700 | * @param {string} locals.dom DOM of current page.
|
701 | * @param {Object} response Initial response.
|
702 | * @param {Object} request Initial request.
|
703 | */
|
704 | NA.controllers[NA.webconfig.controller].changeDom.call(NA,
|
705 |
|
706 | /**
|
707 | * Next steps after changeDomSpecific is done.
|
708 | * @callback changeDomSpecific~callback
|
709 | * @param {Object} dom DOM with modifications.
|
710 | */
|
711 | function (dom) {
|
712 | if (typeof dom === "object") {
|
713 | locals.dom = dom.serialize();
|
714 | }
|
715 | NA.changeDomSpecific(locals, request, response, next);
|
716 | }, locals, request, response);
|
717 | /* ...else, just continue. */
|
718 | } else {
|
719 | NA.changeDomSpecific(locals, request, response, next);
|
720 | }
|
721 | });
|
722 | };
|
723 |
|
724 | /**
|
725 | * Intercept DOM from specific file.
|
726 | * @private
|
727 | * @function changeDomSpecific
|
728 | * @memberOf NA#
|
729 | * @param {Object} locals Local variables for the current page.
|
730 | * @param {Object} request Information from request.
|
731 | * @param {Object} response Information from response.
|
732 | * @param {NA~callback} next Next step after.
|
733 | */
|
734 | exports.changeDomSpecific = function (locals, request, response, next) {
|
735 | var NA = this;
|
736 |
|
737 | if (typeof NA.controllers[locals.routeParameters.controller] !== 'undefined' &&
|
738 | typeof NA.controllers[locals.routeParameters.controller].changeDom !== 'undefined') {
|
739 |
|
740 | locals.virtualDom = function () {
|
741 | var jsdom = NA.modules.jsdom;
|
742 | return new jsdom.JSDOM(data);
|
743 | };
|
744 |
|
745 | /** Use the `NA.controllers[<controller>].changeVariations(...)` function if set... */
|
746 | NA.controllers[locals.routeParameters.controller].changeDom.call(NA, function (dom) {
|
747 | if (typeof dom === "object") {
|
748 | locals.dom = dom.serialize();
|
749 | }
|
750 | NA.intoBrowserAndFiles(locals, request, response, next);
|
751 | }, locals, request, response);
|
752 | } else {
|
753 | /** ...else, just continue. */
|
754 | NA.intoBrowserAndFiles(locals, request, response, next);
|
755 | }
|
756 | };
|
757 |
|
758 | /**
|
759 | * Inject CSS into DOM if needed.
|
760 | * @private
|
761 | * @function intoBrowserAndFiles
|
762 | * @memberOf NA#
|
763 | * @param {Object} locals Local variables for the current page.
|
764 | * @param {Object} request Information from request.
|
765 | * @param {Object} response Information from response.
|
766 | * @param {NA~callback} next Next step after.
|
767 | */
|
768 | exports.intoBrowserAndFiles = function (locals, request, response, next) {
|
769 | var NA = this;
|
770 |
|
771 | /* Inject CSS into DOM... */
|
772 | if (NA.webconfig.injectCss || locals.routeParameters.injectCss) {
|
773 | NA.injectCss(locals.dom, locals.routeParameters.injectCss, function (dom) {
|
774 | NA.renderTemplate(dom, locals, request, response, next);
|
775 | });
|
776 | /* ...or do nothing. */
|
777 | } else {
|
778 | NA.renderTemplate(locals.dom, locals, request, response, next);
|
779 | }
|
780 | };
|
781 |
|
782 | /**
|
783 | * Write file or/and send response.
|
784 | * @private
|
785 | * @function renderTemplate
|
786 | * @memberOf NA#
|
787 | * @param {string} data HTML DOM ready for sending.
|
788 | * @param {Object} locals Local variables for the current page.
|
789 | * @param {Object} request Information from request.
|
790 | * @param {Object} response Information from response.
|
791 | * @param {NA~callback} next Next step after.
|
792 | */
|
793 | exports.renderTemplate = function (data, locals, request, response, next) {
|
794 | var NA = this,
|
795 | async = NA.modules.async,
|
796 |
|
797 | /**
|
798 | * Allow NodeAtlas to generate real file into `NA#webconfig.serverlessRelativePath` directory if set to true.
|
799 | * @public
|
800 | * @alias htmlGenerationBeforeResponse
|
801 | * @type {boolean}
|
802 | * @memberOf NA#webconfig
|
803 | * @default false
|
804 | */
|
805 | htmlGenerationBeforeResponse = NA.webconfig.htmlGenerationBeforeResponse,
|
806 | output = (typeof NA.webconfig.output === 'boolean') ? NA.webconfig.output : true,
|
807 | templateRenderName;
|
808 |
|
809 | /* Create the file for asset mode */
|
810 | if (typeof response === "undefined" || (htmlGenerationBeforeResponse && output)) {
|
811 |
|
812 | /**
|
813 | * Output name of file generate if `NA#webconfig.htmlGenerationBeforeResponse` is set to true or if `--generate` command is used.
|
814 | * If value is set to `false`, no generate page will be generated.
|
815 | * @public
|
816 | * @alias output
|
817 | * @type {string|boolean}
|
818 | * @memberOf NA#locals.routeParameters
|
819 | */
|
820 | templateRenderName = locals.route;
|
821 |
|
822 | if (typeof locals.routeParameters.output !== 'undefined') {
|
823 | templateRenderName = locals.routeParameters.output;
|
824 | }
|
825 |
|
826 | NA.saveRender(data, templateRenderName);
|
827 | }
|
828 |
|
829 | /* Run page into browser. */
|
830 | if (typeof response !== "undefined") {
|
831 | /* Compression of CSS, JS and Images if required. */
|
832 | async.parallel([
|
833 | NA.cssCompilation.bind(NA),
|
834 | NA.jsObfuscation.bind(NA)
|
835 | ], function () {
|
836 | NA.sendResponse(request, response, data, next);
|
837 | });
|
838 | }
|
839 | }; |
\ | No newline at end of file |