Updated the files.
This commit is contained in:
parent
1553e6b971
commit
753967d4f5
23418 changed files with 3784666 additions and 0 deletions
6769
my-app/node_modules/@angular/common/fesm2022/common.mjs
generated
vendored
Executable file
6769
my-app/node_modules/@angular/common/fesm2022/common.mjs
generated
vendored
Executable file
File diff suppressed because one or more lines are too long
1
my-app/node_modules/@angular/common/fesm2022/common.mjs.map
generated
vendored
Executable file
1
my-app/node_modules/@angular/common/fesm2022/common.mjs.map
generated
vendored
Executable file
File diff suppressed because one or more lines are too long
2959
my-app/node_modules/@angular/common/fesm2022/http.mjs
generated
vendored
Executable file
2959
my-app/node_modules/@angular/common/fesm2022/http.mjs
generated
vendored
Executable file
File diff suppressed because it is too large
Load diff
1
my-app/node_modules/@angular/common/fesm2022/http.mjs.map
generated
vendored
Executable file
1
my-app/node_modules/@angular/common/fesm2022/http.mjs.map
generated
vendored
Executable file
File diff suppressed because one or more lines are too long
359
my-app/node_modules/@angular/common/fesm2022/http/testing.mjs
generated
vendored
Executable file
359
my-app/node_modules/@angular/common/fesm2022/http/testing.mjs
generated
vendored
Executable file
|
@ -0,0 +1,359 @@
|
|||
/**
|
||||
* @license Angular v17.1.3
|
||||
* (c) 2010-2022 Google LLC. https://angular.io/
|
||||
* License: MIT
|
||||
*/
|
||||
|
||||
import { HttpHeaders, HttpStatusCode, HttpResponse, HttpErrorResponse, HttpEventType, HttpBackend, HttpClientModule } from '@angular/common/http';
|
||||
import * as i0 from '@angular/core';
|
||||
import { Injectable, NgModule } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
/**
|
||||
* Controller to be injected into tests, that allows for mocking and flushing
|
||||
* of requests.
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
class HttpTestingController {
|
||||
}
|
||||
|
||||
/**
|
||||
* A mock requests that was received and is ready to be answered.
|
||||
*
|
||||
* This interface allows access to the underlying `HttpRequest`, and allows
|
||||
* responding with `HttpEvent`s or `HttpErrorResponse`s.
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
class TestRequest {
|
||||
/**
|
||||
* Whether the request was cancelled after it was sent.
|
||||
*/
|
||||
get cancelled() {
|
||||
return this._cancelled;
|
||||
}
|
||||
constructor(request, observer) {
|
||||
this.request = request;
|
||||
this.observer = observer;
|
||||
/**
|
||||
* @internal set by `HttpClientTestingBackend`
|
||||
*/
|
||||
this._cancelled = false;
|
||||
}
|
||||
/**
|
||||
* Resolve the request by returning a body plus additional HTTP information (such as response
|
||||
* headers) if provided.
|
||||
* If the request specifies an expected body type, the body is converted into the requested type.
|
||||
* Otherwise, the body is converted to `JSON` by default.
|
||||
*
|
||||
* Both successful and unsuccessful responses can be delivered via `flush()`.
|
||||
*/
|
||||
flush(body, opts = {}) {
|
||||
if (this.cancelled) {
|
||||
throw new Error(`Cannot flush a cancelled request.`);
|
||||
}
|
||||
const url = this.request.urlWithParams;
|
||||
const headers = opts.headers instanceof HttpHeaders ? opts.headers : new HttpHeaders(opts.headers);
|
||||
body = _maybeConvertBody(this.request.responseType, body);
|
||||
let statusText = opts.statusText;
|
||||
let status = opts.status !== undefined ? opts.status : HttpStatusCode.Ok;
|
||||
if (opts.status === undefined) {
|
||||
if (body === null) {
|
||||
status = HttpStatusCode.NoContent;
|
||||
statusText ||= 'No Content';
|
||||
}
|
||||
else {
|
||||
statusText ||= 'OK';
|
||||
}
|
||||
}
|
||||
if (statusText === undefined) {
|
||||
throw new Error('statusText is required when setting a custom status.');
|
||||
}
|
||||
if (status >= 200 && status < 300) {
|
||||
this.observer.next(new HttpResponse({ body, headers, status, statusText, url }));
|
||||
this.observer.complete();
|
||||
}
|
||||
else {
|
||||
this.observer.error(new HttpErrorResponse({ error: body, headers, status, statusText, url }));
|
||||
}
|
||||
}
|
||||
error(error, opts = {}) {
|
||||
if (this.cancelled) {
|
||||
throw new Error(`Cannot return an error for a cancelled request.`);
|
||||
}
|
||||
if (opts.status && opts.status >= 200 && opts.status < 300) {
|
||||
throw new Error(`error() called with a successful status.`);
|
||||
}
|
||||
const headers = opts.headers instanceof HttpHeaders ? opts.headers : new HttpHeaders(opts.headers);
|
||||
this.observer.error(new HttpErrorResponse({
|
||||
error,
|
||||
headers,
|
||||
status: opts.status || 0,
|
||||
statusText: opts.statusText || '',
|
||||
url: this.request.urlWithParams,
|
||||
}));
|
||||
}
|
||||
/**
|
||||
* Deliver an arbitrary `HttpEvent` (such as a progress event) on the response stream for this
|
||||
* request.
|
||||
*/
|
||||
event(event) {
|
||||
if (this.cancelled) {
|
||||
throw new Error(`Cannot send events to a cancelled request.`);
|
||||
}
|
||||
this.observer.next(event);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Helper function to convert a response body to an ArrayBuffer.
|
||||
*/
|
||||
function _toArrayBufferBody(body) {
|
||||
if (typeof ArrayBuffer === 'undefined') {
|
||||
throw new Error('ArrayBuffer responses are not supported on this platform.');
|
||||
}
|
||||
if (body instanceof ArrayBuffer) {
|
||||
return body;
|
||||
}
|
||||
throw new Error('Automatic conversion to ArrayBuffer is not supported for response type.');
|
||||
}
|
||||
/**
|
||||
* Helper function to convert a response body to a Blob.
|
||||
*/
|
||||
function _toBlob(body) {
|
||||
if (typeof Blob === 'undefined') {
|
||||
throw new Error('Blob responses are not supported on this platform.');
|
||||
}
|
||||
if (body instanceof Blob) {
|
||||
return body;
|
||||
}
|
||||
if (ArrayBuffer && body instanceof ArrayBuffer) {
|
||||
return new Blob([body]);
|
||||
}
|
||||
throw new Error('Automatic conversion to Blob is not supported for response type.');
|
||||
}
|
||||
/**
|
||||
* Helper function to convert a response body to JSON data.
|
||||
*/
|
||||
function _toJsonBody(body, format = 'JSON') {
|
||||
if (typeof ArrayBuffer !== 'undefined' && body instanceof ArrayBuffer) {
|
||||
throw new Error(`Automatic conversion to ${format} is not supported for ArrayBuffers.`);
|
||||
}
|
||||
if (typeof Blob !== 'undefined' && body instanceof Blob) {
|
||||
throw new Error(`Automatic conversion to ${format} is not supported for Blobs.`);
|
||||
}
|
||||
if (typeof body === 'string' ||
|
||||
typeof body === 'number' ||
|
||||
typeof body === 'object' ||
|
||||
typeof body === 'boolean' ||
|
||||
Array.isArray(body)) {
|
||||
return body;
|
||||
}
|
||||
throw new Error(`Automatic conversion to ${format} is not supported for response type.`);
|
||||
}
|
||||
/**
|
||||
* Helper function to convert a response body to a string.
|
||||
*/
|
||||
function _toTextBody(body) {
|
||||
if (typeof body === 'string') {
|
||||
return body;
|
||||
}
|
||||
if (typeof ArrayBuffer !== 'undefined' && body instanceof ArrayBuffer) {
|
||||
throw new Error('Automatic conversion to text is not supported for ArrayBuffers.');
|
||||
}
|
||||
if (typeof Blob !== 'undefined' && body instanceof Blob) {
|
||||
throw new Error('Automatic conversion to text is not supported for Blobs.');
|
||||
}
|
||||
return JSON.stringify(_toJsonBody(body, 'text'));
|
||||
}
|
||||
/**
|
||||
* Convert a response body to the requested type.
|
||||
*/
|
||||
function _maybeConvertBody(responseType, body) {
|
||||
if (body === null) {
|
||||
return null;
|
||||
}
|
||||
switch (responseType) {
|
||||
case 'arraybuffer':
|
||||
return _toArrayBufferBody(body);
|
||||
case 'blob':
|
||||
return _toBlob(body);
|
||||
case 'json':
|
||||
return _toJsonBody(body);
|
||||
case 'text':
|
||||
return _toTextBody(body);
|
||||
default:
|
||||
throw new Error(`Unsupported responseType: ${responseType}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A testing backend for `HttpClient` which both acts as an `HttpBackend`
|
||||
* and as the `HttpTestingController`.
|
||||
*
|
||||
* `HttpClientTestingBackend` works by keeping a list of all open requests.
|
||||
* As requests come in, they're added to the list. Users can assert that specific
|
||||
* requests were made and then flush them. In the end, a verify() method asserts
|
||||
* that no unexpected requests were made.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class HttpClientTestingBackend {
|
||||
constructor() {
|
||||
/**
|
||||
* List of pending requests which have not yet been expected.
|
||||
*/
|
||||
this.open = [];
|
||||
}
|
||||
/**
|
||||
* Handle an incoming request by queueing it in the list of open requests.
|
||||
*/
|
||||
handle(req) {
|
||||
return new Observable((observer) => {
|
||||
const testReq = new TestRequest(req, observer);
|
||||
this.open.push(testReq);
|
||||
observer.next({ type: HttpEventType.Sent });
|
||||
return () => {
|
||||
testReq._cancelled = true;
|
||||
};
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Helper function to search for requests in the list of open requests.
|
||||
*/
|
||||
_match(match) {
|
||||
if (typeof match === 'string') {
|
||||
return this.open.filter((testReq) => testReq.request.urlWithParams === match);
|
||||
}
|
||||
else if (typeof match === 'function') {
|
||||
return this.open.filter((testReq) => match(testReq.request));
|
||||
}
|
||||
else {
|
||||
return this.open.filter((testReq) => (!match.method || testReq.request.method === match.method.toUpperCase()) &&
|
||||
(!match.url || testReq.request.urlWithParams === match.url));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Search for requests in the list of open requests, and return all that match
|
||||
* without asserting anything about the number of matches.
|
||||
*/
|
||||
match(match) {
|
||||
const results = this._match(match);
|
||||
results.forEach((result) => {
|
||||
const index = this.open.indexOf(result);
|
||||
if (index !== -1) {
|
||||
this.open.splice(index, 1);
|
||||
}
|
||||
});
|
||||
return results;
|
||||
}
|
||||
/**
|
||||
* Expect that a single outstanding request matches the given matcher, and return
|
||||
* it.
|
||||
*
|
||||
* Requests returned through this API will no longer be in the list of open requests,
|
||||
* and thus will not match twice.
|
||||
*/
|
||||
expectOne(match, description) {
|
||||
description ||= this.descriptionFromMatcher(match);
|
||||
const matches = this.match(match);
|
||||
if (matches.length > 1) {
|
||||
throw new Error(`Expected one matching request for criteria "${description}", found ${matches.length} requests.`);
|
||||
}
|
||||
if (matches.length === 0) {
|
||||
let message = `Expected one matching request for criteria "${description}", found none.`;
|
||||
if (this.open.length > 0) {
|
||||
// Show the methods and URLs of open requests in the error, for convenience.
|
||||
const requests = this.open.map(describeRequest).join(', ');
|
||||
message += ` Requests received are: ${requests}.`;
|
||||
}
|
||||
throw new Error(message);
|
||||
}
|
||||
return matches[0];
|
||||
}
|
||||
/**
|
||||
* Expect that no outstanding requests match the given matcher, and throw an error
|
||||
* if any do.
|
||||
*/
|
||||
expectNone(match, description) {
|
||||
description ||= this.descriptionFromMatcher(match);
|
||||
const matches = this.match(match);
|
||||
if (matches.length > 0) {
|
||||
throw new Error(`Expected zero matching requests for criteria "${description}", found ${matches.length}.`);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Validate that there are no outstanding requests.
|
||||
*/
|
||||
verify(opts = {}) {
|
||||
let open = this.open;
|
||||
// It's possible that some requests may be cancelled, and this is expected.
|
||||
// The user can ask to ignore open requests which have been cancelled.
|
||||
if (opts.ignoreCancelled) {
|
||||
open = open.filter((testReq) => !testReq.cancelled);
|
||||
}
|
||||
if (open.length > 0) {
|
||||
// Show the methods and URLs of open requests in the error, for convenience.
|
||||
const requests = open.map(describeRequest).join(', ');
|
||||
throw new Error(`Expected no open requests, found ${open.length}: ${requests}`);
|
||||
}
|
||||
}
|
||||
descriptionFromMatcher(matcher) {
|
||||
if (typeof matcher === 'string') {
|
||||
return `Match URL: ${matcher}`;
|
||||
}
|
||||
else if (typeof matcher === 'object') {
|
||||
const method = matcher.method || '(any)';
|
||||
const url = matcher.url || '(any)';
|
||||
return `Match method: ${method}, URL: ${url}`;
|
||||
}
|
||||
else {
|
||||
return `Match by function: ${matcher.name}`;
|
||||
}
|
||||
}
|
||||
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: HttpClientTestingBackend, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
||||
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: HttpClientTestingBackend }); }
|
||||
}
|
||||
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: HttpClientTestingBackend, decorators: [{
|
||||
type: Injectable
|
||||
}] });
|
||||
function describeRequest(testRequest) {
|
||||
const url = testRequest.request.urlWithParams;
|
||||
const method = testRequest.request.method;
|
||||
return `${method} ${url}`;
|
||||
}
|
||||
|
||||
function provideHttpClientTesting() {
|
||||
return [
|
||||
HttpClientTestingBackend,
|
||||
{ provide: HttpBackend, useExisting: HttpClientTestingBackend },
|
||||
{ provide: HttpTestingController, useExisting: HttpClientTestingBackend },
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures `HttpClientTestingBackend` as the `HttpBackend` used by `HttpClient`.
|
||||
*
|
||||
* Inject `HttpTestingController` to expect and flush requests in your tests.
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
class HttpClientTestingModule {
|
||||
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: HttpClientTestingModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
||||
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.1.3", ngImport: i0, type: HttpClientTestingModule, imports: [HttpClientModule] }); }
|
||||
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: HttpClientTestingModule, providers: [provideHttpClientTesting()], imports: [HttpClientModule] }); }
|
||||
}
|
||||
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: HttpClientTestingModule, decorators: [{
|
||||
type: NgModule,
|
||||
args: [{
|
||||
imports: [HttpClientModule],
|
||||
providers: [provideHttpClientTesting()],
|
||||
}]
|
||||
}] });
|
||||
|
||||
/**
|
||||
* Generated bundle index. Do not edit.
|
||||
*/
|
||||
|
||||
export { HttpClientTestingModule, HttpTestingController, TestRequest, provideHttpClientTesting };
|
||||
//# sourceMappingURL=testing.mjs.map
|
1
my-app/node_modules/@angular/common/fesm2022/http/testing.mjs.map
generated
vendored
Executable file
1
my-app/node_modules/@angular/common/fesm2022/http/testing.mjs.map
generated
vendored
Executable file
File diff suppressed because one or more lines are too long
511
my-app/node_modules/@angular/common/fesm2022/testing.mjs
generated
vendored
Executable file
511
my-app/node_modules/@angular/common/fesm2022/testing.mjs
generated
vendored
Executable file
|
@ -0,0 +1,511 @@
|
|||
/**
|
||||
* @license Angular v17.1.3
|
||||
* (c) 2010-2022 Google LLC. https://angular.io/
|
||||
* License: MIT
|
||||
*/
|
||||
|
||||
import { ɵnormalizeQueryParams, LocationStrategy, Location } from '@angular/common';
|
||||
import * as i0 from '@angular/core';
|
||||
import { EventEmitter, Injectable, InjectionToken, Inject, Optional } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
/**
|
||||
* A spy for {@link Location} that allows tests to fire simulated location events.
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
class SpyLocation {
|
||||
constructor() {
|
||||
this.urlChanges = [];
|
||||
this._history = [new LocationState('', '', null)];
|
||||
this._historyIndex = 0;
|
||||
/** @internal */
|
||||
this._subject = new EventEmitter();
|
||||
/** @internal */
|
||||
this._basePath = '';
|
||||
/** @internal */
|
||||
this._locationStrategy = null;
|
||||
/** @internal */
|
||||
this._urlChangeListeners = [];
|
||||
/** @internal */
|
||||
this._urlChangeSubscription = null;
|
||||
}
|
||||
/** @nodoc */
|
||||
ngOnDestroy() {
|
||||
this._urlChangeSubscription?.unsubscribe();
|
||||
this._urlChangeListeners = [];
|
||||
}
|
||||
setInitialPath(url) {
|
||||
this._history[this._historyIndex].path = url;
|
||||
}
|
||||
setBaseHref(url) {
|
||||
this._basePath = url;
|
||||
}
|
||||
path() {
|
||||
return this._history[this._historyIndex].path;
|
||||
}
|
||||
getState() {
|
||||
return this._history[this._historyIndex].state;
|
||||
}
|
||||
isCurrentPathEqualTo(path, query = '') {
|
||||
const givenPath = path.endsWith('/') ? path.substring(0, path.length - 1) : path;
|
||||
const currPath = this.path().endsWith('/')
|
||||
? this.path().substring(0, this.path().length - 1)
|
||||
: this.path();
|
||||
return currPath == givenPath + (query.length > 0 ? '?' + query : '');
|
||||
}
|
||||
simulateUrlPop(pathname) {
|
||||
this._subject.emit({ 'url': pathname, 'pop': true, 'type': 'popstate' });
|
||||
}
|
||||
simulateHashChange(pathname) {
|
||||
const path = this.prepareExternalUrl(pathname);
|
||||
this.pushHistory(path, '', null);
|
||||
this.urlChanges.push('hash: ' + pathname);
|
||||
// the browser will automatically fire popstate event before each `hashchange` event, so we need
|
||||
// to simulate it.
|
||||
this._subject.emit({ 'url': pathname, 'pop': true, 'type': 'popstate' });
|
||||
this._subject.emit({ 'url': pathname, 'pop': true, 'type': 'hashchange' });
|
||||
}
|
||||
prepareExternalUrl(url) {
|
||||
if (url.length > 0 && !url.startsWith('/')) {
|
||||
url = '/' + url;
|
||||
}
|
||||
return this._basePath + url;
|
||||
}
|
||||
go(path, query = '', state = null) {
|
||||
path = this.prepareExternalUrl(path);
|
||||
this.pushHistory(path, query, state);
|
||||
const locationState = this._history[this._historyIndex - 1];
|
||||
if (locationState.path == path && locationState.query == query) {
|
||||
return;
|
||||
}
|
||||
const url = path + (query.length > 0 ? '?' + query : '');
|
||||
this.urlChanges.push(url);
|
||||
this._notifyUrlChangeListeners(path + ɵnormalizeQueryParams(query), state);
|
||||
}
|
||||
replaceState(path, query = '', state = null) {
|
||||
path = this.prepareExternalUrl(path);
|
||||
const history = this._history[this._historyIndex];
|
||||
history.state = state;
|
||||
if (history.path == path && history.query == query) {
|
||||
return;
|
||||
}
|
||||
history.path = path;
|
||||
history.query = query;
|
||||
const url = path + (query.length > 0 ? '?' + query : '');
|
||||
this.urlChanges.push('replace: ' + url);
|
||||
this._notifyUrlChangeListeners(path + ɵnormalizeQueryParams(query), state);
|
||||
}
|
||||
forward() {
|
||||
if (this._historyIndex < this._history.length - 1) {
|
||||
this._historyIndex++;
|
||||
this._subject.emit({
|
||||
'url': this.path(),
|
||||
'state': this.getState(),
|
||||
'pop': true,
|
||||
'type': 'popstate',
|
||||
});
|
||||
}
|
||||
}
|
||||
back() {
|
||||
if (this._historyIndex > 0) {
|
||||
this._historyIndex--;
|
||||
this._subject.emit({
|
||||
'url': this.path(),
|
||||
'state': this.getState(),
|
||||
'pop': true,
|
||||
'type': 'popstate',
|
||||
});
|
||||
}
|
||||
}
|
||||
historyGo(relativePosition = 0) {
|
||||
const nextPageIndex = this._historyIndex + relativePosition;
|
||||
if (nextPageIndex >= 0 && nextPageIndex < this._history.length) {
|
||||
this._historyIndex = nextPageIndex;
|
||||
this._subject.emit({
|
||||
'url': this.path(),
|
||||
'state': this.getState(),
|
||||
'pop': true,
|
||||
'type': 'popstate',
|
||||
});
|
||||
}
|
||||
}
|
||||
onUrlChange(fn) {
|
||||
this._urlChangeListeners.push(fn);
|
||||
this._urlChangeSubscription ??= this.subscribe((v) => {
|
||||
this._notifyUrlChangeListeners(v.url, v.state);
|
||||
});
|
||||
return () => {
|
||||
const fnIndex = this._urlChangeListeners.indexOf(fn);
|
||||
this._urlChangeListeners.splice(fnIndex, 1);
|
||||
if (this._urlChangeListeners.length === 0) {
|
||||
this._urlChangeSubscription?.unsubscribe();
|
||||
this._urlChangeSubscription = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
/** @internal */
|
||||
_notifyUrlChangeListeners(url = '', state) {
|
||||
this._urlChangeListeners.forEach((fn) => fn(url, state));
|
||||
}
|
||||
subscribe(onNext, onThrow, onReturn) {
|
||||
return this._subject.subscribe({ next: onNext, error: onThrow, complete: onReturn });
|
||||
}
|
||||
normalize(url) {
|
||||
return null;
|
||||
}
|
||||
pushHistory(path, query, state) {
|
||||
if (this._historyIndex > 0) {
|
||||
this._history.splice(this._historyIndex + 1);
|
||||
}
|
||||
this._history.push(new LocationState(path, query, state));
|
||||
this._historyIndex = this._history.length - 1;
|
||||
}
|
||||
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: SpyLocation, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
||||
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: SpyLocation }); }
|
||||
}
|
||||
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: SpyLocation, decorators: [{
|
||||
type: Injectable
|
||||
}] });
|
||||
class LocationState {
|
||||
constructor(path, query, state) {
|
||||
this.path = path;
|
||||
this.query = query;
|
||||
this.state = state;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A mock implementation of {@link LocationStrategy} that allows tests to fire simulated
|
||||
* location events.
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
class MockLocationStrategy extends LocationStrategy {
|
||||
constructor() {
|
||||
super();
|
||||
this.internalBaseHref = '/';
|
||||
this.internalPath = '/';
|
||||
this.internalTitle = '';
|
||||
this.urlChanges = [];
|
||||
/** @internal */
|
||||
this._subject = new EventEmitter();
|
||||
this.stateChanges = [];
|
||||
}
|
||||
simulatePopState(url) {
|
||||
this.internalPath = url;
|
||||
this._subject.emit(new _MockPopStateEvent(this.path()));
|
||||
}
|
||||
path(includeHash = false) {
|
||||
return this.internalPath;
|
||||
}
|
||||
prepareExternalUrl(internal) {
|
||||
if (internal.startsWith('/') && this.internalBaseHref.endsWith('/')) {
|
||||
return this.internalBaseHref + internal.substring(1);
|
||||
}
|
||||
return this.internalBaseHref + internal;
|
||||
}
|
||||
pushState(ctx, title, path, query) {
|
||||
// Add state change to changes array
|
||||
this.stateChanges.push(ctx);
|
||||
this.internalTitle = title;
|
||||
const url = path + (query.length > 0 ? '?' + query : '');
|
||||
this.internalPath = url;
|
||||
const externalUrl = this.prepareExternalUrl(url);
|
||||
this.urlChanges.push(externalUrl);
|
||||
}
|
||||
replaceState(ctx, title, path, query) {
|
||||
// Reset the last index of stateChanges to the ctx (state) object
|
||||
this.stateChanges[(this.stateChanges.length || 1) - 1] = ctx;
|
||||
this.internalTitle = title;
|
||||
const url = path + (query.length > 0 ? '?' + query : '');
|
||||
this.internalPath = url;
|
||||
const externalUrl = this.prepareExternalUrl(url);
|
||||
this.urlChanges.push('replace: ' + externalUrl);
|
||||
}
|
||||
onPopState(fn) {
|
||||
this._subject.subscribe({ next: fn });
|
||||
}
|
||||
getBaseHref() {
|
||||
return this.internalBaseHref;
|
||||
}
|
||||
back() {
|
||||
if (this.urlChanges.length > 0) {
|
||||
this.urlChanges.pop();
|
||||
this.stateChanges.pop();
|
||||
const nextUrl = this.urlChanges.length > 0 ? this.urlChanges[this.urlChanges.length - 1] : '';
|
||||
this.simulatePopState(nextUrl);
|
||||
}
|
||||
}
|
||||
forward() {
|
||||
throw 'not implemented';
|
||||
}
|
||||
getState() {
|
||||
return this.stateChanges[(this.stateChanges.length || 1) - 1];
|
||||
}
|
||||
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: MockLocationStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
||||
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: MockLocationStrategy }); }
|
||||
}
|
||||
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: MockLocationStrategy, decorators: [{
|
||||
type: Injectable
|
||||
}], ctorParameters: () => [] });
|
||||
class _MockPopStateEvent {
|
||||
constructor(newUrl) {
|
||||
this.newUrl = newUrl;
|
||||
this.pop = true;
|
||||
this.type = 'popstate';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parser from https://tools.ietf.org/html/rfc3986#appendix-B
|
||||
* ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
|
||||
* 12 3 4 5 6 7 8 9
|
||||
*
|
||||
* Example: http://www.ics.uci.edu/pub/ietf/uri/#Related
|
||||
*
|
||||
* Results in:
|
||||
*
|
||||
* $1 = http:
|
||||
* $2 = http
|
||||
* $3 = //www.ics.uci.edu
|
||||
* $4 = www.ics.uci.edu
|
||||
* $5 = /pub/ietf/uri/
|
||||
* $6 = <undefined>
|
||||
* $7 = <undefined>
|
||||
* $8 = #Related
|
||||
* $9 = Related
|
||||
*/
|
||||
const urlParse = /^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/;
|
||||
function parseUrl(urlStr, baseHref) {
|
||||
const verifyProtocol = /^((http[s]?|ftp):\/\/)/;
|
||||
let serverBase;
|
||||
// URL class requires full URL. If the URL string doesn't start with protocol, we need to add
|
||||
// an arbitrary base URL which can be removed afterward.
|
||||
if (!verifyProtocol.test(urlStr)) {
|
||||
serverBase = 'http://empty.com/';
|
||||
}
|
||||
let parsedUrl;
|
||||
try {
|
||||
parsedUrl = new URL(urlStr, serverBase);
|
||||
}
|
||||
catch (e) {
|
||||
const result = urlParse.exec(serverBase || '' + urlStr);
|
||||
if (!result) {
|
||||
throw new Error(`Invalid URL: ${urlStr} with base: ${baseHref}`);
|
||||
}
|
||||
const hostSplit = result[4].split(':');
|
||||
parsedUrl = {
|
||||
protocol: result[1],
|
||||
hostname: hostSplit[0],
|
||||
port: hostSplit[1] || '',
|
||||
pathname: result[5],
|
||||
search: result[6],
|
||||
hash: result[8],
|
||||
};
|
||||
}
|
||||
if (parsedUrl.pathname && parsedUrl.pathname.indexOf(baseHref) === 0) {
|
||||
parsedUrl.pathname = parsedUrl.pathname.substring(baseHref.length);
|
||||
}
|
||||
return {
|
||||
hostname: (!serverBase && parsedUrl.hostname) || '',
|
||||
protocol: (!serverBase && parsedUrl.protocol) || '',
|
||||
port: (!serverBase && parsedUrl.port) || '',
|
||||
pathname: parsedUrl.pathname || '/',
|
||||
search: parsedUrl.search || '',
|
||||
hash: parsedUrl.hash || '',
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Provider for mock platform location config
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
const MOCK_PLATFORM_LOCATION_CONFIG = new InjectionToken('MOCK_PLATFORM_LOCATION_CONFIG');
|
||||
/**
|
||||
* Mock implementation of URL state.
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
class MockPlatformLocation {
|
||||
constructor(config) {
|
||||
this.baseHref = '';
|
||||
this.hashUpdate = new Subject();
|
||||
this.popStateSubject = new Subject();
|
||||
this.urlChangeIndex = 0;
|
||||
this.urlChanges = [{ hostname: '', protocol: '', port: '', pathname: '/', search: '', hash: '', state: null }];
|
||||
if (config) {
|
||||
this.baseHref = config.appBaseHref || '';
|
||||
const parsedChanges = this.parseChanges(null, config.startUrl || 'http://_empty_/', this.baseHref);
|
||||
this.urlChanges[0] = { ...parsedChanges };
|
||||
}
|
||||
}
|
||||
get hostname() {
|
||||
return this.urlChanges[this.urlChangeIndex].hostname;
|
||||
}
|
||||
get protocol() {
|
||||
return this.urlChanges[this.urlChangeIndex].protocol;
|
||||
}
|
||||
get port() {
|
||||
return this.urlChanges[this.urlChangeIndex].port;
|
||||
}
|
||||
get pathname() {
|
||||
return this.urlChanges[this.urlChangeIndex].pathname;
|
||||
}
|
||||
get search() {
|
||||
return this.urlChanges[this.urlChangeIndex].search;
|
||||
}
|
||||
get hash() {
|
||||
return this.urlChanges[this.urlChangeIndex].hash;
|
||||
}
|
||||
get state() {
|
||||
return this.urlChanges[this.urlChangeIndex].state;
|
||||
}
|
||||
getBaseHrefFromDOM() {
|
||||
return this.baseHref;
|
||||
}
|
||||
onPopState(fn) {
|
||||
const subscription = this.popStateSubject.subscribe(fn);
|
||||
return () => subscription.unsubscribe();
|
||||
}
|
||||
onHashChange(fn) {
|
||||
const subscription = this.hashUpdate.subscribe(fn);
|
||||
return () => subscription.unsubscribe();
|
||||
}
|
||||
get href() {
|
||||
let url = `${this.protocol}//${this.hostname}${this.port ? ':' + this.port : ''}`;
|
||||
url += `${this.pathname === '/' ? '' : this.pathname}${this.search}${this.hash}`;
|
||||
return url;
|
||||
}
|
||||
get url() {
|
||||
return `${this.pathname}${this.search}${this.hash}`;
|
||||
}
|
||||
parseChanges(state, url, baseHref = '') {
|
||||
// When the `history.state` value is stored, it is always copied.
|
||||
state = JSON.parse(JSON.stringify(state));
|
||||
return { ...parseUrl(url, baseHref), state };
|
||||
}
|
||||
replaceState(state, title, newUrl) {
|
||||
const { pathname, search, state: parsedState, hash } = this.parseChanges(state, newUrl);
|
||||
this.urlChanges[this.urlChangeIndex] = {
|
||||
...this.urlChanges[this.urlChangeIndex],
|
||||
pathname,
|
||||
search,
|
||||
hash,
|
||||
state: parsedState,
|
||||
};
|
||||
}
|
||||
pushState(state, title, newUrl) {
|
||||
const { pathname, search, state: parsedState, hash } = this.parseChanges(state, newUrl);
|
||||
if (this.urlChangeIndex > 0) {
|
||||
this.urlChanges.splice(this.urlChangeIndex + 1);
|
||||
}
|
||||
this.urlChanges.push({
|
||||
...this.urlChanges[this.urlChangeIndex],
|
||||
pathname,
|
||||
search,
|
||||
hash,
|
||||
state: parsedState,
|
||||
});
|
||||
this.urlChangeIndex = this.urlChanges.length - 1;
|
||||
}
|
||||
forward() {
|
||||
const oldUrl = this.url;
|
||||
const oldHash = this.hash;
|
||||
if (this.urlChangeIndex < this.urlChanges.length) {
|
||||
this.urlChangeIndex++;
|
||||
}
|
||||
this.emitEvents(oldHash, oldUrl);
|
||||
}
|
||||
back() {
|
||||
const oldUrl = this.url;
|
||||
const oldHash = this.hash;
|
||||
if (this.urlChangeIndex > 0) {
|
||||
this.urlChangeIndex--;
|
||||
}
|
||||
this.emitEvents(oldHash, oldUrl);
|
||||
}
|
||||
historyGo(relativePosition = 0) {
|
||||
const oldUrl = this.url;
|
||||
const oldHash = this.hash;
|
||||
const nextPageIndex = this.urlChangeIndex + relativePosition;
|
||||
if (nextPageIndex >= 0 && nextPageIndex < this.urlChanges.length) {
|
||||
this.urlChangeIndex = nextPageIndex;
|
||||
}
|
||||
this.emitEvents(oldHash, oldUrl);
|
||||
}
|
||||
getState() {
|
||||
return this.state;
|
||||
}
|
||||
/**
|
||||
* Browsers are inconsistent in when they fire events and perform the state updates
|
||||
* The most easiest thing to do in our mock is synchronous and that happens to match
|
||||
* Firefox and Chrome, at least somewhat closely
|
||||
*
|
||||
* https://github.com/WICG/navigation-api#watching-for-navigations
|
||||
* https://docs.google.com/document/d/1Pdve-DJ1JCGilj9Yqf5HxRJyBKSel5owgOvUJqTauwU/edit#heading=h.3ye4v71wsz94
|
||||
* popstate is always sent before hashchange:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event#when_popstate_is_sent
|
||||
*/
|
||||
emitEvents(oldHash, oldUrl) {
|
||||
this.popStateSubject.next({
|
||||
type: 'popstate',
|
||||
state: this.getState(),
|
||||
oldUrl,
|
||||
newUrl: this.url,
|
||||
});
|
||||
if (oldHash !== this.hash) {
|
||||
this.hashUpdate.next({
|
||||
type: 'hashchange',
|
||||
state: null,
|
||||
oldUrl,
|
||||
newUrl: this.url,
|
||||
});
|
||||
}
|
||||
}
|
||||
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: MockPlatformLocation, deps: [{ token: MOCK_PLATFORM_LOCATION_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
||||
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: MockPlatformLocation }); }
|
||||
}
|
||||
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: MockPlatformLocation, decorators: [{
|
||||
type: Injectable
|
||||
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
||||
type: Inject,
|
||||
args: [MOCK_PLATFORM_LOCATION_CONFIG]
|
||||
}, {
|
||||
type: Optional
|
||||
}] }] });
|
||||
|
||||
/**
|
||||
* Returns mock providers for the `Location` and `LocationStrategy` classes.
|
||||
* The mocks are helpful in tests to fire simulated location events.
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
function provideLocationMocks() {
|
||||
return [
|
||||
{ provide: Location, useClass: SpyLocation },
|
||||
{ provide: LocationStrategy, useClass: MockLocationStrategy },
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @module
|
||||
* @description
|
||||
* Entry point for all public APIs of the common/testing package.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @module
|
||||
* @description
|
||||
* Entry point for all public APIs of this package.
|
||||
*/
|
||||
// This file only reexports content of the `src` folder. Keep it that way.
|
||||
|
||||
// This file is not used to build this module. It is only used during editing
|
||||
|
||||
/**
|
||||
* Generated bundle index. Do not edit.
|
||||
*/
|
||||
|
||||
export { MOCK_PLATFORM_LOCATION_CONFIG, MockLocationStrategy, MockPlatformLocation, SpyLocation, provideLocationMocks };
|
||||
//# sourceMappingURL=testing.mjs.map
|
1
my-app/node_modules/@angular/common/fesm2022/testing.mjs.map
generated
vendored
Executable file
1
my-app/node_modules/@angular/common/fesm2022/testing.mjs.map
generated
vendored
Executable file
File diff suppressed because one or more lines are too long
889
my-app/node_modules/@angular/common/fesm2022/upgrade.mjs
generated
vendored
Executable file
889
my-app/node_modules/@angular/common/fesm2022/upgrade.mjs
generated
vendored
Executable file
|
@ -0,0 +1,889 @@
|
|||
/**
|
||||
* @license Angular v17.1.3
|
||||
* (c) 2010-2022 Google LLC. https://angular.io/
|
||||
* License: MIT
|
||||
*/
|
||||
|
||||
import * as i0 from '@angular/core';
|
||||
import { ɵisPromise, InjectionToken, Inject, Optional, NgModule } from '@angular/core';
|
||||
import { ReplaySubject } from 'rxjs';
|
||||
import { Location, PlatformLocation, LocationStrategy, APP_BASE_HREF, CommonModule, HashLocationStrategy, PathLocationStrategy } from '@angular/common';
|
||||
import { UpgradeModule } from '@angular/upgrade/static';
|
||||
|
||||
function stripPrefix(val, prefix) {
|
||||
return val.startsWith(prefix) ? val.substring(prefix.length) : val;
|
||||
}
|
||||
function deepEqual(a, b) {
|
||||
if (a === b) {
|
||||
return true;
|
||||
}
|
||||
else if (!a || !b) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
try {
|
||||
if (a.prototype !== b.prototype || (Array.isArray(a) && Array.isArray(b))) {
|
||||
return false;
|
||||
}
|
||||
return JSON.stringify(a) === JSON.stringify(b);
|
||||
}
|
||||
catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
function isAnchor(el) {
|
||||
return el.href !== undefined;
|
||||
}
|
||||
|
||||
const PATH_MATCH = /^([^?#]*)(\?([^#]*))?(#(.*))?$/;
|
||||
const DOUBLE_SLASH_REGEX = /^\s*[\\/]{2,}/;
|
||||
const IGNORE_URI_REGEXP = /^\s*(javascript|mailto):/i;
|
||||
const DEFAULT_PORTS = {
|
||||
'http:': 80,
|
||||
'https:': 443,
|
||||
'ftp:': 21,
|
||||
};
|
||||
/**
|
||||
* Location service that provides a drop-in replacement for the $location service
|
||||
* provided in AngularJS.
|
||||
*
|
||||
* @see [Using the Angular Unified Location Service](guide/upgrade#using-the-unified-angular-location-service)
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
class $locationShim {
|
||||
constructor($injector, location, platformLocation, urlCodec, locationStrategy) {
|
||||
this.location = location;
|
||||
this.platformLocation = platformLocation;
|
||||
this.urlCodec = urlCodec;
|
||||
this.locationStrategy = locationStrategy;
|
||||
this.initializing = true;
|
||||
this.updateBrowser = false;
|
||||
this.$$absUrl = '';
|
||||
this.$$url = '';
|
||||
this.$$host = '';
|
||||
this.$$replace = false;
|
||||
this.$$path = '';
|
||||
this.$$search = '';
|
||||
this.$$hash = '';
|
||||
this.$$changeListeners = [];
|
||||
this.cachedState = null;
|
||||
this.urlChanges = new ReplaySubject(1);
|
||||
this.lastBrowserUrl = '';
|
||||
// This variable should be used *only* inside the cacheState function.
|
||||
this.lastCachedState = null;
|
||||
const initialUrl = this.browserUrl();
|
||||
let parsedUrl = this.urlCodec.parse(initialUrl);
|
||||
if (typeof parsedUrl === 'string') {
|
||||
throw 'Invalid URL';
|
||||
}
|
||||
this.$$protocol = parsedUrl.protocol;
|
||||
this.$$host = parsedUrl.hostname;
|
||||
this.$$port = parseInt(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;
|
||||
this.$$parseLinkUrl(initialUrl, initialUrl);
|
||||
this.cacheState();
|
||||
this.$$state = this.browserState();
|
||||
this.location.onUrlChange((newUrl, newState) => {
|
||||
this.urlChanges.next({ newUrl, newState });
|
||||
});
|
||||
if (ɵisPromise($injector)) {
|
||||
$injector.then(($i) => this.initialize($i));
|
||||
}
|
||||
else {
|
||||
this.initialize($injector);
|
||||
}
|
||||
}
|
||||
initialize($injector) {
|
||||
const $rootScope = $injector.get('$rootScope');
|
||||
const $rootElement = $injector.get('$rootElement');
|
||||
$rootElement.on('click', (event) => {
|
||||
if (event.ctrlKey ||
|
||||
event.metaKey ||
|
||||
event.shiftKey ||
|
||||
event.which === 2 ||
|
||||
event.button === 2) {
|
||||
return;
|
||||
}
|
||||
let elm = event.target;
|
||||
// traverse the DOM up to find first A tag
|
||||
while (elm && elm.nodeName.toLowerCase() !== 'a') {
|
||||
// ignore rewriting if no A tag (reached root element, or no parent - removed from document)
|
||||
if (elm === $rootElement[0] || !(elm = elm.parentNode)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!isAnchor(elm)) {
|
||||
return;
|
||||
}
|
||||
const absHref = elm.href;
|
||||
const relHref = elm.getAttribute('href');
|
||||
// Ignore when url is started with javascript: or mailto:
|
||||
if (IGNORE_URI_REGEXP.test(absHref)) {
|
||||
return;
|
||||
}
|
||||
if (absHref && !elm.getAttribute('target') && !event.isDefaultPrevented()) {
|
||||
if (this.$$parseLinkUrl(absHref, relHref)) {
|
||||
// We do a preventDefault for all urls that are part of the AngularJS application,
|
||||
// in html5mode and also without, so that we are able to abort navigation without
|
||||
// getting double entries in the location history.
|
||||
event.preventDefault();
|
||||
// update location manually
|
||||
if (this.absUrl() !== this.browserUrl()) {
|
||||
$rootScope.$apply();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
this.urlChanges.subscribe(({ newUrl, newState }) => {
|
||||
const oldUrl = this.absUrl();
|
||||
const oldState = this.$$state;
|
||||
this.$$parse(newUrl);
|
||||
newUrl = this.absUrl();
|
||||
this.$$state = newState;
|
||||
const defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl, newState, oldState).defaultPrevented;
|
||||
// if the location was changed by a `$locationChangeStart` handler then stop
|
||||
// processing this location change
|
||||
if (this.absUrl() !== newUrl)
|
||||
return;
|
||||
// If default was prevented, set back to old state. This is the state that was locally
|
||||
// cached in the $location service.
|
||||
if (defaultPrevented) {
|
||||
this.$$parse(oldUrl);
|
||||
this.state(oldState);
|
||||
this.setBrowserUrlWithFallback(oldUrl, false, oldState);
|
||||
this.$$notifyChangeListeners(this.url(), this.$$state, oldUrl, oldState);
|
||||
}
|
||||
else {
|
||||
this.initializing = false;
|
||||
$rootScope.$broadcast('$locationChangeSuccess', newUrl, oldUrl, newState, oldState);
|
||||
this.resetBrowserUpdate();
|
||||
}
|
||||
if (!$rootScope.$$phase) {
|
||||
$rootScope.$digest();
|
||||
}
|
||||
});
|
||||
// update browser
|
||||
$rootScope.$watch(() => {
|
||||
if (this.initializing || this.updateBrowser) {
|
||||
this.updateBrowser = false;
|
||||
const oldUrl = this.browserUrl();
|
||||
const newUrl = this.absUrl();
|
||||
const oldState = this.browserState();
|
||||
let currentReplace = this.$$replace;
|
||||
const urlOrStateChanged = !this.urlCodec.areEqual(oldUrl, newUrl) || oldState !== this.$$state;
|
||||
// Fire location changes one time to on initialization. This must be done on the
|
||||
// next tick (thus inside $evalAsync()) in order for listeners to be registered
|
||||
// before the event fires. Mimicing behavior from $locationWatch:
|
||||
// https://github.com/angular/angular.js/blob/master/src/ng/location.js#L983
|
||||
if (this.initializing || urlOrStateChanged) {
|
||||
this.initializing = false;
|
||||
$rootScope.$evalAsync(() => {
|
||||
// Get the new URL again since it could have changed due to async update
|
||||
const newUrl = this.absUrl();
|
||||
const defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl, this.$$state, oldState).defaultPrevented;
|
||||
// if the location was changed by a `$locationChangeStart` handler then stop
|
||||
// processing this location change
|
||||
if (this.absUrl() !== newUrl)
|
||||
return;
|
||||
if (defaultPrevented) {
|
||||
this.$$parse(oldUrl);
|
||||
this.$$state = oldState;
|
||||
}
|
||||
else {
|
||||
// This block doesn't run when initializing because it's going to perform the update
|
||||
// to the URL which shouldn't be needed when initializing.
|
||||
if (urlOrStateChanged) {
|
||||
this.setBrowserUrlWithFallback(newUrl, currentReplace, oldState === this.$$state ? null : this.$$state);
|
||||
this.$$replace = false;
|
||||
}
|
||||
$rootScope.$broadcast('$locationChangeSuccess', newUrl, oldUrl, this.$$state, oldState);
|
||||
if (urlOrStateChanged) {
|
||||
this.$$notifyChangeListeners(this.url(), this.$$state, oldUrl, oldState);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
this.$$replace = false;
|
||||
});
|
||||
}
|
||||
resetBrowserUpdate() {
|
||||
this.$$replace = false;
|
||||
this.$$state = this.browserState();
|
||||
this.updateBrowser = false;
|
||||
this.lastBrowserUrl = this.browserUrl();
|
||||
}
|
||||
browserUrl(url, replace, state) {
|
||||
// In modern browsers `history.state` is `null` by default; treating it separately
|
||||
// from `undefined` would cause `$browser.url('/foo')` to change `history.state`
|
||||
// to undefined via `pushState`. Instead, let's change `undefined` to `null` here.
|
||||
if (typeof state === 'undefined') {
|
||||
state = null;
|
||||
}
|
||||
// setter
|
||||
if (url) {
|
||||
let sameState = this.lastHistoryState === state;
|
||||
// Normalize the inputted URL
|
||||
url = this.urlCodec.parse(url).href;
|
||||
// Don't change anything if previous and current URLs and states match.
|
||||
if (this.lastBrowserUrl === url && sameState) {
|
||||
return this;
|
||||
}
|
||||
this.lastBrowserUrl = url;
|
||||
this.lastHistoryState = state;
|
||||
// Remove server base from URL as the Angular APIs for updating URL require
|
||||
// it to be the path+.
|
||||
url = this.stripBaseUrl(this.getServerBase(), url) || url;
|
||||
// Set the URL
|
||||
if (replace) {
|
||||
this.locationStrategy.replaceState(state, '', url, '');
|
||||
}
|
||||
else {
|
||||
this.locationStrategy.pushState(state, '', url, '');
|
||||
}
|
||||
this.cacheState();
|
||||
return this;
|
||||
// getter
|
||||
}
|
||||
else {
|
||||
return this.platformLocation.href;
|
||||
}
|
||||
}
|
||||
cacheState() {
|
||||
// This should be the only place in $browser where `history.state` is read.
|
||||
this.cachedState = this.platformLocation.getState();
|
||||
if (typeof this.cachedState === 'undefined') {
|
||||
this.cachedState = null;
|
||||
}
|
||||
// Prevent callbacks fo fire twice if both hashchange & popstate were fired.
|
||||
if (deepEqual(this.cachedState, this.lastCachedState)) {
|
||||
this.cachedState = this.lastCachedState;
|
||||
}
|
||||
this.lastCachedState = this.cachedState;
|
||||
this.lastHistoryState = this.cachedState;
|
||||
}
|
||||
/**
|
||||
* This function emulates the $browser.state() function from AngularJS. It will cause
|
||||
* history.state to be cached unless changed with deep equality check.
|
||||
*/
|
||||
browserState() {
|
||||
return this.cachedState;
|
||||
}
|
||||
stripBaseUrl(base, url) {
|
||||
if (url.startsWith(base)) {
|
||||
return url.slice(base.length);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
getServerBase() {
|
||||
const { protocol, hostname, port } = this.platformLocation;
|
||||
const baseHref = this.locationStrategy.getBaseHref();
|
||||
let url = `${protocol}//${hostname}${port ? ':' + port : ''}${baseHref || '/'}`;
|
||||
return url.endsWith('/') ? url : url + '/';
|
||||
}
|
||||
parseAppUrl(url) {
|
||||
if (DOUBLE_SLASH_REGEX.test(url)) {
|
||||
throw new Error(`Bad Path - URL cannot start with double slashes: ${url}`);
|
||||
}
|
||||
let prefixed = url.charAt(0) !== '/';
|
||||
if (prefixed) {
|
||||
url = '/' + url;
|
||||
}
|
||||
let match = this.urlCodec.parse(url, this.getServerBase());
|
||||
if (typeof match === 'string') {
|
||||
throw new Error(`Bad URL - Cannot parse URL: ${url}`);
|
||||
}
|
||||
let path = prefixed && match.pathname.charAt(0) === '/' ? match.pathname.substring(1) : match.pathname;
|
||||
this.$$path = this.urlCodec.decodePath(path);
|
||||
this.$$search = this.urlCodec.decodeSearch(match.search);
|
||||
this.$$hash = this.urlCodec.decodeHash(match.hash);
|
||||
// make sure path starts with '/';
|
||||
if (this.$$path && this.$$path.charAt(0) !== '/') {
|
||||
this.$$path = '/' + this.$$path;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Registers listeners for URL changes. This API is used to catch updates performed by the
|
||||
* AngularJS framework. These changes are a subset of the `$locationChangeStart` and
|
||||
* `$locationChangeSuccess` events which fire when AngularJS updates its internally-referenced
|
||||
* version of the browser URL.
|
||||
*
|
||||
* It's possible for `$locationChange` events to happen, but for the browser URL
|
||||
* (window.location) to remain unchanged. This `onChange` callback will fire only when AngularJS
|
||||
* actually updates the browser URL (window.location).
|
||||
*
|
||||
* @param fn The callback function that is triggered for the listener when the URL changes.
|
||||
* @param err The callback function that is triggered when an error occurs.
|
||||
*/
|
||||
onChange(fn, err = (e) => { }) {
|
||||
this.$$changeListeners.push([fn, err]);
|
||||
}
|
||||
/** @internal */
|
||||
$$notifyChangeListeners(url = '', state, oldUrl = '', oldState) {
|
||||
this.$$changeListeners.forEach(([fn, err]) => {
|
||||
try {
|
||||
fn(url, state, oldUrl, oldState);
|
||||
}
|
||||
catch (e) {
|
||||
err(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Parses the provided URL, and sets the current URL to the parsed result.
|
||||
*
|
||||
* @param url The URL string.
|
||||
*/
|
||||
$$parse(url) {
|
||||
let pathUrl;
|
||||
if (url.startsWith('/')) {
|
||||
pathUrl = url;
|
||||
}
|
||||
else {
|
||||
// Remove protocol & hostname if URL starts with it
|
||||
pathUrl = this.stripBaseUrl(this.getServerBase(), url);
|
||||
}
|
||||
if (typeof pathUrl === 'undefined') {
|
||||
throw new Error(`Invalid url "${url}", missing path prefix "${this.getServerBase()}".`);
|
||||
}
|
||||
this.parseAppUrl(pathUrl);
|
||||
this.$$path ||= '/';
|
||||
this.composeUrls();
|
||||
}
|
||||
/**
|
||||
* Parses the provided URL and its relative URL.
|
||||
*
|
||||
* @param url The full URL string.
|
||||
* @param relHref A URL string relative to the full URL string.
|
||||
*/
|
||||
$$parseLinkUrl(url, relHref) {
|
||||
// When relHref is passed, it should be a hash and is handled separately
|
||||
if (relHref && relHref[0] === '#') {
|
||||
this.hash(relHref.slice(1));
|
||||
return true;
|
||||
}
|
||||
let rewrittenUrl;
|
||||
let appUrl = this.stripBaseUrl(this.getServerBase(), url);
|
||||
if (typeof appUrl !== 'undefined') {
|
||||
rewrittenUrl = this.getServerBase() + appUrl;
|
||||
}
|
||||
else if (this.getServerBase() === url + '/') {
|
||||
rewrittenUrl = this.getServerBase();
|
||||
}
|
||||
// Set the URL
|
||||
if (rewrittenUrl) {
|
||||
this.$$parse(rewrittenUrl);
|
||||
}
|
||||
return !!rewrittenUrl;
|
||||
}
|
||||
setBrowserUrlWithFallback(url, replace, state) {
|
||||
const oldUrl = this.url();
|
||||
const oldState = this.$$state;
|
||||
try {
|
||||
this.browserUrl(url, replace, state);
|
||||
// Make sure $location.state() returns referentially identical (not just deeply equal)
|
||||
// state object; this makes possible quick checking if the state changed in the digest
|
||||
// loop. Checking deep equality would be too expensive.
|
||||
this.$$state = this.browserState();
|
||||
}
|
||||
catch (e) {
|
||||
// Restore old values if pushState fails
|
||||
this.url(oldUrl);
|
||||
this.$$state = oldState;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
composeUrls() {
|
||||
this.$$url = this.urlCodec.normalize(this.$$path, this.$$search, this.$$hash);
|
||||
this.$$absUrl = this.getServerBase() + this.$$url.slice(1); // remove '/' from front of URL
|
||||
this.updateBrowser = true;
|
||||
}
|
||||
/**
|
||||
* Retrieves the full URL representation with all segments encoded according to
|
||||
* rules specified in
|
||||
* [RFC 3986](https://tools.ietf.org/html/rfc3986).
|
||||
*
|
||||
*
|
||||
* ```js
|
||||
* // given URL http://example.com/#/some/path?foo=bar&baz=xoxo
|
||||
* let absUrl = $location.absUrl();
|
||||
* // => "http://example.com/#/some/path?foo=bar&baz=xoxo"
|
||||
* ```
|
||||
*/
|
||||
absUrl() {
|
||||
return this.$$absUrl;
|
||||
}
|
||||
url(url) {
|
||||
if (typeof url === 'string') {
|
||||
if (!url.length) {
|
||||
url = '/';
|
||||
}
|
||||
const match = PATH_MATCH.exec(url);
|
||||
if (!match)
|
||||
return this;
|
||||
if (match[1] || url === '')
|
||||
this.path(this.urlCodec.decodePath(match[1]));
|
||||
if (match[2] || match[1] || url === '')
|
||||
this.search(match[3] || '');
|
||||
this.hash(match[5] || '');
|
||||
// Chainable method
|
||||
return this;
|
||||
}
|
||||
return this.$$url;
|
||||
}
|
||||
/**
|
||||
* Retrieves the protocol of the current URL.
|
||||
*
|
||||
* ```js
|
||||
* // given URL http://example.com/#/some/path?foo=bar&baz=xoxo
|
||||
* let protocol = $location.protocol();
|
||||
* // => "http"
|
||||
* ```
|
||||
*/
|
||||
protocol() {
|
||||
return this.$$protocol;
|
||||
}
|
||||
/**
|
||||
* Retrieves the protocol of the current URL.
|
||||
*
|
||||
* In contrast to the non-AngularJS version `location.host` which returns `hostname:port`, this
|
||||
* returns the `hostname` portion only.
|
||||
*
|
||||
*
|
||||
* ```js
|
||||
* // given URL http://example.com/#/some/path?foo=bar&baz=xoxo
|
||||
* let host = $location.host();
|
||||
* // => "example.com"
|
||||
*
|
||||
* // given URL http://user:password@example.com:8080/#/some/path?foo=bar&baz=xoxo
|
||||
* host = $location.host();
|
||||
* // => "example.com"
|
||||
* host = location.host;
|
||||
* // => "example.com:8080"
|
||||
* ```
|
||||
*/
|
||||
host() {
|
||||
return this.$$host;
|
||||
}
|
||||
/**
|
||||
* Retrieves the port of the current URL.
|
||||
*
|
||||
* ```js
|
||||
* // given URL http://example.com/#/some/path?foo=bar&baz=xoxo
|
||||
* let port = $location.port();
|
||||
* // => 80
|
||||
* ```
|
||||
*/
|
||||
port() {
|
||||
return this.$$port;
|
||||
}
|
||||
path(path) {
|
||||
if (typeof path === 'undefined') {
|
||||
return this.$$path;
|
||||
}
|
||||
// null path converts to empty string. Prepend with "/" if needed.
|
||||
path = path !== null ? path.toString() : '';
|
||||
path = path.charAt(0) === '/' ? path : '/' + path;
|
||||
this.$$path = path;
|
||||
this.composeUrls();
|
||||
return this;
|
||||
}
|
||||
search(search, paramValue) {
|
||||
switch (arguments.length) {
|
||||
case 0:
|
||||
return this.$$search;
|
||||
case 1:
|
||||
if (typeof search === 'string' || typeof search === 'number') {
|
||||
this.$$search = this.urlCodec.decodeSearch(search.toString());
|
||||
}
|
||||
else if (typeof search === 'object' && search !== null) {
|
||||
// Copy the object so it's never mutated
|
||||
search = { ...search };
|
||||
// remove object undefined or null properties
|
||||
for (const key in search) {
|
||||
if (search[key] == null)
|
||||
delete search[key];
|
||||
}
|
||||
this.$$search = search;
|
||||
}
|
||||
else {
|
||||
throw new Error('LocationProvider.search(): First argument must be a string or an object.');
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (typeof search === 'string') {
|
||||
const currentSearch = this.search();
|
||||
if (typeof paramValue === 'undefined' || paramValue === null) {
|
||||
delete currentSearch[search];
|
||||
return this.search(currentSearch);
|
||||
}
|
||||
else {
|
||||
currentSearch[search] = paramValue;
|
||||
return this.search(currentSearch);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.composeUrls();
|
||||
return this;
|
||||
}
|
||||
hash(hash) {
|
||||
if (typeof hash === 'undefined') {
|
||||
return this.$$hash;
|
||||
}
|
||||
this.$$hash = hash !== null ? hash.toString() : '';
|
||||
this.composeUrls();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Changes to `$location` during the current `$digest` will replace the current
|
||||
* history record, instead of adding a new one.
|
||||
*/
|
||||
replace() {
|
||||
this.$$replace = true;
|
||||
return this;
|
||||
}
|
||||
state(state) {
|
||||
if (typeof state === 'undefined') {
|
||||
return this.$$state;
|
||||
}
|
||||
this.$$state = state;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* The factory function used to create an instance of the `$locationShim` in Angular,
|
||||
* and provides an API-compatible `$locationProvider` for AngularJS.
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
class $locationShimProvider {
|
||||
constructor(ngUpgrade, location, platformLocation, urlCodec, locationStrategy) {
|
||||
this.ngUpgrade = ngUpgrade;
|
||||
this.location = location;
|
||||
this.platformLocation = platformLocation;
|
||||
this.urlCodec = urlCodec;
|
||||
this.locationStrategy = locationStrategy;
|
||||
}
|
||||
/**
|
||||
* Factory method that returns an instance of the $locationShim
|
||||
*/
|
||||
$get() {
|
||||
return new $locationShim(this.ngUpgrade.$injector, this.location, this.platformLocation, this.urlCodec, this.locationStrategy);
|
||||
}
|
||||
/**
|
||||
* Stub method used to keep API compatible with AngularJS. This setting is configured through
|
||||
* the LocationUpgradeModule's `config` method in your Angular app.
|
||||
*/
|
||||
hashPrefix(prefix) {
|
||||
throw new Error('Configure LocationUpgrade through LocationUpgradeModule.config method.');
|
||||
}
|
||||
/**
|
||||
* Stub method used to keep API compatible with AngularJS. This setting is configured through
|
||||
* the LocationUpgradeModule's `config` method in your Angular app.
|
||||
*/
|
||||
html5Mode(mode) {
|
||||
throw new Error('Configure LocationUpgrade through LocationUpgradeModule.config method.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A codec for encoding and decoding URL parts.
|
||||
*
|
||||
* @publicApi
|
||||
**/
|
||||
class UrlCodec {
|
||||
}
|
||||
/**
|
||||
* A `UrlCodec` that uses logic from AngularJS to serialize and parse URLs
|
||||
* and URL parameters.
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
class AngularJSUrlCodec {
|
||||
// https://github.com/angular/angular.js/blob/864c7f0/src/ng/location.js#L15
|
||||
encodePath(path) {
|
||||
const segments = path.split('/');
|
||||
let i = segments.length;
|
||||
while (i--) {
|
||||
// decode forward slashes to prevent them from being double encoded
|
||||
segments[i] = encodeUriSegment(segments[i].replace(/%2F/g, '/'));
|
||||
}
|
||||
path = segments.join('/');
|
||||
return _stripIndexHtml(((path && path[0] !== '/' && '/') || '') + path);
|
||||
}
|
||||
// https://github.com/angular/angular.js/blob/864c7f0/src/ng/location.js#L42
|
||||
encodeSearch(search) {
|
||||
if (typeof search === 'string') {
|
||||
search = parseKeyValue(search);
|
||||
}
|
||||
search = toKeyValue(search);
|
||||
return search ? '?' + search : '';
|
||||
}
|
||||
// https://github.com/angular/angular.js/blob/864c7f0/src/ng/location.js#L44
|
||||
encodeHash(hash) {
|
||||
hash = encodeUriSegment(hash);
|
||||
return hash ? '#' + hash : '';
|
||||
}
|
||||
// https://github.com/angular/angular.js/blob/864c7f0/src/ng/location.js#L27
|
||||
decodePath(path, html5Mode = true) {
|
||||
const segments = path.split('/');
|
||||
let i = segments.length;
|
||||
while (i--) {
|
||||
segments[i] = decodeURIComponent(segments[i]);
|
||||
if (html5Mode) {
|
||||
// encode forward slashes to prevent them from being mistaken for path separators
|
||||
segments[i] = segments[i].replace(/\//g, '%2F');
|
||||
}
|
||||
}
|
||||
return segments.join('/');
|
||||
}
|
||||
// https://github.com/angular/angular.js/blob/864c7f0/src/ng/location.js#L72
|
||||
decodeSearch(search) {
|
||||
return parseKeyValue(search);
|
||||
}
|
||||
// https://github.com/angular/angular.js/blob/864c7f0/src/ng/location.js#L73
|
||||
decodeHash(hash) {
|
||||
hash = decodeURIComponent(hash);
|
||||
return hash[0] === '#' ? hash.substring(1) : hash;
|
||||
}
|
||||
normalize(pathOrHref, search, hash, baseUrl) {
|
||||
if (arguments.length === 1) {
|
||||
const parsed = this.parse(pathOrHref, baseUrl);
|
||||
if (typeof parsed === 'string') {
|
||||
return parsed;
|
||||
}
|
||||
const serverUrl = `${parsed.protocol}://${parsed.hostname}${parsed.port ? ':' + parsed.port : ''}`;
|
||||
return this.normalize(this.decodePath(parsed.pathname), this.decodeSearch(parsed.search), this.decodeHash(parsed.hash), serverUrl);
|
||||
}
|
||||
else {
|
||||
const encPath = this.encodePath(pathOrHref);
|
||||
const encSearch = (search && this.encodeSearch(search)) || '';
|
||||
const encHash = (hash && this.encodeHash(hash)) || '';
|
||||
let joinedPath = (baseUrl || '') + encPath;
|
||||
if (!joinedPath.length || joinedPath[0] !== '/') {
|
||||
joinedPath = '/' + joinedPath;
|
||||
}
|
||||
return joinedPath + encSearch + encHash;
|
||||
}
|
||||
}
|
||||
areEqual(valA, valB) {
|
||||
return this.normalize(valA) === this.normalize(valB);
|
||||
}
|
||||
// https://github.com/angular/angular.js/blob/864c7f0/src/ng/urlUtils.js#L60
|
||||
parse(url, base) {
|
||||
try {
|
||||
// Safari 12 throws an error when the URL constructor is called with an undefined base.
|
||||
const parsed = !base ? new URL(url) : new URL(url, base);
|
||||
return {
|
||||
href: parsed.href,
|
||||
protocol: parsed.protocol ? parsed.protocol.replace(/:$/, '') : '',
|
||||
host: parsed.host,
|
||||
search: parsed.search ? parsed.search.replace(/^\?/, '') : '',
|
||||
hash: parsed.hash ? parsed.hash.replace(/^#/, '') : '',
|
||||
hostname: parsed.hostname,
|
||||
port: parsed.port,
|
||||
pathname: parsed.pathname.charAt(0) === '/' ? parsed.pathname : '/' + parsed.pathname,
|
||||
};
|
||||
}
|
||||
catch (e) {
|
||||
throw new Error(`Invalid URL (${url}) with base (${base})`);
|
||||
}
|
||||
}
|
||||
}
|
||||
function _stripIndexHtml(url) {
|
||||
return url.replace(/\/index.html$/, '');
|
||||
}
|
||||
/**
|
||||
* Tries to decode the URI component without throwing an exception.
|
||||
*
|
||||
* @param str value potential URI component to check.
|
||||
* @returns the decoded URI if it can be decoded or else `undefined`.
|
||||
*/
|
||||
function tryDecodeURIComponent(value) {
|
||||
try {
|
||||
return decodeURIComponent(value);
|
||||
}
|
||||
catch (e) {
|
||||
// Ignore any invalid uri component.
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Parses an escaped url query string into key-value pairs. Logic taken from
|
||||
* https://github.com/angular/angular.js/blob/864c7f0/src/Angular.js#L1382
|
||||
*/
|
||||
function parseKeyValue(keyValue) {
|
||||
const obj = {};
|
||||
(keyValue || '').split('&').forEach((keyValue) => {
|
||||
let splitPoint, key, val;
|
||||
if (keyValue) {
|
||||
key = keyValue = keyValue.replace(/\+/g, '%20');
|
||||
splitPoint = keyValue.indexOf('=');
|
||||
if (splitPoint !== -1) {
|
||||
key = keyValue.substring(0, splitPoint);
|
||||
val = keyValue.substring(splitPoint + 1);
|
||||
}
|
||||
key = tryDecodeURIComponent(key);
|
||||
if (typeof key !== 'undefined') {
|
||||
val = typeof val !== 'undefined' ? tryDecodeURIComponent(val) : true;
|
||||
if (!obj.hasOwnProperty(key)) {
|
||||
obj[key] = val;
|
||||
}
|
||||
else if (Array.isArray(obj[key])) {
|
||||
obj[key].push(val);
|
||||
}
|
||||
else {
|
||||
obj[key] = [obj[key], val];
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return obj;
|
||||
}
|
||||
/**
|
||||
* Serializes into key-value pairs. Logic taken from
|
||||
* https://github.com/angular/angular.js/blob/864c7f0/src/Angular.js#L1409
|
||||
*/
|
||||
function toKeyValue(obj) {
|
||||
const parts = [];
|
||||
for (const key in obj) {
|
||||
let value = obj[key];
|
||||
if (Array.isArray(value)) {
|
||||
value.forEach((arrayValue) => {
|
||||
parts.push(encodeUriQuery(key, true) +
|
||||
(arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true)));
|
||||
});
|
||||
}
|
||||
else {
|
||||
parts.push(encodeUriQuery(key, true) +
|
||||
(value === true ? '' : '=' + encodeUriQuery(value, true)));
|
||||
}
|
||||
}
|
||||
return parts.length ? parts.join('&') : '';
|
||||
}
|
||||
/**
|
||||
* We need our custom method because encodeURIComponent is too aggressive and doesn't follow
|
||||
* https://tools.ietf.org/html/rfc3986 with regards to the character set (pchar) allowed in path
|
||||
* segments:
|
||||
* segment = *pchar
|
||||
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
|
||||
* pct-encoded = "%" HEXDIG HEXDIG
|
||||
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
||||
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
|
||||
* / "*" / "+" / "," / ";" / "="
|
||||
*
|
||||
* Logic from https://github.com/angular/angular.js/blob/864c7f0/src/Angular.js#L1437
|
||||
*/
|
||||
function encodeUriSegment(val) {
|
||||
return encodeUriQuery(val, true).replace(/%26/g, '&').replace(/%3D/gi, '=').replace(/%2B/gi, '+');
|
||||
}
|
||||
/**
|
||||
* This method is intended for encoding *key* or *value* parts of query component. We need a custom
|
||||
* method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be
|
||||
* encoded per https://tools.ietf.org/html/rfc3986:
|
||||
* query = *( pchar / "/" / "?" )
|
||||
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
|
||||
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
||||
* pct-encoded = "%" HEXDIG HEXDIG
|
||||
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
|
||||
* / "*" / "+" / "," / ";" / "="
|
||||
*
|
||||
* Logic from https://github.com/angular/angular.js/blob/864c7f0/src/Angular.js#L1456
|
||||
*/
|
||||
function encodeUriQuery(val, pctEncodeSpaces = false) {
|
||||
return encodeURIComponent(val)
|
||||
.replace(/%40/g, '@')
|
||||
.replace(/%3A/gi, ':')
|
||||
.replace(/%24/g, '$')
|
||||
.replace(/%2C/gi, ',')
|
||||
.replace(/%3B/gi, ';')
|
||||
.replace(/%20/g, pctEncodeSpaces ? '%20' : '+');
|
||||
}
|
||||
|
||||
/**
|
||||
* A provider token used to configure the location upgrade module.
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
const LOCATION_UPGRADE_CONFIGURATION = new InjectionToken(ngDevMode ? 'LOCATION_UPGRADE_CONFIGURATION' : '');
|
||||
const APP_BASE_HREF_RESOLVED = new InjectionToken(ngDevMode ? 'APP_BASE_HREF_RESOLVED' : '');
|
||||
/**
|
||||
* `NgModule` used for providing and configuring Angular's Unified Location Service for upgrading.
|
||||
*
|
||||
* @see [Using the Unified Angular Location Service](guide/upgrade#using-the-unified-angular-location-service)
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
class LocationUpgradeModule {
|
||||
static config(config) {
|
||||
return {
|
||||
ngModule: LocationUpgradeModule,
|
||||
providers: [
|
||||
Location,
|
||||
{
|
||||
provide: $locationShim,
|
||||
useFactory: provide$location,
|
||||
deps: [UpgradeModule, Location, PlatformLocation, UrlCodec, LocationStrategy],
|
||||
},
|
||||
{ provide: LOCATION_UPGRADE_CONFIGURATION, useValue: config ? config : {} },
|
||||
{ provide: UrlCodec, useFactory: provideUrlCodec, deps: [LOCATION_UPGRADE_CONFIGURATION] },
|
||||
{
|
||||
provide: APP_BASE_HREF_RESOLVED,
|
||||
useFactory: provideAppBaseHref,
|
||||
deps: [LOCATION_UPGRADE_CONFIGURATION, [new Inject(APP_BASE_HREF), new Optional()]],
|
||||
},
|
||||
{
|
||||
provide: LocationStrategy,
|
||||
useFactory: provideLocationStrategy,
|
||||
deps: [PlatformLocation, APP_BASE_HREF_RESOLVED, LOCATION_UPGRADE_CONFIGURATION],
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: LocationUpgradeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
||||
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.1.3", ngImport: i0, type: LocationUpgradeModule, imports: [CommonModule] }); }
|
||||
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: LocationUpgradeModule, imports: [CommonModule] }); }
|
||||
}
|
||||
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: LocationUpgradeModule, decorators: [{
|
||||
type: NgModule,
|
||||
args: [{ imports: [CommonModule] }]
|
||||
}] });
|
||||
function provideAppBaseHref(config, appBaseHref) {
|
||||
if (config && config.appBaseHref != null) {
|
||||
return config.appBaseHref;
|
||||
}
|
||||
else if (appBaseHref != null) {
|
||||
return appBaseHref;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
function provideUrlCodec(config) {
|
||||
const codec = (config && config.urlCodec) || AngularJSUrlCodec;
|
||||
return new codec();
|
||||
}
|
||||
function provideLocationStrategy(platformLocation, baseHref, options = {}) {
|
||||
return options.useHash
|
||||
? new HashLocationStrategy(platformLocation, baseHref)
|
||||
: new PathLocationStrategy(platformLocation, baseHref);
|
||||
}
|
||||
function provide$location(ngUpgrade, location, platformLocation, urlCodec, locationStrategy) {
|
||||
const $locationProvider = new $locationShimProvider(ngUpgrade, location, platformLocation, urlCodec, locationStrategy);
|
||||
return $locationProvider.$get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @module
|
||||
* @description
|
||||
* Entry point for all public APIs of this package.
|
||||
*/
|
||||
// This file only reexports content of the `src` folder. Keep it that way.
|
||||
|
||||
// This file is not used to build this module. It is only used during editing
|
||||
|
||||
/**
|
||||
* Generated bundle index. Do not edit.
|
||||
*/
|
||||
|
||||
export { $locationShim, $locationShimProvider, AngularJSUrlCodec, LOCATION_UPGRADE_CONFIGURATION, LocationUpgradeModule, UrlCodec };
|
||||
//# sourceMappingURL=upgrade.mjs.map
|
1
my-app/node_modules/@angular/common/fesm2022/upgrade.mjs.map
generated
vendored
Executable file
1
my-app/node_modules/@angular/common/fesm2022/upgrade.mjs.map
generated
vendored
Executable file
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue