This commit is contained in:
CHEVALLIER Abel
2025-11-13 16:23:22 +01:00
parent de9c515a47
commit cb235644dc
34924 changed files with 3811102 additions and 0 deletions

View File

@@ -0,0 +1,200 @@
/**
* @license Angular v20.3.11
* (c) 2010-2025 Google LLC. https://angular.dev/
* License: MIT
*/
import * as i0 from '@angular/core';
import { Injectable, Inject, ANIMATION_MODULE_TYPE, RendererFactory2, NgZone, NgModule, ɵperformanceMarkFeature as _performanceMarkFeature } from '@angular/core';
export { ANIMATION_MODULE_TYPE } from '@angular/core';
import * as i1 from '@angular/animations/browser';
import { ɵAnimationEngine as _AnimationEngine, AnimationDriver, NoopAnimationDriver, ɵWebAnimationsDriver as _WebAnimationsDriver, ɵAnimationStyleNormalizer as _AnimationStyleNormalizer, ɵWebAnimationsStyleNormalizer as _WebAnimationsStyleNormalizer, ɵAnimationRendererFactory as _AnimationRendererFactory } from '@angular/animations/browser';
import { DOCUMENT } from '@angular/common';
import { DomRendererFactory2 } from './dom_renderer.mjs';
import { BrowserModule } from './browser.mjs';
class InjectableAnimationEngine extends _AnimationEngine {
// The `ApplicationRef` is injected here explicitly to force the dependency ordering.
// Since the `ApplicationRef` should be created earlier before the `AnimationEngine`, they
// both have `ngOnDestroy` hooks and `flush()` must be called after all views are destroyed.
constructor(doc, driver, normalizer) {
super(doc, driver, normalizer);
}
ngOnDestroy() {
this.flush();
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: InjectableAnimationEngine, deps: [{ token: DOCUMENT }, { token: i1.AnimationDriver }, { token: i1.ɵAnimationStyleNormalizer }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: InjectableAnimationEngine });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: InjectableAnimationEngine, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: Document, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }, { type: i1.AnimationDriver }, { type: i1.ɵAnimationStyleNormalizer }] });
function instantiateDefaultStyleNormalizer() {
return new _WebAnimationsStyleNormalizer();
}
function instantiateRendererFactory(renderer, engine, zone) {
return new _AnimationRendererFactory(renderer, engine, zone);
}
const SHARED_ANIMATION_PROVIDERS = [
{ provide: _AnimationStyleNormalizer, useFactory: instantiateDefaultStyleNormalizer },
{ provide: _AnimationEngine, useClass: InjectableAnimationEngine },
{
provide: RendererFactory2,
useFactory: instantiateRendererFactory,
deps: [DomRendererFactory2, _AnimationEngine, NgZone],
},
];
/**
* Separate providers from the actual module so that we can do a local modification in Google3 to
* include them in the BrowserTestingModule.
*/
const BROWSER_NOOP_ANIMATIONS_PROVIDERS = [
{ provide: AnimationDriver, useClass: NoopAnimationDriver },
{ provide: ANIMATION_MODULE_TYPE, useValue: 'NoopAnimations' },
...SHARED_ANIMATION_PROVIDERS,
];
/**
* Separate providers from the actual module so that we can do a local modification in Google3 to
* include them in the BrowserModule.
*/
const BROWSER_ANIMATIONS_PROVIDERS = [
// Note: the `ngServerMode` happen inside factories to give the variable time to initialize.
{
provide: AnimationDriver,
useFactory: () => typeof ngServerMode !== 'undefined' && ngServerMode
? new NoopAnimationDriver()
: new _WebAnimationsDriver(),
},
{
provide: ANIMATION_MODULE_TYPE,
useFactory: () => typeof ngServerMode !== 'undefined' && ngServerMode ? 'NoopAnimations' : 'BrowserAnimations',
},
...SHARED_ANIMATION_PROVIDERS,
];
/**
* Exports `BrowserModule` with additional dependency-injection providers
* for use with animations. See [Animations](guide/animations).
* @publicApi
*
* @deprecated 20.2 Use `animate.enter` or `animate.leave` instead. Intent to remove in v23
*/
class BrowserAnimationsModule {
/**
* Configures the module based on the specified object.
*
* @param config Object used to configure the behavior of the `BrowserAnimationsModule`.
* @see {@link BrowserAnimationsModuleConfig}
*
* @usageNotes
* When registering the `BrowserAnimationsModule`, you can use the `withConfig`
* function as follows:
* ```ts
* @NgModule({
* imports: [BrowserAnimationsModule.withConfig(config)]
* })
* class MyNgModule {}
* ```
*/
static withConfig(config) {
return {
ngModule: BrowserAnimationsModule,
providers: config.disableAnimations
? BROWSER_NOOP_ANIMATIONS_PROVIDERS
: BROWSER_ANIMATIONS_PROVIDERS,
};
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: BrowserAnimationsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.11", ngImport: i0, type: BrowserAnimationsModule, exports: [BrowserModule] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: BrowserAnimationsModule, providers: BROWSER_ANIMATIONS_PROVIDERS, imports: [BrowserModule] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: BrowserAnimationsModule, decorators: [{
type: NgModule,
args: [{
exports: [BrowserModule],
providers: BROWSER_ANIMATIONS_PROVIDERS,
}]
}] });
/**
* Returns the set of dependency-injection providers
* to enable animations in an application. See [animations guide](guide/animations)
* to learn more about animations in Angular.
*
* @usageNotes
*
* The function is useful when you want to enable animations in an application
* bootstrapped using the `bootstrapApplication` function. In this scenario there
* is no need to import the `BrowserAnimationsModule` NgModule at all, just add
* providers returned by this function to the `providers` list as show below.
*
* ```ts
* bootstrapApplication(RootComponent, {
* providers: [
* provideAnimations()
* ]
* });
* ```
*
* @publicApi
*
* @deprecated 20.2 Use `animate.enter` or `animate.leave` instead. Intent to remove in v23
*
*/
function provideAnimations() {
_performanceMarkFeature('NgEagerAnimations');
// Return a copy to prevent changes to the original array in case any in-place
// alterations are performed to the `provideAnimations` call results in app code.
return [...BROWSER_ANIMATIONS_PROVIDERS];
}
/**
* A null player that must be imported to allow disabling of animations.
* @publicApi
*
* @deprecated 20.2 Use `animate.enter` or `animate.leave` instead. Intent to remove in v23
*/
class NoopAnimationsModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: NoopAnimationsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.11", ngImport: i0, type: NoopAnimationsModule, exports: [BrowserModule] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: NoopAnimationsModule, providers: BROWSER_NOOP_ANIMATIONS_PROVIDERS, imports: [BrowserModule] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: NoopAnimationsModule, decorators: [{
type: NgModule,
args: [{
exports: [BrowserModule],
providers: BROWSER_NOOP_ANIMATIONS_PROVIDERS,
}]
}] });
/**
* Returns the set of dependency-injection providers
* to disable animations in an application. See [animations guide](guide/animations)
* to learn more about animations in Angular.
*
* @usageNotes
*
* The function is useful when you want to bootstrap an application using
* the `bootstrapApplication` function, but you need to disable animations
* (for example, when running tests).
*
* ```ts
* bootstrapApplication(RootComponent, {
* providers: [
* provideNoopAnimations()
* ]
* });
* ```
*
* @publicApi
*
* @deprecated 20.2 Use `animate.enter` or `animate.leave` instead. Intent to remove in v23
*/
function provideNoopAnimations() {
// Return a copy to prevent changes to the original array in case any in-place
// alterations are performed to the `provideNoopAnimations` call results in app code.
return [...BROWSER_NOOP_ANIMATIONS_PROVIDERS];
}
export { BrowserAnimationsModule, NoopAnimationsModule, provideAnimations, provideNoopAnimations, InjectableAnimationEngine as ɵInjectableAnimationEngine };
//# sourceMappingURL=animations.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,302 @@
/**
* @license Angular v20.3.11
* (c) 2010-2025 Google LLC. https://angular.dev/
* License: MIT
*/
import { DOCUMENT } from '@angular/common';
import * as i0 from '@angular/core';
import { inject, Injector, ɵRuntimeError as _RuntimeError, ɵChangeDetectionScheduler as _ChangeDetectionScheduler, Injectable, InjectionToken, ɵperformanceMarkFeature as _performanceMarkFeature, makeEnvironmentProviders, RendererFactory2, NgZone, ANIMATION_MODULE_TYPE } from '@angular/core';
import { DomRendererFactory2 } from '../dom_renderer.mjs';
const ANIMATION_PREFIX = '@';
class AsyncAnimationRendererFactory {
doc;
delegate;
zone;
animationType;
moduleImpl;
_rendererFactoryPromise = null;
scheduler = null;
injector = inject(Injector);
loadingSchedulerFn = inject(ɵASYNC_ANIMATION_LOADING_SCHEDULER_FN, {
optional: true,
});
_engine;
/**
*
* @param moduleImpl allows to provide a mock implmentation (or will load the animation module)
*/
constructor(doc, delegate, zone, animationType, moduleImpl) {
this.doc = doc;
this.delegate = delegate;
this.zone = zone;
this.animationType = animationType;
this.moduleImpl = moduleImpl;
}
/** @docs-private */
ngOnDestroy() {
// When the root view is removed, the renderer defers the actual work to the
// `TransitionAnimationEngine` to do this, and the `TransitionAnimationEngine` doesn't actually
// remove the DOM node, but just calls `markElementAsRemoved()`. The actual DOM node is not
// removed until `TransitionAnimationEngine` "flushes".
// Note: we already flush on destroy within the `InjectableAnimationEngine`. The injectable
// engine is not provided when async animations are used.
this._engine?.flush();
}
/**
* @internal
*/
loadImpl() {
// Note on the `.then(m => m)` part below: Closure compiler optimizations in g3 require
// `.then` to be present for a dynamic import (or an import should be `await`ed) to detect
// the set of imported symbols.
const loadFn = () => this.moduleImpl ?? import('@angular/animations/browser').then((m) => m);
let moduleImplPromise;
if (this.loadingSchedulerFn) {
moduleImplPromise = this.loadingSchedulerFn(loadFn);
}
else {
moduleImplPromise = loadFn();
}
return moduleImplPromise
.catch((e) => {
throw new _RuntimeError(5300 /* RuntimeErrorCode.ANIMATION_RENDERER_ASYNC_LOADING_FAILURE */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
'Async loading for animations package was ' +
'enabled, but loading failed. Angular falls back to using regular rendering. ' +
"No animations will be displayed and their styles won't be applied.");
})
.then(({ ɵcreateEngine, ɵAnimationRendererFactory }) => {
// We can't create the renderer yet because we might need the hostElement and the type
// Both are provided in createRenderer().
this._engine = ɵcreateEngine(this.animationType, this.doc);
const rendererFactory = new ɵAnimationRendererFactory(this.delegate, this._engine, this.zone);
this.delegate = rendererFactory;
return rendererFactory;
});
}
/**
* This method is delegating the renderer creation to the factories.
* It uses default factory while the animation factory isn't loaded
* and will rely on the animation factory once it is loaded.
*
* Calling this method will trigger as side effect the loading of the animation module
* if the renderered component uses animations.
*/
createRenderer(hostElement, rendererType) {
const renderer = this.delegate.createRenderer(hostElement, rendererType);
if (renderer.ɵtype === 0 /* AnimationRendererType.Regular */) {
// The factory is already loaded, this is an animation renderer
return renderer;
}
// We need to prevent the DomRenderer to throw an error because of synthetic properties
if (typeof renderer.throwOnSyntheticProps === 'boolean') {
renderer.throwOnSyntheticProps = false;
}
// Using a dynamic renderer to switch the renderer implementation once the module is loaded.
const dynamicRenderer = new DynamicDelegationRenderer(renderer);
// Kick off the module loading if the component uses animations but the module hasn't been
// loaded yet.
if (rendererType?.data?.['animation'] && !this._rendererFactoryPromise) {
this._rendererFactoryPromise = this.loadImpl();
}
this._rendererFactoryPromise
?.then((animationRendererFactory) => {
const animationRenderer = animationRendererFactory.createRenderer(hostElement, rendererType);
dynamicRenderer.use(animationRenderer);
this.scheduler ??= this.injector.get(_ChangeDetectionScheduler, null, { optional: true });
this.scheduler?.notify(10 /* NotificationSource.AsyncAnimationsLoaded */);
})
.catch((e) => {
// Permanently use regular renderer when loading fails.
dynamicRenderer.use(renderer);
});
return dynamicRenderer;
}
begin() {
this.delegate.begin?.();
}
end() {
this.delegate.end?.();
}
whenRenderingDone() {
return this.delegate.whenRenderingDone?.() ?? Promise.resolve();
}
/**
* Used during HMR to clear any cached data about a component.
* @param componentId ID of the component that is being replaced.
*/
componentReplaced(componentId) {
// Flush the engine since the renderer destruction waits for animations to be done.
this._engine?.flush();
this.delegate.componentReplaced?.(componentId);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: AsyncAnimationRendererFactory, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: AsyncAnimationRendererFactory });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: AsyncAnimationRendererFactory, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: Document }, { type: i0.RendererFactory2 }, { type: i0.NgZone }, { type: undefined }, { type: Promise }] });
/**
* The class allows to dynamicly switch between different renderer implementations
* by changing the delegate renderer.
*/
class DynamicDelegationRenderer {
delegate;
// List of callbacks that need to be replayed on the animation renderer once its loaded
replay = [];
ɵtype = 1 /* AnimationRendererType.Delegated */;
constructor(delegate) {
this.delegate = delegate;
}
use(impl) {
this.delegate = impl;
if (this.replay !== null) {
// Replay queued actions using the animation renderer to apply
// all events and properties collected while loading was in progress.
for (const fn of this.replay) {
fn(impl);
}
// Set to `null` to indicate that the queue was processed
// and we no longer need to collect events and properties.
this.replay = null;
}
}
get data() {
return this.delegate.data;
}
destroy() {
this.replay = null;
this.delegate.destroy();
}
createElement(name, namespace) {
return this.delegate.createElement(name, namespace);
}
createComment(value) {
return this.delegate.createComment(value);
}
createText(value) {
return this.delegate.createText(value);
}
get destroyNode() {
return this.delegate.destroyNode;
}
appendChild(parent, newChild) {
this.delegate.appendChild(parent, newChild);
}
insertBefore(parent, newChild, refChild, isMove) {
this.delegate.insertBefore(parent, newChild, refChild, isMove);
}
removeChild(parent, oldChild, isHostElement, requireSynchronousElementRemoval) {
this.delegate.removeChild(parent, oldChild, isHostElement, requireSynchronousElementRemoval);
}
selectRootElement(selectorOrNode, preserveContent) {
return this.delegate.selectRootElement(selectorOrNode, preserveContent);
}
parentNode(node) {
return this.delegate.parentNode(node);
}
nextSibling(node) {
return this.delegate.nextSibling(node);
}
setAttribute(el, name, value, namespace) {
this.delegate.setAttribute(el, name, value, namespace);
}
removeAttribute(el, name, namespace) {
this.delegate.removeAttribute(el, name, namespace);
}
addClass(el, name) {
this.delegate.addClass(el, name);
}
removeClass(el, name) {
this.delegate.removeClass(el, name);
}
setStyle(el, style, value, flags) {
this.delegate.setStyle(el, style, value, flags);
}
removeStyle(el, style, flags) {
this.delegate.removeStyle(el, style, flags);
}
setProperty(el, name, value) {
// We need to keep track of animation properties set on default renderer
// So we can also set them also on the animation renderer
if (this.shouldReplay(name)) {
this.replay.push((renderer) => renderer.setProperty(el, name, value));
}
this.delegate.setProperty(el, name, value);
}
setValue(node, value) {
this.delegate.setValue(node, value);
}
listen(target, eventName, callback, options) {
// We need to keep track of animation events registred by the default renderer
// So we can also register them against the animation renderer
if (this.shouldReplay(eventName)) {
this.replay.push((renderer) => renderer.listen(target, eventName, callback, options));
}
return this.delegate.listen(target, eventName, callback, options);
}
shouldReplay(propOrEventName) {
//`null` indicates that we no longer need to collect events and properties
return this.replay !== null && propOrEventName.startsWith(ANIMATION_PREFIX);
}
}
/**
* Provides a custom scheduler function for the async loading of the animation package.
*
* Private token for investigation purposes
*/
const ɵASYNC_ANIMATION_LOADING_SCHEDULER_FN = new InjectionToken(ngDevMode ? 'async_animation_loading_scheduler_fn' : '');
/**
* Returns the set of dependency-injection providers
* to enable animations in an application. See [animations guide](guide/animations)
* to learn more about animations in Angular.
*
* When you use this function instead of the eager `provideAnimations()`, animations won't be
* rendered until the renderer is loaded.
*
* @usageNotes
*
* The function is useful when you want to enable animations in an application
* bootstrapped using the `bootstrapApplication` function. In this scenario there
* is no need to import the `BrowserAnimationsModule` NgModule at all, just add
* providers returned by this function to the `providers` list as show below.
*
* ```ts
* bootstrapApplication(RootComponent, {
* providers: [
* provideAnimationsAsync()
* ]
* });
* ```
*
* @param type pass `'noop'` as argument to disable animations.
*
* @publicApi
*
* @deprecated 20.2 Use `animate.enter` or `animate.leave` instead. Intent to remove in v23
*/
function provideAnimationsAsync(type = 'animations') {
_performanceMarkFeature('NgAsyncAnimations');
// Animations don't work on the server so we switch them over to no-op automatically.
if (typeof ngServerMode !== 'undefined' && ngServerMode) {
type = 'noop';
}
return makeEnvironmentProviders([
{
provide: RendererFactory2,
useFactory: (doc, renderer, zone) => {
return new AsyncAnimationRendererFactory(doc, renderer, zone, type);
},
deps: [DOCUMENT, DomRendererFactory2, NgZone],
},
{
provide: ANIMATION_MODULE_TYPE,
useValue: type === 'noop' ? 'NoopAnimations' : 'BrowserAnimations',
},
]);
}
export { provideAnimationsAsync, ɵASYNC_ANIMATION_LOADING_SCHEDULER_FN, AsyncAnimationRendererFactory as ɵAsyncAnimationRendererFactory };
//# sourceMappingURL=async.mjs.map

