diff --git a/dev.Dockerfile b/dev.Dockerfile index 7bfb7c1ee9bf2..a67b5ab0e6df5 100644 --- a/dev.Dockerfile +++ b/dev.Dockerfile @@ -16,7 +16,9 @@ COPY requirements.txt /code/ RUN pip install $(grep -ivE "psycopg2" requirements.txt) --compile\ && pip install psycopg2-binary -# install dev dependencies +# install dev dependencies +RUN mkdir /code/requirements/ +COPY requirements/dev.txt /code/requirements/ RUN pip install -r requirements/dev.txt --compile COPY package.json /code/ diff --git a/frontend/src/toolbar/ToolbarApp.tsx b/frontend/src/toolbar/ToolbarApp.tsx index 2a78797581907..c892c008918d3 100644 --- a/frontend/src/toolbar/ToolbarApp.tsx +++ b/frontend/src/toolbar/ToolbarApp.tsx @@ -32,7 +32,7 @@ export function ToolbarApp(props: EditorProps = {}): JSX.Element { return ( <> - +
{didRender ? : null} diff --git a/frontend/src/toolbar/ToolbarContainer.tsx b/frontend/src/toolbar/ToolbarContainer.tsx index 18a51683aac45..e50c8731c4634 100644 --- a/frontend/src/toolbar/ToolbarContainer.tsx +++ b/frontend/src/toolbar/ToolbarContainer.tsx @@ -11,7 +11,7 @@ function _ToolbarContainer(): JSX.Element { const { buttonVisible } = useValues(toolbarLogic) return ( - + diff --git a/frontend/src/toolbar/actions/EditAction.tsx b/frontend/src/toolbar/actions/EditAction.tsx index 5958bb37ef333..d023f91a98175 100644 --- a/frontend/src/toolbar/actions/EditAction.tsx +++ b/frontend/src/toolbar/actions/EditAction.tsx @@ -112,7 +112,12 @@ export function EditAction(): JSX.Element { - + ) : null} diff --git a/frontend/src/toolbar/actions/SelectorCount.tsx b/frontend/src/toolbar/actions/SelectorCount.tsx index b6d27368806ea..44ed96c10f12e 100644 --- a/frontend/src/toolbar/actions/SelectorCount.tsx +++ b/frontend/src/toolbar/actions/SelectorCount.tsx @@ -1,20 +1,24 @@ -import React from 'react' +import React, { useMemo } from 'react' +import { querySelectorAllDeep } from '@mariusandra/query-selector-shadow-dom' interface SelectorCountProps { selector: string } export function SelectorCount({ selector }: SelectorCountProps): JSX.Element { - let selectorError = false - let matches - - if (selector) { - try { - matches = document.querySelectorAll(selector).length - } catch { - selectorError = true + const [matches, selectorError] = useMemo(() => { + let selectorError = false + let matches = 0 + if (selector) { + try { + matches = querySelectorAllDeep(selector).length + } catch { + selectorError = true + } } - } + return [matches, selectorError] + }, [selector]) + return ( {selectorError ? 'Invalid selector' : `Matches ${matches} element${matches === 1 ? '' : 's'}`} diff --git a/frontend/src/toolbar/elements/elementsLogic.ts b/frontend/src/toolbar/elements/elementsLogic.ts index 5744c7bf6b627..5767529a367fd 100644 --- a/frontend/src/toolbar/elements/elementsLogic.ts +++ b/frontend/src/toolbar/elements/elementsLogic.ts @@ -10,6 +10,7 @@ import { ActionStepType, ActionType, ToolbarMode, ToolbarTab } from '~/types' import { ActionElementWithMetadata, ActionForm, ElementWithMetadata } from '~/toolbar/types' import { currentPageLogic } from '~/toolbar/stats/currentPageLogic' import { toolbarLogic } from '~/toolbar/toolbarLogic' +import { collectAllElementsDeep } from '@mariusandra/query-selector-shadow-dom' type ActionElementMap = Map type ElementMap = Map @@ -135,9 +136,10 @@ export const elementsLogic = kea< (s) => [s.displayActionElements, actionsTabLogic.selectors.selectedEditedAction], (displayActionElements, selectedEditedAction): ElementWithMetadata[] => { if (displayActionElements && selectedEditedAction?.steps) { + const allElements = collectAllElementsDeep('', document, null) const steps: ElementWithMetadata[] = [] selectedEditedAction.steps.forEach((step, index) => { - const element = getElementForStep(step) + const element = getElementForStep(step, allElements) if (element) { steps.push({ element, @@ -187,12 +189,13 @@ export const elementsLogic = kea< actionsForElementMap: [ (s) => [actionsLogic.selectors.sortedActions, s.rectUpdateCounter, toolbarLogic.selectors.buttonVisible], (sortedActions): ActionElementMap => { + const allElements = collectAllElementsDeep('', document, null) const actionsForElementMap = new Map() sortedActions.forEach((action, index) => { action.steps ?.filter((step) => step.event === '$autocapture') .forEach((step) => { - const element = getElementForStep(step) + const element = getElementForStep(step, allElements) if (element) { const rect = getRectForElement(element) let array = actionsForElementMap.get(element) diff --git a/frontend/src/toolbar/elements/heatmapLogic.ts b/frontend/src/toolbar/elements/heatmapLogic.ts index 027822da9bcc5..97f7a919a470f 100644 --- a/frontend/src/toolbar/elements/heatmapLogic.ts +++ b/frontend/src/toolbar/elements/heatmapLogic.ts @@ -8,6 +8,7 @@ import { toolbarLogic } from '~/toolbar/toolbarLogic' import { heatmapLogicType } from 'types/toolbar/elements/heatmapLogicType' import { CountedHTMLElement, ElementsEventType } from '~/toolbar/types' import { ActionStepType } from '~/types' +import { collectAllElementsDeep, querySelectorAllDeep } from '@mariusandra/query-selector-shadow-dom' export const heatmapLogic = kea>({ actions: { @@ -77,6 +78,8 @@ export const heatmapLogic = kea [selectors.events], (events) => { + // cache all elements in shadow roots + const allElements = collectAllElementsDeep('', document, null) const elements: CountedHTMLElement[] = [] events.forEach((event) => { let combinedSelector @@ -86,12 +89,14 @@ export const heatmapLogic = kea ${lastSelector}` : selector try { - const domElements = Array.from(document.querySelectorAll(combinedSelector)) + const domElements = Array.from( + querySelectorAllDeep(combinedSelector, document, allElements) + ) as HTMLElement[] if (domElements.length === 1) { const e = event.elements[i] - // element like "svg" as the first one + // element like "svg" (only tag, no class/id/etc) as the first one if ( i === 0 && e.tag_name && diff --git a/frontend/src/toolbar/styles.scss b/frontend/src/toolbar/styles.scss index f279dca52119e..4d27686fa8573 100644 --- a/frontend/src/toolbar/styles.scss +++ b/frontend/src/toolbar/styles.scss @@ -1,3 +1,11 @@ +:host { + // reset fonts + all: initial; + font-family: 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + font-size: 14px; + line-height: 1.5; +} + .toolbar-block { background: white; color: black; diff --git a/frontend/src/toolbar/utils.ts b/frontend/src/toolbar/utils.ts index 0c73428a92aaa..b68cbf6d523c5 100644 --- a/frontend/src/toolbar/utils.ts +++ b/frontend/src/toolbar/utils.ts @@ -2,6 +2,7 @@ import Simmer from '@mariusandra/simmerjs' import { cssEscape } from 'lib/utils/cssEscape' import { ActionStepType, ElementType } from '~/types' import { ActionStepForm, BoxColor } from '~/toolbar/types' +import { querySelectorAllDeep } from '@mariusandra/query-selector-shadow-dom' // these plus any element with cursor:pointer will be click targets const CLICK_TARGET_SELECTOR = `a, button, input, select, textarea, label` @@ -31,7 +32,7 @@ export function elementToQuery(element: HTMLElement): string | undefined { } // Turn tags into lower cases - return simmer(element)?.replace(/(^[A-Z]+| [A-Z]+)/g, (d: string) => d.toLowerCase()) + return simmer(element)?.replace(/(^[A-Z\-]+| [A-Z\-]+)/g, (d: string) => d.toLowerCase()) } export function elementToActionStep(element: HTMLElement): ActionStepType { @@ -81,8 +82,12 @@ export function elementToSelector(element: ElementType): string { return selector } +export function getToolbarElement(): HTMLElement | null { + return window.document.getElementById('__POSTHOG_TOOLBAR__') || null +} + export function getShadowRoot(): ShadowRoot | null { - return window.document.getElementById('__POSTHOG_TOOLBAR__')?.shadowRoot || null + return getToolbarElement()?.shadowRoot || null } export function getShadowRootPopupContainer(): HTMLElement { @@ -93,11 +98,24 @@ export function hasCursorPointer(element: HTMLElement): boolean { return window.getComputedStyle(element)?.getPropertyValue('cursor') === 'pointer' } +export function getParent(element: HTMLElement): HTMLElement | null { + const parent = element.parentNode + // 11 = DOCUMENT_FRAGMENT_NODE + if (parent?.nodeType === window.Node.DOCUMENT_FRAGMENT_NODE) { + return (parent as ShadowRoot).host as HTMLElement + } + if (parent?.nodeType === window.Node.ELEMENT_NODE) { + return parent as HTMLElement + } + return null +} + export function trimElement(element: HTMLElement): HTMLElement | null { if (!element) { return null } - if (element && element.getAttribute('id') === '__POSTHOG_TOOLBAR__') { + const toolbarElement = getToolbarElement() + if (toolbarElement && isParentOf(element, toolbarElement)) { return null } @@ -113,21 +131,28 @@ export function trimElement(element: HTMLElement): HTMLElement | null { } } - while (loopElement?.parentElement) { + while (loopElement) { + const parent = getParent(loopElement) + if (!parent) { + return null + } + // return when we find a click target - if (loopElement.matches(CLICK_TARGET_SELECTOR)) { + if (loopElement.matches?.(CLICK_TARGET_SELECTOR)) { return loopElement } + const compStyles = window.getComputedStyle(loopElement) if (compStyles.getPropertyValue('cursor') === 'pointer') { - const parentStyles = loopElement.parentElement ? window.getComputedStyle(loopElement.parentElement) : null + const parentStyles = parent ? window.getComputedStyle(parent) : null if (!parentStyles || parentStyles.getPropertyValue('cursor') !== 'pointer') { return loopElement } } - loopElement = loopElement.parentElement + loopElement = parent } + return null } @@ -135,10 +160,10 @@ export function inBounds(min: number, value: number, max: number): number { return Math.max(min, Math.min(max, value)) } -export function getAllClickTargets(): HTMLElement[] { - const elements = (document.querySelectorAll(CLICK_TARGET_SELECTOR) as unknown) as HTMLElement[] +export function getAllClickTargets(startNode: Document | HTMLElement | ShadowRoot = document): HTMLElement[] { + const elements = (startNode.querySelectorAll(CLICK_TARGET_SELECTOR) as unknown) as HTMLElement[] - const allElements = [...((document.querySelectorAll('*') as unknown) as HTMLElement[])] + const allElements = [...((startNode.querySelectorAll('*') as unknown) as HTMLElement[])] const clickTags = CLICK_TARGET_SELECTOR.split(',').map((c) => c.trim()) // loop through all elements and getComputedStyle @@ -150,7 +175,13 @@ export function getAllClickTargets(): HTMLElement[] { return compStyles.getPropertyValue('cursor') === 'pointer' }) - const selectedElements = [...elements, ...pointerElements].map((e) => trimElement(e)) + const shadowElements = allElements + .filter((el) => el.shadowRoot && el.getAttribute('id') !== '__POSTHOG_TOOLBAR__') + .map((el: HTMLElement) => (el.shadowRoot ? getAllClickTargets(el.shadowRoot) : [])) + .reduce((a, b) => [...a, ...b], []) + const selectedElements = [...elements, ...pointerElements, ...shadowElements] + .map((e) => trimElement(e)) + .filter((e) => e) const uniqueElements = Array.from(new Set(selectedElements)) as HTMLElement[] return uniqueElements @@ -180,13 +211,13 @@ export function isParentOf(element: HTMLElement, possibleParent: HTMLElement): b if (loopElement !== element && loopElement === possibleParent) { return true } - loopElement = loopElement.parentElement + loopElement = getParent(loopElement) } return false } -export function getElementForStep(step: ActionStepForm): HTMLElement | null { +export function getElementForStep(step: ActionStepForm, allElements?: HTMLElement[]): HTMLElement | null { if (!step) { return null } @@ -208,7 +239,7 @@ export function getElementForStep(step: ActionStepForm): HTMLElement | null { let elements = [] as HTMLElement[] try { - elements = [...((document.querySelectorAll(selector || '*') as unknown) as HTMLElement[])] + elements = [...((querySelectorAllDeep(selector || '*', document, allElements) as unknown) as HTMLElement[])] } catch (e) { console.error('Can not use selector:', selector) throw e @@ -268,12 +299,31 @@ export function actionStepToAntdForm(step: ActionStepType, isNew = false): Actio } if (isNew) { + const hasSelector = !!step.selector if (step.tag_name === 'a') { - return { ...step, href_selected: true, selector_selected: true, text_selected: false, url_selected: false } + return { + ...step, + href_selected: true, + selector_selected: hasSelector, + text_selected: false, + url_selected: false, + } } else if (step.tag_name === 'button') { - return { ...step, text_selected: true, selector_selected: true, href_selected: false, url_selected: false } + return { + ...step, + text_selected: true, + selector_selected: hasSelector, + href_selected: false, + url_selected: false, + } } else { - return { ...step, selector_selected: true, text_selected: false, url_selected: false, href_selected: false } + return { + ...step, + selector_selected: hasSelector, + text_selected: false, + url_selected: false, + href_selected: false, + } } } diff --git a/package.json b/package.json index 134883b8ba697..d43da41a33409 100644 --- a/package.json +++ b/package.json @@ -27,8 +27,9 @@ "dependencies": { "@babel/core": "^7.10.4", "@babel/runtime": "^7.10.4", + "@mariusandra/query-selector-shadow-dom": "0.7.2-posthog.2", "@mariusandra/react-grid-layout": "0.18.3", - "@mariusandra/simmerjs": "0.6.1-posthog.1", + "@mariusandra/simmerjs": "0.7.1-posthog.1", "@types/react-syntax-highlighter": "^11.0.4", "@types/zxcvbn": "^4.4.0", "antd": "^4.1.1", diff --git a/posthog/models/event.py b/posthog/models/event.py index 214611c044f63..ddd7e9181c332 100644 --- a/posthog/models/event.py +++ b/posthog/models/event.py @@ -114,7 +114,7 @@ class Selector(object): def __init__(self, selector: str): self.parts = [] - tags = re.split(" ", selector) + tags = re.split(" ", selector.strip()) tags.reverse() for index, tag in enumerate(tags): if tag == ">": diff --git a/posthog/tasks/status_report.py b/posthog/tasks/status_report.py index 64e6cbb86fea1..45b6c071c55a9 100644 --- a/posthog/tasks/status_report.py +++ b/posthog/tasks/status_report.py @@ -13,7 +13,7 @@ logger = logging.getLogger(__name__) -def status_report() -> None: +def status_report(*, dry_run: bool = False) -> Dict[str, Any]: period_start, period_end = get_previous_week() report: Dict[str, Any] = { "posthog_version": VERSION, @@ -46,35 +46,37 @@ def status_report() -> None: sql.SQL( """ SELECT COUNT(DISTINCT person_id) as persons_count - FROM posthog_event JOIN posthog_persondistinctid ON (posthog_event.distinct_id = posthog_persondistinctid.distinct_id) WHERE posthog_event.team_id = %s AND posthog_event.created_at >= %s AND posthog_event.created_at < %s + FROM posthog_event JOIN posthog_persondistinctid ON (posthog_event.distinct_id = posthog_persondistinctid.distinct_id) WHERE posthog_event.team_id = %s AND posthog_event.created_at >= %s AND posthog_event.created_at <= %s """ ), - (team.id, report["period"]["start_inclusive"], report["period"]["end_exclusive"]), + (team.id, report["period"]["start_inclusive"], report["period"]["end_inclusive"]), ) team_report["persons_count_active_in_period"] = cursor.fetchone()[0] cursor.execute( sql.SQL( """ SELECT properties->>'$lib' as lib, COUNT(*) as count - FROM posthog_event WHERE team_id = %s AND created_at >= %s AND created_at < %s GROUP BY lib + FROM posthog_event WHERE team_id = %s AND created_at >= %s AND created_at <= %s GROUP BY lib """ ), - (team.id, report["period"]["start_inclusive"], report["period"]["end_exclusive"]), + (team.id, report["period"]["start_inclusive"], report["period"]["end_inclusive"]), ) team_report["events_count_by_lib"] = {result.lib: result.count for result in namedtuplefetchall(cursor)} cursor.execute( sql.SQL( """ SELECT event as name, COUNT(*) as count - FROM posthog_event WHERE team_id = %s AND created_at >= %s AND created_at < %s GROUP BY name + FROM posthog_event WHERE team_id = %s AND created_at >= %s AND created_at <= %s GROUP BY name """ ), - (team.id, report["period"]["start_inclusive"], report["period"]["end_exclusive"]), + (team.id, report["period"]["start_inclusive"], report["period"]["end_inclusive"]), ) team_report["events_count_by_name"] = {result.name: result.count for result in namedtuplefetchall(cursor)} report["teams"][team.id] = team_report - posthoganalytics.api_key = "sTMFPsFhdP1Ssg" - disabled = posthoganalytics.disabled - posthoganalytics.disabled = False - posthoganalytics.capture(get_machine_id(), "instance status report", report) - posthoganalytics.disabled = disabled + if not dry_run: + posthoganalytics.api_key = "sTMFPsFhdP1Ssg" + disabled = posthoganalytics.disabled + posthoganalytics.disabled = False + posthoganalytics.capture(get_machine_id(), "instance status report", report) + posthoganalytics.disabled = disabled + return report diff --git a/posthog/tasks/test/test_process_event.py b/posthog/tasks/test/test_process_event.py index 42b19274d9e84..17b2c6956ebc6 100644 --- a/posthog/tasks/test/test_process_event.py +++ b/posthog/tasks/test/test_process_event.py @@ -21,7 +21,7 @@ from posthog.tasks.process_event import process_event -class ProcessEvent(BaseTest): +class TestProcessEvent(BaseTest): def test_capture_new_person(self) -> None: user = self._create_user("tim") action1 = Action.objects.create(team=self.team) diff --git a/posthog/tasks/test/test_status_report.py b/posthog/tasks/test/test_status_report.py new file mode 100644 index 0000000000000..fd3f7d9adb2bc --- /dev/null +++ b/posthog/tasks/test/test_status_report.py @@ -0,0 +1,13 @@ +from freezegun import freeze_time + +from posthog.api.test.base import BaseTest +from posthog.models import Dashboard +from posthog.tasks.status_report import status_report + + +class TestStatusReport(BaseTest): + TESTS_API = True + + def test_sttus_report(self) -> None: + with freeze_time("2020-01-04T13:01:01Z"): + status_report(dry_run=True) diff --git a/posthog/tasks/test/test_webhook_message_formatting.py b/posthog/tasks/test/test_webhook_message_formatting.py index 6077fd8172802..768c2ee716065 100644 --- a/posthog/tasks/test/test_webhook_message_formatting.py +++ b/posthog/tasks/test/test_webhook_message_formatting.py @@ -10,7 +10,7 @@ ) -class WebhookMessage(BaseTest): +class TestWebhookMessage(BaseTest): def test_determine_webhook(self) -> None: self.team.slack_incoming_webhook = "https://hooks.slack.com/services/" webhook_type = determine_webhook_type(self.team) diff --git a/posthog/test/test_email.py b/posthog/test/test_email.py index ba2cbbf123c98..1a559a5382f4f 100644 --- a/posthog/test/test_email.py +++ b/posthog/test/test_email.py @@ -20,6 +20,7 @@ def create_person(self, team: Team, base_distinct_id: str = "") -> Person: person.add_distinct_id(base_distinct_id) return person + @freeze_time("2020-09-21") def setUp(self): super().setUp() self.organization = Organization.objects.create() diff --git a/posthog/test/test_event_model.py b/posthog/test/test_event_model.py index f319a58a8b172..28def40c07ddf 100644 --- a/posthog/test/test_event_model.py +++ b/posthog/test/test_event_model.py @@ -521,6 +521,12 @@ def test_selector_id(self): selector1.parts[1].__dict__, {"data": {"attr_id": "5"}, "direct_descendant": True, "unique_order": 0}, ) + def test_selector_with_spaces(self): + selector1 = Selector("span ") + self.assertEqual( + selector1.parts[0].__dict__, {"data": {"tag_name": "span"}, "direct_descendant": False, "unique_order": 0}, + ) + def test_class(self): selector1 = Selector("div.classone.classtwo > span") self.assertEqual( diff --git a/posthog/utils.py b/posthog/utils.py index b017d04ae544d..9168476a30584 100644 --- a/posthog/utils.py +++ b/posthog/utils.py @@ -8,6 +8,7 @@ import subprocess import time import uuid +from datetime import date from typing import Any, Dict, List, Optional, Tuple, Union from urllib.parse import urljoin, urlparse @@ -33,17 +34,16 @@ def absolute_uri(url: Optional[str] = None) -> str: return urljoin(settings.SITE_URL.rstrip("/") + "/", url.lstrip("/")) -def get_previous_week(at_date: Optional[datetime.datetime] = None) -> Tuple[datetime.datetime, datetime.datetime]: +def get_previous_week(at: Optional[datetime.datetime] = None) -> Tuple[datetime.datetime, datetime.datetime]: """ - Returns a tuple of datetime objects representing the start and end of the immediate - previous week to the passed date. + Returns a pair of datetimes, representing the start and end of the week preceding to the passed date's week. """ - if not at_date: - at_date = timezone.now() + if not at: + at = timezone.now() period_end: datetime.datetime = datetime.datetime.combine( - at_date - datetime.timedelta(timezone.now().weekday() + 1), datetime.time.max, tzinfo=pytz.UTC, + at - datetime.timedelta(timezone.now().weekday() + 1), datetime.time.max, tzinfo=pytz.UTC, ) # very end of the previous Sunday period_start: datetime.datetime = datetime.datetime.combine( diff --git a/yarn.lock b/yarn.lock index 56bc45561ecca..13c504097cfbe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -995,6 +995,16 @@ prop-types "^15.6.2" scheduler "^0.19.0" +"@mariusandra/query-selector-shadow-dom@0.7.2-posthog": + version "0.7.2-posthog" + resolved "https://registry.yarnpkg.com/@mariusandra/query-selector-shadow-dom/-/query-selector-shadow-dom-0.7.2-posthog.tgz#133a043b0a43b358f99d371a80b6c31ff0865c5a" + integrity sha512-lRgyns8UVpJAbzQNTHeuz2Yyn0NBkeL2S8U4WoFg/BDKwm5o3FjkRiHIGINb2umANVRo68/4UumIlPn9CwjwOw== + +"@mariusandra/query-selector-shadow-dom@0.7.2-posthog.2": + version "0.7.2-posthog.2" + resolved "https://registry.yarnpkg.com/@mariusandra/query-selector-shadow-dom/-/query-selector-shadow-dom-0.7.2-posthog.2.tgz#9f32cced63db384e33b6423d2cb539257019401b" + integrity sha512-TodRWt0WvumbIdbGZMj7VQ300GpuX5gA2vZCla7Y/1D8UBbNXLAwyrKl6flUjPopvvnRp3PhNbYgWVsFXi+V3w== + "@mariusandra/react-grid-layout@0.18.3": version "0.18.3" resolved "https://registry.yarnpkg.com/@mariusandra/react-grid-layout/-/react-grid-layout-0.18.3.tgz#6d1f844882222cf2b9f08a1b4aae4789229180f6" @@ -1006,17 +1016,42 @@ react-draggable "^4.0.0" react-resizable "^1.10.0" -"@mariusandra/simmerjs@0.6.1-posthog.1": - version "0.6.1-posthog.1" - resolved "https://registry.yarnpkg.com/@mariusandra/simmerjs/-/simmerjs-0.6.1-posthog.1.tgz#d86b9a0cd6bba363adc43800e7075e85dbf849ae" - integrity sha512-aWfbkhOZCZflzdaqj/zWpNII74wr+VztUshyoX4HWbGnCC6RJLP76ZcPXfPK27iafEhIqgeAEbv+3Fdj8RMhOw== +"@mariusandra/simmerjs@0.7.1-posthog.1": + version "0.7.1-posthog.1" + resolved "https://registry.yarnpkg.com/@mariusandra/simmerjs/-/simmerjs-0.7.1-posthog.1.tgz#45da4a0f98915de40c7a1a0adb9d19dd5adf4167" + integrity sha512-buz5dTu6iVoAJ/4foc/AzKO8UDTfZV0kBuwij7gYnklZLIvlT+aaeqJx/1WOWp0HWGXhFaK1ByX3l+U5XBWEGw== dependencies: + "@babel/runtime" "^7.11.2" + "@mariusandra/query-selector-shadow-dom" "0.7.2-posthog" + "@rollup/plugin-commonjs" "^15.1.0" lodash.difference "^4.5.0" lodash.flatmap "^4.5.0" lodash.isfunction "^3.0.8" lodash.take "^4.1.1" lodash.takeright "^4.1.1" +"@rollup/plugin-commonjs@^15.1.0": + version "15.1.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-15.1.0.tgz#1e7d076c4f1b2abf7e65248570e555defc37c238" + integrity sha512-xCQqz4z/o0h2syQ7d9LskIMvBSH4PX5PjYdpSSvgS+pQik3WahkQVNWg3D8XJeYjZoVWnIUQYDghuEMRGrmQYQ== + dependencies: + "@rollup/pluginutils" "^3.1.0" + commondir "^1.0.1" + estree-walker "^2.0.1" + glob "^7.1.6" + is-reference "^1.2.1" + magic-string "^0.25.7" + resolve "^1.17.0" + +"@rollup/pluginutils@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" + integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg== + dependencies: + "@types/estree" "0.0.39" + estree-walker "^1.0.1" + picomatch "^2.2.2" + "@samverschueren/stream-to-observable@^0.3.0": version "0.3.1" resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz#a21117b19ee9be70c379ec1877537ef2e1c63301" @@ -1051,6 +1086,16 @@ resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== +"@types/estree@*": + version "0.0.45" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.45.tgz#e9387572998e5ecdac221950dab3e8c3b16af884" + integrity sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g== + +"@types/estree@0.0.39": + version "0.0.39" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" + integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== + "@types/glob@^7.1.1": version "7.1.3" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183" @@ -4048,6 +4093,16 @@ estraverse@^5.1.0, estraverse@^5.2.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== +estree-walker@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" + integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== + +estree-walker@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.1.tgz#f8e030fb21cefa183b44b7ad516b747434e7a3e0" + integrity sha512-tF0hv+Yi2Ot1cwj9eYHtxC0jB9bmjacjQs6ZBTj82H8JwUywFuc+7E83NWfNMwHXZc11mjfFcVXPe9gEP4B8dg== + esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -5546,6 +5601,13 @@ is-promise@^2.1.0: resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== +is-reference@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" + integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== + dependencies: + "@types/estree" "*" + is-regex@^1.0.4, is-regex@^1.1.0, is-regex@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" @@ -6123,6 +6185,13 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" +magic-string@^0.25.7: + version "0.25.7" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" + integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== + dependencies: + sourcemap-codec "^1.4.4" + make-dir@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" @@ -7025,7 +7094,7 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= -picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1: +picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1, picomatch@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== @@ -8983,7 +9052,7 @@ source-map@^0.7.3: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== -sourcemap-codec@^1.4.1: +sourcemap-codec@^1.4.1, sourcemap-codec@^1.4.4: version "1.4.8" resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==