@temple-wallet/extension-ads 6.0.0 → 6.2.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.
- package/.editorconfig +9 -0
- package/dist/ads-actions/helpers.d.ts +13 -0
- package/dist/ads-actions/helpers.js +83 -0
- package/dist/ads-actions/helpers.js.map +1 -0
- package/dist/ads-actions/index.d.ts +3 -0
- package/dist/ads-actions/index.js +45 -0
- package/dist/ads-actions/index.js.map +1 -0
- package/dist/ads-actions/process-permanent-rule.d.ts +3 -0
- package/dist/ads-actions/process-permanent-rule.js +132 -0
- package/dist/ads-actions/process-permanent-rule.js.map +1 -0
- package/dist/ads-actions/process-providers-ads.d.ts +3 -0
- package/dist/ads-actions/process-providers-ads.js +113 -0
- package/dist/ads-actions/process-providers-ads.js.map +1 -0
- package/dist/ads-actions/process-rule.d.ts +3 -0
- package/dist/ads-actions/process-rule.js +97 -0
- package/dist/ads-actions/process-rule.js.map +1 -0
- package/dist/ads-configuration.d.ts +33 -0
- package/dist/ads-configuration.js +29 -0
- package/dist/ads-configuration.js.map +1 -0
- package/dist/ads-meta.d.ts +17 -0
- package/dist/ads-meta.js +135 -0
- package/dist/ads-meta.js.map +1 -0
- package/dist/constants.d.ts +8 -0
- package/dist/constants.js +9 -0
- package/dist/constants.js.map +1 -0
- package/dist/execute-ads-actions/ads-views/index.d.ts +3 -0
- package/dist/execute-ads-actions/ads-views/index.js +4 -0
- package/dist/execute-ads-actions/ads-views/index.js.map +1 -0
- package/dist/execute-ads-actions/ads-views/make-hypelab-ad.d.ts +3 -0
- package/dist/execute-ads-actions/ads-views/make-hypelab-ad.js +60 -0
- package/dist/execute-ads-actions/ads-views/make-hypelab-ad.js.map +1 -0
- package/dist/execute-ads-actions/ads-views/make-persona-ad.d.ts +3 -0
- package/dist/execute-ads-actions/ads-views/make-persona-ad.js +11 -0
- package/dist/execute-ads-actions/ads-views/make-persona-ad.js.map +1 -0
- package/dist/execute-ads-actions/ads-views/make-tkey-ad.d.ts +2 -0
- package/dist/execute-ads-actions/ads-views/make-tkey-ad.js +24 -0
- package/dist/execute-ads-actions/ads-views/make-tkey-ad.js.map +1 -0
- package/dist/execute-ads-actions/index.d.ts +2 -0
- package/dist/execute-ads-actions/index.js +23 -0
- package/dist/execute-ads-actions/index.js.map +1 -0
- package/dist/execute-ads-actions/observing.d.ts +1 -0
- package/dist/execute-ads-actions/observing.js +123 -0
- package/dist/execute-ads-actions/observing.js.map +1 -0
- package/dist/execute-ads-actions/override-element-styles.d.ts +2 -0
- package/dist/execute-ads-actions/override-element-styles.js +6 -0
- package/dist/execute-ads-actions/override-element-styles.js.map +1 -0
- package/dist/execute-ads-actions/process-insert-ad-action.d.ts +2 -0
- package/dist/execute-ads-actions/process-insert-ad-action.js +120 -0
- package/dist/execute-ads-actions/process-insert-ad-action.js.map +1 -0
- package/dist/index.d.ts +7 -3
- package/dist/index.js +13 -13
- package/dist/index.js.map +1 -0
- package/dist/render-ads-stack.d.ts +7 -0
- package/dist/render-ads-stack.js +101 -0
- package/dist/render-ads-stack.js.map +1 -0
- package/dist/temple-wallet-api.d.ts +17 -0
- package/dist/temple-wallet-api.js +56 -0
- package/dist/temple-wallet-api.js.map +1 -0
- package/dist/transform-raw-rules.d.ts +3 -0
- package/dist/transform-raw-rules.js +117 -0
- package/dist/transform-raw-rules.js.map +1 -0
- package/dist/types/ad-view.d.ts +3 -0
- package/dist/types/ad-view.js +2 -0
- package/dist/types/ad-view.js.map +1 -0
- package/dist/types/ads-actions.d.ts +54 -0
- package/dist/types/ads-actions.js +15 -0
- package/dist/types/ads-actions.js.map +1 -0
- package/dist/types/ads-meta.d.ts +46 -0
- package/dist/types/ads-meta.js +2 -0
- package/dist/types/ads-meta.js.map +1 -0
- package/dist/types/ads-provider.d.ts +7 -0
- package/dist/types/ads-provider.js +8 -0
- package/dist/types/ads-provider.js.map +1 -0
- package/dist/types/ads-rules.d.ts +17 -0
- package/dist/types/ads-rules.js +2 -0
- package/dist/types/ads-rules.js.map +1 -0
- package/dist/types/temple-wallet-api.d.ts +61 -0
- package/dist/types/temple-wallet-api.js +2 -0
- package/dist/types/temple-wallet-api.js.map +1 -0
- package/dist/utils.d.ts +6 -0
- package/dist/utils.js +4 -0
- package/dist/utils.js.map +1 -0
- package/package.json +1 -1
- package/src/ads-actions/helpers.ts +11 -3
- package/src/ads-actions/process-permanent-rule.ts +26 -10
- package/src/ads-actions/process-providers-ads.ts +12 -7
- package/src/ads-actions/process-rule.ts +3 -3
- package/src/constants.ts +2 -0
- package/src/execute-ads-actions/ads-views/make-hypelab-ad.ts +6 -2
- package/src/execute-ads-actions/observing.ts +15 -11
- package/src/execute-ads-actions/process-insert-ad-action.ts +91 -14
- package/src/render-ads-stack.ts +18 -7
- package/src/types/ads-actions.ts +3 -3
- package/src/types/temple-wallet-api.ts +6 -1
- package/.vscode/settings.json +0 -3
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
interface AdSourceBase {
|
|
2
|
+
shouldNotUseStrictContainerLimits?: boolean;
|
|
3
|
+
}
|
|
4
|
+
interface HypeLabBannerAdSource extends AdSourceBase {
|
|
5
|
+
providerName: 'HypeLab';
|
|
6
|
+
native: false;
|
|
7
|
+
size: 'small' | 'high' | 'wide';
|
|
8
|
+
}
|
|
9
|
+
interface HypeLabNativeAdSource extends AdSourceBase {
|
|
10
|
+
providerName: 'HypeLab';
|
|
11
|
+
native: true;
|
|
12
|
+
slug: string;
|
|
13
|
+
}
|
|
14
|
+
/** Only covers TKEY ads for now */
|
|
15
|
+
interface TempleAdSource extends AdSourceBase {
|
|
16
|
+
providerName: 'Temple';
|
|
17
|
+
}
|
|
18
|
+
/** See: https://pub.persona3.io/docs
|
|
19
|
+
* `regular` - 321x101
|
|
20
|
+
* `medium` - 600x160
|
|
21
|
+
* `wide` - 970x90
|
|
22
|
+
* `squarish` - 300x250
|
|
23
|
+
*/
|
|
24
|
+
export type PersonaAdShape = 'regular' | 'medium' | 'wide' | 'squarish';
|
|
25
|
+
interface PersonaAdSource extends AdSourceBase {
|
|
26
|
+
providerName: 'Persona';
|
|
27
|
+
shape: PersonaAdShape;
|
|
28
|
+
}
|
|
29
|
+
export type HypeLabAdSources = HypeLabBannerAdSource | HypeLabNativeAdSource;
|
|
30
|
+
type AdSource = HypeLabAdSources | TempleAdSource | PersonaAdSource;
|
|
31
|
+
export interface AdDimensions {
|
|
32
|
+
width: number;
|
|
33
|
+
height: number;
|
|
34
|
+
minContainerWidth: number;
|
|
35
|
+
minContainerHeight: number;
|
|
36
|
+
maxContainerWidth: number;
|
|
37
|
+
maxContainerHeight: number;
|
|
38
|
+
}
|
|
39
|
+
export interface AdMetadata {
|
|
40
|
+
source: AdSource;
|
|
41
|
+
dimensions: {
|
|
42
|
+
width?: number;
|
|
43
|
+
height: number;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ads-meta.js","sourceRoot":"","sources":["../../src/types/ads-meta.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export var AdsProviderTitle;
|
|
2
|
+
(function (AdsProviderTitle) {
|
|
3
|
+
AdsProviderTitle["Optimal"] = "Optimal";
|
|
4
|
+
AdsProviderTitle["HypeLab"] = "HypeLab";
|
|
5
|
+
AdsProviderTitle["Persona"] = "Persona";
|
|
6
|
+
AdsProviderTitle["Temple"] = "Temple Wallet";
|
|
7
|
+
})(AdsProviderTitle || (AdsProviderTitle = {}));
|
|
8
|
+
//# sourceMappingURL=ads-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ads-provider.js","sourceRoot":"","sources":["../../src/types/ads-provider.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,gBAKX;AALD,WAAY,gBAAgB;IAC1B,uCAAmB,CAAA;IACnB,uCAAmB,CAAA;IACnB,uCAAmB,CAAA;IACnB,4CAAwB,CAAA;AAC1B,CAAC,EALW,gBAAgB,KAAhB,gBAAgB,QAK3B"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { RawAdPlacesRule, RawPermanentAdPlacesRule } from './temple-wallet-api';
|
|
2
|
+
export interface AdPlacesRule extends Omit<RawAdPlacesRule, 'urlRegexes'> {
|
|
3
|
+
urlRegexes: RegExp[];
|
|
4
|
+
}
|
|
5
|
+
export interface PermanentAdPlacesRule extends Omit<RawPermanentAdPlacesRule, 'urlRegexes'> {
|
|
6
|
+
urlRegexes: RegExp[];
|
|
7
|
+
isNative: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface AdsRules {
|
|
10
|
+
adPlacesRules: Array<Omit<AdPlacesRule, 'urlRegexes'>>;
|
|
11
|
+
permanentAdPlacesRules: PermanentAdPlacesRule[];
|
|
12
|
+
providersSelectors: Array<{
|
|
13
|
+
selector: string;
|
|
14
|
+
parentDepth: number;
|
|
15
|
+
}>;
|
|
16
|
+
timestamp: number;
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ads-rules.js","sourceRoot":"","sources":["../../src/types/ads-rules.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export interface AdStylesOverrides {
|
|
2
|
+
parentDepth: number;
|
|
3
|
+
style: Record<string, string>;
|
|
4
|
+
}
|
|
5
|
+
export interface RawAdPlacesRule {
|
|
6
|
+
urlRegexes: string[];
|
|
7
|
+
selector: {
|
|
8
|
+
isMultiple: boolean;
|
|
9
|
+
cssString: string;
|
|
10
|
+
parentDepth: number;
|
|
11
|
+
shouldUseDivWrapper: boolean;
|
|
12
|
+
divWrapperStyle?: Record<string, string>;
|
|
13
|
+
};
|
|
14
|
+
stylesOverrides?: AdStylesOverrides[];
|
|
15
|
+
shouldHideOriginal?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface RawPermanentAdPlacesRule {
|
|
18
|
+
urlRegexes: string[];
|
|
19
|
+
adSelector: {
|
|
20
|
+
isMultiple: boolean;
|
|
21
|
+
cssString: string;
|
|
22
|
+
parentDepth: number;
|
|
23
|
+
};
|
|
24
|
+
parentSelector: {
|
|
25
|
+
isMultiple: boolean;
|
|
26
|
+
cssString: string;
|
|
27
|
+
parentDepth: number;
|
|
28
|
+
};
|
|
29
|
+
insertionIndex?: number;
|
|
30
|
+
insertBeforeSelector?: string;
|
|
31
|
+
insertAfterSelector?: string;
|
|
32
|
+
insertionsCount?: number;
|
|
33
|
+
shouldUseDivWrapper?: boolean;
|
|
34
|
+
wrapperType?: 'div' | 'tbody';
|
|
35
|
+
colsBefore?: number;
|
|
36
|
+
colspan?: number;
|
|
37
|
+
colsAfter?: number;
|
|
38
|
+
divWrapperStyle?: Record<string, string>;
|
|
39
|
+
wrapperStyle?: Record<string, string>;
|
|
40
|
+
elementStyle?: Record<string, string>;
|
|
41
|
+
elementToMeasureSelector?: string;
|
|
42
|
+
stylesOverrides?: AdStylesOverrides[];
|
|
43
|
+
shouldHideOriginal?: boolean;
|
|
44
|
+
}
|
|
45
|
+
export interface RawAdProvidersRule {
|
|
46
|
+
urlRegexes: string[];
|
|
47
|
+
providers: string[];
|
|
48
|
+
}
|
|
49
|
+
export interface RawAllAdsRules {
|
|
50
|
+
adPlacesRulesForAllDomains: Record<string, RawAdPlacesRule[]>;
|
|
51
|
+
providersRulesForAllDomains: Record<string, RawAdProvidersRule[]>;
|
|
52
|
+
providersSelectors: Record<string, (string | {
|
|
53
|
+
selector: string;
|
|
54
|
+
parentDepth: number;
|
|
55
|
+
})[]>;
|
|
56
|
+
providersToReplaceAtAllSites: string[];
|
|
57
|
+
permanentAdPlacesRulesForAllDomains: Record<string, RawPermanentAdPlacesRule[]>;
|
|
58
|
+
permanentNativeAdPlacesRulesForAllDomains: Record<string, RawPermanentAdPlacesRule[]>;
|
|
59
|
+
adsReplaceUrlsBlacklist: string[];
|
|
60
|
+
timestamp: number;
|
|
61
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"temple-wallet-api.js","sourceRoot":"","sources":["../../src/types/temple-wallet-api.ts"],"names":[],"mappings":""}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** From lodash */
|
|
2
|
+
type Truthy<T> = T extends null | undefined | void | false | '' | 0 | 0n ? never : T;
|
|
3
|
+
export declare const isTruthy: <T>(value: T) => value is Truthy<T>;
|
|
4
|
+
export declare const delay: (ms?: number) => Promise<unknown>;
|
|
5
|
+
export type StringRecord<T = string> = Record<string, T>;
|
|
6
|
+
export {};
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAI,KAAQ,EAAsB,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAE5E,MAAM,aAAa,GAAG,GAAG,CAAC;AAE1B,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,EAAE,GAAG,aAAa,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
import { BANNER_ADS_META, buildHypeLabNativeMeta } from 'src/ads-meta';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
SIBLING_REPLACEMENT_ATTRIBUTE_NAME,
|
|
4
|
+
TEMPLE_WALLET_AD_ATTRIBUTE_NAME,
|
|
5
|
+
TEMPLE_WALLET_NATIVE_AD_ATTRIBUTE_NAME
|
|
6
|
+
} from 'src/constants';
|
|
3
7
|
import { AdType } from 'src/types/ads-actions';
|
|
4
8
|
import { AdMetadata } from 'src/types/ads-meta';
|
|
5
9
|
|
|
6
|
-
export const
|
|
10
|
+
export const PX_VALUE_REGEX = /[\d.]+(px)?$/;
|
|
11
|
+
|
|
12
|
+
export const ourAdQuerySelector = `[${TEMPLE_WALLET_AD_ATTRIBUTE_NAME}]`;
|
|
13
|
+
export const ourBannerAdQuerySelector = `[${TEMPLE_WALLET_AD_ATTRIBUTE_NAME}]:not([${TEMPLE_WALLET_NATIVE_AD_ATTRIBUTE_NAME}])`;
|
|
14
|
+
export const ourNativeAdQuerySelector = `[${TEMPLE_WALLET_NATIVE_AD_ATTRIBUTE_NAME}]`;
|
|
7
15
|
|
|
8
16
|
export const elementIsOurAd = (element: Element) => Boolean(element.closest(ourAdQuerySelector));
|
|
9
17
|
|
|
@@ -21,7 +29,7 @@ export const getFinalSize = (element: Element) => {
|
|
|
21
29
|
const rawDimensionFromAttribute = element.getAttribute(dimension);
|
|
22
30
|
const rawDimension = rawDimensionFromAttribute || rawDimensionFromStyle;
|
|
23
31
|
|
|
24
|
-
if (
|
|
32
|
+
if (PX_VALUE_REGEX.test(rawDimension)) {
|
|
25
33
|
size[dimension] = Number(rawDimension.replace('px', ''));
|
|
26
34
|
}
|
|
27
35
|
if (dimension === 'width' && x < 0) {
|
|
@@ -17,7 +17,8 @@ import {
|
|
|
17
17
|
applyQuerySelector,
|
|
18
18
|
elementIsOurAd,
|
|
19
19
|
getParentOfDepth,
|
|
20
|
-
|
|
20
|
+
ourBannerAdQuerySelector,
|
|
21
|
+
ourNativeAdQuerySelector,
|
|
21
22
|
prevBannerSiblingIsReplacement
|
|
22
23
|
} from './helpers';
|
|
23
24
|
|
|
@@ -56,6 +57,7 @@ const processPermanentAdsParent = (
|
|
|
56
57
|
const {
|
|
57
58
|
shouldUseDivWrapper,
|
|
58
59
|
divWrapperStyle: originalDivWrapperStyle,
|
|
60
|
+
wrapperStyle: originalWrapperStyle,
|
|
59
61
|
elementStyle,
|
|
60
62
|
adSelector,
|
|
61
63
|
insertionIndex,
|
|
@@ -65,9 +67,16 @@ const processPermanentAdsParent = (
|
|
|
65
67
|
elementToMeasureSelector,
|
|
66
68
|
stylesOverrides,
|
|
67
69
|
shouldHideOriginal = false,
|
|
68
|
-
isNative
|
|
70
|
+
isNative,
|
|
71
|
+
urlRegexes,
|
|
72
|
+
parentSelector,
|
|
73
|
+
...restProps
|
|
69
74
|
} = rule;
|
|
70
|
-
const
|
|
75
|
+
const wrapperStyle = restProps.wrapperType
|
|
76
|
+
? originalWrapperStyle
|
|
77
|
+
: shouldUseDivWrapper
|
|
78
|
+
? originalDivWrapperStyle
|
|
79
|
+
: { display: 'contents' };
|
|
71
80
|
|
|
72
81
|
const {
|
|
73
82
|
isMultiple: shouldSearchForManyBannersInParent,
|
|
@@ -75,7 +84,11 @@ const processPermanentAdsParent = (
|
|
|
75
84
|
parentDepth: bannerParentDepth
|
|
76
85
|
} = adSelector;
|
|
77
86
|
|
|
78
|
-
const ourAds = applyQuerySelector(
|
|
87
|
+
const ourAds = applyQuerySelector(
|
|
88
|
+
isNative ? ourNativeAdQuerySelector : ourBannerAdQuerySelector,
|
|
89
|
+
true,
|
|
90
|
+
parent
|
|
91
|
+
).reduce<Element[]>((acc, element) => {
|
|
79
92
|
if (acc.some(prevElement => prevElement.contains(element) || element.contains(prevElement))) {
|
|
80
93
|
return acc;
|
|
81
94
|
}
|
|
@@ -107,9 +120,10 @@ const processPermanentAdsParent = (
|
|
|
107
120
|
const replaceActionBase: OmitAdInAction<ReplaceElementWithAdAction> = {
|
|
108
121
|
type: AdActionType.ReplaceElement,
|
|
109
122
|
element: banner,
|
|
110
|
-
|
|
123
|
+
wrapperStyle,
|
|
111
124
|
elementStyle,
|
|
112
|
-
stylesOverrides
|
|
125
|
+
stylesOverrides,
|
|
126
|
+
...restProps
|
|
113
127
|
};
|
|
114
128
|
const hideActionBase: HideElementAction = {
|
|
115
129
|
type: AdActionType.HideElement,
|
|
@@ -117,12 +131,13 @@ const processPermanentAdsParent = (
|
|
|
117
131
|
};
|
|
118
132
|
const insertActionBase: OmitAdInAction<SimpleInsertAdAction> = {
|
|
119
133
|
type: AdActionType.SimpleInsertAd,
|
|
120
|
-
|
|
134
|
+
wrapperStyle,
|
|
121
135
|
elementStyle,
|
|
122
136
|
parent: banner.parentElement!,
|
|
123
137
|
insertionIndex: Array.from(banner.parentElement!.children).indexOf(banner),
|
|
124
138
|
isSiblingReplacement: true,
|
|
125
|
-
stylesOverrides
|
|
139
|
+
stylesOverrides,
|
|
140
|
+
...restProps
|
|
126
141
|
};
|
|
127
142
|
|
|
128
143
|
let actionsToInsert: (InsertAdActionWithoutMeta | HideElementAction | RemoveElementAction)[] = [];
|
|
@@ -179,12 +194,13 @@ const processPermanentAdsParent = (
|
|
|
179
194
|
if (normalizedInsertionIndex !== -1) {
|
|
180
195
|
const actionBase: OmitAdInAction<SimpleInsertAdAction> = {
|
|
181
196
|
type: AdActionType.SimpleInsertAd,
|
|
182
|
-
|
|
197
|
+
wrapperStyle,
|
|
183
198
|
elementStyle,
|
|
184
199
|
parent: insertionParentElement,
|
|
185
200
|
insertionIndex: normalizedInsertionIndex,
|
|
186
201
|
isSiblingReplacement: false,
|
|
187
|
-
stylesOverrides
|
|
202
|
+
stylesOverrides,
|
|
203
|
+
...restProps
|
|
188
204
|
};
|
|
189
205
|
|
|
190
206
|
addActionsIfAdResolutionAvailable(
|
|
@@ -16,7 +16,8 @@ import {
|
|
|
16
16
|
prevBannerSiblingIsReplacement,
|
|
17
17
|
getFinalSize,
|
|
18
18
|
ourAdQuerySelector,
|
|
19
|
-
getParentOfDepth
|
|
19
|
+
getParentOfDepth,
|
|
20
|
+
PX_VALUE_REGEX
|
|
20
21
|
} from './helpers';
|
|
21
22
|
|
|
22
23
|
const styleToAdjustProps = [
|
|
@@ -69,8 +70,9 @@ export const processProvidersAds = async (
|
|
|
69
70
|
return action.element.parentElement?.contains(newBanner) || newBanner.contains(action.element);
|
|
70
71
|
});
|
|
71
72
|
const bannerIsHiddenByParent = parentStyles?.display === 'none' || parentStyles?.visibility === 'hidden';
|
|
73
|
+
const hasAnchorParent = parentElementIndex >= 0 && acc[parentElementIndex] instanceof HTMLAnchorElement;
|
|
72
74
|
|
|
73
|
-
if (bannerIsTouchedByOtherActions || width === 0 || height === 0 || bannerIsHiddenByParent) {
|
|
75
|
+
if (bannerIsTouchedByOtherActions || width === 0 || height === 0 || bannerIsHiddenByParent || hasAnchorParent) {
|
|
74
76
|
return acc;
|
|
75
77
|
}
|
|
76
78
|
|
|
@@ -90,10 +92,13 @@ export const processProvidersAds = async (
|
|
|
90
92
|
await delay(0);
|
|
91
93
|
|
|
92
94
|
const parent = banner.parentElement;
|
|
95
|
+
const { width: bannerStyleWidth, height: bannerStyleHeight } = window.getComputedStyle(banner);
|
|
93
96
|
const elementToMeasure =
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
+
PX_VALUE_REGEX.test(bannerStyleWidth) && PX_VALUE_REGEX.test(bannerStyleHeight)
|
|
98
|
+
? banner
|
|
99
|
+
: parent?.closest<HTMLElement>('div, article, aside, footer, header') ??
|
|
100
|
+
(parent?.tagName.toLowerCase() === 'body' ? undefined : parent) ??
|
|
101
|
+
banner;
|
|
97
102
|
|
|
98
103
|
if (
|
|
99
104
|
!elementIsOurAd(banner) &&
|
|
@@ -120,7 +125,7 @@ export const processProvidersAds = async (
|
|
|
120
125
|
|
|
121
126
|
const bannerStyle = window.getComputedStyle(banner as HTMLElement);
|
|
122
127
|
|
|
123
|
-
const
|
|
128
|
+
const wrapperStyle = {
|
|
124
129
|
...Object.fromEntries(styleToAdjustProps.map(propName => [propName, bannerStyle.getPropertyValue(propName)])),
|
|
125
130
|
...bannerStyleFromAttribute
|
|
126
131
|
};
|
|
@@ -130,7 +135,7 @@ export const processProvidersAds = async (
|
|
|
130
135
|
};
|
|
131
136
|
const insertAdAction: OmitAdInAction<SimpleInsertAdAction> = {
|
|
132
137
|
type: AdActionType.SimpleInsertAd,
|
|
133
|
-
|
|
138
|
+
wrapperStyle,
|
|
134
139
|
parent: banner.parentElement ?? document.body,
|
|
135
140
|
insertionIndex: Array.from(banner.parentElement?.children ?? []).indexOf(banner),
|
|
136
141
|
isSiblingReplacement: true
|
|
@@ -64,7 +64,7 @@ const processSelectedElement = (
|
|
|
64
64
|
|
|
65
65
|
const actionBaseCommonProps = {
|
|
66
66
|
shouldUseDivWrapper,
|
|
67
|
-
divWrapperStyle
|
|
67
|
+
wrapperStyle: divWrapperStyle
|
|
68
68
|
};
|
|
69
69
|
|
|
70
70
|
let actionsBases: (InsertAdActionWithoutMeta | HideElementAction | RemoveElementAction)[];
|
|
@@ -108,7 +108,7 @@ const processSelectedElement = (
|
|
|
108
108
|
insertionIndex: 0,
|
|
109
109
|
stylesOverrides,
|
|
110
110
|
isSiblingReplacement: true,
|
|
111
|
-
|
|
111
|
+
wrapperStyle: { display: 'contents' }
|
|
112
112
|
};
|
|
113
113
|
|
|
114
114
|
actionsBases = Array.from(banner.children)
|
|
@@ -122,7 +122,7 @@ const processSelectedElement = (
|
|
|
122
122
|
type: AdActionType.ReplaceAllChildren,
|
|
123
123
|
parent: banner,
|
|
124
124
|
stylesOverrides,
|
|
125
|
-
|
|
125
|
+
wrapperStyle: { display: 'contents' }
|
|
126
126
|
};
|
|
127
127
|
actionsBases = [replaceAllChildrenActionBase];
|
|
128
128
|
}
|
package/src/constants.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export const TEMPLE_WALLET_AD_ATTRIBUTE_NAME = 'twa';
|
|
2
|
+
export const TEMPLE_WALLET_NATIVE_AD_ATTRIBUTE_NAME = 'twa-native';
|
|
2
3
|
export const SIBLING_REPLACEMENT_ATTRIBUTE_NAME = 'twa-sibling-replacement';
|
|
3
4
|
export const AD_SEEN_THRESHOLD = 0.5;
|
|
4
5
|
export const AD_RENDER_START_MESSAGE_TYPE = 'adRenderStart';
|
|
5
6
|
export const AD_RESIZE_MESSAGE_TYPE = 'resize';
|
|
6
7
|
export const AD_READY_MESSAGE_TYPE = 'ready';
|
|
7
8
|
export const AD_ERROR_MESSAGE_TYPE = 'error';
|
|
9
|
+
export const AD_VARIANT_READY_TIMEOUT = 10_000;
|
|
@@ -9,7 +9,7 @@ export const makeHypelabAdView = (source: HypeLabAdSources, dimensions: AdDimens
|
|
|
9
9
|
|
|
10
10
|
const iframe = document.createElement('iframe');
|
|
11
11
|
iframe.src = getHypelabIframeUrl(source, origin, width, height, iframe.id);
|
|
12
|
-
iframe.style.width = `${width}px`;
|
|
12
|
+
iframe.style.width = source.native ? '100%' : `${width}px`;
|
|
13
13
|
iframe.style.height = `${height}px`;
|
|
14
14
|
iframe.style.border = 'none';
|
|
15
15
|
|
|
@@ -56,7 +56,11 @@ const getHypelabIframeUrl = (
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
const url = new URL(AdsConfiguration.HYPELAB_ADS_WINDOW_URL);
|
|
59
|
-
|
|
59
|
+
if (source.native) {
|
|
60
|
+
url.searchParams.set('vh', String(height ?? defaultHeight));
|
|
61
|
+
} else {
|
|
62
|
+
url.searchParams.set('w', String(width ?? defaultWidth));
|
|
63
|
+
}
|
|
60
64
|
url.searchParams.set('h', String(height ?? defaultHeight));
|
|
61
65
|
url.searchParams.set('p', placementSlug);
|
|
62
66
|
url.searchParams.set('o', encryptWithAES(origin));
|
|
@@ -15,8 +15,6 @@ const loadingAdsIds = new Set();
|
|
|
15
15
|
const loadedAdsIds = new Set();
|
|
16
16
|
const alreadySentAnalyticsAdsIds = new Set();
|
|
17
17
|
|
|
18
|
-
const IFRAME_READY_TIMEOUT = 30_000;
|
|
19
|
-
|
|
20
18
|
export const subscribeToAdsStackIframeLoadIfNecessary = async (element: HTMLIFrameElement) => {
|
|
21
19
|
const adId = element.id;
|
|
22
20
|
|
|
@@ -27,11 +25,6 @@ export const subscribeToAdsStackIframeLoadIfNecessary = async (element: HTMLIFra
|
|
|
27
25
|
loadingAdsIds.add(adId);
|
|
28
26
|
|
|
29
27
|
return new Promise<AdMetadata['source']['providerName']>((resolve, reject) => {
|
|
30
|
-
setTimeout(() => {
|
|
31
|
-
window.removeEventListener('message', messageListener);
|
|
32
|
-
reject(new Error(`Timeout exceeded for ${adId}`));
|
|
33
|
-
}, IFRAME_READY_TIMEOUT);
|
|
34
|
-
|
|
35
28
|
const messageListener = (event: MessageEvent<any>) => {
|
|
36
29
|
if (event.source !== element.contentWindow) return;
|
|
37
30
|
|
|
@@ -40,6 +33,9 @@ export const subscribeToAdsStackIframeLoadIfNecessary = async (element: HTMLIFra
|
|
|
40
33
|
|
|
41
34
|
if (data.id !== adId) return;
|
|
42
35
|
|
|
36
|
+
const horizontalBordersWidth = element.offsetWidth - element.clientWidth;
|
|
37
|
+
const verticalBordersWidth = element.offsetHeight - element.clientHeight;
|
|
38
|
+
|
|
43
39
|
switch (data.type) {
|
|
44
40
|
case AD_READY_MESSAGE_TYPE:
|
|
45
41
|
resolve(data.adMetadata.source.providerName);
|
|
@@ -53,14 +49,18 @@ export const subscribeToAdsStackIframeLoadIfNecessary = async (element: HTMLIFra
|
|
|
53
49
|
const { dimensions }: AdMetadata = data.adMetadata;
|
|
54
50
|
const { width, height } = dimensions;
|
|
55
51
|
if (width > 0 && height > 0) {
|
|
56
|
-
element.style.width
|
|
52
|
+
if (!element.style.width?.endsWith('%')) {
|
|
53
|
+
element.style.width = `${dimensions.width}px`;
|
|
54
|
+
}
|
|
57
55
|
element.style.height = `${dimensions.height}px`;
|
|
58
56
|
}
|
|
59
57
|
break;
|
|
60
58
|
case AD_RESIZE_MESSAGE_TYPE:
|
|
61
59
|
const { width: newWidth, height: newHeight } = data;
|
|
62
|
-
element.style.width
|
|
63
|
-
|
|
60
|
+
if (!element.style.width?.endsWith('%')) {
|
|
61
|
+
element.style.width = `${newWidth + horizontalBordersWidth}px`;
|
|
62
|
+
}
|
|
63
|
+
element.style.height = `${newHeight + verticalBordersWidth}px`;
|
|
64
64
|
}
|
|
65
65
|
} catch (error) {
|
|
66
66
|
console.error('Observing error:', error);
|
|
@@ -81,7 +81,11 @@ export const subscribeToAdsStackIframeLoadIfNecessary = async (element: HTMLIFra
|
|
|
81
81
|
observeIntersection(element, providerName);
|
|
82
82
|
}
|
|
83
83
|
})
|
|
84
|
-
.catch(
|
|
84
|
+
.catch(e => {
|
|
85
|
+
console.error(e);
|
|
86
|
+
|
|
87
|
+
throw e;
|
|
88
|
+
})
|
|
85
89
|
.finally(() => void loadingAdsIds.delete(adId));
|
|
86
90
|
};
|
|
87
91
|
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { nanoid } from 'nanoid';
|
|
2
2
|
|
|
3
|
+
import { PX_VALUE_REGEX } from 'src/ads-actions/helpers';
|
|
3
4
|
import { AdsConfiguration } from 'src/ads-configuration';
|
|
4
5
|
import { BANNER_ADS_META } from 'src/ads-meta';
|
|
5
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
SIBLING_REPLACEMENT_ATTRIBUTE_NAME,
|
|
8
|
+
TEMPLE_WALLET_AD_ATTRIBUTE_NAME,
|
|
9
|
+
TEMPLE_WALLET_NATIVE_AD_ATTRIBUTE_NAME
|
|
10
|
+
} from 'src/constants';
|
|
6
11
|
import { AdActionType, InsertAdAction } from 'src/types/ads-actions';
|
|
7
12
|
import { AdDimensions } from 'src/types/ads-meta';
|
|
8
13
|
|
|
@@ -13,7 +18,7 @@ const adjustToAd = (wrapperElement: HTMLDivElement, adDimensions: AdDimensions)
|
|
|
13
18
|
const predefinedStylesKeyToOverride = ['width', 'height'] as const;
|
|
14
19
|
predefinedStylesKeyToOverride.forEach(dimensionName => {
|
|
15
20
|
const predefinedStyleValue = wrapperElement.style[dimensionName] ?? '';
|
|
16
|
-
if (
|
|
21
|
+
if (PX_VALUE_REGEX.test(predefinedStyleValue)) {
|
|
17
22
|
const predefinedSize = parseInt(predefinedStyleValue, 10);
|
|
18
23
|
if (predefinedSize < adDimensions[dimensionName]) {
|
|
19
24
|
wrapperElement.style.removeProperty(dimensionName);
|
|
@@ -22,8 +27,20 @@ const adjustToAd = (wrapperElement: HTMLDivElement, adDimensions: AdDimensions)
|
|
|
22
27
|
});
|
|
23
28
|
};
|
|
24
29
|
|
|
25
|
-
const
|
|
26
|
-
|
|
30
|
+
const sumPxValues = (values: string[]) =>
|
|
31
|
+
values.reduce((acc, value) => {
|
|
32
|
+
const parsedValue = parseInt(value, 10);
|
|
33
|
+
|
|
34
|
+
return isNaN(parsedValue) && PX_VALUE_REGEX.test(value) ? acc : acc + parsedValue;
|
|
35
|
+
}, 0);
|
|
36
|
+
|
|
37
|
+
const processInsertAdActionOnce = async (
|
|
38
|
+
action: InsertAdAction,
|
|
39
|
+
wrapperElement: HTMLDivElement,
|
|
40
|
+
insertionPoint: HTMLDivElement | HTMLTableCellElement,
|
|
41
|
+
onAdsStackError: (error: Error) => void
|
|
42
|
+
) => {
|
|
43
|
+
const { elementStyle = {}, stylesOverrides = [], adsMetadata, wrapperType } = action;
|
|
27
44
|
|
|
28
45
|
stylesOverrides.sort((a, b) => a.parentDepth - b.parentDepth);
|
|
29
46
|
|
|
@@ -36,7 +53,7 @@ const processInsertAdActionOnce = async (action: InsertAdAction, wrapperElement:
|
|
|
36
53
|
const firstAdMetadataOrId = action.adsMetadata[0];
|
|
37
54
|
const { dimensions } =
|
|
38
55
|
typeof firstAdMetadataOrId === 'number' ? BANNER_ADS_META[firstAdMetadataOrId] : firstAdMetadataOrId;
|
|
39
|
-
adElement.style.width = `${dimensions.width}px`;
|
|
56
|
+
adElement.style.width = wrapperType === 'tbody' ? '100%' : `${dimensions.width}px`;
|
|
40
57
|
adElement.style.height = `${dimensions.height}px`;
|
|
41
58
|
adElement.style.border = 'none';
|
|
42
59
|
for (const styleProp in elementStyle) {
|
|
@@ -45,7 +62,7 @@ const processInsertAdActionOnce = async (action: InsertAdAction, wrapperElement:
|
|
|
45
62
|
adElement.setAttribute(TEMPLE_WALLET_AD_ATTRIBUTE_NAME, 'true');
|
|
46
63
|
|
|
47
64
|
adjustToAd(wrapperElement, dimensions);
|
|
48
|
-
|
|
65
|
+
insertionPoint.appendChild(adElement);
|
|
49
66
|
|
|
50
67
|
switch (action.type) {
|
|
51
68
|
case AdActionType.ReplaceAllChildren:
|
|
@@ -66,7 +83,36 @@ const processInsertAdActionOnce = async (action: InsertAdAction, wrapperElement:
|
|
|
66
83
|
break;
|
|
67
84
|
}
|
|
68
85
|
|
|
69
|
-
|
|
86
|
+
if (wrapperType !== 'tbody') {
|
|
87
|
+
const {
|
|
88
|
+
borderLeftWidth: adElementBLWidth,
|
|
89
|
+
borderRightWidth: adElementBRWidth,
|
|
90
|
+
borderTopWidth: adElementBTWidth,
|
|
91
|
+
borderBottomWidth: adElementBBWidth
|
|
92
|
+
} = window.getComputedStyle(adElement);
|
|
93
|
+
const {
|
|
94
|
+
borderLeftWidth: wrapperElementBLWidth,
|
|
95
|
+
borderRightWidth: wrapperElementBRWidth,
|
|
96
|
+
borderTopWidth: wrapperElementBTWidth,
|
|
97
|
+
borderBottomWidth: wrapperElementBBWidth
|
|
98
|
+
} = window.getComputedStyle(wrapperElement);
|
|
99
|
+
const horizontalBordersWidth = sumPxValues([
|
|
100
|
+
adElementBLWidth,
|
|
101
|
+
adElementBRWidth,
|
|
102
|
+
wrapperElementBLWidth,
|
|
103
|
+
wrapperElementBRWidth
|
|
104
|
+
]);
|
|
105
|
+
const verticalBordersWidth = sumPxValues([
|
|
106
|
+
adElementBTWidth,
|
|
107
|
+
adElementBBWidth,
|
|
108
|
+
wrapperElementBTWidth,
|
|
109
|
+
wrapperElementBBWidth
|
|
110
|
+
]);
|
|
111
|
+
adElement.style.width = `${dimensions.width - horizontalBordersWidth}px`;
|
|
112
|
+
adElement.style.height = `${dimensions.height - verticalBordersWidth}px`;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
subscribeToAdsStackIframeLoadIfNecessary(adElement).catch(onAdsStackError);
|
|
70
116
|
|
|
71
117
|
let currentParentDepth = 0;
|
|
72
118
|
stylesOverrides.forEach(({ parentDepth, style }) => {
|
|
@@ -81,20 +127,51 @@ const processInsertAdActionOnce = async (action: InsertAdAction, wrapperElement:
|
|
|
81
127
|
};
|
|
82
128
|
|
|
83
129
|
export const processInsertAdAction = async (action: InsertAdAction) => {
|
|
84
|
-
const {
|
|
85
|
-
|
|
86
|
-
|
|
130
|
+
const { wrapperStyle = {}, adsMetadata, wrapperType = 'div', colsAfter = 0, colsBefore = 0, colspan = 1 } = action;
|
|
131
|
+
const isNativeAd = adsMetadata.every(adMetadata => typeof adMetadata === 'object');
|
|
132
|
+
|
|
133
|
+
let wrapperElement: HTMLDivElement | HTMLTableSectionElement;
|
|
134
|
+
let insertionPoint: HTMLDivElement | HTMLTableCellElement;
|
|
135
|
+
if (wrapperType === 'div') {
|
|
136
|
+
wrapperElement = document.createElement('div');
|
|
137
|
+
insertionPoint = wrapperElement;
|
|
138
|
+
} else {
|
|
139
|
+
wrapperElement = document.createElement('tbody');
|
|
140
|
+
const row = document.createElement('tr');
|
|
141
|
+
wrapperElement.appendChild(row);
|
|
142
|
+
for (let i = 0; i < colsBefore; i++) {
|
|
143
|
+
row.appendChild(document.createElement('td'));
|
|
144
|
+
}
|
|
145
|
+
const cell = document.createElement('td');
|
|
146
|
+
cell.colSpan = colspan;
|
|
147
|
+
row.appendChild(cell);
|
|
148
|
+
insertionPoint = cell;
|
|
149
|
+
for (let i = 0; i < colsAfter; i++) {
|
|
150
|
+
row.appendChild(document.createElement('td'));
|
|
151
|
+
}
|
|
152
|
+
}
|
|
87
153
|
wrapperElement.setAttribute(TEMPLE_WALLET_AD_ATTRIBUTE_NAME, 'true');
|
|
154
|
+
if (isNativeAd) {
|
|
155
|
+
wrapperElement.setAttribute(TEMPLE_WALLET_NATIVE_AD_ATTRIBUTE_NAME, 'true');
|
|
156
|
+
}
|
|
88
157
|
|
|
89
|
-
overrideElementStyles(wrapperElement,
|
|
90
|
-
|
|
91
|
-
await processInsertAdActionOnce(action, wrapperElement).catch(error => {
|
|
92
|
-
console.error('Inserting an ad attempt error:', error);
|
|
158
|
+
overrideElementStyles(wrapperElement, wrapperStyle);
|
|
93
159
|
|
|
160
|
+
const hideFailedAd = () => {
|
|
94
161
|
const emptyAdElement = document.createElement('div');
|
|
95
162
|
emptyAdElement.setAttribute(TEMPLE_WALLET_AD_ATTRIBUTE_NAME, 'true');
|
|
163
|
+
if (isNativeAd) {
|
|
164
|
+
emptyAdElement.setAttribute(TEMPLE_WALLET_NATIVE_AD_ATTRIBUTE_NAME, 'true');
|
|
165
|
+
}
|
|
96
166
|
emptyAdElement.style.display = 'none';
|
|
97
167
|
wrapperElement.replaceWith(emptyAdElement);
|
|
168
|
+
};
|
|
169
|
+
await processInsertAdActionOnce(action, wrapperElement, insertionPoint, error => {
|
|
170
|
+
console.error('Failed to render ads', error);
|
|
171
|
+
hideFailedAd();
|
|
172
|
+
}).catch(error => {
|
|
173
|
+
console.error('Inserting an ad attempt error:', error);
|
|
174
|
+
hideFailedAd();
|
|
98
175
|
|
|
99
176
|
throw error;
|
|
100
177
|
});
|