File diff suppressed because one or more lines are too long

541
node_modules/@angular/platform-browser/fesm2022/browser.mjs generated vendored Executable file
View File

@@ -0,0 +1,541 @@
/**
* @license Angular v20.3.11
* (c) 2010-2025 Google LLC. https://angular.dev/
* License: MIT
*/
import { ɵDomAdapter as _DomAdapter, ɵsetRootDomAdapter as _setRootDomAdapter, ɵparseCookieValue as _parseCookieValue, ɵgetDOM as _getDOM, DOCUMENT, ɵPLATFORM_BROWSER_ID as _PLATFORM_BROWSER_ID, XhrFactory, CommonModule } from '@angular/common';
import * as i0 from '@angular/core';
import { ɵglobal as _global, ɵRuntimeError as _RuntimeError, Injectable, Inject, ɵresolveComponentResources as _resolveComponentResources, ɵinternalCreateApplication as _internalCreateApplication, PLATFORM_ID, PLATFORM_INITIALIZER, createPlatformFactory, platformCore, InjectionToken, ɵTESTABILITY_GETTER as _TESTABILITY_GETTER, ɵTESTABILITY as _TESTABILITY, Testability, NgZone, TestabilityRegistry, ɵINJECTOR_SCOPE as _INJECTOR_SCOPE, ErrorHandler, RendererFactory2, inject, ApplicationModule, NgModule, ɵsetDocument as _setDocument } from '@angular/core';
import { EventManagerPlugin, EVENT_MANAGER_PLUGINS, DomEventsPlugin, DomRendererFactory2, SharedStylesHost, EventManager } from './dom_renderer.mjs';
/**
* A `DomAdapter` powered by full browser DOM APIs.
*
* @security Tread carefully! Interacting with the DOM directly is dangerous and
* can introduce XSS risks.
*/
class BrowserDomAdapter extends _DomAdapter {
supportsDOMEvents = true;
static makeCurrent() {
_setRootDomAdapter(new BrowserDomAdapter());
}
onAndCancel(el, evt, listener, options) {
el.addEventListener(evt, listener, options);
return () => {
el.removeEventListener(evt, listener, options);
};
}
dispatchEvent(el, evt) {
el.dispatchEvent(evt);
}
remove(node) {
node.remove();
}
createElement(tagName, doc) {
doc = doc || this.getDefaultDocument();
return doc.createElement(tagName);
}
createHtmlDocument() {
return document.implementation.createHTMLDocument('fakeTitle');
}
getDefaultDocument() {
return document;
}
isElementNode(node) {
return node.nodeType === Node.ELEMENT_NODE;
}
isShadowRoot(node) {
return node instanceof DocumentFragment;
}
/** @deprecated No longer being used in Ivy code. To be removed in version 14. */
getGlobalEventTarget(doc, target) {
if (target === 'window') {
return window;
}
if (target === 'document') {
return doc;
}
if (target === 'body') {
return doc.body;
}
return null;
}
getBaseHref(doc) {
const href = getBaseElementHref();
return href == null ? null : relativePath(href);
}
resetBaseElement() {
baseElement = null;
}
getUserAgent() {
return window.navigator.userAgent;
}
getCookie(name) {
return _parseCookieValue(document.cookie, name);
}
}
let baseElement = null;
function getBaseElementHref() {
baseElement = baseElement || document.head.querySelector('base');
return baseElement ? baseElement.getAttribute('href') : null;
}
function relativePath(url) {
// The base URL doesn't really matter, we just need it so relative paths have something
// to resolve against. In the browser `HTMLBaseElement.href` is always absolute.
return new URL(url, document.baseURI).pathname;
}
class BrowserGetTestability {
addToWindow(registry) {
_global['getAngularTestability'] = (elem, findInAncestors = true) => {
const testability = registry.findTestabilityInTree(elem, findInAncestors);
if (testability == null) {
throw new _RuntimeError(5103 /* RuntimeErrorCode.TESTABILITY_NOT_FOUND */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
'Could not find testability for element.');
}
return testability;
};
_global['getAllAngularTestabilities'] = () => registry.getAllTestabilities();
_global['getAllAngularRootElements'] = () => registry.getAllRootElements();
const whenAllStable = (callback) => {
const testabilities = _global['getAllAngularTestabilities']();
let count = testabilities.length;
const decrement = function () {
count--;
if (count == 0) {
callback();
}
};
testabilities.forEach((testability) => {
testability.whenStable(decrement);
});
};
if (!_global['frameworkStabilizers']) {
_global['frameworkStabilizers'] = [];
}
_global['frameworkStabilizers'].push(whenAllStable);
}
findTestabilityInTree(registry, elem, findInAncestors) {
if (elem == null) {
return null;
}
const t = registry.getTestability(elem);
if (t != null) {
return t;
}
else if (!findInAncestors) {
return null;
}
if (_getDOM().isShadowRoot(elem)) {
return this.findTestabilityInTree(registry, elem.host, true);
}
return this.findTestabilityInTree(registry, elem.parentElement, true);
}
}
/**
* A factory for `HttpXhrBackend` that uses the `XMLHttpRequest` browser API.
*/
class BrowserXhr {
build() {
return new XMLHttpRequest();
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: BrowserXhr, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: BrowserXhr });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: BrowserXhr, decorators: [{
type: Injectable
}] });
/**
* Defines supported modifiers for key events.
*/
const MODIFIER_KEYS = ['alt', 'control', 'meta', 'shift'];
// The following values are here for cross-browser compatibility and to match the W3C standard
// cf https://www.w3.org/TR/DOM-Level-3-Events-key/
const _keyMap = {
'\b': 'Backspace',
'\t': 'Tab',
'\x7F': 'Delete',
'\x1B': 'Escape',
'Del': 'Delete',
'Esc': 'Escape',
'Left': 'ArrowLeft',
'Right': 'ArrowRight',
'Up': 'ArrowUp',
'Down': 'ArrowDown',
'Menu': 'ContextMenu',
'Scroll': 'ScrollLock',
'Win': 'OS',
};
/**
* Retrieves modifiers from key-event objects.
*/
const MODIFIER_KEY_GETTERS = {
'alt': (event) => event.altKey,
'control': (event) => event.ctrlKey,
'meta': (event) => event.metaKey,
'shift': (event) => event.shiftKey,
};
/**
* A browser plug-in that provides support for handling of key events in Angular.
*/
class KeyEventsPlugin extends EventManagerPlugin {
/**
* Initializes an instance of the browser plug-in.
* @param doc The document in which key events will be detected.
*/
constructor(doc) {
super(doc);
}
/**
* Reports whether a named key event is supported.
* @param eventName The event name to query.
* @return True if the named key event is supported.
*/
supports(eventName) {
return KeyEventsPlugin.parseEventName(eventName) != null;
}
/**
* Registers a handler for a specific element and key event.
* @param element The HTML element to receive event notifications.
* @param eventName The name of the key event to listen for.
* @param handler A function to call when the notification occurs. Receives the
* event object as an argument.
* @returns The key event that was registered.
*/
addEventListener(element, eventName, handler, options) {
const parsedEvent = KeyEventsPlugin.parseEventName(eventName);
const outsideHandler = KeyEventsPlugin.eventCallback(parsedEvent['fullKey'], handler, this.manager.getZone());
return this.manager.getZone().runOutsideAngular(() => {
return _getDOM().onAndCancel(element, parsedEvent['domEventName'], outsideHandler, options);
});
}
/**
* Parses the user provided full keyboard event definition and normalizes it for
* later internal use. It ensures the string is all lowercase, converts special
* characters to a standard spelling, and orders all the values consistently.
*
* @param eventName The name of the key event to listen for.
* @returns an object with the full, normalized string, and the dom event name
* or null in the case when the event doesn't match a keyboard event.
*/
static parseEventName(eventName) {
const parts = eventName.toLowerCase().split('.');
const domEventName = parts.shift();
if (parts.length === 0 || !(domEventName === 'keydown' || domEventName === 'keyup')) {
return null;
}
const key = KeyEventsPlugin._normalizeKey(parts.pop());
let fullKey = '';
let codeIX = parts.indexOf('code');
if (codeIX > -1) {
parts.splice(codeIX, 1);
fullKey = 'code.';
}
MODIFIER_KEYS.forEach((modifierName) => {
const index = parts.indexOf(modifierName);
if (index > -1) {
parts.splice(index, 1);
fullKey += modifierName + '.';
}
});
fullKey += key;
if (parts.length != 0 || key.length === 0) {
// returning null instead of throwing to let another plugin process the event
return null;
}
// NOTE: Please don't rewrite this as so, as it will break JSCompiler property renaming.
// The code must remain in the `result['domEventName']` form.
// return {domEventName, fullKey};
const result = {};
result['domEventName'] = domEventName;
result['fullKey'] = fullKey;
return result;
}
/**
* Determines whether the actual keys pressed match the configured key code string.
* The `fullKeyCode` event is normalized in the `parseEventName` method when the
* event is attached to the DOM during the `addEventListener` call. This is unseen
* by the end user and is normalized for internal consistency and parsing.
*
* @param event The keyboard event.
* @param fullKeyCode The normalized user defined expected key event string
* @returns boolean.
*/
static matchEventFullKeyCode(event, fullKeyCode) {
let keycode = _keyMap[event.key] || event.key;
let key = '';
if (fullKeyCode.indexOf('code.') > -1) {
keycode = event.code;
key = 'code.';
}
// the keycode could be unidentified so we have to check here
if (keycode == null || !keycode)
return false;
keycode = keycode.toLowerCase();
if (keycode === ' ') {
keycode = 'space'; // for readability
}
else if (keycode === '.') {
keycode = 'dot'; // because '.' is used as a separator in event names
}
MODIFIER_KEYS.forEach((modifierName) => {
if (modifierName !== keycode) {
const modifierGetter = MODIFIER_KEY_GETTERS[modifierName];
if (modifierGetter(event)) {
key += modifierName + '.';
}
}
});
key += keycode;
return key === fullKeyCode;
}
/**
* Configures a handler callback for a key event.
* @param fullKey The event name that combines all simultaneous keystrokes.
* @param handler The function that responds to the key event.
* @param zone The zone in which the event occurred.
* @returns A callback function.
*/
static eventCallback(fullKey, handler, zone) {
return (event) => {
if (KeyEventsPlugin.matchEventFullKeyCode(event, fullKey)) {
zone.runGuarded(() => handler(event));
}
};
}
/** @internal */
static _normalizeKey(keyName) {
return keyName === 'esc' ? 'escape' : keyName;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: KeyEventsPlugin, deps: [{ token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: KeyEventsPlugin });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: KeyEventsPlugin, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }] });
/**
* Bootstraps an instance of an Angular application and renders a standalone component as the
* application's root component. More information about standalone components can be found in [this
* guide](guide/components/importing).
*
* @usageNotes
* The root component passed into this function *must* be a standalone one (should have the
* `standalone: true` flag in the `@Component` decorator config).
*
* ```angular-ts
* @Component({
* standalone: true,
* template: 'Hello world!'
* })
* class RootComponent {}
*
* const appRef: ApplicationRef = await bootstrapApplication(RootComponent);
* ```
*
* You can add the list of providers that should be available in the application injector by
* specifying the `providers` field in an object passed as the second argument:
*
* ```ts
* await bootstrapApplication(RootComponent, {
* providers: [
* {provide: BACKEND_URL, useValue: 'https://yourdomain.com/api'}
* ]
* });
* ```
*
* The `importProvidersFrom` helper method can be used to collect all providers from any
* existing NgModule (and transitively from all NgModules that it imports):
*
* ```ts
* await bootstrapApplication(RootComponent, {
* providers: [
* importProvidersFrom(SomeNgModule)
* ]
* });
* ```
*
* Note: the `bootstrapApplication` method doesn't include [Testability](api/core/Testability) by
* default. You can add [Testability](api/core/Testability) by getting the list of necessary
* providers using `provideProtractorTestingSupport()` function and adding them into the `providers`
* array, for example:
*
* ```ts
* import {provideProtractorTestingSupport} from '@angular/platform-browser';
*
* await bootstrapApplication(RootComponent, {providers: [provideProtractorTestingSupport()]});
* ```
*
* @param rootComponent A reference to a standalone component that should be rendered.
* @param options Extra configuration for the bootstrap operation, see `ApplicationConfig` for
* additional info.
* @param context Optional context object that can be used to provide a pre-existing
* platform injector. This is useful for advanced use-cases, for example, server-side
* rendering, where the platform is created for each request.
* @returns A promise that returns an `ApplicationRef` instance once resolved.
*
* @publicApi
*/
function bootstrapApplication(rootComponent, options, context) {
const config = {
rootComponent,
platformRef: context?.platformRef,
...createProvidersConfig(options),
};
// Attempt to resolve component resources before bootstrapping in JIT mode,
// however don't interrupt the bootstrapping process.
if ((typeof ngJitMode === 'undefined' || ngJitMode) && typeof fetch === 'function') {
return _resolveComponentResources(fetch)
.catch((error) => {
console.error(error);
return Promise.resolve();
})
.then(() => _internalCreateApplication(config));
}
return _internalCreateApplication(config);
}
/**
* Create an instance of an Angular application without bootstrapping any components. This is useful
* for the situation where one wants to decouple application environment creation (a platform and
* associated injectors) from rendering components on a screen. Components can be subsequently
* bootstrapped on the returned `ApplicationRef`.
*
* @param options Extra configuration for the application environment, see `ApplicationConfig` for
* additional info.
* @returns A promise that returns an `ApplicationRef` instance once resolved.
*
* @publicApi
*/
function createApplication(options) {
return _internalCreateApplication(createProvidersConfig(options));
}
function createProvidersConfig(options) {
return {
appProviders: [...BROWSER_MODULE_PROVIDERS, ...(options?.providers ?? [])],
platformProviders: INTERNAL_BROWSER_PLATFORM_PROVIDERS,
};
}
/**
* Returns a set of providers required to setup [Testability](api/core/Testability) for an
* application bootstrapped using the `bootstrapApplication` function. The set of providers is
* needed to support testing an application with Protractor (which relies on the Testability APIs
* to be present).
*
* @returns An array of providers required to setup Testability for an application and make it
* available for testing using Protractor.
*
* @publicApi
*/
function provideProtractorTestingSupport() {
// Return a copy to prevent changes to the original array in case any in-place
// alterations are performed to the `provideProtractorTestingSupport` call results in app
// code.
return [...TESTABILITY_PROVIDERS];
}
function initDomAdapter() {
BrowserDomAdapter.makeCurrent();
}
function errorHandler() {
return new ErrorHandler();
}
function _document() {
// Tell ivy about the global document
_setDocument(document);
return document;
}
const INTERNAL_BROWSER_PLATFORM_PROVIDERS = [
{ provide: PLATFORM_ID, useValue: _PLATFORM_BROWSER_ID },
{ provide: PLATFORM_INITIALIZER, useValue: initDomAdapter, multi: true },
{ provide: DOCUMENT, useFactory: _document },
];
/**
* A factory function that returns a `PlatformRef` instance associated with browser service
* providers.
*
* @publicApi
*/
const platformBrowser = createPlatformFactory(platformCore, 'browser', INTERNAL_BROWSER_PLATFORM_PROVIDERS);
/**
* Internal marker to signal whether providers from the `BrowserModule` are already present in DI.
* This is needed to avoid loading `BrowserModule` providers twice. We can't rely on the
* `BrowserModule` presence itself, since the standalone-based bootstrap just imports
* `BrowserModule` providers without referencing the module itself.
*/
const BROWSER_MODULE_PROVIDERS_MARKER = new InjectionToken(typeof ngDevMode === 'undefined' || ngDevMode ? 'BrowserModule Providers Marker' : '');
const TESTABILITY_PROVIDERS = [
{
provide: _TESTABILITY_GETTER,
useClass: BrowserGetTestability,
},
{
provide: _TESTABILITY,
useClass: Testability,
deps: [NgZone, TestabilityRegistry, _TESTABILITY_GETTER],
},
{
provide: Testability, // Also provide as `Testability` for backwards-compatibility.
useClass: Testability,
deps: [NgZone, TestabilityRegistry, _TESTABILITY_GETTER],
},
];
const BROWSER_MODULE_PROVIDERS = [
{ provide: _INJECTOR_SCOPE, useValue: 'root' },
{ provide: ErrorHandler, useFactory: errorHandler },
{
provide: EVENT_MANAGER_PLUGINS,
useClass: DomEventsPlugin,
multi: true,
deps: [DOCUMENT],
},
{ provide: EVENT_MANAGER_PLUGINS, useClass: KeyEventsPlugin, multi: true, deps: [DOCUMENT] },
DomRendererFactory2,
SharedStylesHost,
EventManager,
{ provide: RendererFactory2, useExisting: DomRendererFactory2 },
{ provide: XhrFactory, useClass: BrowserXhr },
typeof ngDevMode === 'undefined' || ngDevMode
? { provide: BROWSER_MODULE_PROVIDERS_MARKER, useValue: true }
: [],
];
/**
* Exports required infrastructure for all Angular apps.
* Included by default in all Angular apps created with the CLI
* `new` command.
* Re-exports `CommonModule` and `ApplicationModule`, making their
* exports and providers available to all apps.
*
* @publicApi
*/
class BrowserModule {
constructor() {
if (typeof ngDevMode === 'undefined' || ngDevMode) {
const providersAlreadyPresent = inject(BROWSER_MODULE_PROVIDERS_MARKER, {
optional: true,
skipSelf: true,
});
if (providersAlreadyPresent) {
throw new _RuntimeError(5100 /* RuntimeErrorCode.BROWSER_MODULE_ALREADY_LOADED */, `Providers from the \`BrowserModule\` have already been loaded. If you need access ` +
`to common directives such as NgIf and NgFor, import the \`CommonModule\` instead.`);
}
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: BrowserModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.11", ngImport: i0, type: BrowserModule, exports: [CommonModule, ApplicationModule] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: BrowserModule, providers: [...BROWSER_MODULE_PROVIDERS, ...TESTABILITY_PROVIDERS], imports: [CommonModule, ApplicationModule] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: BrowserModule, decorators: [{
type: NgModule,
args: [{
providers: [...BROWSER_MODULE_PROVIDERS, ...TESTABILITY_PROVIDERS],
exports: [CommonModule, ApplicationModule],
}]
}], ctorParameters: () => [] });
export { BrowserDomAdapter, BrowserGetTestability, BrowserModule, KeyEventsPlugin, bootstrapApplication, createApplication, platformBrowser, provideProtractorTestingSupport };
//# sourceMappingURL=browser.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,818 @@
/**
* @license Angular v20.3.11
* (c) 2010-2025 Google LLC. https://angular.dev/
* License: MIT
*/
import { DOCUMENT, ɵgetDOM as _getDOM } from '@angular/common';
import * as i0 from '@angular/core';
import { Injectable, Inject, InjectionToken, ɵRuntimeError as _RuntimeError, APP_ID, CSP_NONCE, PLATFORM_ID, Optional, ViewEncapsulation, ɵTracingService as _TracingService, RendererStyleFlags2, ɵallLeavingAnimations as _allLeavingAnimations } from '@angular/core';
/**
* The plugin definition for the `EventManager` class
*
* It can be used as a base class to create custom manager plugins, i.e. you can create your own
* class that extends the `EventManagerPlugin` one.
*
* @see [Extend event handling](guide/templates/event-listeners#extend-event-handling)
*
* @publicApi
*/
class EventManagerPlugin {
_doc;
// TODO: remove (has some usage in G3)
constructor(_doc) {
this._doc = _doc;
}
// Using non-null assertion because it's set by EventManager's constructor
manager;
}
class DomEventsPlugin extends EventManagerPlugin {
constructor(doc) {
super(doc);
}
// This plugin should come last in the list of plugins, because it accepts all
// events.
supports(eventName) {
return true;
}
addEventListener(element, eventName, handler, options) {
element.addEventListener(eventName, handler, options);
return () => this.removeEventListener(element, eventName, handler, options);
}
removeEventListener(target, eventName, callback, options) {
return target.removeEventListener(eventName, callback, options);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: DomEventsPlugin, deps: [{ token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: DomEventsPlugin });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: DomEventsPlugin, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }] });
/**
* The injection token for plugins of the `EventManager` service.
*
* @see [Extend event handling](guide/templates/event-listeners#extend-event-handling)
*
* @publicApi
*/
const EVENT_MANAGER_PLUGINS = new InjectionToken(ngDevMode ? 'EventManagerPlugins' : '');
/**
* An injectable service that provides event management for Angular
* through a browser plug-in.
*
* @publicApi
*/
class EventManager {
_zone;
_plugins;
_eventNameToPlugin = new Map();
/**
* Initializes an instance of the event-manager service.
*/
constructor(plugins, _zone) {
this._zone = _zone;
plugins.forEach((plugin) => {
plugin.manager = this;
});
const otherPlugins = plugins.filter((p) => !(p instanceof DomEventsPlugin));
this._plugins = otherPlugins.slice().reverse();
// DomEventsPlugin.supports() always returns true, it should always be the last plugin.
const domEventPlugin = plugins.find((p) => p instanceof DomEventsPlugin);
if (domEventPlugin) {
this._plugins.push(domEventPlugin);
}
}
/**
* Registers a handler for a specific element and event.
*
* @param element The HTML element to receive event notifications.
* @param eventName The name of the event to listen for.
* @param handler A function to call when the notification occurs. Receives the
* event object as an argument.
* @param options Options that configure how the event listener is bound.
* @returns A callback function that can be used to remove the handler.
*/
addEventListener(element, eventName, handler, options) {
const plugin = this._findPluginFor(eventName);
return plugin.addEventListener(element, eventName, handler, options);
}
/**
* Retrieves the compilation zone in which event listeners are registered.
*/
getZone() {
return this._zone;
}
/** @internal */
_findPluginFor(eventName) {
let plugin = this._eventNameToPlugin.get(eventName);
if (plugin) {
return plugin;
}
const plugins = this._plugins;
plugin = plugins.find((plugin) => plugin.supports(eventName));
if (!plugin) {
throw new _RuntimeError(5101 /* RuntimeErrorCode.NO_PLUGIN_FOR_EVENT */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
`No event manager plugin found for event ${eventName}`);
}
this._eventNameToPlugin.set(eventName, plugin);
return plugin;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: EventManager, deps: [{ token: EVENT_MANAGER_PLUGINS }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: EventManager });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: EventManager, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Inject,
args: [EVENT_MANAGER_PLUGINS]
}] }, { type: i0.NgZone }] });
/** The style elements attribute name used to set value of `APP_ID` token. */
const APP_ID_ATTRIBUTE_NAME = 'ng-app-id';
/**
* Removes all provided elements from the document.
* @param elements An array of HTML Elements.
*/
function removeElements(elements) {
for (const element of elements) {
element.remove();
}
}
/**
* Creates a `style` element with the provided inline style content.
* @param style A string of the inline style content.
* @param doc A DOM Document to use to create the element.
* @returns An HTMLStyleElement instance.
*/
function createStyleElement(style, doc) {
const styleElement = doc.createElement('style');
styleElement.textContent = style;
return styleElement;
}
/**
* Searches a DOM document's head element for style elements with a matching application
* identifier attribute (`ng-app-id`) to the provide identifier and adds usage records for each.
* @param doc An HTML DOM document instance.
* @param appId A string containing an Angular application identifer.
* @param inline A Map object for tracking inline (defined via `styles` in component decorator) style usage.
* @param external A Map object for tracking external (defined via `styleUrls` in component decorator) style usage.
*/
function addServerStyles(doc, appId, inline, external) {
const elements = doc.head?.querySelectorAll(`style[${APP_ID_ATTRIBUTE_NAME}="${appId}"],link[${APP_ID_ATTRIBUTE_NAME}="${appId}"]`);
if (elements) {
for (const styleElement of elements) {
styleElement.removeAttribute(APP_ID_ATTRIBUTE_NAME);
if (styleElement instanceof HTMLLinkElement) {
// Only use filename from href
// The href is build time generated with a unique value to prevent duplicates.
external.set(styleElement.href.slice(styleElement.href.lastIndexOf('/') + 1), {
usage: 0,
elements: [styleElement],
});
}
else if (styleElement.textContent) {
inline.set(styleElement.textContent, { usage: 0, elements: [styleElement] });
}
}
}
}
/**
* Creates a `link` element for the provided external style URL.
* @param url A string of the URL for the stylesheet.
* @param doc A DOM Document to use to create the element.
* @returns An HTMLLinkElement instance.
*/
function createLinkElement(url, doc) {
const linkElement = doc.createElement('link');
linkElement.setAttribute('rel', 'stylesheet');
linkElement.setAttribute('href', url);
return linkElement;
}
class SharedStylesHost {
doc;
appId;
nonce;
/**
* Provides usage information for active inline style content and associated HTML <style> elements.
* Embedded styles typically originate from the `styles` metadata of a rendered component.
*/
inline = new Map();
/**
* Provides usage information for active external style URLs and the associated HTML <link> elements.
* External styles typically originate from the `ɵɵExternalStylesFeature` of a rendered component.
*/
external = new Map();
/**
* Set of host DOM nodes that will have styles attached.
*/
hosts = new Set();
constructor(doc, appId, nonce,
// Cannot remove it due to backward compatibility
// (it seems some TGP targets might be calling this constructor directly).
platformId = {}) {
this.doc = doc;
this.appId = appId;
this.nonce = nonce;
addServerStyles(doc, appId, this.inline, this.external);
this.hosts.add(doc.head);
}
/**
* Adds embedded styles to the DOM via HTML `style` elements.
* @param styles An array of style content strings.
*/
addStyles(styles, urls) {
for (const value of styles) {
this.addUsage(value, this.inline, createStyleElement);
}
urls?.forEach((value) => this.addUsage(value, this.external, createLinkElement));
}
/**
* Removes embedded styles from the DOM that were added as HTML `style` elements.
* @param styles An array of style content strings.
*/
removeStyles(styles, urls) {
for (const value of styles) {
this.removeUsage(value, this.inline);
}
urls?.forEach((value) => this.removeUsage(value, this.external));
}
addUsage(value, usages, creator) {
// Attempt to get any current usage of the value
const record = usages.get(value);
// If existing, just increment the usage count
if (record) {
if ((typeof ngDevMode === 'undefined' || ngDevMode) && record.usage === 0) {
// A usage count of zero indicates a preexisting server generated style.
// This attribute is solely used for debugging purposes of SSR style reuse.
record.elements.forEach((element) => element.setAttribute('ng-style-reused', ''));
}
record.usage++;
}
else {
// Otherwise, create an entry to track the elements and add element for each host
usages.set(value, {
usage: 1,
elements: [...this.hosts].map((host) => this.addElement(host, creator(value, this.doc))),
});
}
}
removeUsage(value, usages) {
// Attempt to get any current usage of the value
const record = usages.get(value);
// If there is a record, reduce the usage count and if no longer used,
// remove from DOM and delete usage record.
if (record) {
record.usage--;
if (record.usage <= 0) {
removeElements(record.elements);
usages.delete(value);
}
}
}
ngOnDestroy() {
for (const [, { elements }] of [...this.inline, ...this.external]) {
removeElements(elements);
}
this.hosts.clear();
}
/**
* Adds a host node to the set of style hosts and adds all existing style usage to
* the newly added host node.
*
* This is currently only used for Shadow DOM encapsulation mode.
*/
addHost(hostNode) {
this.hosts.add(hostNode);
// Add existing styles to new host
for (const [style, { elements }] of this.inline) {
elements.push(this.addElement(hostNode, createStyleElement(style, this.doc)));
}
for (const [url, { elements }] of this.external) {
elements.push(this.addElement(hostNode, createLinkElement(url, this.doc)));
}
}
removeHost(hostNode) {
this.hosts.delete(hostNode);
}
addElement(host, element) {
// Add a nonce if present
if (this.nonce) {
element.setAttribute('nonce', this.nonce);
}
// Add application identifier when on the server to support client-side reuse
if (typeof ngServerMode !== 'undefined' && ngServerMode) {
element.setAttribute(APP_ID_ATTRIBUTE_NAME, this.appId);
}
// Insert the element into the DOM with the host node as parent
return host.appendChild(element);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: SharedStylesHost, deps: [{ token: DOCUMENT }, { token: APP_ID }, { token: CSP_NONCE, optional: true }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: SharedStylesHost });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: SharedStylesHost, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: Document, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [APP_ID]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [CSP_NONCE]
}, {
type: Optional
}] }, { type: undefined, decorators: [{
type: Inject,
args: [PLATFORM_ID]
}] }] });
const NAMESPACE_URIS = {
'svg': 'http://www.w3.org/2000/svg',
'xhtml': 'http://www.w3.org/1999/xhtml',
'xlink': 'http://www.w3.org/1999/xlink',
'xml': 'http://www.w3.org/XML/1998/namespace',
'xmlns': 'http://www.w3.org/2000/xmlns/',
'math': 'http://www.w3.org/1998/Math/MathML',
};
const COMPONENT_REGEX = /%COMP%/g;
const SOURCEMAP_URL_REGEXP = /\/\*#\s*sourceMappingURL=(.+?)\s*\*\//;
const PROTOCOL_REGEXP = /^https?:/;
const COMPONENT_VARIABLE = '%COMP%';
const HOST_ATTR = `_nghost-${COMPONENT_VARIABLE}`;
const CONTENT_ATTR = `_ngcontent-${COMPONENT_VARIABLE}`;
/**
* The default value for the `REMOVE_STYLES_ON_COMPONENT_DESTROY` DI token.
*/
const REMOVE_STYLES_ON_COMPONENT_DESTROY_DEFAULT = true;
/**
* A DI token that indicates whether styles
* of destroyed components should be removed from DOM.
*
* By default, the value is set to `true`.
* @publicApi
*/
const REMOVE_STYLES_ON_COMPONENT_DESTROY = new InjectionToken(ngDevMode ? 'RemoveStylesOnCompDestroy' : '', {
providedIn: 'root',
factory: () => REMOVE_STYLES_ON_COMPONENT_DESTROY_DEFAULT,
});
function shimContentAttribute(componentShortId) {
return CONTENT_ATTR.replace(COMPONENT_REGEX, componentShortId);
}
function shimHostAttribute(componentShortId) {
return HOST_ATTR.replace(COMPONENT_REGEX, componentShortId);
}
function shimStylesContent(compId, styles) {
return styles.map((s) => s.replace(COMPONENT_REGEX, compId));
}
/**
* Prepends a baseHref to the `sourceMappingURL` within the provided CSS content.
* If the `sourceMappingURL` contains an inline (encoded) map, the function skips processing.
*
* @note For inline stylesheets, the `sourceMappingURL` is relative to the page's origin
* and not the provided baseHref. This function is needed as when accessing the page with a URL
* containing two or more segments.
* For example, if the baseHref is set to `/`, and you visit a URL like `http://localhost/foo/bar`,
* the map would be requested from `http://localhost/foo/bar/comp.css.map` instead of what you'd expect,
* which is `http://localhost/comp.css.map`. This behavior is corrected by modifying the `sourceMappingURL`
* to ensure external source maps are loaded relative to the baseHref.
*
* @param baseHref - The base URL to prepend to the `sourceMappingURL`.
* @param styles - An array of CSS content strings, each potentially containing a `sourceMappingURL`.
* @returns The updated array of CSS content strings with modified `sourceMappingURL` values,
* or the original content if no modification is needed.
*/
function addBaseHrefToCssSourceMap(baseHref, styles) {
if (!baseHref) {
return styles;
}
const absoluteBaseHrefUrl = new URL(baseHref, 'http://localhost');
return styles.map((cssContent) => {
if (!cssContent.includes('sourceMappingURL=')) {
return cssContent;
}
return cssContent.replace(SOURCEMAP_URL_REGEXP, (_, sourceMapUrl) => {
if (sourceMapUrl[0] === '/' ||
sourceMapUrl.startsWith('data:') ||
PROTOCOL_REGEXP.test(sourceMapUrl)) {
return `/*# sourceMappingURL=${sourceMapUrl} */`;
}
const { pathname: resolvedSourceMapUrl } = new URL(sourceMapUrl, absoluteBaseHrefUrl);
return `/*# sourceMappingURL=${resolvedSourceMapUrl} */`;
});
});
}
class DomRendererFactory2 {
eventManager;
sharedStylesHost;
appId;
removeStylesOnCompDestroy;
doc;
ngZone;
nonce;
tracingService;
rendererByCompId = new Map();
defaultRenderer;
platformIsServer;
constructor(eventManager, sharedStylesHost, appId, removeStylesOnCompDestroy, doc, ngZone, nonce = null, tracingService = null) {
this.eventManager = eventManager;
this.sharedStylesHost = sharedStylesHost;
this.appId = appId;
this.removeStylesOnCompDestroy = removeStylesOnCompDestroy;
this.doc = doc;
this.ngZone = ngZone;
this.nonce = nonce;
this.tracingService = tracingService;
this.platformIsServer = typeof ngServerMode !== 'undefined' && ngServerMode;
this.defaultRenderer = new DefaultDomRenderer2(eventManager, doc, ngZone, this.platformIsServer, this.tracingService);
}
createRenderer(element, type) {
if (!element || !type) {
return this.defaultRenderer;
}
if (typeof ngServerMode !== 'undefined' &&
ngServerMode &&
type.encapsulation === ViewEncapsulation.ShadowDom) {
// Domino does not support shadow DOM.
type = { ...type, encapsulation: ViewEncapsulation.Emulated };
}
const renderer = this.getOrCreateRenderer(element, type);
// Renderers have different logic due to different encapsulation behaviours.
// Ex: for emulated, an attribute is added to the element.
if (renderer instanceof EmulatedEncapsulationDomRenderer2) {
renderer.applyToHost(element);
}
else if (renderer instanceof NoneEncapsulationDomRenderer) {
renderer.applyStyles();
}
return renderer;
}
getOrCreateRenderer(element, type) {
const rendererByCompId = this.rendererByCompId;
let renderer = rendererByCompId.get(type.id);
if (!renderer) {
const doc = this.doc;
const ngZone = this.ngZone;
const eventManager = this.eventManager;
const sharedStylesHost = this.sharedStylesHost;
const removeStylesOnCompDestroy = this.removeStylesOnCompDestroy;
const platformIsServer = this.platformIsServer;
const tracingService = this.tracingService;
switch (type.encapsulation) {
case ViewEncapsulation.Emulated:
renderer = new EmulatedEncapsulationDomRenderer2(eventManager, sharedStylesHost, type, this.appId, removeStylesOnCompDestroy, doc, ngZone, platformIsServer, tracingService);
break;
case ViewEncapsulation.ShadowDom:
return new ShadowDomRenderer(eventManager, sharedStylesHost, element, type, doc, ngZone, this.nonce, platformIsServer, tracingService);
default:
renderer = new NoneEncapsulationDomRenderer(eventManager, sharedStylesHost, type, removeStylesOnCompDestroy, doc, ngZone, platformIsServer, tracingService);
break;
}
rendererByCompId.set(type.id, renderer);
}
return renderer;
}
ngOnDestroy() {
this.rendererByCompId.clear();
}
/**
* Used during HMR to clear any cached data about a component.
* @param componentId ID of the component that is being replaced.
*/
componentReplaced(componentId) {
this.rendererByCompId.delete(componentId);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: DomRendererFactory2, deps: [{ token: EventManager }, { token: SharedStylesHost }, { token: APP_ID }, { token: REMOVE_STYLES_ON_COMPONENT_DESTROY }, { token: DOCUMENT }, { token: i0.NgZone }, { token: CSP_NONCE }, { token: _TracingService, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: DomRendererFactory2 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: DomRendererFactory2, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: EventManager }, { type: SharedStylesHost }, { type: undefined, decorators: [{
type: Inject,
args: [APP_ID]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [REMOVE_STYLES_ON_COMPONENT_DESTROY]
}] }, { type: Document, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }, { type: i0.NgZone }, { type: undefined, decorators: [{
type: Inject,
args: [CSP_NONCE]
}] }, { type: i0.ɵTracingService, decorators: [{
type: Inject,
args: [_TracingService]
}, {
type: Optional
}] }] });
class DefaultDomRenderer2 {
eventManager;
doc;
ngZone;
platformIsServer;
tracingService;
data = Object.create(null);
/**
* By default this renderer throws when encountering synthetic properties
* This can be disabled for example by the AsyncAnimationRendererFactory
*/
throwOnSyntheticProps = true;
constructor(eventManager, doc, ngZone, platformIsServer, tracingService) {
this.eventManager = eventManager;
this.doc = doc;
this.ngZone = ngZone;
this.platformIsServer = platformIsServer;
this.tracingService = tracingService;
}
destroy() { }
destroyNode = null;
createElement(name, namespace) {
if (namespace) {
// TODO: `|| namespace` was added in
// https://github.com/angular/angular/commit/2b9cc8503d48173492c29f5a271b61126104fbdb to
// support how Ivy passed around the namespace URI rather than short name at the time. It did
// not, however extend the support to other parts of the system (setAttribute, setAttribute,
// and the ServerRenderer). We should decide what exactly the semantics for dealing with
// namespaces should be and make it consistent.
// Related issues:
// https://github.com/angular/angular/issues/44028
// https://github.com/angular/angular/issues/44883
return this.doc.createElementNS(NAMESPACE_URIS[namespace] || namespace, name);
}
return this.doc.createElement(name);
}
createComment(value) {
return this.doc.createComment(value);
}
createText(value) {
return this.doc.createTextNode(value);
}
appendChild(parent, newChild) {
const targetParent = isTemplateNode(parent) ? parent.content : parent;
targetParent.appendChild(newChild);
}
insertBefore(parent, newChild, refChild) {
if (parent) {
const targetParent = isTemplateNode(parent) ? parent.content : parent;
targetParent.insertBefore(newChild, refChild);
}
}
removeChild(_parent, oldChild) {
// child was removed
oldChild.remove();
}
selectRootElement(selectorOrNode, preserveContent) {
let el = typeof selectorOrNode === 'string' ? this.doc.querySelector(selectorOrNode) : selectorOrNode;
if (!el) {
throw new _RuntimeError(-5104 /* RuntimeErrorCode.ROOT_NODE_NOT_FOUND */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
`The selector "${selectorOrNode}" did not match any elements`);
}
if (!preserveContent) {
el.textContent = '';
}
return el;
}
parentNode(node) {
return node.parentNode;
}
nextSibling(node) {
return node.nextSibling;
}
setAttribute(el, name, value, namespace) {
if (namespace) {
name = namespace + ':' + name;
const namespaceUri = NAMESPACE_URIS[namespace];
if (namespaceUri) {
el.setAttributeNS(namespaceUri, name, value);
}
else {
el.setAttribute(name, value);
}
}
else {
el.setAttribute(name, value);
}
}
removeAttribute(el, name, namespace) {
if (namespace) {
const namespaceUri = NAMESPACE_URIS[namespace];
if (namespaceUri) {
el.removeAttributeNS(namespaceUri, name);
}
else {
el.removeAttribute(`${namespace}:${name}`);
}
}
else {
el.removeAttribute(name);
}
}
addClass(el, name) {
el.classList.add(name);
}
removeClass(el, name) {
el.classList.remove(name);
}
setStyle(el, style, value, flags) {
if (flags & (RendererStyleFlags2.DashCase | RendererStyleFlags2.Important)) {
el.style.setProperty(style, value, flags & RendererStyleFlags2.Important ? 'important' : '');
}
else {
el.style[style] = value;
}
}
removeStyle(el, style, flags) {
if (flags & RendererStyleFlags2.DashCase) {
// removeProperty has no effect when used on camelCased properties.
el.style.removeProperty(style);
}
else {
el.style[style] = '';
}
}
setProperty(el, name, value) {
if (el == null) {
return;
}
(typeof ngDevMode === 'undefined' || ngDevMode) &&
this.throwOnSyntheticProps &&
checkNoSyntheticProp(name, 'property');
el[name] = value;
}
setValue(node, value) {
node.nodeValue = value;
}
listen(target, event, callback, options) {
(typeof ngDevMode === 'undefined' || ngDevMode) &&
this.throwOnSyntheticProps &&
checkNoSyntheticProp(event, 'listener');
if (typeof target === 'string') {
target = _getDOM().getGlobalEventTarget(this.doc, target);
if (!target) {
throw new _RuntimeError(5102 /* RuntimeErrorCode.UNSUPPORTED_EVENT_TARGET */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
`Unsupported event target ${target} for event ${event}`);
}
}
let wrappedCallback = this.decoratePreventDefault(callback);
if (this.tracingService?.wrapEventListener) {
wrappedCallback = this.tracingService.wrapEventListener(target, event, wrappedCallback);
}
return this.eventManager.addEventListener(target, event, wrappedCallback, options);
}
decoratePreventDefault(eventHandler) {
// `DebugNode.triggerEventHandler` needs to know if the listener was created with
// decoratePreventDefault or is a listener added outside the Angular context so it can handle
// the two differently. In the first case, the special '__ngUnwrap__' token is passed to the
// unwrap the listener (see below).
return (event) => {
// Ivy uses '__ngUnwrap__' as a special token that allows us to unwrap the function
// so that it can be invoked programmatically by `DebugNode.triggerEventHandler`. The
// debug_node can inspect the listener toString contents for the existence of this special
// token. Because the token is a string literal, it is ensured to not be modified by compiled
// code.
if (event === '__ngUnwrap__') {
return eventHandler;
}
// Run the event handler inside the ngZone because event handlers are not patched
// by Zone on the server. This is required only for tests.
const allowDefaultBehavior = typeof ngServerMode !== 'undefined' && ngServerMode
? this.ngZone.runGuarded(() => eventHandler(event))
: eventHandler(event);
if (allowDefaultBehavior === false) {
event.preventDefault();
}
return undefined;
};
}
}
const AT_CHARCODE = (() => '@'.charCodeAt(0))();
function checkNoSyntheticProp(name, nameKind) {
if (name.charCodeAt(0) === AT_CHARCODE) {
throw new _RuntimeError(5105 /* RuntimeErrorCode.UNEXPECTED_SYNTHETIC_PROPERTY */, `Unexpected synthetic ${nameKind} ${name} found. Please make sure that:
- Make sure \`provideAnimationsAsync()\`, \`provideAnimations()\` or \`provideNoopAnimations()\` call was added to a list of providers used to bootstrap an application.
- There is a corresponding animation configuration named \`${name}\` defined in the \`animations\` field of the \`@Component\` decorator (see https://angular.dev/api/core/Component#animations).`);
}
}
function isTemplateNode(node) {
return node.tagName === 'TEMPLATE' && node.content !== undefined;
}
class ShadowDomRenderer extends DefaultDomRenderer2 {
sharedStylesHost;
hostEl;
shadowRoot;
constructor(eventManager, sharedStylesHost, hostEl, component, doc, ngZone, nonce, platformIsServer, tracingService) {
super(eventManager, doc, ngZone, platformIsServer, tracingService);
this.sharedStylesHost = sharedStylesHost;
this.hostEl = hostEl;
this.shadowRoot = hostEl.attachShadow({ mode: 'open' });
this.sharedStylesHost.addHost(this.shadowRoot);
let styles = component.styles;
if (ngDevMode) {
// We only do this in development, as for production users should not add CSS sourcemaps to components.
const baseHref = _getDOM().getBaseHref(doc) ?? '';
styles = addBaseHrefToCssSourceMap(baseHref, styles);
}
styles = shimStylesContent(component.id, styles);
for (const style of styles) {
const styleEl = document.createElement('style');
if (nonce) {
styleEl.setAttribute('nonce', nonce);
}
styleEl.textContent = style;
this.shadowRoot.appendChild(styleEl);
}
// Apply any external component styles to the shadow root for the component's element.
// The ShadowDOM renderer uses an alternative execution path for component styles that
// does not use the SharedStylesHost that other encapsulation modes leverage. Much like
// the manual addition of embedded styles directly above, any external stylesheets
// must be manually added here to ensure ShadowDOM components are correctly styled.
// TODO: Consider reworking the DOM Renderers to consolidate style handling.
const styleUrls = component.getExternalStyles?.();
if (styleUrls) {
for (const styleUrl of styleUrls) {
const linkEl = createLinkElement(styleUrl, doc);
if (nonce) {
linkEl.setAttribute('nonce', nonce);
}
this.shadowRoot.appendChild(linkEl);
}
}
}
nodeOrShadowRoot(node) {
return node === this.hostEl ? this.shadowRoot : node;
}
appendChild(parent, newChild) {
return super.appendChild(this.nodeOrShadowRoot(parent), newChild);
}
insertBefore(parent, newChild, refChild) {
return super.insertBefore(this.nodeOrShadowRoot(parent), newChild, refChild);
}
removeChild(_parent, oldChild) {
return super.removeChild(null, oldChild);
}
parentNode(node) {
return this.nodeOrShadowRoot(super.parentNode(this.nodeOrShadowRoot(node)));
}
destroy() {
this.sharedStylesHost.removeHost(this.shadowRoot);
}
}
class NoneEncapsulationDomRenderer extends DefaultDomRenderer2 {
sharedStylesHost;
removeStylesOnCompDestroy;
styles;
styleUrls;
constructor(eventManager, sharedStylesHost, component, removeStylesOnCompDestroy, doc, ngZone, platformIsServer, tracingService, compId) {
super(eventManager, doc, ngZone, platformIsServer, tracingService);
this.sharedStylesHost = sharedStylesHost;
this.removeStylesOnCompDestroy = removeStylesOnCompDestroy;
let styles = component.styles;
if (ngDevMode) {
// We only do this in development, as for production users should not add CSS sourcemaps to components.
const baseHref = _getDOM().getBaseHref(doc) ?? '';
styles = addBaseHrefToCssSourceMap(baseHref, styles);
}
this.styles = compId ? shimStylesContent(compId, styles) : styles;
this.styleUrls = component.getExternalStyles?.(compId);
}
applyStyles() {
this.sharedStylesHost.addStyles(this.styles, this.styleUrls);
}
destroy() {
if (!this.removeStylesOnCompDestroy) {
return;
}
if (_allLeavingAnimations.size === 0) {
this.sharedStylesHost.removeStyles(this.styles, this.styleUrls);
}
}
}
class EmulatedEncapsulationDomRenderer2 extends NoneEncapsulationDomRenderer {
contentAttr;
hostAttr;
constructor(eventManager, sharedStylesHost, component, appId, removeStylesOnCompDestroy, doc, ngZone, platformIsServer, tracingService) {
const compId = appId + '-' + component.id;
super(eventManager, sharedStylesHost, component, removeStylesOnCompDestroy, doc, ngZone, platformIsServer, tracingService, compId);
this.contentAttr = shimContentAttribute(compId);
this.hostAttr = shimHostAttribute(compId);
}
applyToHost(element) {
this.applyStyles();
this.setAttribute(element, this.hostAttr, '');
}
createElement(parent, name) {
const el = super.createElement(parent, name);
super.setAttribute(el, this.contentAttr, '');
return el;
}
}
export { DomEventsPlugin, DomRendererFactory2, EVENT_MANAGER_PLUGINS, EventManager, EventManagerPlugin, REMOVE_STYLES_ON_COMPONENT_DESTROY, SharedStylesHost };
//# sourceMappingURL=dom_renderer.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,999 @@
/**
* @license Angular v20.3.11
* (c) 2010-2025 Google LLC. https://angular.dev/
* License: MIT
*/
export { BrowserModule, bootstrapApplication, createApplication, platformBrowser, provideProtractorTestingSupport, BrowserDomAdapter as ɵBrowserDomAdapter, BrowserGetTestability as ɵBrowserGetTestability, KeyEventsPlugin as ɵKeyEventsPlugin } from './browser.mjs';
import { ɵgetDOM as _getDOM, DOCUMENT } from '@angular/common';
export { ɵgetDOM } from '@angular/common';
import * as i0 from '@angular/core';
import { Injectable, Inject, ɵglobal as _global, ApplicationRef, InjectionToken, ɵConsole as _Console, Optional, Injector, NgModule, forwardRef, ɵRuntimeError as _RuntimeError, ɵXSS_SECURITY_URL as _XSS_SECURITY_URL, SecurityContext, ɵallowSanitizationBypassAndThrow as _allowSanitizationBypassAndThrow, ɵunwrapSafeValue as _unwrapSafeValue, ɵ_sanitizeUrl as __sanitizeUrl, ɵ_sanitizeHtml as __sanitizeHtml, ɵbypassSanitizationTrustHtml as _bypassSanitizationTrustHtml, ɵbypassSanitizationTrustStyle as _bypassSanitizationTrustStyle, ɵbypassSanitizationTrustScript as _bypassSanitizationTrustScript, ɵbypassSanitizationTrustUrl as _bypassSanitizationTrustUrl, ɵbypassSanitizationTrustResourceUrl as _bypassSanitizationTrustResourceUrl, ɵwithI18nSupport as _withI18nSupport, ɵwithEventReplay as _withEventReplay, ɵwithIncrementalHydration as _withIncrementalHydration, makeEnvironmentProviders, ɵwithDomHydration as _withDomHydration, ENVIRONMENT_INITIALIZER, inject, NgZone, ɵZONELESS_ENABLED as _ZONELESS_ENABLED, ɵformatRuntimeError as _formatRuntimeError, ɵIS_ENABLED_BLOCKING_INITIAL_NAVIGATION as _IS_ENABLED_BLOCKING_INITIAL_NAVIGATION, Version } from '@angular/core';
import { EventManagerPlugin, EVENT_MANAGER_PLUGINS } from './dom_renderer.mjs';
export { EventManager, REMOVE_STYLES_ON_COMPONENT_DESTROY, DomEventsPlugin as ɵDomEventsPlugin, DomRendererFactory2 as ɵDomRendererFactory2, SharedStylesHost as ɵSharedStylesHost } from './dom_renderer.mjs';
import { ɵwithHttpTransferCache as _withHttpTransferCache } from '@angular/common/http';
/**
* A service for managing HTML `<meta>` tags.
*
* Properties of the `MetaDefinition` object match the attributes of the
* HTML `<meta>` tag. These tags define document metadata that is important for
* things like configuring a Content Security Policy, defining browser compatibility
* and security settings, setting HTTP Headers, defining rich content for social sharing,
* and Search Engine Optimization (SEO).
*
* To identify specific `<meta>` tags in a document, use an attribute selection
* string in the format `"tag_attribute='value string'"`.
* For example, an `attrSelector` value of `"name='description'"` matches a tag
* whose `name` attribute has the value `"description"`.
* Selectors are used with the `querySelector()` Document method,
* in the format `meta[{attrSelector}]`.
*
* @see [HTML meta tag](https://developer.mozilla.org/docs/Web/HTML/Element/meta)
* @see [Document.querySelector()](https://developer.mozilla.org/docs/Web/API/Document/querySelector)
*
*
* @publicApi
*/
class Meta {
_doc;
_dom;
constructor(_doc) {
this._doc = _doc;
this._dom = _getDOM();
}
/**
* Retrieves or creates a specific `<meta>` tag element in the current HTML document.
* In searching for an existing tag, Angular attempts to match the `name` or `property` attribute
* values in the provided tag definition, and verifies that all other attribute values are equal.
* If an existing element is found, it is returned and is not modified in any way.
* @param tag The definition of a `<meta>` element to match or create.
* @param forceCreation True to create a new element without checking whether one already exists.
* @returns The existing element with the same attributes and values if found,
* the new element if no match is found, or `null` if the tag parameter is not defined.
*/
addTag(tag, forceCreation = false) {
if (!tag)
return null;
return this._getOrCreateElement(tag, forceCreation);
}
/**
* Retrieves or creates a set of `<meta>` tag elements in the current HTML document.
* In searching for an existing tag, Angular attempts to match the `name` or `property` attribute
* values in the provided tag definition, and verifies that all other attribute values are equal.
* @param tags An array of tag definitions to match or create.
* @param forceCreation True to create new elements without checking whether they already exist.
* @returns The matching elements if found, or the new elements.
*/
addTags(tags, forceCreation = false) {
if (!tags)
return [];
return tags.reduce((result, tag) => {
if (tag) {
result.push(this._getOrCreateElement(tag, forceCreation));
}
return result;
}, []);
}
/**
* Retrieves a `<meta>` tag element in the current HTML document.
* @param attrSelector The tag attribute and value to match against, in the format
* `"tag_attribute='value string'"`.
* @returns The matching element, if any.
*/
getTag(attrSelector) {
if (!attrSelector)
return null;
return this._doc.querySelector(`meta[${attrSelector}]`) || null;
}
/**
* Retrieves a set of `<meta>` tag elements in the current HTML document.
* @param attrSelector The tag attribute and value to match against, in the format
* `"tag_attribute='value string'"`.
* @returns The matching elements, if any.
*/
getTags(attrSelector) {
if (!attrSelector)
return [];
const list /*NodeList*/ = this._doc.querySelectorAll(`meta[${attrSelector}]`);
return list ? [].slice.call(list) : [];
}
/**
* Modifies an existing `<meta>` tag element in the current HTML document.
* @param tag The tag description with which to replace the existing tag content.
* @param selector A tag attribute and value to match against, to identify
* an existing tag. A string in the format `"tag_attribute=`value string`"`.
* If not supplied, matches a tag with the same `name` or `property` attribute value as the
* replacement tag.
* @return The modified element.
*/
updateTag(tag, selector) {
if (!tag)
return null;
selector = selector || this._parseSelector(tag);
const meta = this.getTag(selector);
if (meta) {
return this._setMetaElementAttributes(tag, meta);
}
return this._getOrCreateElement(tag, true);
}
/**
* Removes an existing `<meta>` tag element from the current HTML document.
* @param attrSelector A tag attribute and value to match against, to identify
* an existing tag. A string in the format `"tag_attribute=`value string`"`.
*/
removeTag(attrSelector) {
this.removeTagElement(this.getTag(attrSelector));
}
/**
* Removes an existing `<meta>` tag element from the current HTML document.
* @param meta The tag definition to match against to identify an existing tag.
*/
removeTagElement(meta) {
if (meta) {
this._dom.remove(meta);
}
}
_getOrCreateElement(meta, forceCreation = false) {
if (!forceCreation) {
const selector = this._parseSelector(meta);
// It's allowed to have multiple elements with the same name so it's not enough to
// just check that element with the same name already present on the page. We also need to
// check if element has tag attributes
const elem = this.getTags(selector).filter((elem) => this._containsAttributes(meta, elem))[0];
if (elem !== undefined)
return elem;
}
const element = this._dom.createElement('meta');
this._setMetaElementAttributes(meta, element);
const head = this._doc.getElementsByTagName('head')[0];
head.appendChild(element);
return element;
}
_setMetaElementAttributes(tag, el) {
Object.keys(tag).forEach((prop) => el.setAttribute(this._getMetaKeyMap(prop), tag[prop]));
return el;
}
_parseSelector(tag) {
const attr = tag.name ? 'name' : 'property';
return `${attr}="${tag[attr]}"`;
}
_containsAttributes(tag, elem) {
return Object.keys(tag).every((key) => elem.getAttribute(this._getMetaKeyMap(key)) === tag[key]);
}
_getMetaKeyMap(prop) {
return META_KEYS_MAP[prop] || prop;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: Meta, deps: [{ token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: Meta, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: Meta, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }] });
/**
* Mapping for MetaDefinition properties with their correct meta attribute names
*/
const META_KEYS_MAP = {
httpEquiv: 'http-equiv',
};
/**
* A service that can be used to get and set the title of a current HTML document.
*
* Since an Angular application can't be bootstrapped on the entire HTML document (`<html>` tag)
* it is not possible to bind to the `text` property of the `HTMLTitleElement` elements
* (representing the `<title>` tag). Instead, this service can be used to set and get the current
* title value.
*
* @publicApi
*/
class Title {
_doc;
constructor(_doc) {
this._doc = _doc;
}
/**
* Get the title of the current HTML document.
*/
getTitle() {
return this._doc.title;
}
/**
* Set the title of the current HTML document.
* @param newTitle
*/
setTitle(newTitle) {
this._doc.title = newTitle || '';
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: Title, deps: [{ token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: Title, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: Title, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }] });
/// <reference path="../../../goog.d.ts" />
/**
* Exports the value under a given `name` in the global property `ng`. For example `ng.probe` if
* `name` is `'probe'`.
* @param name Name under which it will be exported. Keep in mind this will be a property of the
* global `ng` object.
* @param value The value to export.
*/
function exportNgVar(name, value) {
if (typeof COMPILED === 'undefined' || !COMPILED) {
// Note: we can't export `ng` when using closure enhanced optimization as:
// - closure declares globals itself for minified names, which sometimes clobber our `ng` global
// - we can't declare a closure extern as the namespace `ng` is already used within Google
// for typings for angularJS (via `goog.provide('ng....')`).
const ng = (_global['ng'] = _global['ng'] || {});
ng[name] = value;
}
}
class ChangeDetectionPerfRecord {
msPerTick;
numTicks;
constructor(msPerTick, numTicks) {
this.msPerTick = msPerTick;
this.numTicks = numTicks;
}
}
/**
* Entry point for all Angular profiling-related debug tools. This object
* corresponds to the `ng.profiler` in the dev console.
*/
class AngularProfiler {
appRef;
constructor(ref) {
this.appRef = ref.injector.get(ApplicationRef);
}
// tslint:disable:no-console
/**
* Exercises change detection in a loop and then prints the average amount of
* time in milliseconds how long a single round of change detection takes for
* the current state of the UI. It runs a minimum of 5 rounds for a minimum
* of 500 milliseconds.
*
* Optionally, a user may pass a `config` parameter containing a map of
* options. Supported options are:
*
* `record` (boolean) - causes the profiler to record a CPU profile while
* it exercises the change detector. Example:
*
* ```ts
* ng.profiler.timeChangeDetection({record: true})
* ```
*/
timeChangeDetection(config) {
const record = config && config['record'];
const profileName = 'Change Detection';
// Profiler is not available in Android browsers without dev tools opened
if (record && 'profile' in console && typeof console.profile === 'function') {
console.profile(profileName);
}
const start = performance.now();
let numTicks = 0;
while (numTicks < 5 || performance.now() - start < 500) {
this.appRef.tick();
numTicks++;
}
const end = performance.now();
if (record && 'profileEnd' in console && typeof console.profileEnd === 'function') {
console.profileEnd(profileName);
}
const msPerTick = (end - start) / numTicks;
console.log(`ran ${numTicks} change detection cycles`);
console.log(`${msPerTick.toFixed(2)} ms per check`);
return new ChangeDetectionPerfRecord(msPerTick, numTicks);
}
}
const PROFILER_GLOBAL_NAME = 'profiler';
/**
* Enabled Angular debug tools that are accessible via your browser's
* developer console.
*
* Usage:
*
* 1. Open developer console (e.g. in Chrome Ctrl + Shift + j)
* 1. Type `ng.` (usually the console will show auto-complete suggestion)
* 1. Try the change detection profiler `ng.profiler.timeChangeDetection()`
* then hit Enter.
*
* @publicApi
*/
function enableDebugTools(ref) {
exportNgVar(PROFILER_GLOBAL_NAME, new AngularProfiler(ref));
return ref;
}
/**
* Disables Angular tools.
*
* @publicApi
*/
function disableDebugTools() {
exportNgVar(PROFILER_GLOBAL_NAME, null);
}
/**
* Predicates for use with {@link DebugElement}'s query functions.
*
* @publicApi
*/
class By {
/**
* Match all nodes.
*
* @usageNotes
* ### Example
*
* {@example platform-browser/dom/debug/ts/by/by.ts region='by_all'}
*/
static all() {
return () => true;
}
/**
* Match elements by the given CSS selector.
*
* @usageNotes
* ### Example
*
* {@example platform-browser/dom/debug/ts/by/by.ts region='by_css'}
*/
static css(selector) {
return (debugElement) => {
return debugElement.nativeElement != null
? elementMatches(debugElement.nativeElement, selector)
: false;
};
}
/**
* Match nodes that have the given directive present.
*
* @usageNotes
* ### Example
*
* {@example platform-browser/dom/debug/ts/by/by.ts region='by_directive'}
*/
static directive(type) {
return (debugNode) => debugNode.providerTokens.indexOf(type) !== -1;
}
}
function elementMatches(n, selector) {
if (_getDOM().isElementNode(n)) {
return ((n.matches && n.matches(selector)) ||
(n.msMatchesSelector && n.msMatchesSelector(selector)) ||
(n.webkitMatchesSelector && n.webkitMatchesSelector(selector)));
}
return false;
}
/// <reference types="hammerjs" />
/**
* Supported HammerJS recognizer event names.
*/
const EVENT_NAMES = {
// pan
'pan': true,
'panstart': true,
'panmove': true,
'panend': true,
'pancancel': true,
'panleft': true,
'panright': true,
'panup': true,
'pandown': true,
// pinch
'pinch': true,
'pinchstart': true,
'pinchmove': true,
'pinchend': true,
'pinchcancel': true,
'pinchin': true,
'pinchout': true,
// press
'press': true,
'pressup': true,
// rotate
'rotate': true,
'rotatestart': true,
'rotatemove': true,
'rotateend': true,
'rotatecancel': true,
// swipe
'swipe': true,
'swipeleft': true,
'swiperight': true,
'swipeup': true,
'swipedown': true,
// tap
'tap': true,
'doubletap': true,
};
/**
* DI token for providing [HammerJS](https://hammerjs.github.io/) support to Angular.
* @see {@link HammerGestureConfig}
*
* @ngModule HammerModule
* @publicApi
*
* @deprecated The HammerJS integration is deprecated. Replace it by your own implementation.
*/
const HAMMER_GESTURE_CONFIG = new InjectionToken(typeof ngDevMode === 'undefined' || ngDevMode ? 'HammerGestureConfig' : '');
/**
* Injection token used to provide a HammerLoader to Angular.
*
* @see {@link HammerLoader}
*
* @publicApi
*
* @deprecated The HammerJS integration is deprecated. Replace it by your own implementation.
*/
const HAMMER_LOADER = new InjectionToken(typeof ngDevMode === 'undefined' || ngDevMode ? 'HammerLoader' : '');
/**
* An injectable [HammerJS Manager](https://hammerjs.github.io/api/#hammermanager)
* for gesture recognition. Configures specific event recognition.
* @publicApi
*
* @deprecated The HammerJS integration is deprecated. Replace it by your own implementation.
*/
class HammerGestureConfig {
/**
* A set of supported event names for gestures to be used in Angular.
* Angular supports all built-in recognizers, as listed in
* [HammerJS documentation](https://hammerjs.github.io/).
*/
events = [];
/**
* Maps gesture event names to a set of configuration options
* that specify overrides to the default values for specific properties.
*
* The key is a supported event name to be configured,
* and the options object contains a set of properties, with override values
* to be applied to the named recognizer event.
* For example, to disable recognition of the rotate event, specify
* `{"rotate": {"enable": false}}`.
*
* Properties that are not present take the HammerJS default values.
* For information about which properties are supported for which events,
* and their allowed and default values, see
* [HammerJS documentation](https://hammerjs.github.io/).
*
*/
overrides = {};
/**
* Properties whose default values can be overridden for a given event.
* Different sets of properties apply to different events.
* For information about which properties are supported for which events,
* and their allowed and default values, see
* [HammerJS documentation](https://hammerjs.github.io/).
*/
options;
/**
* Creates a [HammerJS Manager](https://hammerjs.github.io/api/#hammermanager)
* and attaches it to a given HTML element.
* @param element The element that will recognize gestures.
* @returns A HammerJS event-manager object.
*/
buildHammer(element) {
const mc = new Hammer(element, this.options);
mc.get('pinch').set({ enable: true });
mc.get('rotate').set({ enable: true });
for (const eventName in this.overrides) {
mc.get(eventName).set(this.overrides[eventName]);
}
return mc;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: HammerGestureConfig, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: HammerGestureConfig });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: HammerGestureConfig, decorators: [{
type: Injectable
}] });
/**
* Event plugin that adds Hammer support to an application.
*
* @ngModule HammerModule
*/
class HammerGesturesPlugin extends EventManagerPlugin {
_config;
_injector;
loader;
_loaderPromise = null;
constructor(doc, _config, _injector, loader) {
super(doc);
this._config = _config;
this._injector = _injector;
this.loader = loader;
}
supports(eventName) {
if (!EVENT_NAMES.hasOwnProperty(eventName.toLowerCase()) && !this.isCustomEvent(eventName)) {
return false;
}
if (!window.Hammer && !this.loader) {
if (typeof ngDevMode === 'undefined' || ngDevMode) {
// Get a `Console` through an injector to tree-shake the
// class when it is unused in production.
const _console = this._injector.get(_Console);
_console.warn(`The "${eventName}" event cannot be bound because Hammer.JS is not ` +
`loaded and no custom loader has been specified.`);
}
return false;
}
return true;
}
addEventListener(element, eventName, handler) {
const zone = this.manager.getZone();
eventName = eventName.toLowerCase();
// If Hammer is not present but a loader is specified, we defer adding the event listener
// until Hammer is loaded.
if (!window.Hammer && this.loader) {
this._loaderPromise = this._loaderPromise || zone.runOutsideAngular(() => this.loader());
// This `addEventListener` method returns a function to remove the added listener.
// Until Hammer is loaded, the returned function needs to *cancel* the registration rather
// than remove anything.
let cancelRegistration = false;
let deregister = () => {
cancelRegistration = true;
};
zone.runOutsideAngular(() => this._loaderPromise.then(() => {
// If Hammer isn't actually loaded when the custom loader resolves, give up.
if (!window.Hammer) {
if (typeof ngDevMode === 'undefined' || ngDevMode) {
const _console = this._injector.get(_Console);
_console.warn(`The custom HAMMER_LOADER completed, but Hammer.JS is not present.`);
}
deregister = () => { };
return;
}
if (!cancelRegistration) {
// Now that Hammer is loaded and the listener is being loaded for real,
// the deregistration function changes from canceling registration to
// removal.
deregister = this.addEventListener(element, eventName, handler);
}
}).catch(() => {
if (typeof ngDevMode === 'undefined' || ngDevMode) {
const _console = this._injector.get(_Console);
_console.warn(`The "${eventName}" event cannot be bound because the custom ` +
`Hammer.JS loader failed.`);
}
deregister = () => { };
}));
// Return a function that *executes* `deregister` (and not `deregister` itself) so that we
// can change the behavior of `deregister` once the listener is added. Using a closure in
// this way allows us to avoid any additional data structures to track listener removal.
return () => {
deregister();
};
}
return zone.runOutsideAngular(() => {
// Creating the manager bind events, must be done outside of angular
const mc = this._config.buildHammer(element);
const callback = function (eventObj) {
zone.runGuarded(function () {
handler(eventObj);
});
};
mc.on(eventName, callback);
return () => {
mc.off(eventName, callback);
// destroy mc to prevent memory leak
if (typeof mc.destroy === 'function') {
mc.destroy();
}
};
});
}
isCustomEvent(eventName) {
return this._config.events.indexOf(eventName) > -1;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: HammerGesturesPlugin, deps: [{ token: DOCUMENT }, { token: HAMMER_GESTURE_CONFIG }, { token: i0.Injector }, { token: HAMMER_LOADER, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: HammerGesturesPlugin });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: HammerGesturesPlugin, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }, { type: HammerGestureConfig, decorators: [{
type: Inject,
args: [HAMMER_GESTURE_CONFIG]
}] }, { type: i0.Injector }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [HAMMER_LOADER]
}] }] });
/**
* Adds support for HammerJS.
*
* Import this module at the root of your application so that Angular can work with
* HammerJS to detect gesture events.
*
* Note that applications still need to include the HammerJS script itself. This module
* simply sets up the coordination layer between HammerJS and Angular's `EventManager`.
*
* @publicApi
*
* @deprecated The hammer integration is deprecated. Replace it by your own implementation.
*/
class HammerModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: HammerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.11", ngImport: i0, type: HammerModule });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: HammerModule, providers: [
{
provide: EVENT_MANAGER_PLUGINS,
useClass: HammerGesturesPlugin,
multi: true,
deps: [DOCUMENT, HAMMER_GESTURE_CONFIG, Injector, [new Optional(), HAMMER_LOADER]],
},
{ provide: HAMMER_GESTURE_CONFIG, useClass: HammerGestureConfig },
] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: HammerModule, decorators: [{
type: NgModule,
args: [{
providers: [
{
provide: EVENT_MANAGER_PLUGINS,
useClass: HammerGesturesPlugin,
multi: true,
deps: [DOCUMENT, HAMMER_GESTURE_CONFIG, Injector, [new Optional(), HAMMER_LOADER]],
},
{ provide: HAMMER_GESTURE_CONFIG, useClass: HammerGestureConfig },
],
}]
}] });
/**
* DomSanitizer helps preventing Cross Site Scripting Security bugs (XSS) by sanitizing
* values to be safe to use in the different DOM contexts.
*
* For example, when binding a URL in an `<a [href]="someValue">` hyperlink, `someValue` will be
* sanitized so that an attacker cannot inject e.g. a `javascript:` URL that would execute code on
* the website.
*
* In specific situations, it might be necessary to disable sanitization, for example if the
* application genuinely needs to produce a `javascript:` style link with a dynamic value in it.
* Users can bypass security by constructing a value with one of the `bypassSecurityTrust...`
* methods, and then binding to that value from the template.
*
* These situations should be very rare, and extraordinary care must be taken to avoid creating a
* Cross Site Scripting (XSS) security bug!
*
* When using `bypassSecurityTrust...`, make sure to call the method as early as possible and as
* close as possible to the source of the value, to make it easy to verify no security bug is
* created by its use.
*
* It is not required (and not recommended) to bypass security if the value is safe, e.g. a URL that
* does not start with a suspicious protocol, or an HTML snippet that does not contain dangerous
* code. The sanitizer leaves safe values intact.
*
* @security Calling any of the `bypassSecurityTrust...` APIs disables Angular's built-in
* sanitization for the value passed in. Carefully check and audit all values and code paths going
* into this call. Make sure any user data is appropriately escaped for this security context.
* For more detail, see the [Security Guide](https://g.co/ng/security).
*
* @publicApi
*/
class DomSanitizer {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: DomSanitizer, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: DomSanitizer, providedIn: 'root', useExisting: i0.forwardRef(() => DomSanitizerImpl) });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: DomSanitizer, decorators: [{
type: Injectable,
args: [{ providedIn: 'root', useExisting: forwardRef(() => DomSanitizerImpl) }]
}] });
class DomSanitizerImpl extends DomSanitizer {
_doc;
constructor(_doc) {
super();
this._doc = _doc;
}
sanitize(ctx, value) {
if (value == null)
return null;
switch (ctx) {
case SecurityContext.NONE:
return value;
case SecurityContext.HTML:
if (_allowSanitizationBypassAndThrow(value, "HTML" /* BypassType.Html */)) {
return _unwrapSafeValue(value);
}
return __sanitizeHtml(this._doc, String(value)).toString();
case SecurityContext.STYLE:
if (_allowSanitizationBypassAndThrow(value, "Style" /* BypassType.Style */)) {
return _unwrapSafeValue(value);
}
return value;
case SecurityContext.SCRIPT:
if (_allowSanitizationBypassAndThrow(value, "Script" /* BypassType.Script */)) {
return _unwrapSafeValue(value);
}
throw new _RuntimeError(5200 /* RuntimeErrorCode.SANITIZATION_UNSAFE_SCRIPT */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
'unsafe value used in a script context');
case SecurityContext.URL:
if (_allowSanitizationBypassAndThrow(value, "URL" /* BypassType.Url */)) {
return _unwrapSafeValue(value);
}
return __sanitizeUrl(String(value));
case SecurityContext.RESOURCE_URL:
if (_allowSanitizationBypassAndThrow(value, "ResourceURL" /* BypassType.ResourceUrl */)) {
return _unwrapSafeValue(value);
}
throw new _RuntimeError(5201 /* RuntimeErrorCode.SANITIZATION_UNSAFE_RESOURCE_URL */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
`unsafe value used in a resource URL context (see ${_XSS_SECURITY_URL})`);
default:
throw new _RuntimeError(5202 /* RuntimeErrorCode.SANITIZATION_UNEXPECTED_CTX */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
`Unexpected SecurityContext ${ctx} (see ${_XSS_SECURITY_URL})`);
}
}
bypassSecurityTrustHtml(value) {
return _bypassSanitizationTrustHtml(value);
}
bypassSecurityTrustStyle(value) {
return _bypassSanitizationTrustStyle(value);
}
bypassSecurityTrustScript(value) {
return _bypassSanitizationTrustScript(value);
}
bypassSecurityTrustUrl(value) {
return _bypassSanitizationTrustUrl(value);
}
bypassSecurityTrustResourceUrl(value) {
return _bypassSanitizationTrustResourceUrl(value);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: DomSanitizerImpl, deps: [{ token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: DomSanitizerImpl, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: DomSanitizerImpl, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }] });
/**
* The list of features as an enum to uniquely type each `HydrationFeature`.
* @see {@link HydrationFeature}
*
* @publicApi
*/
var HydrationFeatureKind;
(function (HydrationFeatureKind) {
HydrationFeatureKind[HydrationFeatureKind["NoHttpTransferCache"] = 0] = "NoHttpTransferCache";
HydrationFeatureKind[HydrationFeatureKind["HttpTransferCacheOptions"] = 1] = "HttpTransferCacheOptions";
HydrationFeatureKind[HydrationFeatureKind["I18nSupport"] = 2] = "I18nSupport";
HydrationFeatureKind[HydrationFeatureKind["EventReplay"] = 3] = "EventReplay";
HydrationFeatureKind[HydrationFeatureKind["IncrementalHydration"] = 4] = "IncrementalHydration";
})(HydrationFeatureKind || (HydrationFeatureKind = {}));
/**
* Helper function to create an object that represents a Hydration feature.
*/
function hydrationFeature(ɵkind, ɵproviders = [], ɵoptions = {}) {
return { ɵkind, ɵproviders };
}
/**
* Disables HTTP transfer cache. Effectively causes HTTP requests to be performed twice: once on the
* server and other one on the browser.
*
* @see [Disabling Caching](guide/ssr#disabling-caching)
*
* @publicApi
*/
function withNoHttpTransferCache() {
// This feature has no providers and acts as a flag that turns off
// HTTP transfer cache (which otherwise is turned on by default).
return hydrationFeature(HydrationFeatureKind.NoHttpTransferCache);
}
/**
* The function accepts an object, which allows to configure cache parameters,
* such as which headers should be included (no headers are included by default),
* whether POST requests should be cached or a callback function to determine if a
* particular request should be cached.
*
* @see [Configuring HTTP transfer cache options](guide/ssr#caching-data-when-using-httpclient)
*
* @publicApi
*/
function withHttpTransferCacheOptions(options) {
// This feature has no providers and acts as a flag to pass options to the HTTP transfer cache.
return hydrationFeature(HydrationFeatureKind.HttpTransferCacheOptions, _withHttpTransferCache(options));
}
/**
* Enables support for hydrating i18n blocks.
*
* @publicApi 20.0
*/
function withI18nSupport() {
return hydrationFeature(HydrationFeatureKind.I18nSupport, _withI18nSupport());
}
/**
* Enables support for replaying user events (e.g. `click`s) that happened on a page
* before hydration logic has completed. Once an application is hydrated, all captured
* events are replayed and relevant event listeners are executed.
*
* @usageNotes
*
* Basic example of how you can enable event replay in your application when
* `bootstrapApplication` function is used:
* ```ts
* bootstrapApplication(AppComponent, {
* providers: [provideClientHydration(withEventReplay())]
* });
* ```
* @publicApi
* @see {@link provideClientHydration}
*/
function withEventReplay() {
return hydrationFeature(HydrationFeatureKind.EventReplay, _withEventReplay());
}
/**
* Enables support for incremental hydration using the `hydrate` trigger syntax.
*
* @usageNotes
*
* Basic example of how you can enable incremental hydration in your application when
* the `bootstrapApplication` function is used:
* ```ts
* bootstrapApplication(AppComponent, {
* providers: [provideClientHydration(withIncrementalHydration())]
* });
* ```
* @publicApi 20.0
* @see {@link provideClientHydration}
*/
function withIncrementalHydration() {
return hydrationFeature(HydrationFeatureKind.IncrementalHydration, _withIncrementalHydration());
}
/**
* Returns an `ENVIRONMENT_INITIALIZER` token setup with a function
* that verifies whether compatible ZoneJS was used in an application
* and logs a warning in a console if it's not the case.
*/
function provideZoneJsCompatibilityDetector() {
return [
{
provide: ENVIRONMENT_INITIALIZER,
useValue: () => {
const ngZone = inject(NgZone);
const isZoneless = inject(_ZONELESS_ENABLED);
// Checking `ngZone instanceof NgZone` would be insufficient here,
// because custom implementations might use NgZone as a base class.
if (!isZoneless && ngZone.constructor !== NgZone) {
const console = inject(_Console);
const message = _formatRuntimeError(-5000 /* RuntimeErrorCode.UNSUPPORTED_ZONEJS_INSTANCE */, 'Angular detected that hydration was enabled for an application ' +
'that uses a custom or a noop Zone.js implementation. ' +
'This is not yet a fully supported configuration.');
console.warn(message);
}
},
multi: true,
},
];
}
/**
* Returns an `ENVIRONMENT_INITIALIZER` token setup with a function
* that verifies whether enabledBlocking initial navigation is used in an application
* and logs a warning in a console if it's not compatible with hydration.
*/
function provideEnabledBlockingInitialNavigationDetector() {
return [
{
provide: ENVIRONMENT_INITIALIZER,
useValue: () => {
const isEnabledBlockingInitialNavigation = inject(_IS_ENABLED_BLOCKING_INITIAL_NAVIGATION, {
optional: true,
});
if (isEnabledBlockingInitialNavigation) {
const console = inject(_Console);
const message = _formatRuntimeError(5001 /* RuntimeErrorCode.HYDRATION_CONFLICTING_FEATURES */, 'Configuration error: found both hydration and enabledBlocking initial navigation ' +
'in the same application, which is a contradiction.');
console.warn(message);
}
},
multi: true,
},
];
}
/**
* Sets up providers necessary to enable hydration functionality for the application.
*
* By default, the function enables the recommended set of features for the optimal
* performance for most of the applications. It includes the following features:
*
* * Reconciling DOM hydration. Learn more about it [here](guide/hydration).
* * [`HttpClient`](api/common/http/HttpClient) response caching while running on the server and
* transferring this cache to the client to avoid extra HTTP requests. Learn more about data caching
* [here](guide/ssr#caching-data-when-using-httpclient).
*
* These functions allow you to disable some of the default features or enable new ones:
*
* * {@link withNoHttpTransferCache} to disable HTTP transfer cache
* * {@link withHttpTransferCacheOptions} to configure some HTTP transfer cache options
* * {@link withI18nSupport} to enable hydration support for i18n blocks
* * {@link withEventReplay} to enable support for replaying user events
*
* @usageNotes
*
* Basic example of how you can enable hydration in your application when
* `bootstrapApplication` function is used:
* ```ts
* bootstrapApplication(AppComponent, {
* providers: [provideClientHydration()]
* });
* ```
*
* Alternatively if you are using NgModules, you would add `provideClientHydration`
* to your root app module's provider list.
* ```ts
* @NgModule({
* declarations: [RootCmp],
* bootstrap: [RootCmp],
* providers: [provideClientHydration()],
* })
* export class AppModule {}
* ```
*
* @see {@link withNoHttpTransferCache}
* @see {@link withHttpTransferCacheOptions}
* @see {@link withI18nSupport}
* @see {@link withEventReplay}
*
* @param features Optional features to configure additional hydration behaviors.
* @returns A set of providers to enable hydration.
*
* @publicApi 17.0
*/
function provideClientHydration(...features) {
const providers = [];
const featuresKind = new Set();
for (const { ɵproviders, ɵkind } of features) {
featuresKind.add(ɵkind);
if (ɵproviders.length) {
providers.push(ɵproviders);
}
}
const hasHttpTransferCacheOptions = featuresKind.has(HydrationFeatureKind.HttpTransferCacheOptions);
if (typeof ngDevMode !== 'undefined' &&
ngDevMode &&
featuresKind.has(HydrationFeatureKind.NoHttpTransferCache) &&
hasHttpTransferCacheOptions) {
throw new _RuntimeError(5001 /* RuntimeErrorCode.HYDRATION_CONFLICTING_FEATURES */, 'Configuration error: found both withHttpTransferCacheOptions() and withNoHttpTransferCache() in the same call to provideClientHydration(), which is a contradiction.');
}
return makeEnvironmentProviders([
typeof ngDevMode !== 'undefined' && ngDevMode ? provideZoneJsCompatibilityDetector() : [],
typeof ngDevMode !== 'undefined' && ngDevMode
? provideEnabledBlockingInitialNavigationDetector()
: [],
_withDomHydration(),
featuresKind.has(HydrationFeatureKind.NoHttpTransferCache) || hasHttpTransferCacheOptions
? []
: _withHttpTransferCache({}),
providers,
]);
}
/**
* @module
* @description
* Entry point for all public APIs of the platform-browser package.
*/
/**
* @publicApi
*/
const VERSION = /* @__PURE__ */ new Version('20.3.11');
export { By, DomSanitizer, EVENT_MANAGER_PLUGINS, EventManagerPlugin, HAMMER_GESTURE_CONFIG, HAMMER_LOADER, HammerGestureConfig, HammerModule, HydrationFeatureKind, Meta, Title, VERSION, disableDebugTools, enableDebugTools, provideClientHydration, withEventReplay, withHttpTransferCacheOptions, withI18nSupport, withIncrementalHydration, withNoHttpTransferCache, DomSanitizerImpl as ɵDomSanitizerImpl, HammerGesturesPlugin as ɵHammerGesturesPlugin };
//# sourceMappingURL=platform-browser.mjs.map

