{"version":3,"mappings":"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","names":["props","__props","carouselConfig","articleHeaderRef","useTemplateRef","shouldUseWideHeroOnDesktop","nextTick","enableHearts","lastItemInFirstColumn","hasContent","ref","relatedArticles","getArticles","articlesJSON","populateContentTiles","fallbackArticlesJSON","articles","articleCount","article","articleIndex","generateCmsImageUrl","cobrandLink","componentToRender","shallowRef","relatedArticlesSearchCriteria","componentMap","defineAsyncComponent","__vitePreload","initializeFeatureFlags","getFeatureFlag","tag","buildRelatedArticlesQuery","shouldSortByModifiedDate","articleSearchCriteria","adZoneLabel","topAdZoneId","articleHeader","articleTags","isReady","displayFallback","useTopAdZone","extendedBodyContent","findAnAdvisorCta","productsHeader","products","hideFindAnAdvisor","componentRoot","adZoneId","computed","numArticleFields","item","numImageFields","hasProducts","isProductPopulated","i","_a","_b","_c","getArticle","articleResponse","transformCmsBasicArticle","transformCmsBasicArticleHeader","transformCmsBasicArticleFindAnAdvisorCta","transformCmsArticleProductCards","qsParams","parseURLParameters","translateLinksToConsumerUrl","cobrandLinks","goToURLHash","destinationHubTags","trackEvent","toastError","app","createApp","ArticleBasicComponent","mountApp"],"ignoreList":[],"sources":["../../../scripts/components/article/article-header.vue","../../../scripts/components/article/article-itinerary.vue","../../../scripts/components/article/related-articles.vue","../../../scripts/components/article/related-content.vue","../../../scripts/components/pages/articles-landing.vue","../../../scripts/components/shared/ad-zone.vue","../../../scripts/components/pages/article-basic.vue","../../../scripts/entry-points/articles.ts"],"sourcesContent":["<template>\r\n    <div ref=\"article-header\" data-testid=\"article-header\" :class=\"['container p-0 mb-3 article-header', {'extra-wide-1920 text-center': content.useWideHeroImage}, content.useWideHeroHeadlineOverlay ? '-overlay mt-0' : 'mt-2']\">\r\n        <div class=\"position-relative\">\r\n            <div :class=\"['title-container px-2 p-md-0 mb-2', {'context-dark': content.useWideHeroHeadlineOverlay}]\">\r\n                <h1 v-html=\"content.headline\"></h1>\r\n                <template v-if=\"!content.useWideHeroImage\">\r\n                    <div v-if=\"content.author\" class=\"article-author weglot-exclude\">{{ content.author }}</div>\r\n                    <div v-if=\"content.date\" class=\"article-date\">{{ content.date }}</div>\r\n                    <button class=\"wl-heartable -save-this d-xl-none mt-1 ps-0\" data-wl-type=\"article\" :data-wl-id=\"content.identifier\" :data-wl-title=\"content.headline\"></button>\r\n                </template>\r\n                <div class=\"position-relative\">\r\n                    <button v-if=\"!content.useWideHeroImage\" class=\"wl-heartable -save-this -right d-none d-xl-block\" data-wl-type=\"article\" :data-wl-id=\"content.identifier\" :data-wl-title=\"content.headline\"></button>\r\n                    <ul v-if=\"content.categories.length && !isEmbeddedMode()\" class=\"category-links mt-1 context-dark\" aria-label=\"Article Categories\">\r\n                        <li v-for=\"(category, index) in content.categories\" :key=\"index\">\r\n                            <a :href=\"getCategoryLink(category)\" :class=\"['-tag', {'-emphasis' : !content.useWideHeroHeadlineOverlay}]\">{{ category }}</a>\r\n                        </li>\r\n                    </ul>\r\n                </div>\r\n            </div>\r\n\r\n            <captioned-image-carousel-component v-if=\"content.heroImages.length === 3\" carousel-class=\"carousel-responsive-3vert\" :slides=\"content.heroImages\" :carousel-config=\"carouselConfig\" data-testid=\"captioned-image-carousel\"></captioned-image-carousel-component>\r\n            <captioned-image-component v-if=\"content.heroImages.length === 1\" :caption-class=\"content.useWideHeroImage ? '-cozy mx-2' : 'mx-2'\" container-class=\"mb-3 hero-horizontal\" :content=\"content.heroImages[0]\" data-testid=\"captioned-image\" :should-use-wide-hero-on-desktop=\"shouldUseWideHeroOnDesktop\"></captioned-image-component>\r\n        </div>\r\n        <template v-if=\"content.useWideHeroImage\">\r\n            <div class=\"d-flex flex-column flex-md-row gap-md-2 align-items-center justify-content-center px-2\">\r\n                <span v-if=\"content.author\" class=\"article-author weglot-exclude text-emphasis\">{{ content.author }}</span>\r\n                <span class=\"text--small d-none d-md-block\">&#8226;</span>\r\n                <span v-if=\"content.date\" class=\"article-date\">{{ content.date }}</span>\r\n                <span class=\"text--small d-none d-md-block\">&#8226;</span>\r\n                <button class=\"wl-heartable -save-this p-1\" data-wl-type=\"article\" :data-wl-id=\"content.identifier\" :data-wl-title=\"content.headline\"></button>\r\n            </div>\r\n        </template>\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\n    import CaptionedImageCarouselComponent from \"components/shared/captioned-image-carousel.vue\";\r\n    import CaptionedImageComponent from \"components/shared/captioned-image.vue\";\r\n    import { ArticleHeader } from \"interfaces/article\";\r\n    import { CarouselConfigOptions } from \"interfaces/carousel\";\r\n    import { getCategoryLink } from \"services/helpers/categories\";\r\n    import { isEmbeddedMode } from \"services/layout/environment\";\r\n    import { enableHearts } from \"services/wanderlist\";\r\n    import { nextTick, PropType, useTemplateRef } from \"vue\";\r\n\r\n    const props = defineProps({\r\n        content: {\r\n            type: Object as PropType<ArticleHeader>,\r\n            default: undefined\r\n        }\r\n    });\r\n\r\n    const carouselConfig: CarouselConfigOptions = {\r\n        arrows: false,\r\n        mediaQuery: \"max\",\r\n        destroy: true,\r\n        focus: \"center\",\r\n        gap: 0,\r\n        padding: {right: \"3rem\" },\r\n        fixedWidth: \"300px\",\r\n        breakpoints:{\r\n            1200:\r\n                {\r\n                    destroy: false\r\n                }\r\n        }\r\n    };\r\n\r\n    const articleHeaderRef = useTemplateRef(\"article-header\");\r\n    const shouldUseWideHeroOnDesktop = props.content.useWideHeroImage && props.content.useWideHeroHeadlineOverlay;\r\n\r\n    nextTick(() => {\r\n        enableHearts(articleHeaderRef.value);\r\n    });\r\n</script>\r\n","<template>\r\n    <div class=\"editorial-itinerary\">\r\n        <div class=\"table-of-contents\">\r\n            <h3>{{ tableOfContents.header }}</h3>\r\n\r\n            <ul :class=\"['list-unstyled', {'short-list': tableOfContents.items.length < 6 } ]\">\r\n                <li v-for=\"(item, idx) in tableOfContents.items\" :key=\"idx\" :class=\"['my-1 gap-1', {'break-column': idx === lastItemInFirstColumn} ]\">\r\n                    <span v-if=\"item.label\" class=\"fw-bold text--small text--sans-serif text-nowrap item-label\">{{ item.label }}</span>\r\n                    <a :href=\"`#${item.jumpLinkId}`\" class=\"-no-decoration-idle\">{{ item.text }}</a>\r\n                </li>\r\n            </ul>\r\n        </div>\r\n\r\n        <div class=\"itinerary-section\">\r\n            <template v-for=\"(item, idx) in content\" :key=\"idx\">\r\n                <div class=\"itinerary-item\">\r\n                    <CaptionedImagePair :left-image=\"item.imageLeft\" :right-image=\"item.imageRight\"></CaptionedImagePair>\r\n\r\n                    <h3 :id=\"item.jumpLinkId\" class=\"section-header\">{{ item.header }}</h3>\r\n\r\n                    <div class=\"section-content\" v-html=\"item.text\"></div>\r\n                </div>\r\n                \r\n                <FindAnAdvisorCtaComponent v-if=\"idx == 2 && !isEmbeddedMode()\" :button-text=\"advisorCta.buttonText\" :custom-button-link=\"advisorCta.buttonLink\" :custom-content-text=\"advisorCta.contentText\" :custom-header-text=\"advisorCta.header\" :option-index=\"1\"></FindAnAdvisorCtaComponent>\r\n            </template>\r\n        </div>\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\n    import FindAnAdvisorCtaComponent from \"components/advisor/find-an-advisor-cta.vue\";\r\n    import CaptionedImagePair from \"components/shared/captioned-image-pair.vue\";\r\n    import { FindAnAdvisorCTA } from \"interfaces/advisor\";\r\n    import { ItineraryItem, ItineraryTableOfContents } from \"interfaces/article\";\r\n    import { isEmbeddedMode } from \"services/layout/environment\";\r\n    import { PropType } from \"vue\";\r\n\r\n                                \r\n    const props = defineProps({\r\n        tableOfContents: {\r\n            type: Object as PropType<ItineraryTableOfContents>,\r\n            default: () => ({})\r\n        },\r\n        content: {\r\n            type: Array as PropType<ItineraryItem[]>,\r\n            default: () => [] as ItineraryItem[]\r\n        },\r\n        advisorCta: {\r\n            type: Object as PropType<FindAnAdvisorCTA>,\r\n            default: () => ({})\r\n        }\r\n    });\r\n\r\n    const lastItemInFirstColumn = Math.floor((props.tableOfContents.items.length + 1) / 2) - 1;\r\n\r\n    \r\n</script>\r\n","<template>\r\n    <div v-if=\"hasContent\" class=\"container px-lg-0\">\r\n        <h2 v-if=\"header\" class=\"text--serif mb-2\" v-html=\"header\"></h2>\r\n        <content-tiles :content-tiles=\"relatedArticles\" layout-class=\"-mixed\" :should-track-content-tile-views=\"true\"></content-tiles>\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\n    import ContentTiles from \"components/shared/content-tiles.vue\";\r\n    import { DotCMSBasicArticleResponse } from \"interfaces/responses/dotcms-responses\";\r\n    import { ContentTile } from \"interfaces/card\";\r\n    import { CmsSearchCriteria } from \"interfaces/cms\";\r\n    import { getArticles } from \"services/api/articles\";\r\n    import { generateCmsImageUrl } from \"services/helpers/images\";\r\n    import { cobrandLink } from \"virtuoso-shared-web-ui\";\r\n    import { PropType, ref } from \"vue\";\r\n\r\n    const props = defineProps({\r\n        header: {\r\n            type: String,\r\n            default: \"\"\r\n        },\r\n        searchCriteria: {\r\n            type: Object as PropType<CmsSearchCriteria>,\r\n            default: () => ({})\r\n        }\r\n    });\r\n\r\n    const hasContent = ref(false);\r\n    const relatedArticles = ref<ContentTile[]>([]);\r\n\r\n    getArticles(props.searchCriteria)\r\n        .then((articlesJSON) => {\r\n\r\n            if (articlesJSON.articles.length) {\r\n                populateContentTiles(articlesJSON.articles);\r\n            } else {\r\n                console.log(\"No related articles found, getting latest articles instead.\");\r\n\r\n                getArticles({\r\n                    contentTypes: [\"ConsumerArticleBasic\"],\r\n                    limit: 5,\r\n                    sort: \"ConsumerArticleBasic.publish desc\"\r\n                }).then((fallbackArticlesJSON) => {\r\n\r\n                    if (fallbackArticlesJSON.articles.length) {\r\n                        populateContentTiles(fallbackArticlesJSON.articles);\r\n                    }\r\n\r\n                }, () => {\r\n                    // Don't need to display an error on screen\r\n                    console.error(\"Error retrieving latest articles\");\r\n                });\r\n            }\r\n\r\n        }, () => {\r\n            // Don't need to display an error on screen\r\n            console.error(\"Error retrieving related articles\");\r\n        });\r\n\r\n\r\n    function populateContentTiles(articles: DotCMSBasicArticleResponse[]) {\r\n        const articleCount = articles.length;\r\n\r\n        articles.forEach((article: DotCMSBasicArticleResponse, articleIndex: number) => {\r\n            relatedArticles.value.push({\r\n                identifier: article.identifier,\r\n                imageCropFocus: (article.previewImageCropFocus) ? article.previewImageCropFocus : \"center\",\r\n                imageUrl: generateCmsImageUrl(article.previewImage, { width: 576 }),\r\n                sponsoredText: (article.isSponsoredContent === \"1\") ? \"Sponsored\" : \"\",\r\n                title: article.headline,\r\n                url: cobrandLink(`/travel/articles/${article.articleUrl}`),\r\n                tileLayout: (articleCount === 3 || (articleCount === 5 && articleIndex >= 2)) ? \"-square\" : \"\"\r\n            });\r\n        });\r\n\r\n        hasContent.value = true;\r\n    }\r\n</script>\r\n","<template>\r\n    <component :is=\"componentToRender.component\" v-if=\"componentToRender\" v-bind=\"componentToRender.props\"></component>\r\n    <RelatedArticles v-else-if=\"relatedArticlesSearchCriteria\" header=\"More Stories\" :search-criteria=\"relatedArticlesSearchCriteria\"></RelatedArticles>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\n    import RelatedArticles from \"components/article/related-articles.vue\";\r\n    import { buildRelatedArticlesQuery } from \"services/transformers/article\";\r\n    import { getFeatureFlag, initializeFeatureFlags } from \"services/feature-flags\";\r\n    import { defineAsyncComponent, ref, shallowRef, type Component, type PropType } from \"vue\";\r\n\r\n    const props = defineProps({\r\n        tags: {\r\n            type: Array as PropType<string[]>,\r\n            default: (): string[] => []\r\n        },\r\n        identifier: {\r\n            type: String,\r\n            default: \"\"\r\n        }\r\n    });\r\n\r\n    const componentToRender = shallowRef(null);\r\n    const relatedArticlesSearchCriteria = ref(null);\r\n\r\n    const componentMap = new Map<string, {component: Component; props: Record<string, unknown>}>([\r\n        [\"destination-hub:|south-pacific|australia\",\r\n         {\r\n             component: defineAsyncComponent(() => import(\"components/destination/custom/australia-destination-hub-interactive-map.vue\")),\r\n             props: { destinationTag: \"destination-hub:|south-pacific|australia\" }\r\n         }\r\n        ]\r\n    ]);\r\n\r\n    initializeFeatureFlags()\r\n        .finally(() => {\r\n            if (getFeatureFlag(\"consumer-2025-02-article-dde-map-related-content-temp\") === true ) {\r\n                for (const tag of props.tags) {\r\n                    if (componentMap.has(tag)) {\r\n                        componentToRender.value = componentMap.get(tag);\r\n                        break;\r\n                    }\r\n                }\r\n            }\r\n\r\n            // If no matching components are found, fallback to the relatedArticles\r\n            if (!componentToRender.value) {\r\n                relatedArticlesSearchCriteria.value = buildRelatedArticlesQuery(props.tags.join(), props.identifier);\r\n            }\r\n        });\r\n</script>","<template>\r\n    <section>\r\n        <div class=\"container mt-3 px-lg-0\">\r\n            <ArticleCards header-text=\"Articles\" :search-criteria=\"articleSearchCriteria\" :articles-per-page=\"6\" :show-more=\"true\" page-name=\"Article Landing Page\"></ArticleCards>\r\n        </div>\r\n    </section>\r\n</template>\r\n\r\n\r\n<script setup lang=\"ts\">\r\n    import ArticleCards from \"components/article/article-cards.vue\";\r\n    import { CmsSearchCriteria } from \"interfaces/cms\";\r\n\r\n    // Special secret query string paramter to sort by modified date rather than published date\r\n    const shouldSortByModifiedDate = window.location.search.includes(\"sort=modified\");\r\n\r\n    const articleSearchCriteria: CmsSearchCriteria = {\r\n        contentTypes: [\"ConsumerArticleBasic\"],\r\n        sort: shouldSortByModifiedDate ? \"modDate desc\" : \"ConsumerArticleBasic.publish desc\"\r\n    };\r\n\r\n</script>\r\n","<template>\r\n    <div v-if=\"adZoneId\" :class=\"['ad-zone', (isFancy) ? '-fancy' : '']\">\r\n        <div v-if=\"isFancy\" class=\"-top-line\" data-testid=\"ad-zone-label\" v-html=\"adZoneLabel\"></div>\r\n        <broadstreet-zone :zone-id=\"adZoneId\"></broadstreet-zone>\r\n    </div>\r\n</template>\r\n\r\n\r\n<script setup lang=\"ts\">\r\n\r\n    const props = defineProps({\r\n        adZoneId: {\r\n            type: Number,\r\n            default: undefined\r\n        },\r\n        isFancy: {\r\n            type: Boolean,\r\n            default: false\r\n        },\r\n        label: {\r\n            type: String,\r\n            default: undefined\r\n        }\r\n    });\r\n\r\n    const adZoneLabel = (props.label) ? props.label : \"Advertisement\";\r\n\r\n</script>\r\n","<template>\r\n    <section v-if=\"isReady\" ref=\"component-root\" class=\"px-lg-0\">\r\n        <article class=\"vc-article\">\r\n            <!-- Ad Zone 1 -->\r\n            <ad-zone-component v-if=\"useTopAdZone\" :ad-zone-id=\"topAdZoneId\" :label=\"adZoneLabel\" :is-fancy=\"true\"></ad-zone-component>\r\n\r\n            <article-header-component :content=\"articleHeader\"></article-header-component>\r\n\r\n            <div class=\"container row mt-3 px-0\">\r\n                <div class=\"col-12\">\r\n                    <h2 v-if=\"article.subhead\" class=\"article-section\" v-html=\"article.subhead\"></h2>\r\n\r\n                    <div v-if=\"article.articleTextIntro\" class=\"article-section\" v-html=\"article.articleTextIntro\"></div>\r\n\r\n                    <!-- Advisor Tip -->\r\n                    <AdvisorTipComponent v-if=\"article.advisorTipText && !article.itineraryContent\" class=\"article-section\" :tip-text=\"article.advisorTipText\" :attribution=\"article.advisorTipAttribution\" :show-button=\"!article.hideFindAnAdvisor\"></AdvisorTipComponent>\r\n\r\n                    <captioned-media-component v-if=\"article.articleBody[0] && article.articleBody[0].articleMedia\" :media-data=\"article.articleBody[0].articleMedia\" container-class=\"my-3\"></captioned-media-component>\r\n                    <div v-if=\"article.articleBody[0] && article.articleBody[0].articleText\" class=\"article-section\"\r\n                         v-html=\"article.articleBody[0].articleText\"></div>\r\n\r\n                    <!-- Ad Zone 2 -->\r\n                    <ad-zone-component :ad-zone-id=\"adZoneId\" :label=\"adZoneLabel\" :is-fancy=\"true\"></ad-zone-component>\r\n\r\n                    <captioned-media-component v-if=\"article.articleBody[1] && article.articleBody[1].articleMedia\" :media-data=\"article.articleBody[1].articleMedia\" container-class=\"my-3\"></captioned-media-component>\r\n                    <div v-if=\"article.articleBody[1] && article.articleBody[1].articleText\" class=\"article-section\"\r\n                         v-html=\"article.articleBody[1].articleText\"></div>\r\n\r\n                    <captioned-media-component v-if=\"article.articleBody[2] && article.articleBody[2].articleMedia\" :media-data=\"article.articleBody[2].articleMedia\" container-class=\"my-3\"></captioned-media-component>\r\n                    <div v-if=\"article.articleBody[2] && article.articleBody[2].articleText\" class=\"article-section\"\r\n                         v-html=\"article.articleBody[2].articleText\"></div>\r\n\r\n                    <!-- Find an Advisor -->\r\n                    <find-an-advisor-cta-component v-if=\"!article.hideFindAnAdvisor && !isEmbeddedMode() && !article.itineraryContent\" :button-text=\"findAnAdvisorCta.buttonText\" :custom-button-link=\"findAnAdvisorCta.buttonLink\" :custom-content-text=\"findAnAdvisorCta.contentText\" :custom-header-text=\"findAnAdvisorCta.header\" :option-index=\"1\"></find-an-advisor-cta-component>\r\n\r\n                    <captioned-media-component v-if=\"article.articleBody[3] && article.articleBody[3].articleMedia\" :media-data=\"article.articleBody[3].articleMedia\" container-class=\"my-3\"></captioned-media-component>\r\n                    <div v-if=\"article.articleBody[3] && article.articleBody[3].articleText\" class=\"article-section\"\r\n                         v-html=\"article.articleBody[3].articleText\"></div>\r\n\r\n                    <!-- Extended captioned image and article text pairs -->\r\n                    <template v-if=\"extendedBodyContent\">\r\n                        <template v-for=\"(mediaTextPair, index) in extendedBodyContent\">\r\n                            <captioned-media-component v-if=\"mediaTextPair.articleMedia\" :key=\"'m-'+index\" :media-data=\"mediaTextPair.articleMedia\" container-class=\"my-3\"></captioned-media-component>\r\n                            <div v-if=\"mediaTextPair.articleText\" :key=\"'t='+index\" class=\"article-section\" v-html=\"mediaTextPair.articleText\"></div>\r\n                        </template>\r\n                    </template>\r\n\r\n                    <template v-if=\"article.itineraryContent\">\r\n                        <ArticleItinerary :table-of-contents=\"article.itineraryContent.toc\" :content=\"article.itineraryContent.body\" :advisor-cta=\"findAnAdvisorCta\"></ArticleItinerary>\r\n                        <AdvisorTipComponent v-if=\"article.advisorTipText\" class=\"article-section\" :tip-text=\"article.advisorTipText\" :attribution=\"article.advisorTipAttribution\" :show-button=\"!article.hideFindAnAdvisor\"></AdvisorTipComponent>\r\n                    </template>\r\n\r\n                    <!-- Ad Zone 3 -->\r\n                    <ad-zone-component :ad-zone-id=\"adZoneId\" :is-fancy=\"true\"></ad-zone-component>\r\n\r\n                    <div v-if=\"hasProducts\" class=\"article-product-cards-container\">\r\n                        <h2 class=\"mt-5 mb-2\" v-html=\"productsHeader\"></h2>\r\n                        <article-product-cards-component :content=\"products\"></article-product-cards-component>\r\n                    </div>\r\n                </div>\r\n            </div>\r\n        </article>\r\n        <RelatedContent :tags=\"articleTags\" :identifier=\"article.identifier\"></RelatedContent>\r\n    </section>\r\n    <section v-else-if=\"displayFallback\" class=\"container my-3 px-lg-0\">\r\n        We couldn't find the article you're looking for, but these stories might inspire you.\r\n        <ArticlesLanding />\r\n    </section>\r\n    <LogoSplash v-else />\r\n</template>\r\n\r\n\r\n<script setup lang=\"ts\">\r\n    import AdvisorTipComponent from \"components/advisor/advisor-tip.vue\";\r\n    import FindAnAdvisorCtaComponent from \"components/advisor/find-an-advisor-cta.vue\";\r\n    import ArticleHeaderComponent from \"components/article/article-header.vue\";\r\n    import ArticleItinerary from \"components/article/article-itinerary.vue\";\r\n    import ArticleProductCardsComponent from \"components/article/article-product-cards.vue\";\r\n    import RelatedContent from \"components/article/related-content.vue\";\r\n    import ArticlesLanding from \"components/pages/articles-landing.vue\";\r\n    import AdZoneComponent from \"components/shared/ad-zone.vue\";\r\n    import CaptionedMediaComponent from \"components/shared/captioned-media.vue\";\r\n    import LogoSplash from \"components/shared/logo-splash.vue\";\r\n    import { FindAnAdvisorCTA } from \"interfaces/advisor\";\r\n    import { ArticleBasic, ArticleHeader } from \"interfaces/article\";\r\n    import { ContentCard } from \"interfaces/card\";\r\n    import { ArticleMediaTextPair } from \"interfaces/image\";\r\n    import { getArticle } from \"services/api/articles\";\r\n    import { toastError } from \"services/helpers/toasts\";\r\n    import { isEmbeddedMode } from \"services/layout/environment\";\r\n    import { goToURLHash } from \"services/layout/navigation\";\r\n    import { transformCmsBasicArticle, transformCmsBasicArticleFindAnAdvisorCta, transformCmsBasicArticleHeader } from \"services/transformers/article\";\r\n    import { transformCmsArticleProductCards, translateLinksToConsumerUrl } from \"services/transformers/products\";\r\n    import { trackEvent } from \"services/analytics\";\r\n    import { cobrandLinks, parseURLParameters } from \"virtuoso-shared-web-ui\";\r\n    import { computed, nextTick, ref, useTemplateRef } from \"vue\";\r\n\r\n    const article = ref({} as ArticleBasic);\r\n    const articleHeader = ref({} as ArticleHeader);\r\n    const articleTags = ref([] as string[]);\r\n    const isReady = ref(false);\r\n    const displayFallback = ref(false);\r\n    const useTopAdZone = ref(false);\r\n    const topAdZoneId = 163084;\r\n    const extendedBodyContent = ref([] as ArticleMediaTextPair[]);\r\n    const findAnAdvisorCta = ref({} as FindAnAdvisorCTA);\r\n    const productsHeader = ref(\"\");\r\n    const products = ref([] as ContentCard[]);\r\n    const hideFindAnAdvisor = ref(false);\r\n    const componentRoot = useTemplateRef<HTMLElement>(\"component-root\");\r\n\r\n    const adZoneId = computed(() => article.value.isSponsored ? 97491 : 78463); // Sponsored articles use a separate ad zone ID\r\n\r\n    const adZoneLabel = computed(() => {\r\n        const numArticleFields = article.value.articleBody.filter((item) => (item.articleText)).length;\r\n        const numImageFields = article.value.articleBody.filter((item) => (item.articleMedia.imageUrl)).length;\r\n\r\n        return (numArticleFields > 1 || numImageFields > 1) ? \"Story continues below advertisement\" : \"\";\r\n    });\r\n\r\n    const hasProducts = computed(() => {\r\n        // This array of objects is populated with empty values by default, so we can't just check length\r\n        let isProductPopulated = false;\r\n\r\n        for (let i = 0; i <= 5; i++) {\r\n            if (products.value[i]?.content || products.value[i]?.imageUrl || products.value[i]?.title) {\r\n                isProductPopulated = true;\r\n                break;\r\n            }\r\n        }\r\n\r\n        return isProductPopulated;\r\n    });\r\n\r\n    getArticle(window.VIRTUOSO.articleKey).then((articleResponse) => {\r\n            \r\n            useTopAdZone.value = articleResponse.useTopAdZone;\r\n\r\n            article.value = transformCmsBasicArticle(articleResponse);\r\n\r\n            articleHeader.value = transformCmsBasicArticleHeader(articleResponse);\r\n\r\n            articleTags.value = (articleResponse.tags) ? articleResponse.tags.split(\",\") : [];\r\n\r\n            findAnAdvisorCta.value = transformCmsBasicArticleFindAnAdvisorCta(articleResponse);\r\n\r\n            products.value = transformCmsArticleProductCards(articleResponse);\r\n            productsHeader.value = articleResponse.productHeaderText ?? \"\";\r\n\r\n            if (article.value.articleBody.length > 4) {\r\n                extendedBodyContent.value = article.value.articleBody.slice(4);\r\n            }\r\n\r\n            // Suppress the Find an Advisor component if needed\r\n            const qsParams = parseURLParameters();\r\n            hideFindAnAdvisor.value = qsParams.HideFindAnAdvisor === \"1\";\r\n\r\n            // At this point we can render things\r\n            isReady.value = true;\r\n\r\n            nextTick(() => { \r\n                translateLinksToConsumerUrl(componentRoot.value);\r\n                cobrandLinks(componentRoot.value);\r\n                goToURLHash(); // Scroll to an anchor/ID in the content if there's a hash in the URL\r\n            });\r\n\r\n            const destinationHubTags = articleHeader.value.tags?.split(\",\").filter((tag) => tag.startsWith(\"destination-hub:\")) || [];\r\n            // Track article with GA4\r\n            trackEvent(\"view_item\",\r\n                    {\r\n                        item_id: article.value.identifier,\r\n                        item_name: articleHeader.value.headline,\r\n                        item_category: \"web_article\",\r\n                        item_category2: articleHeader.value.author,\r\n                        item_category3: (article.value.isSponsored) ? \"Sponsored\" : \"Not sponsored\",\r\n                        item_category4: articleHeader.value.categories.join(\", \"),\r\n                        // Conditional only added properties\r\n                        ...((destinationHubTags.length && { item_list_name: destinationHubTags.join(\", \") }))\r\n                    });\r\n\r\n        }, () => {\r\n            toastError(\"Error retrieving data\");\r\n            displayFallback.value = true;\r\n        });\r\n\r\n</script>\r\n","import ArticleBasicComponent from \"components/pages/article-basic.vue\";\r\nimport { createApp } from \"vue\";\r\nimport { mountApp } from \"vue-app\";\r\n\r\n\r\nconst app = createApp(ArticleBasicComponent);\r\n\r\nmountApp(app, \"page-app\");\r\n"],"file":"scripts/articles-B_w0Hsw2.js"}