{"version":3,"file":"libs_init.f15b0a3f.js","mappings":"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","sources":["webpack://@finviz/website/./js/app/queryString.ts","webpack://@finviz/website/./js/app/shared/cookie.ts","webpack://@finviz/website/./js/app/shared/hover-chart.ts","webpack://@finviz/website/./js/app/shared/utils.ts","webpack://@finviz/website/./js/main/constants.ts","webpack://@finviz/website/./js/main/libs-init.ts","webpack://@finviz/website/./js/main/types.ts","webpack://@finviz/website/./js/main/util.tsx","webpack://@finviz/website/../charts/app/utils/ticker-sanitizer.ts"],"sourcesContent":["export type ObjectHash = Record\r\n\r\nexport const decodeQueryString = function = ObjectHash>(\r\n search = window.location.search\r\n): T {\r\n const vars = search.substring(1).split('&')\r\n const obj: ObjectHash = {}\r\n vars.forEach((pair) => {\r\n const delimiterPos = pair.indexOf('='),\r\n key = decodeURIComponent(pair.substring(0, delimiterPos)),\r\n value = decodeURIComponent(pair.substring(delimiterPos + 1))\r\n obj[key] = value\r\n })\r\n return obj as T\r\n}\r\n\r\nexport const encodeQueryString = function (values: ObjectHash, whitelistedValues: string[] = []) {\r\n return Object.keys(values).reduce((prev, key) => {\r\n const value = values[key]\r\n if (!['', null, undefined].includes(value) || whitelistedValues.includes(value)) {\r\n return prev + (prev.length > 0 ? '&' : '') + encodeURIComponent(key) + '=' + encodeURIComponent(value)\r\n }\r\n return prev\r\n }, '')\r\n}\r\n","export function getParsedCookies(cookieName: string) {\r\n const parseCookies = document.cookie\r\n .split(';')\r\n .map((cookieString) => cookieString.split('='))\r\n .reduce(\r\n (acc, v) => {\r\n acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim())\r\n return acc\r\n },\r\n {} as Record\r\n )\r\n\r\n return cookieName ? parseCookies[cookieName] : parseCookies\r\n}\r\n\r\nexport function getCookie(name: string) {\r\n var re = new RegExp('(?:(?:^|.*;\\\\s*)' + name + '\\\\s*\\\\=\\\\s*([^;]*).*$)|^.*$')\r\n return document.cookie.replace(re, '$1')\r\n}\r\n\r\nexport function setCookie(name: string, value: string, expires: Date) {\r\n var cookie = name + '=' + value + '; expires=' + expires.toUTCString()\r\n if (/\\bfinviz\\b/.test(document.location.hostname)) {\r\n cookie += '; domain=.finviz.com'\r\n }\r\n document.cookie = cookie\r\n}\r\n","import { HTMLAttributeReferrerPolicy } from 'react'\r\n\r\nimport { Instrument } from '../../main/types'\r\nimport { cleanTicker } from '../../main/util'\r\nimport { encodeQueryString } from '../queryString'\r\n\r\nconst DEFAULT_OVERLAYS =\r\n '&o[0][ot]=sma&o[0][op]=50&o[0][oc]=FF8F33C6&o[1][ot]=sma&o[1][op]=200&o[1][oc]=DCB3326D&o[2][ot]=patterns&o[2][op]=&o[2][oc]=000'\r\n\r\nexport function getHoverChartUrl(\r\n ticker: string,\r\n escaped: boolean = false,\r\n timeframe = FinvizSettings.hoverCharts?.stock?.timeframe,\r\n dateRange = FinvizSettings.hoverCharts?.stock?.dateRange\r\n): string {\r\n const theme = FinvizSettings.hasDarkTheme ? 'd' : undefined\r\n const overlays = FinvizSettings.hasUserPremium && FinvizSettings.hoverCharts?.stock?.patterns ? DEFAULT_OVERLAYS : ''\r\n const query = encodeQueryString({\r\n cs: 'm',\r\n t: ticker,\r\n tf: timeframe ?? 'd',\r\n ct: 'candle_stick',\r\n r: dateRange,\r\n tm: theme,\r\n })\r\n\r\n let imgUrl = `${FinvizSettings.nodeChartsDomain}/chart.ashx?${query}${overlays}`\r\n\r\n if (escaped) {\r\n // \"Escaping\" [ and ] because of how boxover.js works\r\n imgUrl = imgUrl.replace(/\\[/g, '[[').replace(/]/g, ']]')\r\n }\r\n return imgUrl\r\n}\r\n\r\nfunction timeframeToDeprecatedTimeframe(timeframeString: string) {\r\n switch (timeframeString) {\r\n case 'i1':\r\n case 'i2':\r\n return 'm1'\r\n case 'i3':\r\n return 'm3'\r\n case 'i5':\r\n return 'm5'\r\n case 'i10':\r\n case 'i15':\r\n return 'm15'\r\n case 'i30':\r\n return 'm30'\r\n case 'h':\r\n case 'h2':\r\n case 'h4':\r\n return 'h1'\r\n case 'w':\r\n return 'w1'\r\n case 'm':\r\n return 'mo'\r\n default:\r\n case 'd':\r\n return 'd1'\r\n }\r\n}\r\n\r\nfunction getOldChartsUrl(ticker: string, timeframe: string = 'd1', instrument: Instrument) {\r\n const oldPeriod = timeframeToDeprecatedTimeframe(timeframe)\r\n\r\n switch (instrument) {\r\n case Instrument.Crypto:\r\n case Instrument.Forex:\r\n return `/fx_image.ashx?${cleanTicker(ticker).toLowerCase()}_${oldPeriod}_s.png`\r\n default:\r\n case Instrument.Futures:\r\n return `/fut_image.ashx?${cleanTicker(ticker).toLowerCase()}_${oldPeriod}_s.png`\r\n }\r\n}\r\n\r\nexport function getHoverChartDimensions() {\r\n switch (FinvizSettings.hoverCharts?.stock?.timeframe) {\r\n case 'i3':\r\n case 'i15':\r\n return { width: 584, height: 180 }\r\n case 'i5':\r\n return { width: 376, height: 180 }\r\n case 'd':\r\n if (FinvizSettings.hoverCharts?.stock?.patterns) return { width: 464, height: 230 }\r\n return { width: 324, height: 180 }\r\n default:\r\n return { width: 324, height: 180 }\r\n }\r\n}\r\n\r\nexport function getReferrerPolicy(): HTMLAttributeReferrerPolicy {\r\n return 'no-referrer-when-downgrade'\r\n}\r\n\r\nexport function getHoverChartImg(\r\n ticker: string,\r\n escaped: boolean = false,\r\n timeframe = FinvizSettings.hoverCharts?.stock?.timeframe,\r\n dateRange?: string,\r\n instrument: Instrument = Instrument.Stock\r\n) {\r\n const useOldCharts = !FinvizSettings.hasForexFuturesCryptoNodeCharts && instrument !== Instrument.Stock\r\n const chartSize = useOldCharts ? { width: 320, height: 180 } : getHoverChartDimensions()\r\n const referrerPolicy = getReferrerPolicy()\r\n const url = useOldCharts\r\n ? getOldChartsUrl(ticker, timeframe, instrument)\r\n : getHoverChartUrl(ticker, escaped, timeframe, dateRange)\r\n const srcSet = useOldCharts ? '' : getSrcSet(url)\r\n const srcsetString = srcSet?.length ? ` srcset='${srcSet}'` : ''\r\n\r\n return {\r\n img: ``,\r\n ...chartSize,\r\n }\r\n}\r\n\r\nexport function getSrcSet(url: string) {\r\n // You must keep a space after , for refresh to work\r\n return FinvizSettings.hasUserRetinaNodeCharts ? `${url} 1x, ${url}&sf=2 2x` : undefined\r\n}\r\n","import { decodeQueryString, encodeQueryString } from '../queryString'\r\nimport { getCookie, setCookie } from './cookie'\r\n\r\nexport const formatDateToStringUS = (date: Date) =>\r\n date.toLocaleDateString('en-US', {\r\n day: '2-digit',\r\n month: '2-digit',\r\n year: 'numeric',\r\n })\r\n\r\nconst DRAWING_QUOTE_PAGE_COOKIE_NAME = 'charts-draw'\r\nexport function getIsDrawingEnabledOnQuotePage() {\r\n return getCookie(DRAWING_QUOTE_PAGE_COOKIE_NAME) === 'on'\r\n}\r\n\r\nexport async function setIsDrawingEnabledOnQuotePage(isEnabled: boolean) {\r\n return fetch('/api/set_cookie.ashx?cookie=' + DRAWING_QUOTE_PAGE_COOKIE_NAME + '&value=' + (isEnabled ? 'on' : 'off'))\r\n .catch(() => {})\r\n .then((res) => {\r\n if (!res?.ok) {\r\n // fallback to JS otherwise draw toggle won't work if API don't work\r\n setIsDrawingEnabledOnQuotePageCookieViaJS(isEnabled)\r\n }\r\n\r\n const { i: idea, ...rest } = decodeQueryString()\r\n if (idea) {\r\n document.location = `quote.ashx?${encodeQueryString(rest)}`\r\n } else {\r\n document.location.reload()\r\n }\r\n })\r\n}\r\n\r\nfunction setIsDrawingEnabledOnQuotePageCookieViaJS(isEnabled: boolean) {\r\n const expires = new Date()\r\n expires.setMonth(expires.getMonth() + 1)\r\n setCookie(DRAWING_QUOTE_PAGE_COOKIE_NAME, isEnabled ? 'on' : 'off', expires)\r\n}\r\n\r\nexport function parseInitData(elementId: string): T | undefined {\r\n try {\r\n const initDataElement = document.getElementById(elementId)!\r\n return JSON.parse(initDataElement.textContent!)\r\n } catch (e) {\r\n Sentry.captureException(e)\r\n return\r\n }\r\n}\r\n\r\nexport function getSidebarFromCookie() {\r\n const chartsUrl = getCookie('chartsUrl')\r\n const decodedCookie = chartsUrl ? decodeQueryString<{ sidebar?: string }>(chartsUrl) : null\r\n return decodedCookie?.sidebar || undefined\r\n}\r\n","export const CRYPTO_TICKERS = [\r\n 'BTCUSD',\r\n 'LTCUSD',\r\n 'ETHUSD',\r\n 'XRPUSD',\r\n 'BCHUSD',\r\n 'BTCEUR',\r\n 'LTCEUR',\r\n 'ETHEUR',\r\n 'XRPEUR',\r\n 'BCHEUR',\r\n 'LTCBTC',\r\n 'ETHBTC',\r\n 'XRPBTC',\r\n 'BCHBTC',\r\n]\r\n\r\n// Keep in sync with the copy in Charts repo - app/constants/common.ts\r\nexport enum TIMEFRAME {\r\n i1 = 'i1',\r\n i2 = 'i2',\r\n i3 = 'i3',\r\n i5 = 'i5',\r\n i10 = 'i10',\r\n i15 = 'i15',\r\n i30 = 'i30',\r\n h = 'h',\r\n h2 = 'h2',\r\n h4 = 'h4',\r\n d = 'd',\r\n w = 'w',\r\n m = 'm',\r\n}\r\n\r\nexport enum SpecificChartFunctionality {\r\n default = 'default',\r\n quotePage = 'quotePage',\r\n quotePerf = 'quotePerf',\r\n chartPage = 'chartPage',\r\n smallIndex = 'smallIndex',\r\n offScreen = 'offScreen',\r\n forexPage = 'forexPage',\r\n futuresPage = 'futuresPage',\r\n cryptoPage = 'cryptoPage',\r\n}\r\n","import { getHoverChartImg } from '../app/shared/hover-chart'\r\nimport { getSanitizedTicker } from '../app/shared/ticker-sanitizer'\r\n\r\ndeclare global {\r\n interface Window {\r\n FLibs: any\r\n }\r\n}\r\nwindow.FLibs = window.FLibs || {}\r\nwindow.FLibs.getHoverChartImg = getHoverChartImg\r\nwindow.FLibs.getSanitizedTicker = getSanitizedTicker\r\n","export enum Instrument {\r\n Stock = 'stock',\r\n Forex = 'forex',\r\n Crypto = 'crypto',\r\n Futures = 'futures',\r\n MarketSentiment = 'market_sentiment',\r\n Group = 'group',\r\n}\r\n\r\nexport type RecordType = Record\r\n\r\nexport type PartialBy = Omit & Partial>\r\n\r\nexport type NullableNumbers = { [K in keyof Obj]: Obj[K] extends number ? number | null : Obj[K] }\r\n\r\nexport enum DateRangeType {\r\n d1 = 'd1',\r\n d5 = 'd5',\r\n m1 = 'm1',\r\n m3 = 'm3',\r\n m6 = 'm6',\r\n ytd = 'ytd',\r\n y1 = 'y1',\r\n y2 = 'y2',\r\n y5 = 'y5',\r\n max = 'max',\r\n}\r\n\r\nexport type SortableValue = string | null | number | Date\r\nexport type SortDirectionValue = 1 | -1\r\n","import isPlainObject from 'lodash.isplainobject'\r\nimport { ComponentType, LazyExoticComponent, lazy } from 'react'\r\nimport { ShouldRevalidateFunction, ShouldRevalidateFunctionArgs } from 'react-router-dom'\r\n\r\nimport { getCookie } from '../app/shared/cookie'\r\nimport { parseInitData } from '../app/shared/utils'\r\nimport { CRYPTO_TICKERS } from './constants'\r\nimport { Instrument, SortDirectionValue, SortableValue } from './types'\r\nimport { RecordType } from './types'\r\n\r\n/**\r\n * Function which wraps React.lazy and checks whether a chunk is preloaded\r\n * from async-manifest. If yes, kick in the promise resolve early so we can\r\n * instantly render the component\r\n */\r\nexport function lazyLoadComponent({\r\n chunkName,\r\n load,\r\n}: {\r\n chunkName: string\r\n load: () => Promise<{ default: ComponentType }>\r\n}): LazyExoticComponent> {\r\n // Resolve earlier if prefetch element is present\r\n const hasPreloadElement = document.querySelector(`[data-chunk-id=${chunkName}]`)\r\n\r\n if (hasPreloadElement) {\r\n const componentLoader = load()\r\n\r\n return lazy(() => componentLoader)\r\n }\r\n\r\n return lazy(load)\r\n}\r\n\r\nconst isObject = (value: any): value is RecordType => isPlainObject(value)\r\n\r\n/**\r\n * Parse text as JSON\r\n */\r\nexport function parseAsJSON(value: unknown | Shape): Shape | undefined {\r\n if (isObject(value)) {\r\n return value as Shape\r\n }\r\n\r\n let parsedValue\r\n try {\r\n if (typeof value === 'string') {\r\n parsedValue = JSON.parse(value)\r\n }\r\n } catch (e) {\r\n return\r\n }\r\n return parsedValue\r\n}\r\n\r\n/**\r\n * remove @ symbol from a ticker\r\n */\r\nexport function cleanTicker(ticker: string) {\r\n return ticker.startsWith('@') ? ticker.substring(1) : ticker\r\n}\r\n\r\n/**\r\n * Get instrument for a ticker.\r\n *\r\n * - If ticker doesn’t start with `@` - stock\r\n * - Otherwise\r\n * - one of `CRYPTO_TICKERS` - crypto\r\n * - has length of 6 - forex\r\n * - none of above - future\r\n *\r\n * NOTE: counterpart in charts 'charts/app/utils/chart.js'\r\n */\r\n\r\nexport function getInstrumentForTicker(ticker: string): Instrument {\r\n if (!ticker?.startsWith('@')) return Instrument.Stock\r\n\r\n const cleanedTicker = cleanTicker(ticker)\r\n\r\n if (CRYPTO_TICKERS.includes(cleanedTicker.toUpperCase())) return Instrument.Crypto\r\n if (cleanedTicker.length === 6) return Instrument.Forex\r\n\r\n return Instrument.Futures\r\n}\r\n\r\n/**\r\n * Async load Resize observer polyfill when we need it\r\n */\r\nlet resizeObserverPolyfill: typeof window.ResizeObserver\r\nexport async function loadResizeObserverPolyfill() {\r\n if (typeof window.ResizeObserver === 'undefined') {\r\n const polyfill = await import('resize-observer-polyfill')\r\n resizeObserverPolyfill = polyfill.default\r\n window.ResizeObserver = resizeObserverPolyfill\r\n return resizeObserverPolyfill as typeof window.ResizeObserver\r\n }\r\n}\r\n\r\nexport async function getIsBrave() {\r\n return (navigator.brave && (await navigator.brave.isBrave())) || false\r\n}\r\n\r\nexport function hasDarkModeFeature() {\r\n const ff = getCookie('featureFlags')\r\n return ff.includes('dark:1')\r\n}\r\n\r\nexport function hasRedesignFeature() {\r\n const ff = getCookie('featureFlags')\r\n return ff.includes('redesign:1')\r\n}\r\n\r\nexport function isRedesignFeatureEnabled() {\r\n return hasRedesignFeature() || hasDarkModeFeature()\r\n}\r\n\r\nexport function isDarkModeFeatureEnabled() {\r\n const theme = getCookie('chartsTheme')\r\n return isRedesignFeatureEnabled() && theme.includes('dark')\r\n}\r\n\r\nexport enum ChildPosition {\r\n topLeft,\r\n topRight,\r\n bottomLeft,\r\n bottomRight,\r\n center,\r\n topCenter,\r\n rightCenter,\r\n bottomCenter,\r\n leftCenter,\r\n}\r\n\r\nexport function getFlexAlignClasses(position: ChildPosition) {\r\n return {\r\n 'justify-start': [ChildPosition.topLeft, ChildPosition.bottomLeft, ChildPosition.leftCenter].includes(position),\r\n 'justify-center': [ChildPosition.center, ChildPosition.topCenter, ChildPosition.bottomCenter].includes(position),\r\n 'justify-end': [ChildPosition.topRight, ChildPosition.bottomRight, ChildPosition.rightCenter].includes(position),\r\n 'items-start': [ChildPosition.topLeft, ChildPosition.topRight, ChildPosition.topCenter].includes(position),\r\n 'items-center': [ChildPosition.center, ChildPosition.rightCenter, ChildPosition.leftCenter].includes(position),\r\n 'items-end': [ChildPosition.bottomLeft, ChildPosition.bottomRight, ChildPosition.bottomCenter].includes(position),\r\n }\r\n}\r\n\r\ninterface NumberFormatOptions {\r\n fractions: number\r\n showPlusSign: boolean\r\n defaultValue: string\r\n}\r\n\r\nconst intlCache: { [key: number]: Intl.NumberFormat } = {}\r\nfunction getIntl(fractions: number) {\r\n if (!intlCache[fractions])\r\n intlCache[fractions] = new Intl.NumberFormat('en-US', {\r\n minimumFractionDigits: fractions,\r\n maximumFractionDigits: fractions,\r\n })\r\n return intlCache[fractions]\r\n}\r\n\r\nexport function shortFormatNumber(\r\n value: number | null | undefined,\r\n { fractions = 2, showPlusSign = false, defaultValue = '-' }: Partial = {}\r\n) {\r\n let num = value\r\n if (num === undefined || num === null || !Number.isFinite(num)) return defaultValue\r\n\r\n let suffix = ''\r\n const absValue = Math.abs(num)\r\n if (absValue >= 1e9) {\r\n num /= 1e9\r\n suffix = 'B'\r\n } else if (absValue >= 1e6) {\r\n num /= 1e6\r\n suffix = 'M'\r\n } else if (absValue >= 1000) {\r\n num /= 1000\r\n suffix = 'K'\r\n }\r\n\r\n const formatted = getIntl(fractions).format(num)\r\n\r\n return (showPlusSign && num > 0 ? '+' : '') + formatted + suffix\r\n}\r\n\r\nexport function formatNumber(\r\n value: number | null | undefined,\r\n { fractions = 2, showPlusSign = false, defaultValue = '-' }: Partial = {}\r\n) {\r\n if (value === undefined || value === null) return defaultValue\r\n\r\n const fixedValue = value.toFixed(fractions)\r\n const prefix = showPlusSign && value > 0 ? '+' : ''\r\n\r\n if (parseFloat(fixedValue) === 0 && value !== 0) {\r\n return {prefix + fixedValue}\r\n }\r\n\r\n const formatted = getIntl(fractions).format(value)\r\n\r\n return prefix + formatted\r\n}\r\n\r\nexport interface SortByColumnOptions {\r\n /**\r\n * Change order of `null` values.\r\n * - `false` Force sort null as first (asc) and last (desc)\r\n * - `true` Always sort null as last regardless of order\r\n * @default false\r\n */\r\n sortNullAsLast?: boolean\r\n\r\n /**\r\n * When true, null values will not be treated as special values\r\n * @default false\r\n */\r\n ignoreNullForComparison?: boolean\r\n}\r\n\r\nexport function sortByColumn(\r\n options: SortByColumnOptions & {\r\n a: ItemType\r\n b: ItemType\r\n direction: SortDirectionValue\r\n valueGetter?: (row: ItemType) => SortableValue\r\n }\r\n) {\r\n const valueA = options.valueGetter?.(options.a)\r\n const valueB = options.valueGetter?.(options.b)\r\n // Compare as strings\r\n if (typeof valueA === 'string' && typeof valueB === 'string') return valueA.localeCompare(valueB) * options.direction\r\n\r\n // Always sort null last if enabled\r\n if (options.sortNullAsLast && valueA === null) return Infinity\r\n if (options.sortNullAsLast && valueB === null) return -Infinity\r\n\r\n // Sort null first/last depending on direction\r\n if (!options.ignoreNullForComparison && valueA === null) return -options.direction\r\n if (!options.ignoreNullForComparison && valueB === null) return options.direction\r\n\r\n // Compare as numbers\r\n return (Number(valueA) - Number(valueB)) * options.direction\r\n}\r\n\r\nexport function moveItemInArray(arr: ItemType[], sourceIndex: number, destinationIndex: number) {\r\n // make sure sourceIndex and destinationIndex are inside of arr\r\n const from = Math.max(0, Math.min(sourceIndex, arr.length - 1))\r\n const to = Math.min(arr.length - 1, Math.max(destinationIndex, 0))\r\n\r\n const items = [...arr]\r\n const [removed] = items.splice(from, 1)\r\n items.splice(to, 0, removed)\r\n\r\n return items\r\n}\r\n\r\nexport function randomUUID() {\r\n return `${1e7}-${1e3}-${4e3}-${8e3}-${1e11}`.replace(/[018]/g, (substring) => {\r\n const c = Number(substring)\r\n return (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16)\r\n })\r\n}\r\n\r\nexport function getUuid() {\r\n return window.crypto?.randomUUID?.() ?? randomUUID()\r\n}\r\n\r\n/**\r\n * This fn creates a revalidator rule which always revalidates loader when the\r\n * specified keys change but ignores changes to other keys. It also allows\r\n * `revalidator.revalidate` to work even if the query didn’t\r\n */\r\nexport function revalidateOnQueryChange(keys: string[]): ShouldRevalidateFunction {\r\n return (args) => {\r\n const prevParams = args.currentUrl.searchParams\r\n const nextParams = args.nextUrl.searchParams\r\n const requiredChanged = keys.some((key) => prevParams.get(key) !== nextParams.get(key))\r\n const otherQueryKeys = [...prevParams.keys(), ...nextParams.keys()].filter(\r\n (key, index, arr) => !keys.includes(key) && arr.indexOf(key) === index\r\n )\r\n const otherChanged = otherQueryKeys.some((key) => prevParams.get(key) !== nextParams.get(key))\r\n\r\n if (!requiredChanged && otherChanged) {\r\n return false\r\n }\r\n\r\n return args.defaultShouldRevalidate\r\n }\r\n}\r\n\r\n/**\r\n * This fn does the same as `revalidateOnQueryChange`\r\n * except you need to provide `ShouldRevalidateFunctionArgs` manually\r\n */\r\nexport function shouldRevalidateOnQueryChange(args: ShouldRevalidateFunctionArgs, keys: string[]) {\r\n return revalidateOnQueryChange(keys)(args)\r\n}\r\n\r\nexport function parseRouteInitData({\r\n elementId = 'route-init-data',\r\n fallback,\r\n removeElement = true,\r\n}: { elementId?: string; fallback?: DataType; removeElement?: boolean } = {}): DataType | null {\r\n const element = document.getElementById(elementId)\r\n let initialData = fallback\r\n\r\n if (!element) return fallback ?? null\r\n\r\n try {\r\n const parsedData = parseInitData(elementId)\r\n if (removeElement) element.remove()\r\n\r\n if (parsedData) initialData = parsedData\r\n } catch {\r\n initialData = fallback\r\n }\r\n\r\n return initialData ?? null\r\n}\r\n","function getSanitizedSingleTicker(rawTicker: string, specialTickers: string[] = []) {\r\n return rawTicker\r\n .replace(/\\.+/gi, '-')\r\n .split('-')\r\n .map((x) => {\r\n if (specialTickers.includes(x.toUpperCase())) return x\r\n return x.replace(/([^a-z0-9@-])+/gi, '')\r\n })\r\n .filter((x) => !!x)\r\n .join('-')\r\n .toUpperCase()\r\n}\r\n\r\nexport function getSanitizedTicker(rawTicker: string, isMulti = false, specialTickers: string[] = []) {\r\n if (isMulti) {\r\n return rawTicker\r\n .replace(/ /g, ',')\r\n .split(',')\r\n .map((x) => getSanitizedSingleTicker(x, specialTickers))\r\n .filter((x) => !!x)\r\n .join(',')\r\n }\r\n\r\n return getSanitizedSingleTicker(rawTicker, specialTickers)\r\n}\r\n"],"names":["decodeQueryString","vars","arguments","length","undefined","window","location","search","substring","split","obj","forEach","pair","delimiterPos","indexOf","key","decodeURIComponent","value","encodeQueryString","values","whitelistedValues","Object","keys","reduce","prev","includes","encodeURIComponent","getParsedCookies","cookieName","parseCookies","document","cookie","map","cookieString","acc","v","trim","getCookie","name","re","RegExp","replace","setCookie","expires","toUTCString","test","hostname","DEFAULT_OVERLAYS","getHoverChartUrl","ticker","escaped","timeframe","FinvizSettings","hoverCharts","stock","dateRange","theme","hasDarkTheme","overlays","hasUserPremium","patterns","query","cs","t","tf","ct","r","tm","imgUrl","nodeChartsDomain","getHoverChartDimensions","width","height","getReferrerPolicy","getHoverChartImg","instrument","Instrument","Stock","useOldCharts","hasForexFuturesCryptoNodeCharts","chartSize","url","oldPeriod","timeframeString","timeframeToDeprecatedTimeframe","Crypto","Forex","cleanTicker","toLowerCase","Futures","getOldChartsUrl","srcSet","getSrcSet","img","hasUserRetinaNodeCharts","formatDateToStringUS","date","toLocaleDateString","day","month","year","parseInitData","elementId","initDataElement","getElementById","JSON","parse","textContent","e","Sentry","captureException","getSidebarFromCookie","chartsUrl","decodedCookie","sidebar","CRYPTO_TICKERS","TIMEFRAME","SpecificChartFunctionality","FLibs","getSanitizedTicker","DateRangeType","lazyLoadComponent","_ref","chunkName","load","querySelector","componentLoader","lazy","startsWith","getInstrumentForTicker","cleanedTicker","toUpperCase","resizeObserverPolyfill","async","loadResizeObserverPolyfill","ResizeObserver","polyfill","default","getIsBrave","navigator","brave","isBrave","ChildPosition","getFlexAlignClasses","position","topLeft","bottomLeft","leftCenter","center","topCenter","bottomCenter","topRight","bottomRight","rightCenter","intlCache","getIntl","fractions","Intl","NumberFormat","minimumFractionDigits","maximumFractionDigits","shortFormatNumber","showPlusSign","defaultValue","num","Number","isFinite","suffix","absValue","Math","abs","format","formatNumber","fixedValue","toFixed","prefix","parseFloat","_jsx","title","toString","children","sortByColumn","options","valueA","valueGetter","a","valueB","b","localeCompare","direction","sortNullAsLast","Infinity","ignoreNullForComparison","moveItemInArray","arr","sourceIndex","destinationIndex","from","max","min","to","items","removed","splice","getUuid","crypto","randomUUID","c","getRandomValues","Uint8Array","revalidateOnQueryChange","args","prevParams","currentUrl","searchParams","nextParams","nextUrl","requiredChanged","some","get","otherChanged","filter","index","defaultShouldRevalidate","shouldRevalidateOnQueryChange","parseRouteInitData","fallback","removeElement","element","initialData","parsedData","remove","getSanitizedSingleTicker","rawTicker","specialTickers","x","join"],"sourceRoot":""}