File diff suppressed because one or more lines are too long

93
node_modules/@angular/platform-browser/fesm2022/testing.mjs generated vendored Executable file
View File

@@ -0,0 +1,93 @@
/**
* @license Angular v20.3.11
* (c) 2010-2025 Google LLC. https://angular.dev/
* License: MIT
*/
import { ɵgetDOM as _getDOM, DOCUMENT, PlatformLocation } from '@angular/common';
import { MockPlatformLocation } from '@angular/common/testing';
import * as i0 from '@angular/core';
import { Injectable, Inject, createPlatformFactory, APP_ID, ɵinternalProvideZoneChangeDetection as _internalProvideZoneChangeDetection, ɵChangeDetectionScheduler as _ChangeDetectionScheduler, ɵChangeDetectionSchedulerImpl as _ChangeDetectionSchedulerImpl, NgModule } from '@angular/core';
import { TestComponentRenderer } from '@angular/core/testing';
import { platformBrowser, BrowserModule } from './browser.mjs';
import './dom_renderer.mjs';
/**
* A DOM based implementation of the TestComponentRenderer.
*/
class DOMTestComponentRenderer extends TestComponentRenderer {
_doc;
constructor(_doc) {
super();
this._doc = _doc;
}
insertRootElement(rootElId, tagName = 'div') {
this.removeAllRootElementsImpl();
const rootElement = _getDOM().getDefaultDocument().createElement(tagName);
rootElement.setAttribute('id', rootElId);
this._doc.body.appendChild(rootElement);
}
removeAllRootElements() {
// Check whether the `DOCUMENT` instance retrieved from DI contains
// the necessary function to complete the cleanup. In tests that don't
// interact with DOM, the `DOCUMENT` might be mocked and some functions
// might be missing. For such tests, DOM cleanup is not required and
// we skip the logic if there are missing functions.
if (typeof this._doc.querySelectorAll === 'function') {
this.removeAllRootElementsImpl();
}
}
removeAllRootElementsImpl() {
const oldRoots = this._doc.querySelectorAll('[id^=root]');
for (let i = 0; i < oldRoots.length; i++) {
_getDOM().remove(oldRoots[i]);
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: DOMTestComponentRenderer, deps: [{ token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: DOMTestComponentRenderer });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: DOMTestComponentRenderer, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }] });
/**
* Platform for testing
*
* @publicApi
*/
const platformBrowserTesting = createPlatformFactory(platformBrowser, 'browserTesting');
/**
* NgModule for testing.
*
* @publicApi
*/
class BrowserTestingModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: BrowserTestingModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.11", ngImport: i0, type: BrowserTestingModule, exports: [BrowserModule] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: BrowserTestingModule, providers: [
{ provide: APP_ID, useValue: 'a' },
_internalProvideZoneChangeDetection({}),
{ provide: _ChangeDetectionScheduler, useExisting: _ChangeDetectionSchedulerImpl },
{ provide: PlatformLocation, useClass: MockPlatformLocation },
{ provide: TestComponentRenderer, useClass: DOMTestComponentRenderer },
], imports: [BrowserModule] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: BrowserTestingModule, decorators: [{
type: NgModule,
args: [{
exports: [BrowserModule],
providers: [
{ provide: APP_ID, useValue: 'a' },
_internalProvideZoneChangeDetection({}),
{ provide: _ChangeDetectionScheduler, useExisting: _ChangeDetectionSchedulerImpl },
{ provide: PlatformLocation, useClass: MockPlatformLocation },
{ provide: TestComponentRenderer, useClass: DOMTestComponentRenderer },
],
}]
}] });
export { BrowserTestingModule, platformBrowserTesting };
//# sourceMappingURL=testing.mjs.map

File diff suppressed because one or more lines are too long