UNPKG

@o3r/dynamic-content

Version:

This module provides a mechanism to retrieve media and data depending on the host or a server specific url.

681 lines (662 loc) 29.3 kB
import * as i0 from '@angular/core'; import { InjectionToken, NgModule, inject, Injectable, ChangeDetectorRef, Pipe, makeEnvironmentProviders } from '@angular/core'; import * as i1 from '@ngrx/store'; import { createAction, props, on, createReducer, StoreModule, createFeatureSelector, createSelector, Store, select } from '@ngrx/store'; import { of, firstValueFrom } from 'rxjs'; import { map, distinctUntilChanged, shareReplay } from 'rxjs/operators'; /** Actions */ const ACTION_SET = '[AssetPathOverride] set entities'; /** * Clear all overrides and fill the store with the payload */ const setAssetPathOverride = createAction(ACTION_SET, props()); /** * AssetPathOverride Store initial value */ const assetPathOverrideInitialState = { assetPathOverrides: {} }; /** * List of basic actions for AssetPathOverride Store */ const assetPathOverrideReducerFeatures = [ on(setAssetPathOverride, (_state, payload) => ({ ...payload.state })) ]; /** * AssetPathOverride Store reducer */ const assetPathOverrideReducer = createReducer(assetPathOverrideInitialState, ...assetPathOverrideReducerFeatures); /** * Name of the AssetPathOverride Store */ const ASSET_PATH_OVERRIDE_STORE_NAME = 'assetPathOverride'; /** Token of the AssetPathOverride reducer */ const ASSET_PATH_OVERRIDE_REDUCER_TOKEN = new InjectionToken('Feature AssetPathOverride Reducer'); /** Provide default reducer for AssetPathOverride store */ function getDefaultAssetPathOverrideReducer() { return assetPathOverrideReducer; } class AssetPathOverrideStoreModule { static forRoot(reducerFactory) { return { ngModule: AssetPathOverrideStoreModule, providers: [ { provide: ASSET_PATH_OVERRIDE_REDUCER_TOKEN, useFactory: reducerFactory } ] }; } /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: AssetPathOverrideStoreModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } /** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.7", ngImport: i0, type: AssetPathOverrideStoreModule, imports: [i1.StoreFeatureModule] }); } /** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: AssetPathOverrideStoreModule, providers: [ { provide: ASSET_PATH_OVERRIDE_REDUCER_TOKEN, useFactory: getDefaultAssetPathOverrideReducer } ], imports: [StoreModule.forFeature(ASSET_PATH_OVERRIDE_STORE_NAME, ASSET_PATH_OVERRIDE_REDUCER_TOKEN)] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: AssetPathOverrideStoreModule, decorators: [{ type: NgModule, args: [{ imports: [ StoreModule.forFeature(ASSET_PATH_OVERRIDE_STORE_NAME, ASSET_PATH_OVERRIDE_REDUCER_TOKEN) ], providers: [ { provide: ASSET_PATH_OVERRIDE_REDUCER_TOKEN, useFactory: getDefaultAssetPathOverrideReducer } ] }] }] }); /** Select AssetPathOverride State */ const selectAssetPathOverrideState = createFeatureSelector(ASSET_PATH_OVERRIDE_STORE_NAME); /** Select all assetPath override map */ const selectAssetPathOverride = createSelector(selectAssetPathOverrideState, (state) => state?.assetPathOverrides || {}); /** * Deserializer * @param rawObject */ const assetPathOverrideStorageDeserializer = (rawObject) => { if (!rawObject) { return assetPathOverrideInitialState; } return rawObject; }; const assetPathOverrideStorageSync = { deserialize: assetPathOverrideStorageDeserializer }; /** * Injection token for the rootpath of dynamic content */ const DYNAMIC_CONTENT_BASE_PATH_TOKEN = new InjectionToken('Dynamic content path injection token'); /** * Injection token for the assets path injected by the cms * This token will be injected only in editor mode */ const CMS_ASSETS_PATH_TOKEN = new InjectionToken('CMS assets path injection token'); const MEDIA_FOLDER_NAME = 'assets'; /** * Service for getting dynamic content path */ class DynamicContentService { constructor() { this.cmsOnlyAssetsPath = inject(CMS_ASSETS_PATH_TOKEN); this.store = inject(Store, { optional: true }); const dynamicContentPath = inject(DYNAMIC_CONTENT_BASE_PATH_TOKEN); this.basePath = dynamicContentPath.replace(/\/$/, ''); this.mediaFolder = MEDIA_FOLDER_NAME; } normalizePath(assetPath) { return assetPath ? assetPath.replace(/^\//, '') : ''; } getContentPath(assetPath) { const normalizedAssetPath = this.normalizePath(assetPath); return this.basePath === '' ? assetPath || '' : `${this.basePath}/${normalizedAssetPath}`; } getMediaPath(assetPath) { if (this.cmsOnlyAssetsPath && assetPath) { return assetPath.startsWith('/') ? assetPath : `${this.cmsOnlyAssetsPath.replace(/\/$/, '')}/${assetPath}`; } return this.getContentPath(this.mediaFolder ? `${this.mediaFolder}/${this.normalizePath(assetPath)}` : assetPath); } /** * Gets the full path of a content relative to the root * Content path doesn't consider any override, you will always get the same file * @param assetPath asset location in the root folder * @example * ```typescript * getMediaPath('assets/imgs/my-image.png') // will give you the basePath + 'assets/imgs/my-image.png' * ``` */ getContentPathStream(assetPath) { return of(this.getContentPath(assetPath)); } /** * Gets the stream that provides the full path of a media content * A Media content is always stored in the 'assets' media folder, no external content will be accessible through this function * If any override is applied to the content, returns the override path instead * @param assetPath asset location in the media folder (e.g imgs/my-image.png) * @example * ```typescript * getMediaPathStream('imgs/my-image.png') // will give you the basePath + mediaFolder + 'imgs/my-image.png' * ``` */ getMediaPathStream(assetPath) { if (!this.store) { return of(this.getMediaPath(assetPath)); } return this.store.pipe(select(selectAssetPathOverride), map((entities) => assetPath && entities && entities[assetPath] ? entities[assetPath] : assetPath), map((finalAssetPath) => this.getMediaPath(finalAssetPath)), distinctUntilChanged(), shareReplay({ bufferSize: 1, refCount: true })); } /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: DynamicContentService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: DynamicContentService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: DynamicContentService, decorators: [{ type: Injectable }], ctorParameters: () => [] }); class O3rDynamicContentPipe { constructor() { this.service = inject(DynamicContentService); this.cd = inject(ChangeDetectorRef); /** Path to the media */ this.mediaPath = ''; } /** @inheritDoc */ transform(query) { if (query !== this.lastQuery) { this.lastQuery = query; if (this.onMediaPathChange) { this.onMediaPathChange.unsubscribe(); } this.onMediaPathChange = this.service.getMediaPathStream(query).subscribe((mediaPath) => { this.mediaPath = mediaPath; this.cd.markForCheck(); }); } return this.mediaPath; } /** @inheritDoc */ ngOnDestroy() { if (this.onMediaPathChange) { this.onMediaPathChange.unsubscribe(); } } /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: O3rDynamicContentPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); } /** @nocollapse */ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.0.7", ngImport: i0, type: O3rDynamicContentPipe, isStandalone: true, name: "o3rDynamicContent", pure: false }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: O3rDynamicContentPipe, decorators: [{ type: Pipe, args: [{ name: 'o3rDynamicContent', pure: false }] }] }); /** * Function to get dynamic content from body dataset */ function getDynamicContent() { return document.body.dataset.dynamiccontentpath || ''; } /** * Function to get the cms assets from body dataset * This will be used only in a CMS context(not in local or prod) to display correctly the assets in the editor */ function getCmsAssets() { return document.body.dataset.cmsassetspath || ''; } /** * DynamicContent module * @deprecated Will be removed in v14. */ class DynamicContentModule { /** * Customize the location where the application will search for the base path of dynamic content * @param dynamicPath Configuration for dynamic content path * @param dynamicPath.content The string will be used as base path of dynamic content * @param dynamicPath.cmsAssets The string will be used for the the base path of cms assets * @note The cmsAssets will be used only in the cms editor mode and it will take priority over dynamic content * @deprecated Please use {@link provideDynamicContent} instead. Will be removed in v14. */ static forRoot(dynamicPath) { const providers = []; if ('content' in dynamicPath) { providers.push({ provide: DYNAMIC_CONTENT_BASE_PATH_TOKEN, useValue: dynamicPath.content }); } if ('cmsAssets' in dynamicPath) { providers.push({ provide: CMS_ASSETS_PATH_TOKEN, useValue: dynamicPath.cmsAssets }); } return { ngModule: DynamicContentModule, providers }; } /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: DynamicContentModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } /** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.7", ngImport: i0, type: DynamicContentModule, imports: [O3rDynamicContentPipe], exports: [O3rDynamicContentPipe] }); } /** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: DynamicContentModule, providers: [ { provide: DYNAMIC_CONTENT_BASE_PATH_TOKEN, useFactory: getDynamicContent }, { provide: CMS_ASSETS_PATH_TOKEN, useFactory: getCmsAssets }, DynamicContentService ] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: DynamicContentModule, decorators: [{ type: NgModule, args: [{ providers: [ { provide: DYNAMIC_CONTENT_BASE_PATH_TOKEN, useFactory: getDynamicContent }, { provide: CMS_ASSETS_PATH_TOKEN, useFactory: getCmsAssets }, DynamicContentService ], imports: [O3rDynamicContentPipe], exports: [O3rDynamicContentPipe] }] }] }); /** * Specify a custom base path * @param basePath */ function withBasePath(basePath) { return { ɵkind: 'base-path', ɵproviders: [ { provide: DYNAMIC_CONTENT_BASE_PATH_TOKEN, ...(typeof basePath === 'string' ? { useValue: basePath } : { useFactory: basePath }) } ] }; } /** * Specify a custom CMS assets path * @param cmsAssetsPath */ function withCmsAssetsPath(cmsAssetsPath) { return { ɵkind: 'cms-assets-path', ɵproviders: [ { provide: CMS_ASSETS_PATH_TOKEN, ...(typeof cmsAssetsPath === 'string' ? { useValue: cmsAssetsPath } : { useFactory: cmsAssetsPath }) } ] }; } /** * Provide dynamic content default configuration. * To customize the location where the application will search for the base path of dynamic content * @see {@link withBasePath} * @see {@link withCmsAssetsPath} * @note The cmsAssets will be used only in the cms editor mode and it will take priority over dynamic content * @param features * @example * ```typescript * bootstrapApplication(AppComponent, * { * providers: [ * provideDynamicContent( * withBasePath('custom/base/path'), * withCmsAssetsPath('custom/cms/assets/path'), * ) * ] * } * ); */ function provideDynamicContent(...features) { const providers = [ DynamicContentService ]; const basePathFeature = features.find((f) => f.ɵkind === 'base-path') ?? withBasePath(getDynamicContent); providers.push(basePathFeature.ɵproviders); const cmsAssetsPathFeature = features.find((f) => f.ɵkind === 'cms-assets-path') ?? withCmsAssetsPath(getCmsAssets); providers.push(cmsAssetsPathFeature.ɵproviders); return makeEnvironmentProviders(providers); } /** * Strategies available to read / write data in the RequestParameters service. * Rehydrate: if the storage already have data, those will be used by the service, ignoring new data. Otherwise set the storage * Merge: storage data will be merged with the ones provided. (provided data has priority) * Replace: storage data will be completely replaced by the ones provided * ReplaceIfNotEmpty: If no parameters are provided, use the content from storage. Otherwise use the ones provided and update the storage with them. */ var StorageStrategy; (function (StorageStrategy) { // eslint-disable-next-line @typescript-eslint/naming-convention -- required naming convention StorageStrategy[StorageStrategy["Rehydrate"] = 0] = "Rehydrate"; // eslint-disable-next-line @typescript-eslint/naming-convention -- required naming convention StorageStrategy[StorageStrategy["Merge"] = 1] = "Merge"; // eslint-disable-next-line @typescript-eslint/naming-convention -- required naming convention StorageStrategy[StorageStrategy["Replace"] = 2] = "Replace"; // eslint-disable-next-line @typescript-eslint/naming-convention -- required naming convention StorageStrategy[StorageStrategy["ReplaceIfNotEmpty"] = 3] = "ReplaceIfNotEmpty"; })(StorageStrategy || (StorageStrategy = {})); const defaultRequestParametersConfig = { storage: (typeof window === 'undefined') ? undefined : window.sessionStorage, strategy: StorageStrategy.Rehydrate, queryParamsValue: (typeof document !== 'undefined' && document.body?.dataset?.query) || '{}', postParamsValue: (typeof document !== 'undefined' && document.body?.dataset?.post) || '{}' }; /** * Token to be provided in case of service customization needs. */ const REQUEST_PARAMETERS_CONFIG_TOKEN = new InjectionToken('RequestParametersConfig injection token', { factory: () => ({}) }); /** * Service used to store the request parameters of your requests so that subsequent calls or refresh the page will preserve * them. */ class RequestParametersService { constructor() { this._query = {}; this._post = {}; const config = inject(REQUEST_PARAMETERS_CONFIG_TOKEN); this.config = defaultRequestParametersConfig; Object.keys(config) .filter((key) => config[key] !== undefined) .forEach((key) => this.config[key] = config[key]); this.setParameters('query', JSON.parse(this.config.queryParamsValue)); this.setParameters('post', JSON.parse(this.config.postParamsValue)); } /** * Depending on the strategy, set the internal values for the parameters. * See StorageStrategy for more info. * @param key * @param value */ setParameters(key, value) { const privateKey = `_${key}`; if (!this.config.storage) { // No storage is available , cannot set items return; } switch (this.config.strategy) { case StorageStrategy.Rehydrate: { if (!this.config.storage.getItem(privateKey)) { this[privateKey] = value; this.config.storage.setItem(privateKey, JSON.stringify(value)); break; } this[privateKey] = JSON.parse(this.config.storage.getItem(privateKey) || '{}'); break; } case StorageStrategy.Replace: { this[privateKey] = value; this.config.storage.setItem(privateKey, JSON.stringify(value)); break; } case StorageStrategy.Merge: { const storageData = Object.assign(JSON.parse(this.config.storage.getItem(privateKey) || '{}'), value); this[privateKey] = storageData; this.config.storage.setItem(privateKey, JSON.stringify(storageData)); break; } case StorageStrategy.ReplaceIfNotEmpty: { if (Object.keys(value).length > 0) { this[privateKey] = value; this.config.storage.setItem(privateKey, JSON.stringify(value)); break; } this[privateKey] = JSON.parse(this.config.storage.getItem(privateKey) || '{}'); break; } } } /** * Get all the query parameters in a map. */ get query() { return this._query; } /** * Get all the post parameters in a map. */ get post() { return this._post; } /** * Get a specific query parameter value, given the key. * @param key */ getQueryParameter(key) { return this._query[key]; } /** * Get a specific query parameter value as boolean, given the key. * @param key */ getQueryParameterAsBoolean(key) { const queryParameter = this.getQueryParameter(key); return queryParameter ? queryParameter.toLowerCase() === 'true' : undefined; } /** * Get a specific post parameter value, given the key. * @param key */ getPostParameter(key) { return this._post[key]; } /** * Get a specific post parameter value as boolean, given the key. * @param key */ getPostParameterAsBoolean(key) { const postParameter = this.getPostParameter(key); return postParameter ? postParameter.toLowerCase() === 'true' : undefined; } /** * Get a specific parameter value, given the key. * @param key */ getParameter(key) { return this._query[key] || this._post[key]; } /** * Get a specific parameter value as boolean, given the key. * @param key */ getParameterAsBoolean(key) { const parameter = this.getParameter(key); return parameter ? parameter.toLowerCase() === 'true' : undefined; } /** * Clear GET parameters from the storage * @param paramsToClear the list on key that you want to clear in get parameters */ clearQueryParameters(paramsToClear) { const newQuery = (paramsToClear ? Object.keys(this._query).filter((key) => !paramsToClear.includes(key)) : []) .reduce((acc, key) => { acc[key] = this._query[key]; return acc; }, {}); if (this.config.storage) { this.config.storage.setItem('_query', JSON.stringify(newQuery)); } this._query = newQuery; } /** * Clear POST parameters from the storage * @param paramsToClear the list on key that you want to clean in post parameters */ clearPostParameters(paramsToClear) { const newPost = (paramsToClear ? Object.keys(this._post).filter((key) => !paramsToClear.includes(key)) : []) .reduce((acc, key) => { acc[key] = this._post[key]; return acc; }, {}); if (this.config.storage) { this.config.storage.setItem('_post', JSON.stringify(newPost)); } this._post = newPost; } /** * Get all the parameters in a map. * @param priority the parameter to be given priority in case same key is in get and post params. */ getParams(priority = 'query') { return priority === 'query' ? { ...this._post, ...this._query } : { ...this._query, ...this._post }; } /** * Filter Parameters(both Query/POST) from the storage * @param paramstoFilter the list on key that you want to filter from parameters * @param priority the priorty of the parameter type(POST/Query) */ getFilteredParameters(paramstoFilter, priority = 'query') { const params = this.getParams(priority); if (!paramstoFilter) { return params; } return Object.keys(params) .filter((key) => !paramstoFilter.includes(key)) .reduce((acc, key) => { acc[key] = params[key]; return acc; }, {}); } /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: RequestParametersService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: RequestParametersService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: RequestParametersService, decorators: [{ type: Injectable }], ctorParameters: () => [] }); /** * Empty configuration factory, used when config is not provided. It needs a separate function for AOT. */ function defaultConfigFactory() { return {}; } /** * RequestParametersService Module * @deprecated Will be removed in v14. */ class RequestParametersModule { /** * Provide request parameters config * @param config * @deprecated Please use {@link provideRequestParameters} instead. Will be removed in v14. */ static forRoot(config = defaultConfigFactory) { return { ngModule: RequestParametersModule, providers: [ { provide: REQUEST_PARAMETERS_CONFIG_TOKEN, useFactory: config }, RequestParametersService ] }; } /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: RequestParametersModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } /** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.7", ngImport: i0, type: RequestParametersModule }); } /** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: RequestParametersModule, providers: [ { provide: REQUEST_PARAMETERS_CONFIG_TOKEN, useValue: {} }, RequestParametersService ] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: RequestParametersModule, decorators: [{ type: NgModule, args: [{ imports: [], providers: [ { provide: REQUEST_PARAMETERS_CONFIG_TOKEN, useValue: {} }, RequestParametersService ] }] }] }); /** * Provide request parameters config * We don't provide directly the value and use a factory because otherwise AOT compilation will resolve to undefined whatever is taken from window * @param config */ function provideRequestParameters(config = defaultConfigFactory) { return makeEnvironmentProviders([ { provide: REQUEST_PARAMETERS_CONFIG_TOKEN, useFactory: config }, RequestParametersService ]); } class StyleLazyLoaderModule { /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: StyleLazyLoaderModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } /** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.7", ngImport: i0, type: StyleLazyLoaderModule, imports: [DynamicContentModule] }); } /** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: StyleLazyLoaderModule, imports: [DynamicContentModule] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: StyleLazyLoaderModule, decorators: [{ type: NgModule, args: [{ imports: [DynamicContentModule] }] }] }); /** * Service to lazy load a CSS file */ class StyleLazyLoader { constructor() { this.dcService = inject(DynamicContentService); this.DEFAULT_STYLE_ELEMENT_ID = 'external-theme'; } /** * Load a new CSS from an absolute URL, if we already HTML element exists with the url, otherwise * @param styleUrlConfig object containing CSS File absolute URL to load, integrity and crossOrigin attributes * and the styleId id of the dynamic style in the body tag. */ loadStyleFromURL(styleUrlConfig) { const elementId = styleUrlConfig.id || this.DEFAULT_STYLE_ELEMENT_ID; let style = document.querySelector(`#${elementId}`); if (style === null) { style = document.createElement('link'); style.rel = 'stylesheet'; style.type = 'text/css'; const head = document.querySelectorAll('head')[0]; head.append(style); } if (styleUrlConfig.integrity) { style.integrity = styleUrlConfig.integrity; } if (styleUrlConfig.crossOrigin !== undefined) { style.crossOrigin = styleUrlConfig.crossOrigin; } style.href = styleUrlConfig.href; return style; } /** * Load a new CSS File * @param styleUrlConfig CSS File config containing URL to load, integrity and crossOrigin attributes * and the styleId id of the dynamic style in the body tag */ async asyncLoadStyleFromDynamicContent(styleUrlConfig) { const dynamicContentPath = await firstValueFrom(this.dcService.getContentPathStream(styleUrlConfig.href)); styleUrlConfig.href = dynamicContentPath; this.loadStyleFromURL(styleUrlConfig); } /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: StyleLazyLoader, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: StyleLazyLoader, providedIn: StyleLazyLoaderModule }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.7", ngImport: i0, type: StyleLazyLoader, decorators: [{ type: Injectable, args: [{ providedIn: StyleLazyLoaderModule }] }] }); /** * Generated bundle index. Do not edit. */ export { ASSET_PATH_OVERRIDE_REDUCER_TOKEN, ASSET_PATH_OVERRIDE_STORE_NAME, AssetPathOverrideStoreModule, CMS_ASSETS_PATH_TOKEN, DYNAMIC_CONTENT_BASE_PATH_TOKEN, DynamicContentModule, DynamicContentService, O3rDynamicContentPipe, RequestParametersModule, RequestParametersService, StorageStrategy, StyleLazyLoader, StyleLazyLoaderModule, assetPathOverrideInitialState, assetPathOverrideReducer, assetPathOverrideReducerFeatures, assetPathOverrideStorageDeserializer, assetPathOverrideStorageSync, defaultConfigFactory, defaultRequestParametersConfig, getCmsAssets, getDefaultAssetPathOverrideReducer, getDynamicContent, provideDynamicContent, provideRequestParameters, selectAssetPathOverride, selectAssetPathOverrideState, setAssetPathOverride, withBasePath, withCmsAssetsPath }; //# sourceMappingURL=o3r-dynamic-content.mjs.map