UNPKG

43.8 kBJavaScriptView Raw
1/**
2 * @license Angular v14.0.4
3 * (c) 2010-2022 Google LLC. https://angular.io/
4 * License: MIT
5 */
6
7import { ɵsetRootDomAdapter, DOCUMENT, XhrFactory, PlatformLocation, ɵgetDOM, ɵPLATFORM_SERVER_ID, ViewportScroller, ɵNullViewportScroller } from '@angular/common';
8import * as i0 from '@angular/core';
9import { Injectable, Inject, InjectionToken, Injector, Optional, ViewEncapsulation, RendererStyleFlags2, PLATFORM_ID, PLATFORM_INITIALIZER, ɵALLOW_MULTIPLE_PLATFORMS, RendererFactory2, NgZone, Testability, ɵTESTABILITY, NgModule, ɵsetDocument, createPlatformFactory, platformCore, APP_ID, ApplicationRef, ɵisPromise, importProvidersFrom, ɵinternalBootstrapApplication, Version } from '@angular/core';
10import * as i1 from '@angular/platform-browser';
11import { ɵBrowserDomAdapter, ɵflattenStyles, ɵNAMESPACE_URIS, ɵshimContentAttribute, ɵshimHostAttribute, ɵSharedStylesHost, ɵTRANSITION_ID, EVENT_MANAGER_PLUGINS, BrowserModule, ɵescapeHtml, TransferState } from '@angular/platform-browser';
12import * as domino from 'domino';
13import { ɵAnimationEngine } from '@angular/animations/browser';
14import { ɵHttpInterceptingHandler, HttpHandler, HttpBackend, HttpClientModule } from '@angular/common/http';
15import { ɵplatformCoreDynamic } from '@angular/platform-browser-dynamic';
16import { ɵAnimationRendererFactory, NoopAnimationsModule } from '@angular/platform-browser/animations';
17import { Observable, Subject } from 'rxjs';
18import * as xhr2 from 'xhr2';
19import * as url from 'url';
20import { DomElementSchemaRegistry } from '@angular/compiler';
21import { first } from 'rxjs/operators';
22
23/**
24 * @license
25 * Copyright Google LLC All Rights Reserved.
26 *
27 * Use of this source code is governed by an MIT-style license that can be
28 * found in the LICENSE file at https://angular.io/license
29 */
30function setDomTypes() {
31 // Make all Domino types available in the global env.
32 Object.assign(global, domino.impl);
33 global['KeyboardEvent'] = domino.impl.Event;
34}
35/**
36 * Parses a document string to a Document object.
37 */
38function parseDocument(html, url = '/') {
39 let window = domino.createWindow(html, url);
40 let doc = window.document;
41 return doc;
42}
43/**
44 * Serializes a document to string.
45 */
46function serializeDocument(doc) {
47 return doc.serialize();
48}
49/**
50 * DOM Adapter for the server platform based on https://github.com/fgnass/domino.
51 */
52class DominoAdapter extends ɵBrowserDomAdapter {
53 constructor() {
54 super(...arguments);
55 this.supportsDOMEvents = false;
56 }
57 static makeCurrent() {
58 setDomTypes();
59 ɵsetRootDomAdapter(new DominoAdapter());
60 }
61 createHtmlDocument() {
62 return parseDocument('<html><head><title>fakeTitle</title></head><body></body></html>');
63 }
64 getDefaultDocument() {
65 if (!DominoAdapter.defaultDoc) {
66 DominoAdapter.defaultDoc = domino.createDocument();
67 }
68 return DominoAdapter.defaultDoc;
69 }
70 isElementNode(node) {
71 return node ? node.nodeType === DominoAdapter.defaultDoc.ELEMENT_NODE : false;
72 }
73 isShadowRoot(node) {
74 return node.shadowRoot == node;
75 }
76 /** @deprecated No longer being used in Ivy code. To be removed in version 14. */
77 getGlobalEventTarget(doc, target) {
78 if (target === 'window') {
79 return doc.defaultView;
80 }
81 if (target === 'document') {
82 return doc;
83 }
84 if (target === 'body') {
85 return doc.body;
86 }
87 return null;
88 }
89 getBaseHref(doc) {
90 var _a;
91 // TODO(alxhub): Need relative path logic from BrowserDomAdapter here?
92 return ((_a = doc.documentElement.querySelector('base')) === null || _a === void 0 ? void 0 : _a.getAttribute('href')) || '';
93 }
94 dispatchEvent(el, evt) {
95 el.dispatchEvent(evt);
96 // Dispatch the event to the window also.
97 const doc = el.ownerDocument || el;
98 const win = doc.defaultView;
99 if (win) {
100 win.dispatchEvent(evt);
101 }
102 }
103 getUserAgent() {
104 return 'Fake user agent';
105 }
106 getCookie(name) {
107 throw new Error('getCookie has not been implemented');
108 }
109}
110
111/**
112 * @license
113 * Copyright Google LLC All Rights Reserved.
114 *
115 * Use of this source code is governed by an MIT-style license that can be
116 * found in the LICENSE file at https://angular.io/license
117 */
118/**
119 * Representation of the current platform state.
120 *
121 * @publicApi
122 */
123class PlatformState {
124 constructor(_doc) {
125 this._doc = _doc;
126 }
127 /**
128 * Renders the current state of the platform to string.
129 */
130 renderToString() {
131 return serializeDocument(this._doc);
132 }
133 /**
134 * Returns the current DOM state.
135 */
136 getDocument() {
137 return this._doc;
138 }
139}
140PlatformState.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.4", ngImport: i0, type: PlatformState, deps: [{ token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
141PlatformState.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.4", ngImport: i0, type: PlatformState });
142i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.4", ngImport: i0, type: PlatformState, decorators: [{
143 type: Injectable
144 }], ctorParameters: function () {
145 return [{ type: undefined, decorators: [{
146 type: Inject,
147 args: [DOCUMENT]
148 }] }];
149 } });
150
151/**
152 * @license
153 * Copyright Google LLC All Rights Reserved.
154 *
155 * Use of this source code is governed by an MIT-style license that can be
156 * found in the LICENSE file at https://angular.io/license
157 */
158/**
159 * The DI token for setting the initial config for the platform.
160 *
161 * @publicApi
162 */
163const INITIAL_CONFIG = new InjectionToken('Server.INITIAL_CONFIG');
164/**
165 * A function that will be executed when calling `renderApplication`, `renderModuleFactory` or
166 * `renderModule` just before current platform state is rendered to string.
167 *
168 * @publicApi
169 */
170const BEFORE_APP_SERIALIZED = new InjectionToken('Server.RENDER_MODULE_HOOK');
171
172/**
173 * @license
174 * Copyright Google LLC All Rights Reserved.
175 *
176 * Use of this source code is governed by an MIT-style license that can be
177 * found in the LICENSE file at https://angular.io/license
178 */
179// @see https://www.w3.org/Protocols/HTTP/1.1/draft-ietf-http-v11-spec-01#URI-syntax
180const isAbsoluteUrl = /^[a-zA-Z\-\+.]+:\/\//;
181class ServerXhr {
182 build() {
183 return new xhr2.XMLHttpRequest();
184 }
185}
186ServerXhr.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.4", ngImport: i0, type: ServerXhr, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
187ServerXhr.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.4", ngImport: i0, type: ServerXhr });
188i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.4", ngImport: i0, type: ServerXhr, decorators: [{
189 type: Injectable
190 }] });
191class ZoneMacroTaskWrapper {
192 wrap(request) {
193 return new Observable((observer) => {
194 let task = null;
195 let scheduled = false;
196 let sub = null;
197 let savedResult = null;
198 let savedError = null;
199 const scheduleTask = (_task) => {
200 task = _task;
201 scheduled = true;
202 const delegate = this.delegate(request);
203 sub = delegate.subscribe(res => savedResult = res, err => {
204 if (!scheduled) {
205 throw new Error('An http observable was completed twice. This shouldn\'t happen, please file a bug.');
206 }
207 savedError = err;
208 scheduled = false;
209 task.invoke();
210 }, () => {
211 if (!scheduled) {
212 throw new Error('An http observable was completed twice. This shouldn\'t happen, please file a bug.');
213 }
214 scheduled = false;
215 task.invoke();
216 });
217 };
218 const cancelTask = (_task) => {
219 if (!scheduled) {
220 return;
221 }
222 scheduled = false;
223 if (sub) {
224 sub.unsubscribe();
225 sub = null;
226 }
227 };
228 const onComplete = () => {
229 if (savedError !== null) {
230 observer.error(savedError);
231 }
232 else {
233 observer.next(savedResult);
234 observer.complete();
235 }
236 };
237 // MockBackend for Http is synchronous, which means that if scheduleTask is by
238 // scheduleMacroTask, the request will hit MockBackend and the response will be
239 // sent, causing task.invoke() to be called.
240 const _task = Zone.current.scheduleMacroTask('ZoneMacroTaskWrapper.subscribe', onComplete, {}, () => null, cancelTask);
241 scheduleTask(_task);
242 return () => {
243 if (scheduled && task) {
244 task.zone.cancelTask(task);
245 scheduled = false;
246 }
247 if (sub) {
248 sub.unsubscribe();
249 sub = null;
250 }
251 };
252 });
253 }
254}
255class ZoneClientBackend extends ZoneMacroTaskWrapper {
256 constructor(backend, platformLocation, config) {
257 super();
258 this.backend = backend;
259 this.platformLocation = platformLocation;
260 this.config = config;
261 }
262 handle(request) {
263 const { href, protocol, hostname, port } = this.platformLocation;
264 if (this.config.useAbsoluteUrl && !isAbsoluteUrl.test(request.url) &&
265 isAbsoluteUrl.test(href)) {
266 const baseHref = this.platformLocation.getBaseHrefFromDOM() || href;
267 const urlPrefix = `${protocol}//${hostname}` + (port ? `:${port}` : '');
268 const baseUrl = new URL(baseHref, urlPrefix);
269 const url = new URL(request.url, baseUrl);
270 return this.wrap(request.clone({ url: url.toString() }));
271 }
272 return this.wrap(request);
273 }
274 delegate(request) {
275 return this.backend.handle(request);
276 }
277}
278function zoneWrappedInterceptingHandler(backend, injector, platformLocation, config) {
279 const realBackend = new ɵHttpInterceptingHandler(backend, injector);
280 return new ZoneClientBackend(realBackend, platformLocation, config);
281}
282const SERVER_HTTP_PROVIDERS = [
283 { provide: XhrFactory, useClass: ServerXhr }, {
284 provide: HttpHandler,
285 useFactory: zoneWrappedInterceptingHandler,
286 deps: [HttpBackend, Injector, PlatformLocation, INITIAL_CONFIG]
287 }
288];
289
290/**
291 * @license
292 * Copyright Google LLC All Rights Reserved.
293 *
294 * Use of this source code is governed by an MIT-style license that can be
295 * found in the LICENSE file at https://angular.io/license
296 */
297function parseUrl(urlStr) {
298 const parsedUrl = url.parse(urlStr);
299 return {
300 hostname: parsedUrl.hostname || '',
301 protocol: parsedUrl.protocol || '',
302 port: parsedUrl.port || '',
303 pathname: parsedUrl.pathname || '',
304 search: parsedUrl.search || '',
305 hash: parsedUrl.hash || '',
306 };
307}
308/**
309 * Server-side implementation of URL state. Implements `pathname`, `search`, and `hash`
310 * but not the state stack.
311 */
312class ServerPlatformLocation {
313 constructor(_doc, _config) {
314 this._doc = _doc;
315 this.href = '/';
316 this.hostname = '/';
317 this.protocol = '/';
318 this.port = '/';
319 this.pathname = '/';
320 this.search = '';
321 this.hash = '';
322 this._hashUpdate = new Subject();
323 const config = _config;
324 if (!config) {
325 return;
326 }
327 if (config.url) {
328 const url = parseUrl(config.url);
329 this.protocol = url.protocol;
330 this.hostname = url.hostname;
331 this.port = url.port;
332 this.pathname = url.pathname;
333 this.search = url.search;
334 this.hash = url.hash;
335 this.href = _doc.location.href;
336 }
337 if (config.useAbsoluteUrl) {
338 if (!config.baseUrl) {
339 throw new Error(`"PlatformConfig.baseUrl" must be set if "useAbsoluteUrl" is true`);
340 }
341 const url = parseUrl(config.baseUrl);
342 this.protocol = url.protocol;
343 this.hostname = url.hostname;
344 this.port = url.port;
345 }
346 }
347 getBaseHrefFromDOM() {
348 return ɵgetDOM().getBaseHref(this._doc);
349 }
350 onPopState(fn) {
351 // No-op: a state stack is not implemented, so
352 // no events will ever come.
353 return () => { };
354 }
355 onHashChange(fn) {
356 const subscription = this._hashUpdate.subscribe(fn);
357 return () => subscription.unsubscribe();
358 }
359 get url() {
360 return `${this.pathname}${this.search}${this.hash}`;
361 }
362 setHash(value, oldUrl) {
363 if (this.hash === value) {
364 // Don't fire events if the hash has not changed.
365 return;
366 }
367 this.hash = value;
368 const newUrl = this.url;
369 scheduleMicroTask(() => this._hashUpdate.next({ type: 'hashchange', state: null, oldUrl, newUrl }));
370 }
371 replaceState(state, title, newUrl) {
372 const oldUrl = this.url;
373 const parsedUrl = parseUrl(newUrl);
374 this.pathname = parsedUrl.pathname;
375 this.search = parsedUrl.search;
376 this.setHash(parsedUrl.hash, oldUrl);
377 }
378 pushState(state, title, newUrl) {
379 this.replaceState(state, title, newUrl);
380 }
381 forward() {
382 throw new Error('Not implemented');
383 }
384 back() {
385 throw new Error('Not implemented');
386 }
387 // History API isn't available on server, therefore return undefined
388 getState() {
389 return undefined;
390 }
391}
392ServerPlatformLocation.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.4", ngImport: i0, type: ServerPlatformLocation, deps: [{ token: DOCUMENT }, { token: INITIAL_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
393ServerPlatformLocation.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.4", ngImport: i0, type: ServerPlatformLocation });
394i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.4", ngImport: i0, type: ServerPlatformLocation, decorators: [{
395 type: Injectable
396 }], ctorParameters: function () {
397 return [{ type: undefined, decorators: [{
398 type: Inject,
399 args: [DOCUMENT]
400 }] }, { type: undefined, decorators: [{
401 type: Optional
402 }, {
403 type: Inject,
404 args: [INITIAL_CONFIG]
405 }] }];
406 } });
407function scheduleMicroTask(fn) {
408 Zone.current.scheduleMicroTask('scheduleMicrotask', fn);
409}
410
411/**
412 * @license
413 * Copyright Google LLC All Rights Reserved.
414 *
415 * Use of this source code is governed by an MIT-style license that can be
416 * found in the LICENSE file at https://angular.io/license
417 */
418class ServerEventManagerPlugin /* extends EventManagerPlugin which is private */ {
419 constructor(doc) {
420 this.doc = doc;
421 }
422 // Handle all events on the server.
423 supports(eventName) {
424 return true;
425 }
426 addEventListener(element, eventName, handler) {
427 return ɵgetDOM().onAndCancel(element, eventName, handler);
428 }
429 /** @deprecated No longer being used in Ivy code. To be removed in version 14. */
430 addGlobalEventListener(element, eventName, handler) {
431 const target = ɵgetDOM().getGlobalEventTarget(this.doc, element);
432 if (!target) {
433 throw new Error(`Unsupported event target ${target} for event ${eventName}`);
434 }
435 return this.addEventListener(target, eventName, handler);
436 }
437}
438ServerEventManagerPlugin.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.4", ngImport: i0, type: ServerEventManagerPlugin /* extends EventManagerPlugin which is private */, deps: [{ token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
439ServerEventManagerPlugin.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.4", ngImport: i0, type: ServerEventManagerPlugin /* extends EventManagerPlugin which is private */ });
440i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.4", ngImport: i0, type: ServerEventManagerPlugin /* extends EventManagerPlugin which is private */, decorators: [{
441 type: Injectable
442 }], ctorParameters: function () {
443 return [{ type: undefined, decorators: [{
444 type: Inject,
445 args: [DOCUMENT]
446 }] }];
447 } });
448
449/**
450 * @license
451 * Copyright Google LLC All Rights Reserved.
452 *
453 * Use of this source code is governed by an MIT-style license that can be
454 * found in the LICENSE file at https://angular.io/license
455 */
456const EMPTY_ARRAY = [];
457const DEFAULT_SCHEMA = new DomElementSchemaRegistry();
458class ServerRendererFactory2 {
459 constructor(eventManager, ngZone, document, sharedStylesHost) {
460 this.eventManager = eventManager;
461 this.ngZone = ngZone;
462 this.document = document;
463 this.sharedStylesHost = sharedStylesHost;
464 this.rendererByCompId = new Map();
465 this.schema = DEFAULT_SCHEMA;
466 this.defaultRenderer = new DefaultServerRenderer2(eventManager, document, ngZone, this.schema);
467 }
468 createRenderer(element, type) {
469 if (!element || !type) {
470 return this.defaultRenderer;
471 }
472 switch (type.encapsulation) {
473 case ViewEncapsulation.Emulated: {
474 let renderer = this.rendererByCompId.get(type.id);
475 if (!renderer) {
476 renderer = new EmulatedEncapsulationServerRenderer2(this.eventManager, this.document, this.ngZone, this.sharedStylesHost, this.schema, type);
477 this.rendererByCompId.set(type.id, renderer);
478 }
479 renderer.applyToHost(element);
480 return renderer;
481 }
482 default: {
483 if (!this.rendererByCompId.has(type.id)) {
484 const styles = ɵflattenStyles(type.id, type.styles, []);
485 this.sharedStylesHost.addStyles(styles);
486 this.rendererByCompId.set(type.id, this.defaultRenderer);
487 }
488 return this.defaultRenderer;
489 }
490 }
491 }
492 begin() { }
493 end() { }
494}
495ServerRendererFactory2.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.4", ngImport: i0, type: ServerRendererFactory2, deps: [{ token: i1.EventManager }, { token: i0.NgZone }, { token: DOCUMENT }, { token: i1.ɵSharedStylesHost }], target: i0.ɵɵFactoryTarget.Injectable });
496ServerRendererFactory2.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.4", ngImport: i0, type: ServerRendererFactory2 });
497i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.4", ngImport: i0, type: ServerRendererFactory2, decorators: [{
498 type: Injectable
499 }], ctorParameters: function () {
500 return [{ type: i1.EventManager }, { type: i0.NgZone }, { type: undefined, decorators: [{
501 type: Inject,
502 args: [DOCUMENT]
503 }] }, { type: i1.ɵSharedStylesHost }];
504 } });
505class DefaultServerRenderer2 {
506 constructor(eventManager, document, ngZone, schema) {
507 this.eventManager = eventManager;
508 this.document = document;
509 this.ngZone = ngZone;
510 this.schema = schema;
511 this.data = Object.create(null);
512 this.destroyNode = null;
513 }
514 destroy() { }
515 createElement(name, namespace, debugInfo) {
516 if (namespace) {
517 const doc = this.document || ɵgetDOM().getDefaultDocument();
518 return doc.createElementNS(ɵNAMESPACE_URIS[namespace], name);
519 }
520 return ɵgetDOM().createElement(name, this.document);
521 }
522 createComment(value, debugInfo) {
523 return ɵgetDOM().getDefaultDocument().createComment(value);
524 }
525 createText(value, debugInfo) {
526 const doc = ɵgetDOM().getDefaultDocument();
527 return doc.createTextNode(value);
528 }
529 appendChild(parent, newChild) {
530 const targetParent = isTemplateNode(parent) ? parent.content : parent;
531 targetParent.appendChild(newChild);
532 }
533 insertBefore(parent, newChild, refChild) {
534 if (parent) {
535 const targetParent = isTemplateNode(parent) ? parent.content : parent;
536 targetParent.insertBefore(newChild, refChild);
537 }
538 }
539 removeChild(parent, oldChild) {
540 if (parent) {
541 parent.removeChild(oldChild);
542 }
543 }
544 selectRootElement(selectorOrNode, debugInfo) {
545 let el;
546 if (typeof selectorOrNode === 'string') {
547 el = this.document.querySelector(selectorOrNode);
548 if (!el) {
549 throw new Error(`The selector "${selectorOrNode}" did not match any elements`);
550 }
551 }
552 else {
553 el = selectorOrNode;
554 }
555 while (el.firstChild) {
556 el.removeChild(el.firstChild);
557 }
558 return el;
559 }
560 parentNode(node) {
561 return node.parentNode;
562 }
563 nextSibling(node) {
564 return node.nextSibling;
565 }
566 setAttribute(el, name, value, namespace) {
567 if (namespace) {
568 el.setAttributeNS(ɵNAMESPACE_URIS[namespace], namespace + ':' + name, value);
569 }
570 else {
571 el.setAttribute(name, value);
572 }
573 }
574 removeAttribute(el, name, namespace) {
575 if (namespace) {
576 el.removeAttributeNS(ɵNAMESPACE_URIS[namespace], name);
577 }
578 else {
579 el.removeAttribute(name);
580 }
581 }
582 addClass(el, name) {
583 el.classList.add(name);
584 }
585 removeClass(el, name) {
586 el.classList.remove(name);
587 }
588 setStyle(el, style, value, flags) {
589 style = style.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
590 value = value == null ? '' : `${value}`.trim();
591 const styleMap = _readStyleAttribute(el);
592 if (flags & RendererStyleFlags2.Important) {
593 value += ' !important';
594 }
595 styleMap[style] = value;
596 _writeStyleAttribute(el, styleMap);
597 }
598 removeStyle(el, style, flags) {
599 // IE requires '' instead of null
600 // see https://github.com/angular/angular/issues/7916
601 this.setStyle(el, style, '', flags);
602 }
603 // The value was validated already as a property binding, against the property name.
604 // To know this value is safe to use as an attribute, the security context of the
605 // attribute with the given name is checked against that security context of the
606 // property.
607 _isSafeToReflectProperty(tagName, propertyName) {
608 return this.schema.securityContext(tagName, propertyName, true) ===
609 this.schema.securityContext(tagName, propertyName, false);
610 }
611 setProperty(el, name, value) {
612 checkNoSyntheticProp(name, 'property');
613 if (name === 'innerText') {
614 // Domino does not support innerText. Just map it to textContent.
615 el.textContent = value;
616 }
617 el[name] = value;
618 // Mirror property values for known HTML element properties in the attributes.
619 // Skip `innerhtml` which is conservatively marked as an attribute for security
620 // purposes but is not actually an attribute.
621 const tagName = el.tagName.toLowerCase();
622 if (value != null && (typeof value === 'number' || typeof value == 'string') &&
623 name.toLowerCase() !== 'innerhtml' && this.schema.hasElement(tagName, EMPTY_ARRAY) &&
624 this.schema.hasProperty(tagName, name, EMPTY_ARRAY) &&
625 this._isSafeToReflectProperty(tagName, name)) {
626 this.setAttribute(el, name, value.toString());
627 }
628 }
629 setValue(node, value) {
630 node.textContent = value;
631 }
632 listen(target, eventName, callback) {
633 checkNoSyntheticProp(eventName, 'listener');
634 if (typeof target === 'string') {
635 return this.eventManager.addGlobalEventListener(target, eventName, this.decoratePreventDefault(callback));
636 }
637 return this.eventManager.addEventListener(target, eventName, this.decoratePreventDefault(callback));
638 }
639 decoratePreventDefault(eventHandler) {
640 return (event) => {
641 // Ivy uses `Function` as a special token that allows us to unwrap the function
642 // so that it can be invoked programmatically by `DebugNode.triggerEventHandler`.
643 if (event === Function) {
644 return eventHandler;
645 }
646 // Run the event handler inside the ngZone because event handlers are not patched
647 // by Zone on the server. This is required only for tests.
648 const allowDefaultBehavior = this.ngZone.runGuarded(() => eventHandler(event));
649 if (allowDefaultBehavior === false) {
650 event.preventDefault();
651 event.returnValue = false;
652 }
653 return undefined;
654 };
655 }
656}
657const AT_CHARCODE = '@'.charCodeAt(0);
658function checkNoSyntheticProp(name, nameKind) {
659 if (name.charCodeAt(0) === AT_CHARCODE) {
660 throw new Error(`Unexpected synthetic ${nameKind} ${name} found. Please make sure that:
661 - Either \`BrowserAnimationsModule\` or \`NoopAnimationsModule\` are imported in your application.
662 - There is corresponding configuration for the animation named \`${name}\` defined in the \`animations\` field of the \`@Component\` decorator (see https://angular.io/api/core/Component#animations).`);
663 }
664}
665function isTemplateNode(node) {
666 return node.tagName === 'TEMPLATE' && node.content !== undefined;
667}
668class EmulatedEncapsulationServerRenderer2 extends DefaultServerRenderer2 {
669 constructor(eventManager, document, ngZone, sharedStylesHost, schema, component) {
670 super(eventManager, document, ngZone, schema);
671 this.component = component;
672 // Add a 's' prefix to style attributes to indicate server.
673 const componentId = 's' + component.id;
674 const styles = ɵflattenStyles(componentId, component.styles, []);
675 sharedStylesHost.addStyles(styles);
676 this.contentAttr = ɵshimContentAttribute(componentId);
677 this.hostAttr = ɵshimHostAttribute(componentId);
678 }
679 applyToHost(element) {
680 super.setAttribute(element, this.hostAttr, '');
681 }
682 createElement(parent, name) {
683 const el = super.createElement(parent, name, this.document);
684 super.setAttribute(el, this.contentAttr, '');
685 return el;
686 }
687}
688function _readStyleAttribute(element) {
689 const styleMap = {};
690 const styleAttribute = element.getAttribute('style');
691 if (styleAttribute) {
692 const styleList = styleAttribute.split(/;+/g);
693 for (let i = 0; i < styleList.length; i++) {
694 const style = styleList[i].trim();
695 if (style.length > 0) {
696 const colonIndex = style.indexOf(':');
697 if (colonIndex === -1) {
698 throw new Error(`Invalid CSS style: ${style}`);
699 }
700 const name = style.slice(0, colonIndex).trim();
701 styleMap[name] = style.slice(colonIndex + 1).trim();
702 }
703 }
704 }
705 return styleMap;
706}
707function _writeStyleAttribute(element, styleMap) {
708 // We have to construct the `style` attribute ourselves, instead of going through
709 // `element.style.setProperty` like the other renderers, because `setProperty` won't
710 // write newer CSS properties that Domino doesn't know about like `clip-path`.
711 let styleAttrValue = '';
712 for (const key in styleMap) {
713 const newValue = styleMap[key];
714 if (newValue != null && newValue !== '') {
715 styleAttrValue += key + ':' + newValue + ';';
716 }
717 }
718 if (styleAttrValue) {
719 element.setAttribute('style', styleAttrValue);
720 }
721 else {
722 element.removeAttribute('style');
723 }
724}
725
726/**
727 * @license
728 * Copyright Google LLC All Rights Reserved.
729 *
730 * Use of this source code is governed by an MIT-style license that can be
731 * found in the LICENSE file at https://angular.io/license
732 */
733class ServerStylesHost extends ɵSharedStylesHost {
734 constructor(doc, transitionId) {
735 super();
736 this.doc = doc;
737 this.transitionId = transitionId;
738 this.head = null;
739 this._styleNodes = new Set();
740 this.head = doc.getElementsByTagName('head')[0];
741 }
742 _addStyle(style) {
743 let adapter = ɵgetDOM();
744 const el = adapter.createElement('style');
745 el.textContent = style;
746 if (!!this.transitionId) {
747 el.setAttribute('ng-transition', this.transitionId);
748 }
749 this.head.appendChild(el);
750 this._styleNodes.add(el);
751 }
752 onStylesAdded(additions) {
753 additions.forEach(style => this._addStyle(style));
754 }
755 ngOnDestroy() {
756 this._styleNodes.forEach(styleNode => styleNode.remove());
757 }
758}
759ServerStylesHost.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.4", ngImport: i0, type: ServerStylesHost, deps: [{ token: DOCUMENT }, { token: ɵTRANSITION_ID, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
760ServerStylesHost.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.4", ngImport: i0, type: ServerStylesHost });
761i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.4", ngImport: i0, type: ServerStylesHost, decorators: [{
762 type: Injectable
763 }], ctorParameters: function () {
764 return [{ type: undefined, decorators: [{
765 type: Inject,
766 args: [DOCUMENT]
767 }] }, { type: undefined, decorators: [{
768 type: Optional
769 }, {
770 type: Inject,
771 args: [ɵTRANSITION_ID]
772 }] }];
773 } });
774
775/**
776 * @license
777 * Copyright Google LLC All Rights Reserved.
778 *
779 * Use of this source code is governed by an MIT-style license that can be
780 * found in the LICENSE file at https://angular.io/license
781 */
782const INTERNAL_SERVER_PLATFORM_PROVIDERS = [
783 { provide: DOCUMENT, useFactory: _document, deps: [Injector] },
784 { provide: PLATFORM_ID, useValue: ɵPLATFORM_SERVER_ID },
785 { provide: PLATFORM_INITIALIZER, useFactory: initDominoAdapter, multi: true, deps: [Injector] }, {
786 provide: PlatformLocation,
787 useClass: ServerPlatformLocation,
788 deps: [DOCUMENT, [Optional, INITIAL_CONFIG]]
789 },
790 { provide: PlatformState, deps: [DOCUMENT] },
791 // Add special provider that allows multiple instances of platformServer* to be created.
792 { provide: ɵALLOW_MULTIPLE_PLATFORMS, useValue: true }
793];
794function initDominoAdapter(injector) {
795 return () => {
796 DominoAdapter.makeCurrent();
797 };
798}
799function instantiateServerRendererFactory(renderer, engine, zone) {
800 return new ɵAnimationRendererFactory(renderer, engine, zone);
801}
802const SERVER_RENDER_PROVIDERS = [
803 ServerRendererFactory2,
804 {
805 provide: RendererFactory2,
806 useFactory: instantiateServerRendererFactory,
807 deps: [ServerRendererFactory2, ɵAnimationEngine, NgZone]
808 },
809 ServerStylesHost,
810 { provide: ɵSharedStylesHost, useExisting: ServerStylesHost },
811 { provide: EVENT_MANAGER_PLUGINS, multi: true, useClass: ServerEventManagerPlugin },
812];
813/**
814 * The ng module for the server.
815 *
816 * @publicApi
817 */
818class ServerModule {
819}
820ServerModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.4", ngImport: i0, type: ServerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
821ServerModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.4", ngImport: i0, type: ServerModule, imports: [HttpClientModule, NoopAnimationsModule], exports: [BrowserModule] });
822ServerModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.4", ngImport: i0, type: ServerModule, providers: [
823 SERVER_RENDER_PROVIDERS,
824 SERVER_HTTP_PROVIDERS,
825 { provide: Testability, useValue: null },
826 { provide: ɵTESTABILITY, useValue: null },
827 { provide: ViewportScroller, useClass: ɵNullViewportScroller },
828 ], imports: [HttpClientModule, NoopAnimationsModule, BrowserModule] });
829i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.4", ngImport: i0, type: ServerModule, decorators: [{
830 type: NgModule,
831 args: [{
832 exports: [BrowserModule],
833 imports: [HttpClientModule, NoopAnimationsModule],
834 providers: [
835 SERVER_RENDER_PROVIDERS,
836 SERVER_HTTP_PROVIDERS,
837 { provide: Testability, useValue: null },
838 { provide: ɵTESTABILITY, useValue: null },
839 { provide: ViewportScroller, useClass: ɵNullViewportScroller },
840 ],
841 }]
842 }] });
843function _document(injector) {
844 let config = injector.get(INITIAL_CONFIG, null);
845 const document = config && config.document ? parseDocument(config.document, config.url) :
846 ɵgetDOM().createHtmlDocument();
847 // Tell ivy about the global document
848 ɵsetDocument(document);
849 return document;
850}
851/**
852 * @publicApi
853 */
854const platformServer = createPlatformFactory(platformCore, 'server', INTERNAL_SERVER_PLATFORM_PROVIDERS);
855/**
856 * The server platform that supports the runtime compiler.
857 *
858 * @publicApi
859 */
860const platformDynamicServer = createPlatformFactory(ɵplatformCoreDynamic, 'serverDynamic', INTERNAL_SERVER_PLATFORM_PROVIDERS);
861
862/**
863 * @license
864 * Copyright Google LLC All Rights Reserved.
865 *
866 * Use of this source code is governed by an MIT-style license that can be
867 * found in the LICENSE file at https://angular.io/license
868 */
869function serializeTransferStateFactory(doc, appId, transferStore) {
870 return () => {
871 const script = doc.createElement('script');
872 script.id = appId + '-state';
873 script.setAttribute('type', 'application/json');
874 script.textContent = ɵescapeHtml(transferStore.toJson());
875 doc.body.appendChild(script);
876 };
877}
878/**
879 * NgModule to install on the server side while using the `TransferState` to transfer state from
880 * server to client.
881 *
882 * @publicApi
883 */
884class ServerTransferStateModule {
885}
886ServerTransferStateModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.4", ngImport: i0, type: ServerTransferStateModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
887ServerTransferStateModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.4", ngImport: i0, type: ServerTransferStateModule });
888ServerTransferStateModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.4", ngImport: i0, type: ServerTransferStateModule, providers: [
889 TransferState, {
890 provide: BEFORE_APP_SERIALIZED,
891 useFactory: serializeTransferStateFactory,
892 deps: [DOCUMENT, APP_ID, TransferState],
893 multi: true,
894 }
895 ] });
896i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.4", ngImport: i0, type: ServerTransferStateModule, decorators: [{
897 type: NgModule,
898 args: [{
899 providers: [
900 TransferState, {
901 provide: BEFORE_APP_SERIALIZED,
902 useFactory: serializeTransferStateFactory,
903 deps: [DOCUMENT, APP_ID, TransferState],
904 multi: true,
905 }
906 ]
907 }]
908 }] });
909
910/**
911 * @license
912 * Copyright Google LLC All Rights Reserved.
913 *
914 * Use of this source code is governed by an MIT-style license that can be
915 * found in the LICENSE file at https://angular.io/license
916 */
917function _getPlatform(platformFactory, options) {
918 var _a;
919 const extraProviders = (_a = options.platformProviders) !== null && _a !== void 0 ? _a : [];
920 return platformFactory([
921 { provide: INITIAL_CONFIG, useValue: { document: options.document, url: options.url } },
922 extraProviders
923 ]);
924}
925function _render(platform, bootstrapPromise) {
926 return bootstrapPromise.then((moduleOrApplicationRef) => {
927 const environmentInjector = moduleOrApplicationRef.injector;
928 const transitionId = environmentInjector.get(ɵTRANSITION_ID, null);
929 if (!transitionId) {
930 throw new Error(`renderModule[Factory]() requires the use of BrowserModule.withServerTransition() to ensure
931the server-rendered app can be properly bootstrapped into a client app.`);
932 }
933 const applicationRef = moduleOrApplicationRef instanceof ApplicationRef ?
934 moduleOrApplicationRef :
935 environmentInjector.get(ApplicationRef);
936 return applicationRef.isStable.pipe((first((isStable) => isStable)))
937 .toPromise()
938 .then(() => {
939 const platformState = platform.injector.get(PlatformState);
940 const asyncPromises = [];
941 // Run any BEFORE_APP_SERIALIZED callbacks just before rendering to string.
942 const callbacks = environmentInjector.get(BEFORE_APP_SERIALIZED, null);
943 if (callbacks) {
944 for (const callback of callbacks) {
945 try {
946 const callbackResult = callback();
947 if (ɵisPromise(callbackResult)) {
948 // TODO: in TS3.7, callbackResult is void.
949 asyncPromises.push(callbackResult);
950 }
951 }
952 catch (e) {
953 // Ignore exceptions.
954 console.warn('Ignoring BEFORE_APP_SERIALIZED Exception: ', e);
955 }
956 }
957 }
958 const complete = () => {
959 const output = platformState.renderToString();
960 platform.destroy();
961 return output;
962 };
963 if (asyncPromises.length === 0) {
964 return complete();
965 }
966 return Promise
967 .all(asyncPromises.map(asyncPromise => {
968 return asyncPromise.catch(e => {
969 console.warn('Ignoring BEFORE_APP_SERIALIZED Exception: ', e);
970 });
971 }))
972 .then(complete);
973 });
974 });
975}
976/**
977 * Renders a Module to string.
978 *
979 * `document` is the full document HTML of the page to render, as a string.
980 * `url` is the URL for the current render request.
981 * `extraProviders` are the platform level providers for the current render request.
982 *
983 * @publicApi
984 */
985function renderModule(module, options) {
986 const { document, url, extraProviders: platformProviders } = options;
987 const platform = _getPlatform(platformDynamicServer, { document, url, platformProviders });
988 return _render(platform, platform.bootstrapModule(module));
989}
990/**
991 * Bootstraps an instance of an Angular application and renders it to a string.
992 *
993 * Note: the root component passed into this function *must* be a standalone one (should have the
994 * `standalone: true` flag in the `@Component` decorator config).
995 *
996 * ```typescript
997 * @Component({
998 * standalone: true,
999 * template: 'Hello world!'
1000 * })
1001 * class RootComponent {}
1002 *
1003 * const output: string = await renderApplication(RootComponent, {appId: 'server-app'});
1004 * ```
1005 *
1006 * @param rootComponent A reference to a Standalone Component that should be rendered.
1007 * @param options Additional configuration for the render operation:
1008 * - `appId` - a string identifier of this application. The appId is used to prefix all
1009 * server-generated stylings and state keys of the application in TransferState
1010 * use-cases.
1011 * - `document` - the full document HTML of the page to render, as a string.
1012 * - `url` - the URL for the current render request.
1013 * - `providers` - set of application level providers for the current render request.
1014 * - `platformProviders` - the platform level providers for the current render request.
1015 * @returns A Promise, that returns serialized (to a string) rendered page, once resolved.
1016 *
1017 * @publicApi
1018 * @developerPreview
1019 */
1020function renderApplication(rootComponent, options) {
1021 var _a;
1022 const { document, url, platformProviders, appId } = options;
1023 const platform = _getPlatform(platformDynamicServer, { document, url, platformProviders });
1024 const appProviders = [
1025 importProvidersFrom(BrowserModule.withServerTransition({ appId })),
1026 importProvidersFrom(ServerModule),
1027 ...((_a = options.providers) !== null && _a !== void 0 ? _a : []),
1028 ];
1029 return _render(platform, ɵinternalBootstrapApplication({ rootComponent, appProviders }));
1030}
1031/**
1032 * Renders a {@link NgModuleFactory} to string.
1033 *
1034 * `document` is the full document HTML of the page to render, as a string.
1035 * `url` is the URL for the current render request.
1036 * `extraProviders` are the platform level providers for the current render request.
1037 *
1038 * @publicApi
1039 *
1040 * @deprecated
1041 * This symbol is no longer necessary as of Angular v13.
1042 * Use {@link renderModule} API instead.
1043 */
1044function renderModuleFactory(moduleFactory, options) {
1045 const { document, url, extraProviders: platformProviders } = options;
1046 const platform = _getPlatform(platformServer, { document, url, platformProviders });
1047 return _render(platform, platform.bootstrapModuleFactory(moduleFactory));
1048}
1049
1050/**
1051 * @license
1052 * Copyright Google LLC All Rights Reserved.
1053 *
1054 * Use of this source code is governed by an MIT-style license that can be
1055 * found in the LICENSE file at https://angular.io/license
1056 */
1057
1058/**
1059 * @license
1060 * Copyright Google LLC All Rights Reserved.
1061 *
1062 * Use of this source code is governed by an MIT-style license that can be
1063 * found in the LICENSE file at https://angular.io/license
1064 */
1065/**
1066 * @publicApi
1067 */
1068const VERSION = new Version('14.0.4');
1069
1070/**
1071 * @license
1072 * Copyright Google LLC All Rights Reserved.
1073 *
1074 * Use of this source code is governed by an MIT-style license that can be
1075 * found in the LICENSE file at https://angular.io/license
1076 */
1077
1078/**
1079 * @license
1080 * Copyright Google LLC All Rights Reserved.
1081 *
1082 * Use of this source code is governed by an MIT-style license that can be
1083 * found in the LICENSE file at https://angular.io/license
1084 */
1085// This file only reexports content of the `src` folder. Keep it that way.
1086
1087/**
1088 * @license
1089 * Copyright Google LLC All Rights Reserved.
1090 *
1091 * Use of this source code is governed by an MIT-style license that can be
1092 * found in the LICENSE file at https://angular.io/license
1093 */
1094
1095/**
1096 * Generated bundle index. Do not edit.
1097 */
1098
1099export { BEFORE_APP_SERIALIZED, INITIAL_CONFIG, PlatformState, ServerModule, ServerTransferStateModule, VERSION, platformDynamicServer, platformServer, renderApplication, renderModule, renderModuleFactory, INTERNAL_SERVER_PLATFORM_PROVIDERS as ɵINTERNAL_SERVER_PLATFORM_PROVIDERS, SERVER_RENDER_PROVIDERS as ɵSERVER_RENDER_PROVIDERS, ServerRendererFactory2 as ɵServerRendererFactory2, setDomTypes as ɵsetDomTypes };
1100//# sourceMappingURL=platform-server.mjs.map