{"version":3,"sources":["node_modules/@fortawesome/free-solid-svg-icons/faCircleInfo.js","node_modules/reading-time/dist/reading-time.js","src/app/features/knowledge/knowledge-article-detail/knowledge-article-detail.component.ts","src/app/features/knowledge/knowledge-article-detail/knowledge-article-detail.component.html","src/app/features/contentful-dynamic/rich-text/utils/convert-to-plain-text-string.ts","src/app/features/knowledge/knowledge-highlighted-text/knowledge-highlighted-text.component.ts","src/app/features/knowledge/knowledge-highlighted-text/knowledge-highlighted-text.component.html","src/app/features/knowledge/knowledge-read-next/knowledge-read-next.component.ts","src/app/features/knowledge/knowledge-read-next/knowledge-read-next.component.html","src/app/features/knowledge/knowledge-cta/knowledge-cta.component.ts","src/app/features/knowledge/knowledge-cta/knowledge-cta.component.html","src/app/features/knowledge/knowledge-quick-tips/knowledge-quick-tips.component.ts","src/app/features/knowledge/knowledge-quick-tips/knowledge-quick-tips.component.html","src/app/features/knowledge/knowledge-article-breadcrumbs/knowledge-article-breadcrumbs.component.ts","src/app/features/knowledge/knowledge-article-breadcrumbs/knowledge-article-breadcrumbs.component.html","src/app/features/knowledge/knowledge-article-toc/knowledge-article-toc.component.ts","src/app/features/knowledge/knowledge-article-toc/knowledge-article-toc.component.html","src/app/features/knowledge/knowledge-article-author/knowledge-article-author.component.ts","src/app/features/knowledge/knowledge-article-author/knowledge-article-author.component.html","src/app/pages/knowledge-pages/knowledge-article-page/knowledge-article-page.component.ts","src/app/pages/knowledge-pages/knowledge-article-page/knowledge-article-page.component.html"],"sourcesContent":["'use strict';\n\nObject.defineProperty(exports, '__esModule', {\n value: true\n});\nvar prefix = 'fas';\nvar iconName = 'circle-info';\nvar width = 512;\nvar height = 512;\nvar aliases = [\"info-circle\"];\nvar unicode = 'f05a';\nvar svgPathData = 'M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM216 336l24 0 0-64-24 0c-13.3 0-24-10.7-24-24s10.7-24 24-24l48 0c13.3 0 24 10.7 24 24l0 88 8 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-80 0c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-208a32 32 0 1 1 0 64 32 32 0 1 1 0-64z';\nexports.definition = {\n prefix: prefix,\n iconName: iconName,\n icon: [width, height, aliases, unicode, svgPathData]\n};\nexports.faCircleInfo = exports.definition;\nexports.prefix = prefix;\nexports.iconName = iconName;\nexports.width = width;\nexports.height = height;\nexports.ligatures = aliases;\nexports.unicode = unicode;\nexports.svgPathData = svgPathData;\nexports.aliases = aliases;","\"use strict\";\n\n/*!\n * reading-time\n * Copyright (c) Nicolas Gryman \n * MIT Licensed\n */\nvar __assign = this && this.__assign || function () {\n __assign = Object.assign || function (t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\n }\n return t;\n };\n return __assign.apply(this, arguments);\n};\nexports.__esModule = true;\nexports.readingTimeWithCount = exports.countWords = void 0;\nfunction codeIsInRanges(number, arrayOfRanges) {\n return arrayOfRanges.some(function (_a) {\n var lowerBound = _a[0],\n upperBound = _a[1];\n return lowerBound <= number && number <= upperBound;\n });\n}\nvar isCJK = function (c) {\n var charCode = c.charCodeAt(0);\n // Help wanted!\n // This should be good for most cases, but if you find it unsatisfactory\n // (e.g. some other language where each character should be standalone words),\n // contributions welcome!\n return codeIsInRanges(charCode, [\n // Hiragana (Katakana not included on purpose,\n // context: https://github.com/ngryman/reading-time/pull/35#issuecomment-853364526)\n // If you think Katakana should be included and have solid reasons, improvement is welcomed\n [0x3040, 0x309f],\n // CJK Unified ideographs\n [0x4e00, 0x9fff],\n // Hangul\n [0xac00, 0xd7a3],\n // CJK extensions\n [0x20000, 0x2ebe0]]);\n};\nvar isAnsiWordBound = function (c) {\n return ' \\n\\r\\t'.includes(c);\n};\nvar isPunctuation = function (c) {\n var charCode = c.charCodeAt(0);\n return codeIsInRanges(charCode, [[0x21, 0x2f], [0x3a, 0x40], [0x5b, 0x60], [0x7b, 0x7e],\n // CJK Symbols and Punctuation\n [0x3000, 0x303f],\n // Full-width ASCII punctuation variants\n [0xff00, 0xffef]]);\n};\nfunction countWords(text, options) {\n if (options === void 0) {\n options = {};\n }\n var words = 0,\n start = 0,\n end = text.length - 1;\n var _a = options.wordBound,\n isWordBound = _a === void 0 ? isAnsiWordBound : _a;\n // fetch bounds\n while (isWordBound(text[start])) start++;\n while (isWordBound(text[end])) end--;\n // Add a trailing word bound to make handling edges more convenient\n var normalizedText = text + \"\\n\";\n // calculate the number of words\n for (var i = start; i <= end; i++) {\n // A CJK character is a always word;\n // A non-word bound followed by a word bound / CJK is the end of a word.\n if (isCJK(normalizedText[i]) || !isWordBound(normalizedText[i]) && (isWordBound(normalizedText[i + 1]) || isCJK(normalizedText[i + 1]))) {\n words++;\n }\n // In case of CJK followed by punctuations, those characters have to be eaten as well\n if (isCJK(normalizedText[i])) {\n while (i <= end && (isPunctuation(normalizedText[i + 1]) || isWordBound(normalizedText[i + 1]))) {\n i++;\n }\n }\n }\n return {\n total: words\n };\n}\nexports.countWords = countWords;\nfunction readingTimeWithCount(words, options) {\n if (options === void 0) {\n options = {};\n }\n var _a = options.wordsPerMinute,\n wordsPerMinute = _a === void 0 ? 200 : _a;\n // reading time stats\n var minutes = words.total / wordsPerMinute;\n // Math.round used to resolve floating point funkiness\n // http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html\n var time = Math.round(minutes * 60 * 1000);\n var displayed = Math.ceil(parseFloat(minutes.toFixed(2)));\n return {\n minutes: displayed,\n time: time\n };\n}\nexports.readingTimeWithCount = readingTimeWithCount;\nfunction readingTime(text, options) {\n if (options === void 0) {\n options = {};\n }\n var words = countWords(text, options);\n return __assign(__assign({}, readingTimeWithCount(words, options)), {\n words: words\n });\n}\nexports[\"default\"] = readingTime;","import { AsyncPipe, DatePipe, DOCUMENT } from '@angular/common';\nimport {\n AfterViewInit,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n Inject,\n Input,\n OnDestroy,\n OnInit,\n ViewChild,\n} from '@angular/core';\nimport { MetaDefinition } from '@angular/platform-browser';\nimport { Router } from '@angular/router';\nimport { BLOCKS, INLINES } from '@contentful/rich-text-types';\nimport { CacheService } from '@core/services/cache.service';\nimport {\n ContentfulService,\n ContentTypes,\n} from '@core/services/contentful.service';\nimport { DeviceService } from '@core/services/device.service';\nimport { EnvironmentService } from '@core/services/environment.service';\nimport { MetadataService } from '@core/services/metadata.service';\nimport { SeoService } from '@core/services/seo.service';\nimport { WINDOW } from '@core/services/window.service';\nimport { documentToPlainTextString } from '@features/contentful-dynamic/rich-text/utils/convert-to-plain-text-string';\nimport {\n fakeAsset,\n fixAssetUrl,\n} from '@features/contentful/helpers/assetHelpers';\nimport { KnowledgeHighlightedTextComponent } from '@features/knowledge/knowledge-highlighted-text/knowledge-highlighted-text.component';\nimport { KnowledgeReadNextComponent } from '@features/knowledge/knowledge-read-next/knowledge-read-next.component';\nimport {\n Configurations,\n CropFocus,\n LazyPictureComponent,\n Stops,\n} from '@features/lazy-image/components/lazy-picture/lazy-picture.component';\nimport { LeadMagnetActiveCampaignComponent } from '@features/lead-magnet/components/lead-magnet-active-campaign/lead-magnet-active-campaign.component';\nimport { YoutubePlayerContentfulComponent } from '@features/youtube/components/youtube-player-contentful/youtube-player-contentful.component';\nimport { faCalendar, faClock } from '@fortawesome/free-regular-svg-icons';\nimport {\n Asset,\n Entry,\n KnowledgeArticle,\n KnowledgeDestination,\n Person,\n} from '@generated/graphql';\nimport readingTime from 'reading-time';\nimport { combineLatest, fromEvent, Observable, of, Subject } from 'rxjs';\nimport {\n debounceTime,\n distinctUntilChanged,\n filter,\n map,\n pairwise,\n scan,\n shareReplay,\n startWith,\n switchMap,\n takeUntil,\n tap,\n} from 'rxjs/operators';\nimport { Article, WithContext } from 'schema-dts';\nimport { KnowledgeCtaComponent } from '../knowledge-cta/knowledge-cta.component';\nimport { KnowledgeQuickTipsComponent } from '../knowledge-quick-tips/knowledge-quick-tips.component';\nimport { KnowledgeVariationCardsComponent } from '../knowledge-variation-cards/knowledge-variation-cards.component';\n\nimport { ObserversModule } from '@angular/cdk/observers';\nimport { FontAwesomeModule } from '@fortawesome/angular-fontawesome';\nimport { RichTextDocumentComponent } from '../../contentful-dynamic/rich-text/rich-text-document/rich-text-document.component';\nimport { KnowledgeArticleBreadcrumbsComponent } from '../knowledge-article-breadcrumbs/knowledge-article-breadcrumbs.component';\nimport { KnowledgeArticleTocComponent } from '../knowledge-article-toc/knowledge-article-toc.component';\n\nimport { EventTrackerService } from '@core/services/event-tracker.service';\nimport { ANALYTICS_EVENTS } from '@core/utils/AnalyticsEvents';\nimport { LazyAssetComponent } from '@features/lazy-image/components/lazy-asset/lazy-asset.component';\nimport { LeadMagnetExitIntentComponent } from '@features/lead-magnet/components/lead-magnet-exit-intent/lead-magnet-exit-intent.component';\nimport { NotFoundComponent } from '@features/not-found/components/not-found/not-found.component';\nimport { JsonLdComponent } from '@features/seo/json-ld/json-ld.component';\nimport { WithLoadingPipe } from '@shared/with-loading/with-loading.pipe';\nimport { LoaderComponent } from '../../../shared/loader/loader.component';\nimport { KnowledgeArticleAuthorComponent } from '../knowledge-article-author/knowledge-article-author.component';\n\n@Component({\n selector: 'app-knowledge-article-detail',\n templateUrl: './knowledge-article-detail.component.html',\n\n styles: `\n .blogBackgroundImage {\n background-image: url('/assets/images/trips/trip-background-map-new.svg');\n background-size: 100%;\n background-repeat: no-repeat space;\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n standalone: true,\n imports: [\n LoaderComponent,\n FontAwesomeModule,\n KnowledgeArticleBreadcrumbsComponent,\n KnowledgeArticleTocComponent,\n RichTextDocumentComponent,\n ObserversModule,\n KnowledgeVariationCardsComponent,\n AsyncPipe,\n DatePipe,\n LeadMagnetExitIntentComponent,\n AsyncPipe,\n DatePipe,\n LazyPictureComponent,\n WithLoadingPipe,\n JsonLdComponent,\n NotFoundComponent,\n KnowledgeArticleAuthorComponent,\n KnowledgeReadNextComponent,\n LazyAssetComponent,\n ],\n})\nexport class KnowledgeArticleDetailComponent\n implements OnInit, AfterViewInit, OnDestroy\n{\n @Input() urlSlug: Observable;\n\n scrollTo(targetId: string): void {\n const element = document.getElementById(targetId);\n if (element) {\n element.scrollIntoView({ behavior: 'smooth' });\n }\n }\n\n @ViewChild('stickyContainer') stickyContainer;\n article$: Observable;\n destination$: Observable;\n author$: Observable;\n featuredImageConfiguration: Observable;\n schemaArticle: Observable>;\n bottomScroll: Observable;\n sidebarResize = new Subject();\n loading = false;\n defaultTextStyle = 'break-words mx-auto';\n readonly defaultPersonId = '59BUCq5dXdLZD6O6ATJF8D';\n\n footerConfiguration = {\n image: fakeAsset(\n '/assets/images/ai_footer_image.png',\n 'Footer image with a hut in the mountains'\n ),\n ratioWidth: 1,\n ratioHeight: 1,\n width: 9999,\n width2x: 9999,\n };\n\n balloonConfiguration = {\n image: fakeAsset(\n 'assets/images/trips/trip-background-balloon-new.svg',\n 'Hot air balloon vector background image'\n ),\n ratioWidth: 1,\n ratioHeight: 1,\n width: 9999,\n width2x: 9999,\n };\n compassConfiguration = {\n image: fakeAsset(\n '/assets/images/trips/trip-background-compass-new.svg',\n 'Compass vector background image'\n ),\n ratioWidth: 1,\n ratioHeight: 1,\n width: 9999,\n width2x: 9999,\n };\n\n contentfulDynamicStylesOverrides = {\n [INLINES.ENTRY_HYPERLINK]: 'text-link-blue',\n [INLINES.HYPERLINK]: 'text-link-blue',\n [BLOCKS.HEADING_2]: `${this.defaultTextStyle} font-semibold font-heading mt-8 text-darkgrey text-bold`,\n [BLOCKS.HEADING_3]: `${this.defaultTextStyle} font-semibold font-heading`,\n [BLOCKS.HEADING_4]: `${this.defaultTextStyle} font-bold font-heading`,\n [BLOCKS.HEADING_5]: `${this.defaultTextStyle} font-bold font-heading`,\n [BLOCKS.HEADING_6]: `${this.defaultTextStyle} font-bold font-heading`,\n [BLOCKS.OL_LIST]: `${this.defaultTextStyle} font-serif font-serif tracking-wide leading-relaxed !pb-6 pl-2 text-darkgrey`,\n [BLOCKS.UL_LIST]: `${this.defaultTextStyle} font-serif font-serif tracking-wide leading-relaxed !pb-6 pl-2 text-darkgrey`,\n [BLOCKS.PARAGRAPH]: `${this.defaultTextStyle} font-serif tracking-wide leading-relaxed !pb-8 text-darkgrey text-lg`,\n [BLOCKS.QUOTE]: `${this.defaultTextStyle} block !px-8 py-8 my-6 border-l-4 md:border-l-2 border-lightgrey bg-lightergrey/75 md:rounded-r-fa font-serif tracking-wide leading-relaxed`,\n [BLOCKS.TABLE_HEADER_CELL]:\n 'border border-lightgrey text-left p-4 bg-grey-100 font-serif text-darkgrey',\n [BLOCKS.TABLE_CELL]: `${this.defaultTextStyle} border border-lightgrey p-6 pl-4 tracking-wide leading-relaxed font-serif text-darkgrey`,\n [BLOCKS.EMBEDDED_ASSET]: `${this.defaultTextStyle} shadow-[20px_20px_0px_#E8F3F5] rounded-lg mb-4`,\n };\n\n contentfulDynamicComponentOverrides = {\n [ContentTypes.highlightedText]: KnowledgeHighlightedTextComponent,\n [ContentTypes.activeCampaignLeadMagnet]:\n LeadMagnetActiveCampaignComponent,\n [ContentTypes.youtubeVideo]: YoutubePlayerContentfulComponent,\n [ContentTypes.callToAction]: KnowledgeCtaComponent,\n [ContentTypes.quickTips]: KnowledgeQuickTipsComponent,\n };\n\n generateMetaTagsForService = (data: KnowledgeArticle): MetaDefinition[] => {\n return [\n {\n name: 'description',\n content: data.description,\n },\n {\n property: 'og:description',\n content: data.description,\n },\n {\n property: 'og:image',\n content: `${fixAssetUrl(\n data?.featuredImageSquare?.url\n )}?w=1200&h=800&f=${\n data?.featuredImageCropFocus || 'center'\n }&fit=fill&fm=jpg`,\n },\n {\n property: 'og:image:secure_url',\n content: `${fixAssetUrl(\n data?.featuredImageSquare?.url\n )}?w=1200&h=800&f=${\n data?.featuredImageCropFocus || 'center'\n }&fit=fill&fm=jpg`,\n },\n {\n property: 'og:image:type',\n content: 'image/jpeg',\n },\n {\n property: 'og:image:width',\n content: '1200',\n },\n {\n property: 'og:image:height',\n content: '800',\n },\n {\n property: 'og:type',\n content: 'article',\n },\n {\n property: 'article:section',\n content: 'Travel',\n },\n {\n property: 'article:published_time',\n content: data.sys.firstPublishedAt,\n },\n {\n property: 'article:modified_time',\n content: data.sys.publishedAt,\n },\n {\n property: 'og:updated_time',\n content: data.sys.publishedAt,\n },\n ];\n };\n\n relatedArticles: Observable;\n private destroy$ = new Subject();\n resolvedLinks: Observable>;\n readingTime: Observable;\n faCalendar = faCalendar;\n faClock = faClock;\n\n constructor(\n private contentfulService: ContentfulService,\n private seoService: SeoService,\n private deviceService: DeviceService,\n private cd: ChangeDetectorRef,\n private eventTrackerService: EventTrackerService,\n private environmentService: EnvironmentService,\n private cacheService: CacheService,\n private metadataService: MetadataService,\n private router: Router,\n @Inject(WINDOW) private window: Window,\n @Inject(DOCUMENT) private document: Document\n ) {}\n\n ngOnInit(): void {\n this.article$ = this.urlSlug.pipe(\n tap(() => {\n this.loading = true;\n this.cd.detectChanges();\n }),\n switchMap(slug =>\n combineLatest([\n this.contentfulService.article(slug),\n this.contentfulService.faqOfArticle(slug),\n ]).pipe(\n map(([article, faqs]) => ({\n ...article,\n faqsCollection: faqs.faqsCollection,\n }))\n )\n ),\n tap(() => {\n this.loading = false;\n this.cd.detectChanges();\n }),\n tap(data => {\n // Adding Meta Tags from contentful Data\n this.metadataService.setTitle(data.title);\n\n this.generateMetaTagsForService(data).forEach(metaObj => {\n this.metadataService.setAttribute(metaObj);\n });\n\n this.metadataService.setCanonicalUrl(this.router.url);\n }),\n switchMap(article => {\n if (article.author) {\n return of(article);\n }\n // switch to a default author\n return this.contentfulService.person(this.defaultPersonId).pipe(\n map(author => {\n return {\n ...article,\n author: author.person,\n };\n })\n );\n }),\n shareReplay(1)\n );\n\n this.destination$ = this.article$.pipe(\n map(article => article.destinationsCollection.items[0]),\n shareReplay(1)\n );\n\n this.readingTime = this.article$.pipe(\n map(article => documentToPlainTextString(article.body.json)),\n map(plainArticleString => readingTime(plainArticleString).minutes),\n tap(readingTime => {\n this.metadataService.setAttribute({\n name: 'twitter:card',\n content: 'summary',\n });\n this.metadataService.setAttribute({\n name: 'twitter:label1',\n content: 'Est. reading time',\n });\n this.metadataService.setAttribute({\n name: 'twitter:data1',\n content: `${readingTime} minutes`,\n });\n }),\n shareReplay()\n );\n\n this.author$ = this.article$.pipe(map(article => article.author));\n\n this.featuredImageConfiguration = this.article$.pipe(\n filter(destination => !!destination?.featuredImageSquare?.url),\n map(destination => ({\n [Stops.FALLBACK]: {\n image: destination.featuredImageSquare,\n focus: destination.featuredImageCropFocus as CropFocus,\n ratioHeight: 1,\n ratioWidth: 1,\n width: 1200,\n width2x: 1200,\n },\n [Stops.BASE]: {\n image: destination.featuredImageSquare,\n focus: destination.featuredImageCropFocus as CropFocus,\n ratioHeight: 1,\n ratioWidth: 1,\n width: 400,\n width2x: 600,\n width3x: 800,\n },\n [Stops.SM]: {\n image: destination.featuredImageSquare,\n focus: destination.featuredImageCropFocus as CropFocus,\n ratioHeight: 1,\n ratioWidth: 1,\n width: 800,\n width2x: 1000,\n width3x: 1200,\n },\n [Stops.MD]: {\n image: destination.featuredImageSquare,\n focus: destination.featuredImageCropFocus as CropFocus,\n ratioHeight: 1,\n ratioWidth: 2,\n width: 800,\n width2x: 1000,\n width3x: 1200,\n },\n [Stops.LG]: {\n image: destination.featuredImageSquare,\n focus: destination.featuredImageCropFocus as CropFocus,\n ratioHeight: 1,\n ratioWidth: 2,\n width: 1400,\n width2x: 1600,\n width3x: 2000,\n },\n [Stops.XL]: {\n image: destination.featuredImageSquare,\n focus: destination.featuredImageCropFocus as CropFocus,\n ratioHeight: 1,\n ratioWidth: 2,\n width: 1600,\n width2x: 2000,\n width3x: 2400,\n },\n [Stops.XXL]: {\n image: destination.featuredImageSquare,\n focus: destination.featuredImageCropFocus as CropFocus,\n ratioHeight: 1,\n ratioWidth: 3,\n width: 2000,\n width2x: 3000,\n width3x: 4000,\n },\n })),\n shareReplay(1)\n );\n\n this.relatedArticles = this.article$.pipe(\n map(article => {\n const relatedArticles =\n article.relatedArticlesCollection.items || [];\n return relatedArticles.filter(\n relatedArticle => !!relatedArticle?.urlSlug\n );\n })\n );\n\n this.resolvedLinks = this.article$.pipe(\n map(article => [\n ...(article.body.links.assets.block || []),\n ...(article.body.links.entries.block || []),\n ...(article.body.links.entries.inline || []),\n ...(article.body.links.entries.hyperlink || []),\n ]),\n map(\n (links: (Asset | Entry)[]) =>\n new Map(\n links\n .filter(item => item?.sys?.id)\n .map(item => [item.sys.id, item])\n )\n )\n );\n\n this.schemaArticle = this.article$.pipe(\n map(article => this.seoService.generateArticle(article))\n );\n }\n\n ngAfterViewInit(): void {\n if (this.environmentService.isBrowser()) {\n const scrollEvent = fromEvent(this.window, 'scroll', {\n passive: true,\n });\n\n const sidebarScrollSize = this.sidebarResize.pipe(\n startWith(1),\n switchMap(() => this.deviceService.windowSize),\n debounceTime(100),\n map(\n value =>\n this.stickyContainer.nativeElement.scrollHeight -\n value.innerHeight\n ),\n map(value => Math.max(0, value))\n );\n const scrollDiff = this.deviceService.breakPointSwitch.pipe(\n filter(windowSize => windowSize.isDesktop),\n switchMap(windowSize => scrollEvent),\n startWith(0),\n map(event => this.window.scrollY),\n pairwise(),\n map(([y1, y2]) => y2 - y1)\n );\n this.bottomScroll = combineLatest([\n scrollDiff,\n sidebarScrollSize,\n ]).pipe(\n scan((acc, [value, maxScroll]) => {\n const result = acc + value / 2;\n return Math.max(0, Math.min(result, maxScroll));\n }, 0)\n );\n\n const readingProgress = scrollEvent.pipe(\n debounceTime(100),\n filter(\n scroll =>\n this.document.body.scrollHeight > this.window.scrollY\n ),\n map(\n () =>\n Math.round(\n (this.window.scrollY /\n this.document.body.scrollHeight) *\n 4\n ) / 4\n ),\n distinctUntilChanged(),\n scan((all, current) => {\n if (!all.has(current)) {\n this.eventTrackerService.trackEvent(\n ANALYTICS_EVENTS.KNOWLEDGE_READING_PROGRESS,\n {\n progress: `${current * 100}%`,\n }\n );\n all.add(current);\n }\n return all;\n }, new Set()),\n takeUntil(this.destroy$)\n );\n\n readingProgress.subscribe();\n } else {\n this.bottomScroll = of(0);\n }\n }\n\n sidebarContentChanged($event) {\n this.sidebarResize.next('');\n }\n\n ngOnDestroy(): void {\n this.destroy$.next(null);\n }\n}\n","@if (article$ | withLoading | async; as article) {\n
\n @if (article.loading || loading) {\n
\n \n
\n }\n @if (!article.loading && !loading && !article.value) {\n \n }\n @if (!article.loading && !loading && article.value) {\n
\n
\n \n \n \n \n
\n \n \n \n
\n \n \n \n