@temple-wallet/extension-ads 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,187 @@
1
+ import {
2
+ AdAction,
3
+ AdActionType,
4
+ AddActionsIfAdResolutionAvailable,
5
+ HideElementAction,
6
+ OmitAdInAction,
7
+ ReplaceElementWithAdAction,
8
+ SimpleInsertAdAction
9
+ } from 'src/types/ads-actions';
10
+ import { PermanentAdPlacesRule } from 'src/types/ads-rules';
11
+ import { delay, isTruthy } from 'src/utils';
12
+
13
+ import { applyQuerySelector, elementIsOurAd, getParentOfDepth, ourAdQuerySelector } from './helpers';
14
+
15
+ export const processPermanentAdPlacesRule = async (
16
+ rule: PermanentAdPlacesRule,
17
+ addActionsIfAdResolutionAvailable: AddActionsIfAdResolutionAvailable,
18
+ result: AdAction[]
19
+ ) => {
20
+ const {
21
+ isMultiple: shouldSearchForManyParents,
22
+ cssString: parentCssString,
23
+ parentDepth: parentParentDepth
24
+ } = rule.parentSelector;
25
+
26
+ const parents = applyQuerySelector<HTMLElement>(parentCssString, shouldSearchForManyParents)
27
+ .map(element => getParentOfDepth(element, parentParentDepth))
28
+ .filter((value): value is HTMLElement => Boolean(value));
29
+
30
+ await Promise.all(
31
+ parents.map(async parent => {
32
+ await delay(0);
33
+
34
+ processPermanentAdsParent(parent, rule, addActionsIfAdResolutionAvailable, result);
35
+ })
36
+ );
37
+
38
+ return parents;
39
+ };
40
+
41
+ const processPermanentAdsParent = (
42
+ parent: HTMLElement,
43
+ rule: PermanentAdPlacesRule,
44
+ addActionsIfAdResolutionAvailable: AddActionsIfAdResolutionAvailable,
45
+ result: AdAction[]
46
+ ) => {
47
+ const {
48
+ shouldUseDivWrapper,
49
+ divWrapperStyle,
50
+ elementStyle,
51
+ adSelector,
52
+ insertionIndex,
53
+ insertBeforeSelector,
54
+ insertAfterSelector,
55
+ insertionsCount = 1,
56
+ elementToMeasureSelector,
57
+ stylesOverrides,
58
+ shouldHideOriginal = false,
59
+ isNative
60
+ } = rule;
61
+
62
+ const {
63
+ isMultiple: shouldSearchForManyBannersInParent,
64
+ cssString: bannerCssString,
65
+ parentDepth: bannerParentDepth
66
+ } = adSelector;
67
+
68
+ const ourAds = applyQuerySelector(ourAdQuerySelector, true, parent).reduce<Element[]>((acc, element) => {
69
+ if (acc.some(prevElement => prevElement.contains(element) || element.contains(prevElement))) {
70
+ return acc;
71
+ }
72
+
73
+ return [...acc, element];
74
+ }, []);
75
+
76
+ const ourAdsCount = ourAds.length;
77
+ let insertionsLeft = insertionsCount - ourAdsCount;
78
+
79
+ const banners = applyQuerySelector<HTMLElement>(bannerCssString, shouldSearchForManyBannersInParent, parent)
80
+ .map(element => getParentOfDepth(element, bannerParentDepth))
81
+ .filter((value): value is HTMLElement => isTruthy(value) && !elementIsOurAd(value));
82
+
83
+ banners.forEach(banner => {
84
+ if (insertionsLeft <= 0) {
85
+ const { display: bannerDisplay } = window.getComputedStyle(banner);
86
+ if (!shouldHideOriginal || bannerDisplay !== 'none') {
87
+ result.push({
88
+ type: shouldHideOriginal ? AdActionType.HideElement : AdActionType.RemoveElement,
89
+ element: banner
90
+ });
91
+ }
92
+ } else {
93
+ let elementToMeasure = banner.parentElement?.children.length === 1 ? banner.parentElement : banner;
94
+ if (elementToMeasureSelector) {
95
+ elementToMeasure = document.querySelector(elementToMeasureSelector) ?? elementToMeasure;
96
+ }
97
+ const replaceActionBase: OmitAdInAction<ReplaceElementWithAdAction> = {
98
+ type: AdActionType.ReplaceElement,
99
+ element: banner,
100
+ shouldUseDivWrapper,
101
+ divWrapperStyle,
102
+ elementStyle,
103
+ stylesOverrides
104
+ };
105
+ const hideActionBase: HideElementAction = {
106
+ type: AdActionType.HideElement,
107
+ element: banner
108
+ };
109
+ const insertActionBase: OmitAdInAction<SimpleInsertAdAction> = {
110
+ type: AdActionType.SimpleInsertAd,
111
+ shouldUseDivWrapper,
112
+ divWrapperStyle,
113
+ elementStyle,
114
+ parent: banner.parentElement!,
115
+ insertionIndex: Array.from(banner.parentElement!.children).indexOf(banner),
116
+ stylesOverrides
117
+ };
118
+
119
+ const nextBannerSibling = banner.nextElementSibling;
120
+ const nextBannerSiblingIsOurAd = nextBannerSibling && elementIsOurAd(nextBannerSibling as HTMLElement);
121
+ const actionsToInsert = shouldHideOriginal
122
+ ? nextBannerSiblingIsOurAd
123
+ ? []
124
+ : [hideActionBase, insertActionBase]
125
+ : [replaceActionBase];
126
+ if (
127
+ actionsToInsert.length > 0 &&
128
+ addActionsIfAdResolutionAvailable(elementToMeasure, false, true, isNative, ...actionsToInsert)
129
+ ) {
130
+ insertionsLeft--;
131
+ }
132
+ }
133
+ });
134
+
135
+ if (insertionsLeft <= 0) {
136
+ return;
137
+ }
138
+
139
+ let normalizedInsertionIndex = -1;
140
+ let insertionParentElement = parent;
141
+ let elementToMeasure = parent;
142
+ const insertAnchorSelector = insertBeforeSelector || insertAfterSelector;
143
+ if (insertAnchorSelector) {
144
+ const insertAnchorElement = parent.querySelector(insertAnchorSelector);
145
+ const newInsertionParentElement = insertAnchorElement?.parentElement;
146
+
147
+ if (insertAnchorElement && newInsertionParentElement) {
148
+ insertionParentElement = newInsertionParentElement;
149
+ normalizedInsertionIndex =
150
+ Array.from(parent.children).indexOf(insertAnchorElement) + (insertBeforeSelector ? 0 : 1);
151
+ elementToMeasure =
152
+ (elementToMeasureSelector && document.querySelector(elementToMeasureSelector)) ||
153
+ (insertAnchorElement as HTMLElement);
154
+ }
155
+ } else {
156
+ const insertionIndexWithDefault = insertionIndex ?? 0;
157
+
158
+ normalizedInsertionIndex =
159
+ insertionIndexWithDefault < 0
160
+ ? Math.max(parent.children.length + insertionIndexWithDefault, 0)
161
+ : Math.min(insertionIndexWithDefault, parent.children.length);
162
+
163
+ elementToMeasure =
164
+ (elementToMeasureSelector && document.querySelector(elementToMeasureSelector)) ||
165
+ ((parent.children[normalizedInsertionIndex] as HTMLElement | undefined) ?? parent);
166
+ }
167
+
168
+ if (normalizedInsertionIndex !== -1) {
169
+ const actionBase: OmitAdInAction<SimpleInsertAdAction> = {
170
+ type: AdActionType.SimpleInsertAd,
171
+ shouldUseDivWrapper,
172
+ divWrapperStyle,
173
+ elementStyle,
174
+ parent: insertionParentElement,
175
+ insertionIndex: normalizedInsertionIndex,
176
+ stylesOverrides
177
+ };
178
+
179
+ addActionsIfAdResolutionAvailable(
180
+ elementToMeasure,
181
+ false,
182
+ true,
183
+ isNative,
184
+ ...Array<typeof actionBase>(insertionsLeft).fill(actionBase)
185
+ );
186
+ }
187
+ };
@@ -0,0 +1,123 @@
1
+ import {
2
+ AddActionsIfAdResolutionAvailable,
3
+ AdActionType,
4
+ HideElementAction,
5
+ InsertAdActionWithoutMeta,
6
+ OmitAdInAction,
7
+ RemoveElementAction,
8
+ ReplaceAllChildrenWithAdAction,
9
+ ReplaceElementWithAdAction,
10
+ SimpleInsertAdAction
11
+ } from 'src/types/ads-actions';
12
+ import { AdsRules } from 'src/types/ads-rules';
13
+ import { delay } from 'src/utils';
14
+
15
+ import { applyQuerySelector, elementIsOurAd, getParentOfDepth, ourAdQuerySelector } from './helpers';
16
+
17
+ export const processAdPlacesRule = async (
18
+ rule: AdsRules['adPlacesRules'][number],
19
+ permanentAdsParents: HTMLElement[],
20
+ addActionsIfAdResolutionAvailable: AddActionsIfAdResolutionAvailable
21
+ ) => {
22
+ const { cssString, isMultiple } = rule.selector;
23
+
24
+ const selectedElements = applyQuerySelector<HTMLElement>(cssString, isMultiple);
25
+
26
+ await Promise.all(
27
+ selectedElements.map(async selectedElement => {
28
+ await delay(0);
29
+
30
+ processSelectedElement(selectedElement, rule, permanentAdsParents, addActionsIfAdResolutionAvailable);
31
+ })
32
+ );
33
+ };
34
+
35
+ const processSelectedElement = (
36
+ selectedElement: HTMLElement,
37
+ rule: AdsRules['adPlacesRules'][number],
38
+ permanentAdsParents: HTMLElement[],
39
+ addActionsIfAdResolutionAvailable: AddActionsIfAdResolutionAvailable
40
+ ) => {
41
+ const {
42
+ selector: { shouldUseDivWrapper, parentDepth, divWrapperStyle },
43
+ stylesOverrides,
44
+ shouldHideOriginal
45
+ } = rule;
46
+
47
+ const banner = getParentOfDepth(selectedElement, parentDepth);
48
+
49
+ if (
50
+ !banner ||
51
+ permanentAdsParents.some(parent => parent.contains(banner)) ||
52
+ elementIsOurAd(banner) ||
53
+ banner.querySelector(ourAdQuerySelector)
54
+ ) {
55
+ return;
56
+ }
57
+
58
+ const actionBaseCommonProps = {
59
+ shouldUseDivWrapper,
60
+ divWrapperStyle
61
+ };
62
+
63
+ let actionsBases: (InsertAdActionWithoutMeta | HideElementAction | RemoveElementAction)[];
64
+ if (shouldUseDivWrapper && shouldHideOriginal) {
65
+ const parent = banner.parentElement!;
66
+ const insertAdAction: OmitAdInAction<SimpleInsertAdAction> = {
67
+ type: AdActionType.SimpleInsertAd,
68
+ parent,
69
+ insertionIndex: Array.from(parent.children).indexOf(banner),
70
+ stylesOverrides: stylesOverrides?.map(({ parentDepth, ...restProps }) => ({
71
+ ...restProps,
72
+ parentDepth: parentDepth - 1
73
+ })),
74
+ ...actionBaseCommonProps
75
+ };
76
+
77
+ actionsBases = [];
78
+ if (window.getComputedStyle(banner).display !== 'none') {
79
+ actionsBases.push({ type: AdActionType.HideElement, element: banner });
80
+ }
81
+ if (!parent.querySelector(ourAdQuerySelector)) {
82
+ actionsBases.push(insertAdAction);
83
+ }
84
+ } else if (shouldUseDivWrapper) {
85
+ const replaceElementActionBase: OmitAdInAction<ReplaceElementWithAdAction> = {
86
+ type: AdActionType.ReplaceElement,
87
+ element: banner,
88
+ stylesOverrides: stylesOverrides?.map(({ parentDepth, ...restProps }) => ({
89
+ ...restProps,
90
+ parentDepth: parentDepth - 1
91
+ })),
92
+ ...actionBaseCommonProps
93
+ };
94
+ actionsBases = [replaceElementActionBase];
95
+ } else if (shouldHideOriginal) {
96
+ const insertAdAction: OmitAdInAction<SimpleInsertAdAction> = {
97
+ type: AdActionType.SimpleInsertAd,
98
+ parent: banner,
99
+ insertionIndex: 0,
100
+ stylesOverrides,
101
+ ...actionBaseCommonProps
102
+ };
103
+
104
+ actionsBases = Array.from(banner.children)
105
+ .filter(child => window.getComputedStyle(child).display !== 'none')
106
+ .map((child): HideElementAction => ({ type: AdActionType.HideElement, element: child as HTMLElement }));
107
+ if (!banner.querySelector(ourAdQuerySelector)) {
108
+ actionsBases.push(insertAdAction);
109
+ }
110
+ } else {
111
+ const replaceAllChildrenActionBase: OmitAdInAction<ReplaceAllChildrenWithAdAction> = {
112
+ type: AdActionType.ReplaceAllChildren,
113
+ parent: banner,
114
+ stylesOverrides,
115
+ ...actionBaseCommonProps
116
+ };
117
+ actionsBases = [replaceAllChildrenActionBase];
118
+ }
119
+
120
+ if (actionsBases.length > 0) {
121
+ addActionsIfAdResolutionAvailable(banner, false, false, false, ...actionsBases);
122
+ }
123
+ };
@@ -0,0 +1,43 @@
1
+ export class AdsConfiguration {
2
+ static HYPELAB_NATIVE_PLACEMENT_SLUG = '';
3
+ static HYPELAB_SMALL_PLACEMENT_SLUG = '';
4
+ static HYPELAB_HIGH_PLACEMENT_SLUG = '';
5
+ static HYPELAB_WIDE_PLACEMENT_SLUG = '';
6
+ static HYPELAB_ADS_WINDOW_URL = '';
7
+ static TKEY_INPAGE_AD_URL = '';
8
+ static SWAP_TKEY_URL = '';
9
+ static EXTERNAL_ADS_ACTIVITY_MESSAGE_TYPE = '';
10
+ }
11
+
12
+ interface IAdsConfiguration {
13
+ hypelabNativePlacementSlug: string;
14
+ hypelabSmallPlacementSlug: string;
15
+ hypelabHighPlacementSlug: string;
16
+ hypelabWidePlacementSlug: string;
17
+ hypelabAdsWindowUrl: string;
18
+ tkeyInpageAdUrl: string;
19
+ swapTkeyUrl: string;
20
+ externalAdsActivityMessageType: string;
21
+ }
22
+
23
+ export const configureAds = (config: IAdsConfiguration) => {
24
+ const {
25
+ hypelabNativePlacementSlug,
26
+ hypelabSmallPlacementSlug,
27
+ hypelabHighPlacementSlug,
28
+ hypelabWidePlacementSlug,
29
+ hypelabAdsWindowUrl,
30
+ tkeyInpageAdUrl,
31
+ swapTkeyUrl,
32
+ externalAdsActivityMessageType
33
+ } = config;
34
+
35
+ AdsConfiguration.HYPELAB_NATIVE_PLACEMENT_SLUG = hypelabNativePlacementSlug;
36
+ AdsConfiguration.HYPELAB_SMALL_PLACEMENT_SLUG = hypelabSmallPlacementSlug;
37
+ AdsConfiguration.HYPELAB_HIGH_PLACEMENT_SLUG = hypelabHighPlacementSlug;
38
+ AdsConfiguration.HYPELAB_WIDE_PLACEMENT_SLUG = hypelabWidePlacementSlug;
39
+ AdsConfiguration.HYPELAB_ADS_WINDOW_URL = hypelabAdsWindowUrl;
40
+ AdsConfiguration.TKEY_INPAGE_AD_URL = tkeyInpageAdUrl;
41
+ AdsConfiguration.SWAP_TKEY_URL = swapTkeyUrl;
42
+ AdsConfiguration.EXTERNAL_ADS_ACTIVITY_MESSAGE_TYPE = externalAdsActivityMessageType;
43
+ };
@@ -0,0 +1,108 @@
1
+ import { AdsConfiguration } from 'src/ads-configuration';
2
+ import { AdMetadata } from 'src/types/ads-meta';
3
+
4
+ export const BANNER_ADS_META: AdMetadata[] = [
5
+ {
6
+ source: {
7
+ providerName: 'Persona',
8
+ shape: 'wide'
9
+ },
10
+ dimensions: {
11
+ width: 970,
12
+ height: 90,
13
+ minContainerWidth: 600,
14
+ minContainerHeight: 60,
15
+ maxContainerWidth: 1440,
16
+ maxContainerHeight: 110
17
+ }
18
+ },
19
+ {
20
+ source: {
21
+ providerName: 'Temple'
22
+ },
23
+ dimensions: {
24
+ width: 728,
25
+ height: 90,
26
+ minContainerWidth: 600,
27
+ minContainerHeight: 60,
28
+ maxContainerWidth: 1440,
29
+ maxContainerHeight: 110
30
+ }
31
+ },
32
+ {
33
+ source: {
34
+ providerName: 'HypeLab',
35
+ native: false,
36
+ size: 'high'
37
+ },
38
+ dimensions: {
39
+ width: 300,
40
+ height: 250,
41
+ minContainerWidth: 210,
42
+ minContainerHeight: 170,
43
+ maxContainerWidth: 400,
44
+ maxContainerHeight: 300
45
+ }
46
+ },
47
+ {
48
+ source: {
49
+ providerName: 'Persona',
50
+ shape: 'squarish'
51
+ },
52
+ dimensions: {
53
+ width: 300,
54
+ height: 250,
55
+ minContainerWidth: 210,
56
+ minContainerHeight: 170,
57
+ maxContainerWidth: 400,
58
+ maxContainerHeight: 300
59
+ }
60
+ },
61
+ {
62
+ source: {
63
+ providerName: 'HypeLab',
64
+ native: false,
65
+ size: 'small',
66
+ shouldNotUseStrictContainerLimits: true
67
+ },
68
+ dimensions: {
69
+ width: 320,
70
+ height: 50,
71
+ minContainerWidth: 230,
72
+ minContainerHeight: 32,
73
+ maxContainerWidth: 420,
74
+ maxContainerHeight: 110
75
+ }
76
+ },
77
+ {
78
+ source: {
79
+ providerName: 'Persona',
80
+ shape: 'regular',
81
+ shouldNotUseStrictContainerLimits: true
82
+ },
83
+ dimensions: {
84
+ width: 321,
85
+ height: 101,
86
+ minContainerWidth: 230,
87
+ minContainerHeight: 32,
88
+ maxContainerWidth: 420,
89
+ maxContainerHeight: 110
90
+ }
91
+ }
92
+ ];
93
+
94
+ export const buildHypeLabNativeMeta = (containerWidth: number, containerHeight: number) => ({
95
+ source: {
96
+ providerName: 'HypeLab' as const,
97
+ native: true as const,
98
+ slug: AdsConfiguration.HYPELAB_NATIVE_PLACEMENT_SLUG
99
+ },
100
+ dimensions: {
101
+ width: Math.max(160, containerWidth),
102
+ height: Math.max(16, containerHeight),
103
+ minContainerWidth: 2,
104
+ minContainerHeight: 2,
105
+ maxContainerWidth: Infinity,
106
+ maxContainerHeight: Infinity
107
+ }
108
+ });
@@ -0,0 +1,2 @@
1
+ export const TEMPLE_WALLET_AD_ATTRIBUTE_NAME = 'twa';
2
+ export const AD_SEEN_THRESHOLD = 0.5;
@@ -0,0 +1,3 @@
1
+ export { makeTKeyAdView } from './make-tkey-ad';
2
+ export { makeHypelabAdView } from './make-hypelab-ad';
3
+ export { makePersonaAdView } from './make-persona-ad';
@@ -0,0 +1,77 @@
1
+ import { nanoid } from 'nanoid';
2
+
3
+ import { AdsConfiguration } from 'src/ads-configuration';
4
+ import { AdView } from 'src/types/ad-view';
5
+ import { AdDimensions, HypeLabAdSources } from 'src/types/ads-meta';
6
+ import { StringRecord } from 'src/utils';
7
+
8
+ export const makeHypelabAdView = (
9
+ source: HypeLabAdSources,
10
+ dimensions: AdDimensions,
11
+ elementStyle: StringRecord
12
+ ): AdView => {
13
+ const { width, height } = dimensions;
14
+
15
+ const iframe = document.createElement('iframe');
16
+ iframe.id = nanoid();
17
+ iframe.src = getHypelabIframeUrl(source, window.location.href, width, height, iframe.id);
18
+ iframe.style.width = `${width}px`;
19
+ iframe.style.height = `${height}px`;
20
+ iframe.style.border = 'none';
21
+ for (const styleProp in elementStyle) {
22
+ iframe.style.setProperty(styleProp, elementStyle[styleProp]);
23
+ }
24
+
25
+ return { element: iframe };
26
+ };
27
+
28
+ /**
29
+ * Returns URL for Hypelab ad iframe
30
+ * @param placementType Placement type
31
+ * @param origin Full URL of the page
32
+ * @param width Frame width
33
+ * @param height Frame height
34
+ */
35
+ const getHypelabIframeUrl = (
36
+ source: HypeLabAdSources,
37
+ origin: string,
38
+ width?: number,
39
+ height?: number,
40
+ id?: string
41
+ ) => {
42
+ let defaultWidth: number, defaultHeight: number, placementSlug: string;
43
+
44
+ if (source.native) {
45
+ placementSlug = AdsConfiguration.HYPELAB_NATIVE_PLACEMENT_SLUG;
46
+ defaultWidth = 360;
47
+ defaultHeight = 110;
48
+ } else
49
+ switch (source.size) {
50
+ case 'small':
51
+ defaultWidth = 320;
52
+ defaultHeight = 50;
53
+ placementSlug = AdsConfiguration.HYPELAB_SMALL_PLACEMENT_SLUG;
54
+ break;
55
+ case 'high':
56
+ defaultWidth = 300;
57
+ defaultHeight = 250;
58
+ placementSlug = AdsConfiguration.HYPELAB_HIGH_PLACEMENT_SLUG;
59
+ break;
60
+ case 'wide':
61
+ defaultWidth = 728;
62
+ defaultHeight = 90;
63
+ placementSlug = AdsConfiguration.HYPELAB_WIDE_PLACEMENT_SLUG;
64
+ break;
65
+ }
66
+
67
+ const url = new URL(AdsConfiguration.HYPELAB_ADS_WINDOW_URL);
68
+ url.searchParams.set('w', String(width ?? defaultWidth));
69
+ url.searchParams.set('h', String(height ?? defaultHeight));
70
+ url.searchParams.set('p', placementSlug);
71
+ url.searchParams.set('o', origin);
72
+ if (id) {
73
+ url.searchParams.set('id', id);
74
+ }
75
+
76
+ return url.toString();
77
+ };
@@ -0,0 +1,28 @@
1
+ import { nanoid } from 'nanoid';
2
+ import browser from 'webextension-polyfill';
3
+
4
+ import { AdView } from 'src/types/ad-view';
5
+ import { AdDimensions, PersonaAdShape } from 'src/types/ads-meta';
6
+ import { StringRecord } from 'src/utils';
7
+
8
+ export const makePersonaAdView = (
9
+ shape: PersonaAdShape,
10
+ { width, height }: AdDimensions,
11
+ elementStyle: StringRecord
12
+ ): AdView => {
13
+ const id = nanoid();
14
+
15
+ const element = document.createElement('iframe');
16
+ element.src = browser.runtime.getURL(`iframes/persona-ad.html?id=${id}&shape=${shape}`);
17
+ element.id = id;
18
+
19
+ element.style.width = `${width}px`;
20
+ element.style.height = `${height}px`;
21
+ element.style.border = 'none';
22
+
23
+ for (const styleProp in elementStyle) {
24
+ element.style.setProperty(styleProp, elementStyle[styleProp]);
25
+ }
26
+
27
+ return { element };
28
+ };
@@ -0,0 +1,37 @@
1
+ import { nanoid } from 'nanoid';
2
+
3
+ import { AdsConfiguration } from 'src/ads-configuration';
4
+ import { AdView } from 'src/types/ad-view';
5
+ import { StringRecord } from 'src/utils';
6
+
7
+ export const makeTKeyAdView = (width: number, height: number, elementStyle: StringRecord): AdView => {
8
+ const element = document.createElement('div');
9
+ element.id = nanoid();
10
+ element.style.width = `${width}px`;
11
+ element.style.height = `${height}px`;
12
+ for (const styleProp in elementStyle) {
13
+ element.style.setProperty(styleProp, elementStyle[styleProp]);
14
+ }
15
+
16
+ const div = document.createElement('div');
17
+ div.style.width = `${width}px`;
18
+ div.style.height = `${height}px`;
19
+
20
+ element.appendChild(div);
21
+
22
+ const anchor = document.createElement('a');
23
+ anchor.href = AdsConfiguration.SWAP_TKEY_URL;
24
+ anchor.target = '_blank';
25
+ anchor.rel = 'noopener noreferrer';
26
+ anchor.style.width = '100%';
27
+ anchor.style.height = '100%';
28
+ div.appendChild(anchor);
29
+
30
+ const img = document.createElement('img');
31
+ img.src = AdsConfiguration.TKEY_INPAGE_AD_URL;
32
+ img.style.width = '100%';
33
+ img.style.height = '100%';
34
+ anchor.appendChild(img);
35
+
36
+ return { element };
37
+ };
@@ -0,0 +1,16 @@
1
+ import { AdAction, AdActionType } from 'src/types/ads-actions';
2
+
3
+ import { processInsertAdAction } from './process-insert-ad-action';
4
+
5
+ export const executeAdsActions = (adsActions: AdAction[]) =>
6
+ Promise.allSettled(
7
+ adsActions.map(async action => {
8
+ if (action.type === AdActionType.RemoveElement) {
9
+ action.element.remove();
10
+ } else if (action.type === AdActionType.HideElement) {
11
+ action.element.style.setProperty('display', 'none');
12
+ } else {
13
+ await processInsertAdAction(action, action.ad);
14
+ }
15
+ })
16
+ );