location-Dq4mJT-A.mjs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. /**
  2. * @license Angular v19.2.13
  3. * (c) 2010-2025 Google LLC. https://angular.io/
  4. * License: MIT
  5. */
  6. import * as i0 from '@angular/core';
  7. import { InjectionToken, inject, Injectable, Optional, Inject, ɵɵinject as __inject } from '@angular/core';
  8. import { Subject } from 'rxjs';
  9. import { DOCUMENT } from './dom_tokens-rA0ACyx7.mjs';
  10. let _DOM = null;
  11. function getDOM() {
  12. return _DOM;
  13. }
  14. function setRootDomAdapter(adapter) {
  15. _DOM ??= adapter;
  16. }
  17. /**
  18. * Provides DOM operations in an environment-agnostic way.
  19. *
  20. * @security Tread carefully! Interacting with the DOM directly is dangerous and
  21. * can introduce XSS risks.
  22. */
  23. class DomAdapter {
  24. }
  25. /**
  26. * This class should not be used directly by an application developer. Instead, use
  27. * {@link Location}.
  28. *
  29. * `PlatformLocation` encapsulates all calls to DOM APIs, which allows the Router to be
  30. * platform-agnostic.
  31. * This means that we can have different implementation of `PlatformLocation` for the different
  32. * platforms that Angular supports. For example, `@angular/platform-browser` provides an
  33. * implementation specific to the browser environment, while `@angular/platform-server` provides
  34. * one suitable for use with server-side rendering.
  35. *
  36. * The `PlatformLocation` class is used directly by all implementations of {@link LocationStrategy}
  37. * when they need to interact with the DOM APIs like pushState, popState, etc.
  38. *
  39. * {@link LocationStrategy} in turn is used by the {@link Location} service which is used directly
  40. * by the {@link /api/router/Router Router} in order to navigate between routes. Since all interactions between
  41. * {@link /api/router/Router Router} /
  42. * {@link Location} / {@link LocationStrategy} and DOM APIs flow through the `PlatformLocation`
  43. * class, they are all platform-agnostic.
  44. *
  45. * @publicApi
  46. */
  47. class PlatformLocation {
  48. historyGo(relativePosition) {
  49. throw new Error(ngDevMode ? 'Not implemented' : '');
  50. }
  51. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PlatformLocation, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
  52. static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PlatformLocation, providedIn: 'platform', useFactory: () => inject(BrowserPlatformLocation) });
  53. }
  54. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PlatformLocation, decorators: [{
  55. type: Injectable,
  56. args: [{ providedIn: 'platform', useFactory: () => inject(BrowserPlatformLocation) }]
  57. }] });
  58. /**
  59. * @description
  60. * Indicates when a location is initialized.
  61. *
  62. * @publicApi
  63. */
  64. const LOCATION_INITIALIZED = new InjectionToken(ngDevMode ? 'Location Initialized' : '');
  65. /**
  66. * `PlatformLocation` encapsulates all of the direct calls to platform APIs.
  67. * This class should not be used directly by an application developer. Instead, use
  68. * {@link Location}.
  69. *
  70. * @publicApi
  71. */
  72. class BrowserPlatformLocation extends PlatformLocation {
  73. _location;
  74. _history;
  75. _doc = inject(DOCUMENT);
  76. constructor() {
  77. super();
  78. this._location = window.location;
  79. this._history = window.history;
  80. }
  81. getBaseHrefFromDOM() {
  82. return getDOM().getBaseHref(this._doc);
  83. }
  84. onPopState(fn) {
  85. const window = getDOM().getGlobalEventTarget(this._doc, 'window');
  86. window.addEventListener('popstate', fn, false);
  87. return () => window.removeEventListener('popstate', fn);
  88. }
  89. onHashChange(fn) {
  90. const window = getDOM().getGlobalEventTarget(this._doc, 'window');
  91. window.addEventListener('hashchange', fn, false);
  92. return () => window.removeEventListener('hashchange', fn);
  93. }
  94. get href() {
  95. return this._location.href;
  96. }
  97. get protocol() {
  98. return this._location.protocol;
  99. }
  100. get hostname() {
  101. return this._location.hostname;
  102. }
  103. get port() {
  104. return this._location.port;
  105. }
  106. get pathname() {
  107. return this._location.pathname;
  108. }
  109. get search() {
  110. return this._location.search;
  111. }
  112. get hash() {
  113. return this._location.hash;
  114. }
  115. set pathname(newPath) {
  116. this._location.pathname = newPath;
  117. }
  118. pushState(state, title, url) {
  119. this._history.pushState(state, title, url);
  120. }
  121. replaceState(state, title, url) {
  122. this._history.replaceState(state, title, url);
  123. }
  124. forward() {
  125. this._history.forward();
  126. }
  127. back() {
  128. this._history.back();
  129. }
  130. historyGo(relativePosition = 0) {
  131. this._history.go(relativePosition);
  132. }
  133. getState() {
  134. return this._history.state;
  135. }
  136. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: BrowserPlatformLocation, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
  137. static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: BrowserPlatformLocation, providedIn: 'platform', useFactory: () => new BrowserPlatformLocation() });
  138. }
  139. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: BrowserPlatformLocation, decorators: [{
  140. type: Injectable,
  141. args: [{
  142. providedIn: 'platform',
  143. useFactory: () => new BrowserPlatformLocation(),
  144. }]
  145. }], ctorParameters: () => [] });
  146. /**
  147. * Joins two parts of a URL with a slash if needed.
  148. *
  149. * @param start URL string
  150. * @param end URL string
  151. *
  152. *
  153. * @returns The joined URL string.
  154. */
  155. function joinWithSlash(start, end) {
  156. // If `start` is an empty string, return `end` as the result.
  157. if (!start)
  158. return end;
  159. // If `end` is an empty string, return `start` as the result.
  160. if (!end)
  161. return start;
  162. // If `start` ends with a slash, remove the leading slash from `end`.
  163. if (start.endsWith('/')) {
  164. return end.startsWith('/') ? start + end.slice(1) : start + end;
  165. }
  166. // If `start` doesn't end with a slash, add one if `end` doesn't start with a slash.
  167. return end.startsWith('/') ? start + end : `${start}/${end}`;
  168. }
  169. /**
  170. * Removes a trailing slash from a URL string if needed.
  171. * Looks for the first occurrence of either `#`, `?`, or the end of the
  172. * line as `/` characters and removes the trailing slash if one exists.
  173. *
  174. * @param url URL string.
  175. *
  176. * @returns The URL string, modified if needed.
  177. */
  178. function stripTrailingSlash(url) {
  179. // Find the index of the first occurrence of `#`, `?`, or the end of the string.
  180. // This marks the start of the query string, fragment, or the end of the URL path.
  181. const pathEndIdx = url.search(/#|\?|$/);
  182. // Check if the character before `pathEndIdx` is a trailing slash.
  183. // If it is, remove the trailing slash and return the modified URL.
  184. // Otherwise, return the URL as is.
  185. return url[pathEndIdx - 1] === '/' ? url.slice(0, pathEndIdx - 1) + url.slice(pathEndIdx) : url;
  186. }
  187. /**
  188. * Normalizes URL parameters by prepending with `?` if needed.
  189. *
  190. * @param params String of URL parameters.
  191. *
  192. * @returns The normalized URL parameters string.
  193. */
  194. function normalizeQueryParams(params) {
  195. return params && params[0] !== '?' ? `?${params}` : params;
  196. }
  197. /**
  198. * Enables the `Location` service to read route state from the browser's URL.
  199. * Angular provides two strategies:
  200. * `HashLocationStrategy` and `PathLocationStrategy`.
  201. *
  202. * Applications should use the `Router` or `Location` services to
  203. * interact with application route state.
  204. *
  205. * For instance, `HashLocationStrategy` produces URLs like
  206. * <code class="no-auto-link">http://example.com/#/foo</code>,
  207. * and `PathLocationStrategy` produces
  208. * <code class="no-auto-link">http://example.com/foo</code> as an equivalent URL.
  209. *
  210. * See these two classes for more.
  211. *
  212. * @publicApi
  213. */
  214. class LocationStrategy {
  215. historyGo(relativePosition) {
  216. throw new Error(ngDevMode ? 'Not implemented' : '');
  217. }
  218. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: LocationStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
  219. static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: LocationStrategy, providedIn: 'root', useFactory: () => inject(PathLocationStrategy) });
  220. }
  221. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: LocationStrategy, decorators: [{
  222. type: Injectable,
  223. args: [{ providedIn: 'root', useFactory: () => inject(PathLocationStrategy) }]
  224. }] });
  225. /**
  226. * A predefined DI token for the base href
  227. * to be used with the `PathLocationStrategy`.
  228. * The base href is the URL prefix that should be preserved when generating
  229. * and recognizing URLs.
  230. *
  231. * @usageNotes
  232. *
  233. * The following example shows how to use this token to configure the root app injector
  234. * with a base href value, so that the DI framework can supply the dependency anywhere in the app.
  235. *
  236. * ```ts
  237. * import {NgModule} from '@angular/core';
  238. * import {APP_BASE_HREF} from '@angular/common';
  239. *
  240. * @NgModule({
  241. * providers: [{provide: APP_BASE_HREF, useValue: '/my/app'}]
  242. * })
  243. * class AppModule {}
  244. * ```
  245. *
  246. * @publicApi
  247. */
  248. const APP_BASE_HREF = new InjectionToken(ngDevMode ? 'appBaseHref' : '');
  249. /**
  250. * @description
  251. * A {@link LocationStrategy} used to configure the {@link Location} service to
  252. * represent its state in the
  253. * [path](https://en.wikipedia.org/wiki/Uniform_Resource_Locator#Syntax) of the
  254. * browser's URL.
  255. *
  256. * If you're using `PathLocationStrategy`, you may provide a {@link APP_BASE_HREF}
  257. * or add a `<base href>` element to the document to override the default.
  258. *
  259. * For instance, if you provide an `APP_BASE_HREF` of `'/my/app/'` and call
  260. * `location.go('/foo')`, the browser's URL will become
  261. * `example.com/my/app/foo`. To ensure all relative URIs resolve correctly,
  262. * the `<base href>` and/or `APP_BASE_HREF` should end with a `/`.
  263. *
  264. * Similarly, if you add `<base href='/my/app/'/>` to the document and call
  265. * `location.go('/foo')`, the browser's URL will become
  266. * `example.com/my/app/foo`.
  267. *
  268. * Note that when using `PathLocationStrategy`, neither the query nor
  269. * the fragment in the `<base href>` will be preserved, as outlined
  270. * by the [RFC](https://tools.ietf.org/html/rfc3986#section-5.2.2).
  271. *
  272. * @usageNotes
  273. *
  274. * ### Example
  275. *
  276. * {@example common/location/ts/path_location_component.ts region='LocationComponent'}
  277. *
  278. * @publicApi
  279. */
  280. class PathLocationStrategy extends LocationStrategy {
  281. _platformLocation;
  282. _baseHref;
  283. _removeListenerFns = [];
  284. constructor(_platformLocation, href) {
  285. super();
  286. this._platformLocation = _platformLocation;
  287. this._baseHref =
  288. href ??
  289. this._platformLocation.getBaseHrefFromDOM() ??
  290. inject(DOCUMENT).location?.origin ??
  291. '';
  292. }
  293. /** @docs-private */
  294. ngOnDestroy() {
  295. while (this._removeListenerFns.length) {
  296. this._removeListenerFns.pop()();
  297. }
  298. }
  299. onPopState(fn) {
  300. this._removeListenerFns.push(this._platformLocation.onPopState(fn), this._platformLocation.onHashChange(fn));
  301. }
  302. getBaseHref() {
  303. return this._baseHref;
  304. }
  305. prepareExternalUrl(internal) {
  306. return joinWithSlash(this._baseHref, internal);
  307. }
  308. path(includeHash = false) {
  309. const pathname = this._platformLocation.pathname + normalizeQueryParams(this._platformLocation.search);
  310. const hash = this._platformLocation.hash;
  311. return hash && includeHash ? `${pathname}${hash}` : pathname;
  312. }
  313. pushState(state, title, url, queryParams) {
  314. const externalUrl = this.prepareExternalUrl(url + normalizeQueryParams(queryParams));
  315. this._platformLocation.pushState(state, title, externalUrl);
  316. }
  317. replaceState(state, title, url, queryParams) {
  318. const externalUrl = this.prepareExternalUrl(url + normalizeQueryParams(queryParams));
  319. this._platformLocation.replaceState(state, title, externalUrl);
  320. }
  321. forward() {
  322. this._platformLocation.forward();
  323. }
  324. back() {
  325. this._platformLocation.back();
  326. }
  327. getState() {
  328. return this._platformLocation.getState();
  329. }
  330. historyGo(relativePosition = 0) {
  331. this._platformLocation.historyGo?.(relativePosition);
  332. }
  333. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PathLocationStrategy, deps: [{ token: PlatformLocation }, { token: APP_BASE_HREF, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
  334. static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PathLocationStrategy, providedIn: 'root' });
  335. }
  336. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PathLocationStrategy, decorators: [{
  337. type: Injectable,
  338. args: [{ providedIn: 'root' }]
  339. }], ctorParameters: () => [{ type: PlatformLocation }, { type: undefined, decorators: [{
  340. type: Optional
  341. }, {
  342. type: Inject,
  343. args: [APP_BASE_HREF]
  344. }] }] });
  345. /**
  346. * @description
  347. *
  348. * A service that applications can use to interact with a browser's URL.
  349. *
  350. * Depending on the `LocationStrategy` used, `Location` persists
  351. * to the URL's path or the URL's hash segment.
  352. *
  353. * @usageNotes
  354. *
  355. * It's better to use the `Router.navigate()` service to trigger route changes. Use
  356. * `Location` only if you need to interact with or create normalized URLs outside of
  357. * routing.
  358. *
  359. * `Location` is responsible for normalizing the URL against the application's base href.
  360. * A normalized URL is absolute from the URL host, includes the application's base href, and has no
  361. * trailing slash:
  362. * - `/my/app/user/123` is normalized
  363. * - `my/app/user/123` **is not** normalized
  364. * - `/my/app/user/123/` **is not** normalized
  365. *
  366. * ### Example
  367. *
  368. * {@example common/location/ts/path_location_component.ts region='LocationComponent'}
  369. *
  370. * @publicApi
  371. */
  372. class Location {
  373. /** @internal */
  374. _subject = new Subject();
  375. /** @internal */
  376. _basePath;
  377. /** @internal */
  378. _locationStrategy;
  379. /** @internal */
  380. _urlChangeListeners = [];
  381. /** @internal */
  382. _urlChangeSubscription = null;
  383. constructor(locationStrategy) {
  384. this._locationStrategy = locationStrategy;
  385. const baseHref = this._locationStrategy.getBaseHref();
  386. // Note: This class's interaction with base HREF does not fully follow the rules
  387. // outlined in the spec https://www.freesoft.org/CIE/RFC/1808/18.htm.
  388. // Instead of trying to fix individual bugs with more and more code, we should
  389. // investigate using the URL constructor and providing the base as a second
  390. // argument.
  391. // https://developer.mozilla.org/en-US/docs/Web/API/URL/URL#parameters
  392. this._basePath = _stripOrigin(stripTrailingSlash(_stripIndexHtml(baseHref)));
  393. this._locationStrategy.onPopState((ev) => {
  394. this._subject.next({
  395. 'url': this.path(true),
  396. 'pop': true,
  397. 'state': ev.state,
  398. 'type': ev.type,
  399. });
  400. });
  401. }
  402. /** @docs-private */
  403. ngOnDestroy() {
  404. this._urlChangeSubscription?.unsubscribe();
  405. this._urlChangeListeners = [];
  406. }
  407. /**
  408. * Normalizes the URL path for this location.
  409. *
  410. * @param includeHash True to include an anchor fragment in the path.
  411. *
  412. * @returns The normalized URL path.
  413. */
  414. // TODO: vsavkin. Remove the boolean flag and always include hash once the deprecated router is
  415. // removed.
  416. path(includeHash = false) {
  417. return this.normalize(this._locationStrategy.path(includeHash));
  418. }
  419. /**
  420. * Reports the current state of the location history.
  421. * @returns The current value of the `history.state` object.
  422. */
  423. getState() {
  424. return this._locationStrategy.getState();
  425. }
  426. /**
  427. * Normalizes the given path and compares to the current normalized path.
  428. *
  429. * @param path The given URL path.
  430. * @param query Query parameters.
  431. *
  432. * @returns True if the given URL path is equal to the current normalized path, false
  433. * otherwise.
  434. */
  435. isCurrentPathEqualTo(path, query = '') {
  436. return this.path() == this.normalize(path + normalizeQueryParams(query));
  437. }
  438. /**
  439. * Normalizes a URL path by stripping any trailing slashes.
  440. *
  441. * @param url String representing a URL.
  442. *
  443. * @returns The normalized URL string.
  444. */
  445. normalize(url) {
  446. return Location.stripTrailingSlash(_stripBasePath(this._basePath, _stripIndexHtml(url)));
  447. }
  448. /**
  449. * Normalizes an external URL path.
  450. * If the given URL doesn't begin with a leading slash (`'/'`), adds one
  451. * before normalizing. Adds a hash if `HashLocationStrategy` is
  452. * in use, or the `APP_BASE_HREF` if the `PathLocationStrategy` is in use.
  453. *
  454. * @param url String representing a URL.
  455. *
  456. * @returns A normalized platform-specific URL.
  457. */
  458. prepareExternalUrl(url) {
  459. if (url && url[0] !== '/') {
  460. url = '/' + url;
  461. }
  462. return this._locationStrategy.prepareExternalUrl(url);
  463. }
  464. // TODO: rename this method to pushState
  465. /**
  466. * Changes the browser's URL to a normalized version of a given URL, and pushes a
  467. * new item onto the platform's history.
  468. *
  469. * @param path URL path to normalize.
  470. * @param query Query parameters.
  471. * @param state Location history state.
  472. *
  473. */
  474. go(path, query = '', state = null) {
  475. this._locationStrategy.pushState(state, '', path, query);
  476. this._notifyUrlChangeListeners(this.prepareExternalUrl(path + normalizeQueryParams(query)), state);
  477. }
  478. /**
  479. * Changes the browser's URL to a normalized version of the given URL, and replaces
  480. * the top item on the platform's history stack.
  481. *
  482. * @param path URL path to normalize.
  483. * @param query Query parameters.
  484. * @param state Location history state.
  485. */
  486. replaceState(path, query = '', state = null) {
  487. this._locationStrategy.replaceState(state, '', path, query);
  488. this._notifyUrlChangeListeners(this.prepareExternalUrl(path + normalizeQueryParams(query)), state);
  489. }
  490. /**
  491. * Navigates forward in the platform's history.
  492. */
  493. forward() {
  494. this._locationStrategy.forward();
  495. }
  496. /**
  497. * Navigates back in the platform's history.
  498. */
  499. back() {
  500. this._locationStrategy.back();
  501. }
  502. /**
  503. * Navigate to a specific page from session history, identified by its relative position to the
  504. * current page.
  505. *
  506. * @param relativePosition Position of the target page in the history relative to the current
  507. * page.
  508. * A negative value moves backwards, a positive value moves forwards, e.g. `location.historyGo(2)`
  509. * moves forward two pages and `location.historyGo(-2)` moves back two pages. When we try to go
  510. * beyond what's stored in the history session, we stay in the current page. Same behaviour occurs
  511. * when `relativePosition` equals 0.
  512. * @see https://developer.mozilla.org/en-US/docs/Web/API/History_API#Moving_to_a_specific_point_in_history
  513. */
  514. historyGo(relativePosition = 0) {
  515. this._locationStrategy.historyGo?.(relativePosition);
  516. }
  517. /**
  518. * Registers a URL change listener. Use to catch updates performed by the Angular
  519. * framework that are not detectible through "popstate" or "hashchange" events.
  520. *
  521. * @param fn The change handler function, which take a URL and a location history state.
  522. * @returns A function that, when executed, unregisters a URL change listener.
  523. */
  524. onUrlChange(fn) {
  525. this._urlChangeListeners.push(fn);
  526. this._urlChangeSubscription ??= this.subscribe((v) => {
  527. this._notifyUrlChangeListeners(v.url, v.state);
  528. });
  529. return () => {
  530. const fnIndex = this._urlChangeListeners.indexOf(fn);
  531. this._urlChangeListeners.splice(fnIndex, 1);
  532. if (this._urlChangeListeners.length === 0) {
  533. this._urlChangeSubscription?.unsubscribe();
  534. this._urlChangeSubscription = null;
  535. }
  536. };
  537. }
  538. /** @internal */
  539. _notifyUrlChangeListeners(url = '', state) {
  540. this._urlChangeListeners.forEach((fn) => fn(url, state));
  541. }
  542. /**
  543. * Subscribes to the platform's `popState` events.
  544. *
  545. * Note: `Location.go()` does not trigger the `popState` event in the browser. Use
  546. * `Location.onUrlChange()` to subscribe to URL changes instead.
  547. *
  548. * @param value Event that is triggered when the state history changes.
  549. * @param exception The exception to throw.
  550. *
  551. * @see [onpopstate](https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onpopstate)
  552. *
  553. * @returns Subscribed events.
  554. */
  555. subscribe(onNext, onThrow, onReturn) {
  556. return this._subject.subscribe({
  557. next: onNext,
  558. error: onThrow ?? undefined,
  559. complete: onReturn ?? undefined,
  560. });
  561. }
  562. /**
  563. * Normalizes URL parameters by prepending with `?` if needed.
  564. *
  565. * @param params String of URL parameters.
  566. *
  567. * @returns The normalized URL parameters string.
  568. */
  569. static normalizeQueryParams = normalizeQueryParams;
  570. /**
  571. * Joins two parts of a URL with a slash if needed.
  572. *
  573. * @param start URL string
  574. * @param end URL string
  575. *
  576. *
  577. * @returns The joined URL string.
  578. */
  579. static joinWithSlash = joinWithSlash;
  580. /**
  581. * Removes a trailing slash from a URL string if needed.
  582. * Looks for the first occurrence of either `#`, `?`, or the end of the
  583. * line as `/` characters and removes the trailing slash if one exists.
  584. *
  585. * @param url URL string.
  586. *
  587. * @returns The URL string, modified if needed.
  588. */
  589. static stripTrailingSlash = stripTrailingSlash;
  590. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: Location, deps: [{ token: LocationStrategy }], target: i0.ɵɵFactoryTarget.Injectable });
  591. static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: Location, providedIn: 'root', useFactory: createLocation });
  592. }
  593. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: Location, decorators: [{
  594. type: Injectable,
  595. args: [{
  596. providedIn: 'root',
  597. // See #23917
  598. useFactory: createLocation,
  599. }]
  600. }], ctorParameters: () => [{ type: LocationStrategy }] });
  601. function createLocation() {
  602. return new Location(__inject(LocationStrategy));
  603. }
  604. function _stripBasePath(basePath, url) {
  605. if (!basePath || !url.startsWith(basePath)) {
  606. return url;
  607. }
  608. const strippedUrl = url.substring(basePath.length);
  609. if (strippedUrl === '' || ['/', ';', '?', '#'].includes(strippedUrl[0])) {
  610. return strippedUrl;
  611. }
  612. return url;
  613. }
  614. function _stripIndexHtml(url) {
  615. return url.replace(/\/index.html$/, '');
  616. }
  617. function _stripOrigin(baseHref) {
  618. // DO NOT REFACTOR! Previously, this check looked like this:
  619. // `/^(https?:)?\/\//.test(baseHref)`, but that resulted in
  620. // syntactically incorrect code after Closure Compiler minification.
  621. // This was likely caused by a bug in Closure Compiler, but
  622. // for now, the check is rewritten to use `new RegExp` instead.
  623. const isAbsoluteUrl = new RegExp('^(https?:)?//').test(baseHref);
  624. if (isAbsoluteUrl) {
  625. const [, pathname] = baseHref.split(/\/\/[^\/]+/);
  626. return pathname;
  627. }
  628. return baseHref;
  629. }
  630. export { APP_BASE_HREF, BrowserPlatformLocation, DomAdapter, LOCATION_INITIALIZED, Location, LocationStrategy, PathLocationStrategy, PlatformLocation, getDOM, joinWithSlash, normalizeQueryParams, setRootDomAdapter };
  631. //# sourceMappingURL=location-Dq4mJT-A.mjs.map