{ "version": 3, "sources": ["src/app/features/seo/adapters/article.adapter.ts", "src/app/features/seo/adapters/breadcrumb-list.adapter.ts", "src/app/features/seo/adapters/product.adapter.ts", "src/app/features/seo/adapters/review.adapter.ts", "src/app/features/seo/adapters/youtube-video.adapter.ts", "src/app/models/seo-metadata.model.ts", "src/app/core/services/seo.service.ts"], "sourcesContent": ["import { fixAssetUrl } from '@features/contentful/helpers/assetHelpers';\nimport { KnowledgeArticle } from '@generated/graphql';\nimport { Article } from 'schema-dts';\nimport { Adapter } from './adapter';\n\nexport class ArticleAdapter implements Adapter {\n adapt(input: KnowledgeArticle): Article {\n return {\n '@type': 'BlogPosting',\n headline: input.title,\n url: `/knowledge/${input.urlSlug}`,\n author: {\n '@type': 'Person',\n name: input.author?.fullName || 'Megan White',\n },\n image: [\n fixAssetUrl(\n `${input.featuredImageSquare?.url}?fit=fill&f=${input.featuredImageCropFocus}&w=1600&h=1600&fm=jpg`\n ), //1:1\n fixAssetUrl(\n `${input.featuredImageSquare?.url}?fit=fill&f=${input.featuredImageCropFocus}&w=1600&h=1200&fm=jpg`\n ), //4:3\n fixAssetUrl(\n `${input.featuredImageSquare?.url}?fit=fill&f=${input.featuredImageCropFocus}&w=1600&h=900&fm=jpg`\n ), //16:9\n ],\n datePublished: input.sys.firstPublishedAt,\n dateModified: input.sys.publishedAt,\n };\n }\n}\n", "import { Adapter } from '@features/seo/adapters/adapter';\nimport { BreadcrumbList, ListItem } from 'schema-dts';\n\nexport interface BreadCrumbItem {\n name: string;\n url: string;\n}\n\nexport class BreadcrumbListAdapter\n implements Adapter\n{\n adapt(input: BreadCrumbItem[]): BreadcrumbList {\n return {\n '@type': 'BreadcrumbList',\n itemListElement: this.generateItemList(input),\n };\n }\n\n generateItemList(items: BreadCrumbItem[]): ListItem[] {\n return items.map((data, index) => ({\n '@type': 'ListItem',\n position: index + 1,\n name: data.name,\n item: data.url,\n }));\n }\n}\n", "import { fixAssetUrl } from '@features/contentful/helpers/assetHelpers';\nimport { Itinerary, Review, Trip } from '@generated/graphql';\nimport { Product as SchemaProduct } from 'schema-dts';\nimport { Adapter } from './adapter';\n\nexport class ProductAdapter implements Adapter {\n adapt(input: Trip): SchemaProduct {\n const itineraries = input.linkedFrom?.itineraryCollection?.items || [];\n const prices = itineraries.map(itinerary => itinerary.startingPrice);\n const numberOfReviews = itineraries.reduce(\n (previousValue, currentValue) =>\n previousValue + currentValue.numberOfReviews,\n 0\n );\n const averageReviewRating =\n itineraries\n .map(\n itinerary =>\n itinerary.averageReviewRating *\n itinerary.numberOfReviews\n )\n .reduce(\n (previousValue, currentValue) =>\n previousValue + currentValue,\n 0\n ) / numberOfReviews || 0;\n const identifier = this.contentfulIdToNumber(input.sys.id);\n return {\n '@type': 'Product',\n name: input.title,\n image: [\n `${fixAssetUrl(\n input.featuredImage.url\n )}?w=1200&h=1200&q=85&fm=jpg`,\n `${fixAssetUrl(\n input.featuredImage.url\n )}?w=1200&h=900&q=85&fm=jpg`,\n `${fixAssetUrl(\n input.secondaryFeaturedImage.url\n )}?w=1920&h=1080&q=85&fm=jpg`,\n ],\n description: input.shortDescription,\n mpn: `${identifier}`,\n sku: `${identifier}`,\n brand: {\n '@type': 'Organization',\n name: 'Follow Alice',\n logo: 'https://followalice.com/assets/images/fa-icon.svg',\n url: 'https://followalice.com',\n },\n aggregateRating: {\n '@type': 'AggregateRating',\n ratingValue: averageReviewRating,\n reviewCount: numberOfReviews,\n },\n offers: {\n '@type': 'AggregateOffer',\n offerCount: input.linkedFrom.itineraryCollection.total,\n lowPrice: Math.min(...prices),\n highPrice: Math.max(...prices),\n priceCurrency: 'USD',\n url: `/adventure-trips/${input.urlSlug}`,\n },\n };\n }\n\n adaptFromItinerary(input: Itinerary): SchemaProduct {\n const identifier = this.contentfulIdToNumber(input.sys.id);\n const priceValidUntil = new Date();\n priceValidUntil.setFullYear(priceValidUntil.getFullYear() + 1);\n\n return {\n '@type': 'Product',\n name: input.title,\n image: [\n `${fixAssetUrl(\n input?.featuredImage?.url\n )}?w=1200&h=1200&q=85&fm=jpg`,\n `${fixAssetUrl(\n input?.featuredImage?.url\n )}?w=1200&h=900&q=85&fm=jpg`,\n `${fixAssetUrl(\n input?.featuredImage?.url\n )}?w=1920&h=1080&q=85&fm=jpg`,\n ],\n description: input.shortDescription,\n mpn: `${identifier}`,\n sku: `${identifier}`,\n brand: {\n '@type': 'Organization',\n name: 'Follow Alice',\n logo: 'https://followalice.com/assets/images/fa-icon.svg',\n url: 'https://followalice.com',\n },\n offers: {\n '@type': 'Offer',\n priceCurrency: 'USD',\n price: input.startingPrice,\n availability: 'https://schema.org/InStock',\n priceValidUntil: priceValidUntil.toISOString(),\n url: `/adventure-trips/${input.trip.urlSlug}/${input.urlSlug}`,\n },\n aggregateRating: {\n '@type': 'AggregateRating',\n ratingValue: input.averageReviewRating,\n reviewCount: input.numberOfReviews,\n },\n };\n }\n\n adaptFromReview(review: Review): SchemaProduct {\n const identifier = this.contentfulIdToNumber(review.itinerary?.sys?.id);\n const priceValidUntil = new Date();\n priceValidUntil.setFullYear(priceValidUntil.getFullYear() + 1);\n return {\n '@type': 'Product',\n name: review.itinerary?.title,\n mpn: `${identifier}`,\n sku: `${identifier}`,\n brand: {\n '@type': 'Organization',\n name: 'Follow Alice',\n url: 'https://followalice.com',\n },\n offers: {\n '@type': 'Offer',\n priceCurrency: 'USD',\n price: review?.itinerary?.startingPrice,\n availability: 'https://schema.org/InStock',\n priceValidUntil: priceValidUntil.toISOString(),\n url: `/adventure-trips/${review?.itinerary?.trip?.urlSlug}/${review?.itinerary?.urlSlug}`,\n },\n };\n }\n\n private contentfulIdToNumber(id: string): number {\n let hash = 0,\n chr;\n if (id.length === 0) return hash;\n for (let i = 0; i < id.length; i++) {\n chr = id.charCodeAt(i);\n hash = (hash << 5) - hash + chr;\n hash |= 0; // Convert to 32bit integer\n }\n return Math.abs(hash);\n }\n}\n", "import { ProductAdapter } from '@features/seo/adapters/product.adapter';\nimport { Review } from '@generated/graphql';\nimport { Review as SchemaReview } from 'schema-dts';\nimport { Adapter } from './adapter';\n\nexport class ReviewAdapter implements Adapter {\n adapt(input: Review): SchemaReview {\n const productAdapter = new ProductAdapter();\n\n return {\n '@type': 'Review',\n reviewRating: {\n '@type': 'Rating',\n ratingValue: input.rating,\n bestRating: 5,\n worstRating: 1,\n },\n author: {\n '@type': 'Person',\n name: input.name,\n },\n datePublished: input.date,\n reviewBody: input.body,\n itemReviewed: productAdapter.adaptFromReview(input),\n };\n }\n}\n", "import { Adapter } from '@features/seo/adapters/adapter';\nimport { YoutubeVideo } from '@generated/graphql';\nimport { VideoObject } from 'schema-dts';\n\nexport class YoutubeVideoAdapter implements Adapter {\n adapt(input: YoutubeVideo): VideoObject {\n return {\n '@type': 'VideoObject',\n name: input?.title,\n description: input?.title,\n thumbnailUrl: `https://i.ytimg.com/vi/${this.getVideoId(\n input?.videoUrl\n )}/sddefault.jpg`,\n uploadDate: input?.sys.publishedAt,\n embedUrl: `https://www.youtube-nocookie.com/embed/${this.getVideoId(\n input?.videoUrl\n )}`,\n };\n }\n\n getVideoId(videoUrl: string) {\n const urlParams = new URLSearchParams(videoUrl || '');\n return urlParams.get('https://www.youtube.com/watch?v');\n }\n}\n", "import { MetaDefinition } from '@angular/platform-browser';\nimport { DjangoFactory } from './django-factory';\nimport { DjangoModel } from './django-model';\n\nclass MetaTag extends DjangoModel {\n attribute: string;\n attributeData: string;\n content: string;\n\n automaticDeserializeFields = ['attribute', 'attributeData', 'content'];\n\n get metaDefinition(): MetaDefinition {\n return {\n [this.attribute]: this.attributeData,\n content: this.content,\n };\n }\n}\n\nclass PageSchema extends DjangoModel {\n schema: any;\n\n automaticDeserializeFields = ['schema'];\n}\n\nexport class SeoMetadata extends DjangoModel {\n title: string;\n metaTags: MetaTag[];\n pageSchemas: PageSchema[];\n\n automaticDeserializeFields = ['title'];\n\n deserialize(input: any) {\n super.deserialize(input);\n this.metaTags = DjangoFactory.buildMany(MetaTag, input.meta_tags);\n this.pageSchemas = DjangoFactory.buildMany(\n PageSchema,\n input.page_schemas\n );\n }\n}\n", "import { DOCUMENT } from '@angular/common';\nimport { Inject, Injectable, OnDestroy } from '@angular/core';\nimport {\n ActivatedRouteSnapshot,\n Router,\n RouterStateSnapshot,\n} from '@angular/router';\nimport { fixAssetUrl } from '@features/contentful/helpers/assetHelpers';\nimport { ArticleAdapter } from '@features/seo/adapters/article.adapter';\nimport {\n BreadCrumbItem,\n BreadcrumbListAdapter,\n} from '@features/seo/adapters/breadcrumb-list.adapter';\nimport { ProductAdapter } from '@features/seo/adapters/product.adapter';\nimport { ReviewAdapter } from '@features/seo/adapters/review.adapter';\nimport { YoutubeVideoAdapter } from '@features/seo/adapters/youtube-video.adapter';\nimport {\n BasePage,\n Itinerary,\n KnowledgeArticle,\n Review,\n Trip,\n YoutubeVideo,\n} from '@generated/graphql';\nimport { DjangoFactory } from '@models/django-factory';\nimport { SeoMetadata } from '@models/seo-metadata.model';\nimport { Observable, ReplaySubject, of } from 'rxjs';\nimport { catchError, map, switchMap, tap } from 'rxjs/operators';\nimport {\n AboutPage,\n Article,\n BreadcrumbList,\n Product as SchemaProduct,\n Review as SchemaReview,\n Thing,\n VideoObject,\n WithContext,\n} from 'schema-dts';\nimport { DjangoService } from './django.service';\nimport { EnvironmentService } from './environment.service';\nimport { MetadataService } from './metadata.service';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class SeoService implements OnDestroy {\n public set seoMetadata(metadata: SeoMetadata) {\n this._seoMetadata.next(metadata);\n }\n public get seoMetadata$(): Observable {\n return this._seoMetadata.asObservable();\n }\n\n private _seoMetadata = new ReplaySubject(1);\n\n constructor(\n private router: Router,\n private djangoService: DjangoService,\n private metadataService: MetadataService,\n private environmentService: EnvironmentService,\n @Inject(DOCUMENT) private document: Document\n ) {}\n\n ngOnDestroy(): void {\n this._seoMetadata.complete();\n }\n\n prefetchMetadata(route: string) {\n return this.djangoService.seoMetadata(route);\n }\n\n generateReview(review: Review): WithContext {\n const schema = new ReviewAdapter().adapt(review);\n return SeoService.addContext(schema);\n }\n\n generateProduct(trip: Trip): WithContext {\n const schema = new ProductAdapter().adapt(trip);\n return SeoService.addContext(schema);\n }\n\n generateProductFromItinerary(\n itinerary: Itinerary\n ): WithContext {\n const schema = new ProductAdapter().adaptFromItinerary(itinerary);\n return SeoService.addContext(schema);\n }\n\n generateArticle(article: KnowledgeArticle): WithContext
{\n const schema = new ArticleAdapter().adapt(article);\n return SeoService.addContext(schema);\n }\n\n generateBreadCrumbs(items: BreadCrumbItem[]): WithContext {\n const schema = new BreadcrumbListAdapter().adapt(items);\n return SeoService.addContext(schema);\n }\n\n generateYoutubeVideo(video: YoutubeVideo): WithContext {\n const schema = new YoutubeVideoAdapter().adapt(video);\n return SeoService.addContext(schema);\n }\n\n generateAboutUs(schema: AboutPage): WithContext {\n return SeoService.addContext(schema);\n }\n\n setCanonicalUrl(route: string) {\n let cleanURL = this.router.parseUrl(route);\n cleanURL.queryParams = {};\n const linkElement = this.document.getElementById('canonicalUrl');\n const url = `${this.environmentService.hostName()}${cleanURL.toString()}`;\n linkElement.setAttribute('href', url);\n this.metadataService.setAttribute({ property: 'og:url', content: url });\n }\n\n handleCustomPageMetaTags(pageData: BasePage) {\n if (pageData.seoTitle) {\n this.metadataService.setTitle(pageData.seoTitle);\n } else {\n this.metadataService.setTitle(pageData.title);\n }\n\n let defaultMetaTags = [\n {\n name: 'description',\n content: pageData.seoDescription,\n },\n {\n property: 'og:description',\n content: pageData.seoDescription,\n },\n {\n property: 'og:type',\n content: 'website',\n },\n ];\n\n if (pageData?.featuredImage?.url) {\n defaultMetaTags = [\n ...defaultMetaTags,\n {\n property: 'og:image',\n content: `${fixAssetUrl(\n pageData.featuredImage?.url\n )}?w=1200&h=800&f=center&fit=fill&fm=jpg`,\n },\n {\n property: 'og:image:secure_url',\n content: `${fixAssetUrl(\n pageData.featuredImage?.url\n )}?w=1200&h=800&f=center&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 }\n\n // Adding Meta Tags from contentful Data\n defaultMetaTags.forEach(metaObj => {\n this.metadataService.setAttribute(metaObj);\n });\n this.setCanonicalUrl(this.router.url);\n }\n\n private static addContext(schema: T): WithContext {\n return {\n '@context': 'https://schema.org',\n // https://github.com/microsoft/TypeScript/issues/49982\n // @ts-ignore\n ...schema,\n };\n }\n}\n\n@Injectable({ providedIn: 'root' })\nexport class SeoResolver {\n constructor(\n private router: Router,\n private djangoService: DjangoService,\n private metadataService: MetadataService,\n private seoService: SeoService,\n @Inject(DOCUMENT) private document: Document\n ) {}\n\n resolve(\n route: ActivatedRouteSnapshot,\n state: RouterStateSnapshot\n ): Observable | Promise | any {\n return of(state.url).pipe(\n map((url: string) => this.router.parseUrl(url)),\n tap(urlTree => (urlTree.queryParams = {})),\n map(urlTree => urlTree.toString()),\n tap(route => this.seoService.setCanonicalUrl(route)),\n switchMap(route => this.djangoService.seoMetadata(route)),\n map(seoMetadata => DjangoFactory.build(SeoMetadata, seoMetadata)),\n tap((seoMetadata: SeoMetadata) => {\n if (seoMetadata.title) {\n this.metadataService.setTitle(seoMetadata.title);\n }\n for (let metaTag of seoMetadata.metaTags) {\n this.metadataService.setAttribute(metaTag.metaDefinition);\n }\n }),\n tap(data => (this.seoService.seoMetadata = data)),\n catchError(() => of(null))\n );\n }\n}\n"], "mappings": "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", "names": ["ArticleAdapter", "adapt", "input", "headline", "title", "url", "urlSlug", "author", "name", "fullName", "image", "fixAssetUrl", "featuredImageSquare", "featuredImageCropFocus", "datePublished", "sys", "firstPublishedAt", "dateModified", "publishedAt", "BreadcrumbListAdapter", "adapt", "input", "itemListElement", "generateItemList", "items", "map", "data", "index", "position", "name", "item", "url", "ProductAdapter", "adapt", "input", "itineraries", "linkedFrom", "itineraryCollection", "items", "prices", "map", "itinerary", "startingPrice", "numberOfReviews", "reduce", "previousValue", "currentValue", "averageReviewRating", "identifier", "contentfulIdToNumber", "sys", "id", "name", "title", "image", "fixAssetUrl", "featuredImage", "url", "secondaryFeaturedImage", "description", "shortDescription", "mpn", "sku", "brand", "logo", "aggregateRating", "ratingValue", "reviewCount", "offers", "offerCount", "total", "lowPrice", "Math", "min", "highPrice", "max", "priceCurrency", "urlSlug", "adaptFromItinerary", "priceValidUntil", "Date", "setFullYear", "getFullYear", "price", "availability", "toISOString", "trip", "adaptFromReview", "review", "hash", "chr", "length", "i", "charCodeAt", "abs", "ReviewAdapter", "adapt", "input", "productAdapter", "ProductAdapter", "reviewRating", "ratingValue", "rating", "bestRating", "worstRating", "author", "name", "datePublished", "date", "reviewBody", "body", "itemReviewed", "adaptFromReview", "YoutubeVideoAdapter", "adapt", "input", "name", "title", "description", "thumbnailUrl", "getVideoId", "videoUrl", "uploadDate", "sys", "publishedAt", "embedUrl", "URLSearchParams", "get", "MetaTag", "DjangoModel", "constructor", "automaticDeserializeFields", "metaDefinition", "attribute", "attributeData", "content", "PageSchema", "SeoMetadata", "deserialize", "input", "metaTags", "DjangoFactory", "buildMany", "meta_tags", "pageSchemas", "page_schemas", "SeoService", "seoMetadata", "metadata", "_seoMetadata", "next", "seoMetadata$", "asObservable", "constructor", "router", "djangoService", "metadataService", "environmentService", "document", "ReplaySubject", "ngOnDestroy", "complete", "prefetchMetadata", "route", "generateReview", "review", "schema", "ReviewAdapter", "adapt", "addContext", "generateProduct", "trip", "ProductAdapter", "generateProductFromItinerary", "itinerary", "adaptFromItinerary", "generateArticle", "article", "ArticleAdapter", "generateBreadCrumbs", "items", "BreadcrumbListAdapter", "generateYoutubeVideo", "video", "YoutubeVideoAdapter", "generateAboutUs", "setCanonicalUrl", "cleanURL", "parseUrl", "queryParams", "linkElement", "getElementById", "url", "hostName", "toString", "setAttribute", "property", "content", "handleCustomPageMetaTags", "pageData", "seoTitle", "setTitle", "title", "defaultMetaTags", "name", "seoDescription", "featuredImage", "fixAssetUrl", "forEach", "metaObj", "__spreadValues", "\u0275\u0275inject", "Router", "DjangoService", "MetadataService", "EnvironmentService", "DOCUMENT", "factory", "\u0275fac", "providedIn", "SeoResolver", "seoService", "resolve", "state", "of", "pipe", "map", "tap", "urlTree", "switchMap", "DjangoFactory", "build", "SeoMetadata", "metaTag", "metaTags", "metaDefinition", "data", "catchError"] }