@cunpingtai/webad-react-ad-scripts 0.1.0 → 0.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/dist/index.js CHANGED
@@ -14528,6 +14528,73 @@ function date4(params) {
14528
14528
  // ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/external.js
14529
14529
  config(en_default());
14530
14530
 
14531
+ // ../shared-contract/src/adsterra.ts
14532
+ var PLACEMENT_NAME = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
14533
+ var CONTAINER_ID = /^[A-Za-z][A-Za-z0-9:_-]{0,127}$/;
14534
+ var ZONE_KEY = /^[A-Za-z0-9]{1,128}$/;
14535
+ var PARAM_KEY = /^[A-Za-z0-9_-]{1,64}$/;
14536
+ var MAX_URL_LENGTH = 2048;
14537
+ var AdsterraValueSchema = external_exports.union([
14538
+ external_exports.string().max(256),
14539
+ external_exports.number().finite(),
14540
+ external_exports.boolean()
14541
+ ]);
14542
+ var AdsterraParamsSchema = external_exports.record(external_exports.string().regex(PARAM_KEY), AdsterraValueSchema).refine((params) => Object.keys(params).length <= 16, {
14543
+ message: "Adsterra params must contain at most 16 entries"
14544
+ });
14545
+ var ManagedAdsterraUrlSchema = external_exports.string().min(1).max(MAX_URL_LENGTH).refine(isSafeManagedUrl, { message: "Invalid managed Adsterra URL" });
14546
+ var AdsterraBannerPlacementSchema = external_exports.object({
14547
+ kind: external_exports.literal("banner"),
14548
+ scriptSrc: ManagedAdsterraUrlSchema,
14549
+ zoneKey: external_exports.string().regex(ZONE_KEY),
14550
+ width: external_exports.number().int().min(1).max(2048),
14551
+ height: external_exports.number().int().min(1).max(2048),
14552
+ params: AdsterraParamsSchema
14553
+ }).strict();
14554
+ var AdsterraNativePlacementSchema = external_exports.object({
14555
+ kind: external_exports.literal("native"),
14556
+ scriptSrc: ManagedAdsterraUrlSchema,
14557
+ containerId: external_exports.string().regex(CONTAINER_ID)
14558
+ }).strict();
14559
+ var AdsterraPlacementSchema = external_exports.discriminatedUnion("kind", [
14560
+ AdsterraBannerPlacementSchema,
14561
+ AdsterraNativePlacementSchema
14562
+ ]);
14563
+ var AdsterraPlacementsSchema = external_exports.record(
14564
+ external_exports.string().min(1).max(80).regex(PLACEMENT_NAME),
14565
+ AdsterraPlacementSchema
14566
+ ).refine((placements) => Object.keys(placements).length <= 64, {
14567
+ message: "A site may contain at most 64 Adsterra placements"
14568
+ });
14569
+ var ManagedScriptSchema = external_exports.object({ scriptSrc: ManagedAdsterraUrlSchema }).strict();
14570
+ var ManagedSmartlinkSchema = external_exports.object({ href: ManagedAdsterraUrlSchema }).strict();
14571
+ var SiteAdsterraConfigSchema = external_exports.object({
14572
+ placements: AdsterraPlacementsSchema,
14573
+ socialBar: ManagedScriptSchema.optional(),
14574
+ popunder: ManagedScriptSchema.optional(),
14575
+ smartlink: ManagedSmartlinkSchema.optional()
14576
+ }).strict();
14577
+ function isSafeManagedUrl(value) {
14578
+ if (/\s/.test(value) || value.includes("#") || hasExplicitPort(value)) {
14579
+ return false;
14580
+ }
14581
+ try {
14582
+ const url2 = new URL(value);
14583
+ return url2.protocol === "https:" && url2.username === "" && url2.password === "" && url2.port === "" && url2.hash === "";
14584
+ } catch {
14585
+ return false;
14586
+ }
14587
+ }
14588
+ function hasExplicitPort(value) {
14589
+ const schemeEnd = value.indexOf(":");
14590
+ if (schemeEnd < 0) return false;
14591
+ const remainder = value.slice(schemeEnd + 1).replace(/^[\\/]+/, "");
14592
+ const authorityEnd = remainder.search(/[\\/?#]/);
14593
+ const authority = authorityEnd < 0 ? remainder : remainder.slice(0, authorityEnd);
14594
+ const host = authority.slice(authority.lastIndexOf("@") + 1);
14595
+ return host.startsWith("[") ? host.includes("]:") : host.includes(":");
14596
+ }
14597
+
14531
14598
  // ../shared-contract/src/schemas.ts
14532
14599
  var ScriptDescriptorSchema = external_exports.object({
14533
14600
  id: external_exports.string().min(1).max(80),
@@ -14565,7 +14632,8 @@ var SiteConfigSchema = external_exports.object({
14565
14632
  enabled: external_exports.boolean(),
14566
14633
  mode: external_exports.union([external_exports.enum(AD_MODES), external_exports.literal("inherit")]),
14567
14634
  aliases: external_exports.array(external_exports.string()).max(32),
14568
- providers: ProviderOverridesSchema
14635
+ providers: ProviderOverridesSchema,
14636
+ adsterra: SiteAdsterraConfigSchema.optional()
14569
14637
  }).strict();
14570
14638
  var SnapshotSchema = external_exports.object({
14571
14639
  schemaVersion: external_exports.literal(1),
@@ -14584,7 +14652,8 @@ var PublicConfigSchema = external_exports.object({
14584
14652
  mode: external_exports.enum(AD_MODES),
14585
14653
  allowedScriptHosts: external_exports.array(external_exports.string().min(1).max(253)).max(64),
14586
14654
  scripts: external_exports.array(ScriptDescriptorSchema).max(32),
14587
- ttlSeconds: external_exports.number().int().min(0).max(300)
14655
+ ttlSeconds: external_exports.number().int().min(0).max(300),
14656
+ adsterra: SiteAdsterraConfigSchema.optional()
14588
14657
  }).strict();
14589
14658
 
14590
14659
  // ../shared-contract/src/hostname.ts
@@ -14775,10 +14844,10 @@ function requestConfig(endpoint, host, timeoutMs) {
14775
14844
 
14776
14845
  // src/validation.ts
14777
14846
  var SLOT_ID = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
14778
- var CONTAINER_ID = /^[A-Za-z][A-Za-z0-9:_-]{0,127}$/;
14779
- var ZONE_KEY = /^[A-Za-z0-9]{1,128}$/;
14780
- var PARAM_KEY = /^[A-Za-z0-9_-]{1,64}$/;
14781
- var MAX_URL_LENGTH = 2048;
14847
+ var CONTAINER_ID2 = /^[A-Za-z][A-Za-z0-9:_-]{0,127}$/;
14848
+ var ZONE_KEY2 = /^[A-Za-z0-9]{1,128}$/;
14849
+ var PARAM_KEY2 = /^[A-Za-z0-9_-]{1,64}$/;
14850
+ var MAX_URL_LENGTH2 = 2048;
14782
14851
  function validatePageKey(value) {
14783
14852
  if (typeof value !== "string" || value.length < 1 || value.length > 2048) {
14784
14853
  throw new Error("invalid pageKey");
@@ -14791,13 +14860,13 @@ function validateSlotId(value) {
14791
14860
  }
14792
14861
  return value;
14793
14862
  }
14794
- function validateScriptUrl(value, allowedHosts) {
14863
+ function validateComponentScriptUrl(value) {
14795
14864
  const url2 = parseAbsoluteUrl(value, "scriptSrc");
14796
14865
  if (url2.protocol !== "https:") {
14797
14866
  throw new Error("scriptSrc must use HTTPS");
14798
14867
  }
14799
- if (!allowedHosts.some((host) => host.toLowerCase() === url2.hostname)) {
14800
- throw new Error("scriptSrc hostname is not allowed");
14868
+ if (/[\t\n\r]/.test(value) || value.includes("#") || hasExplicitPort2(value)) {
14869
+ throw new Error("invalid scriptSrc");
14801
14870
  }
14802
14871
  return url2.toString();
14803
14872
  }
@@ -14809,13 +14878,13 @@ function validateSmartlinkUrl(value) {
14809
14878
  return url2.toString();
14810
14879
  }
14811
14880
  function validateContainerId(value) {
14812
- if (typeof value !== "string" || !CONTAINER_ID.test(value)) {
14881
+ if (typeof value !== "string" || !CONTAINER_ID2.test(value)) {
14813
14882
  throw new Error("invalid containerId");
14814
14883
  }
14815
14884
  return value;
14816
14885
  }
14817
14886
  function validateZoneKey(value) {
14818
- if (typeof value !== "string" || !ZONE_KEY.test(value)) {
14887
+ if (typeof value !== "string" || !ZONE_KEY2.test(value)) {
14819
14888
  throw new Error("invalid zoneKey");
14820
14889
  }
14821
14890
  return value;
@@ -14838,7 +14907,7 @@ function validateParams(params) {
14838
14907
  throw new Error("invalid params");
14839
14908
  }
14840
14909
  for (const [key, value] of entries) {
14841
- if (!PARAM_KEY.test(key)) {
14910
+ if (!PARAM_KEY2.test(key)) {
14842
14911
  throw new Error("invalid params");
14843
14912
  }
14844
14913
  if (typeof value === "string") {
@@ -14860,7 +14929,7 @@ function validateParams(params) {
14860
14929
  return { ...params };
14861
14930
  }
14862
14931
  function parseAbsoluteUrl(value, name) {
14863
- if (typeof value !== "string" || value.length < 1 || value.length > MAX_URL_LENGTH) {
14932
+ if (typeof value !== "string" || value.length < 1 || value.length > MAX_URL_LENGTH2) {
14864
14933
  throw new Error(`invalid ${name}`);
14865
14934
  }
14866
14935
  let url2;
@@ -14874,6 +14943,21 @@ function parseAbsoluteUrl(value, name) {
14874
14943
  }
14875
14944
  return url2;
14876
14945
  }
14946
+ function hasExplicitPort2(value) {
14947
+ const source = value.trim();
14948
+ const schemeEnd = source.indexOf(":");
14949
+ if (schemeEnd < 0) {
14950
+ return false;
14951
+ }
14952
+ const remainder = source.slice(schemeEnd + 1).replace(/^[\\/]+/, "");
14953
+ const authorityEnd = remainder.search(/[\\/?#]/);
14954
+ const authority = authorityEnd < 0 ? remainder : remainder.slice(0, authorityEnd);
14955
+ const host = authority.slice(authority.lastIndexOf("@") + 1);
14956
+ if (host.startsWith("[")) {
14957
+ return host.includes("]:");
14958
+ }
14959
+ return host.includes(":");
14960
+ }
14877
14961
  function validDimension(value) {
14878
14962
  return Number.isSafeInteger(value) && value >= 1 && value <= 2048;
14879
14963
  }
@@ -15051,12 +15135,7 @@ function isFormatAllowed(mode, format) {
15051
15135
  // src/AdsterraBanner.tsx
15052
15136
  import { jsx as jsx2 } from "react/jsx-runtime";
15053
15137
  function AdsterraBanner({
15054
- slotId,
15055
- scriptSrc,
15056
- zoneKey,
15057
- width,
15058
- height,
15059
- params,
15138
+ placement,
15060
15139
  className,
15061
15140
  style
15062
15141
  }) {
@@ -15065,14 +15144,17 @@ function AdsterraBanner({
15065
15144
  let validated;
15066
15145
  if (context !== null && isFormatAllowed(context.plan.mode, "banner")) {
15067
15146
  try {
15068
- validateSlotId(slotId);
15069
- const dimensions = validateDimensions(width, height);
15070
- validated = {
15071
- src: validateScriptUrl(scriptSrc, context.plan.allowedScriptHosts),
15072
- zoneKey: validateZoneKey(zoneKey),
15073
- ...dimensions,
15074
- params: validateParams(params)
15075
- };
15147
+ validateSlotId(placement);
15148
+ const managed = context.plan.adsterra?.placements[placement];
15149
+ if (managed?.kind === "banner") {
15150
+ const dimensions = validateDimensions(managed.width, managed.height);
15151
+ validated = {
15152
+ src: validateComponentScriptUrl(managed.scriptSrc),
15153
+ zoneKey: validateZoneKey(managed.zoneKey),
15154
+ ...dimensions,
15155
+ params: validateParams(managed.params)
15156
+ };
15157
+ }
15076
15158
  } catch {
15077
15159
  validated = void 0;
15078
15160
  }
@@ -15082,7 +15164,12 @@ function AdsterraBanner({
15082
15164
  if (context === null || validated === void 0 || container === null) {
15083
15165
  return;
15084
15166
  }
15085
- if (!claimPageSlot(document, context.providerId, context.pageViewId, slotId)) {
15167
+ if (!claimPageSlot(
15168
+ document,
15169
+ context.providerId,
15170
+ context.pageViewId,
15171
+ placement
15172
+ )) {
15086
15173
  return;
15087
15174
  }
15088
15175
  void enqueueBanner(document, async () => {
@@ -15103,7 +15190,7 @@ function AdsterraBanner({
15103
15190
  await appendBannerScript(
15104
15191
  container,
15105
15192
  validated.src,
15106
- slotId,
15193
+ placement,
15107
15194
  context.nonce
15108
15195
  );
15109
15196
  } finally {
@@ -15114,7 +15201,7 @@ function AdsterraBanner({
15114
15201
  }
15115
15202
  }
15116
15203
  }).catch(() => void 0);
15117
- }, [context, slotId, validated]);
15204
+ }, [context, placement, validated]);
15118
15205
  if (validated === void 0) {
15119
15206
  return null;
15120
15207
  }
@@ -15122,7 +15209,7 @@ function AdsterraBanner({
15122
15209
  "div",
15123
15210
  {
15124
15211
  ref: containerRef,
15125
- "data-webad-banner-slot": slotId,
15212
+ "data-webad-banner-slot": placement,
15126
15213
  className,
15127
15214
  style: { ...style, width: validated.width, minHeight: validated.height }
15128
15215
  }
@@ -15152,9 +15239,7 @@ function appendBannerScript(container, src, slotId, nonce) {
15152
15239
  import { useEffect as useEffect3, useRef as useRef3 } from "react";
15153
15240
  import { jsx as jsx3 } from "react/jsx-runtime";
15154
15241
  function AdsterraNativeBanner({
15155
- slotId,
15156
- scriptSrc,
15157
- containerId,
15242
+ placement,
15158
15243
  className,
15159
15244
  style
15160
15245
  }) {
@@ -15164,12 +15249,12 @@ function AdsterraNativeBanner({
15164
15249
  let validatedContainerId = null;
15165
15250
  if (context !== null && isFormatAllowed(context.plan.mode, "native-banner")) {
15166
15251
  try {
15167
- validateSlotId(slotId);
15168
- validatedContainerId = validateContainerId(containerId);
15169
- validatedSrc = validateScriptUrl(
15170
- scriptSrc,
15171
- context.plan.allowedScriptHosts
15172
- );
15252
+ validateSlotId(placement);
15253
+ const managed = context.plan.adsterra?.placements[placement];
15254
+ if (managed?.kind === "native") {
15255
+ validatedContainerId = validateContainerId(managed.containerId);
15256
+ validatedSrc = validateComponentScriptUrl(managed.scriptSrc);
15257
+ }
15173
15258
  } catch {
15174
15259
  validatedSrc = null;
15175
15260
  validatedContainerId = null;
@@ -15180,19 +15265,24 @@ function AdsterraNativeBanner({
15180
15265
  if (context === null || validatedSrc === null || validatedContainerId === null || container === null || document.getElementById(validatedContainerId) !== container) {
15181
15266
  return;
15182
15267
  }
15183
- if (!claimPageSlot(document, context.providerId, context.pageViewId, slotId)) {
15268
+ if (!claimPageSlot(
15269
+ document,
15270
+ context.providerId,
15271
+ context.pageViewId,
15272
+ placement
15273
+ )) {
15184
15274
  return;
15185
15275
  }
15186
15276
  const script = document.createElement("script");
15187
15277
  script.src = validatedSrc;
15188
15278
  script.async = true;
15189
15279
  script.dataset.cfasync = "false";
15190
- script.dataset.webadSlotId = slotId;
15280
+ script.dataset.webadSlotId = placement;
15191
15281
  if (context.nonce !== void 0) {
15192
15282
  script.nonce = context.nonce;
15193
15283
  }
15194
15284
  container.append(script);
15195
- }, [context, slotId, validatedContainerId, validatedSrc]);
15285
+ }, [context, placement, validatedContainerId, validatedSrc]);
15196
15286
  if (validatedSrc === null || validatedContainerId === null) {
15197
15287
  return null;
15198
15288
  }
@@ -15210,7 +15300,6 @@ function AdsterraNativeBanner({
15210
15300
  // src/AdsterraSmartlink.tsx
15211
15301
  import { jsx as jsx4 } from "react/jsx-runtime";
15212
15302
  function AdsterraSmartlink({
15213
- href,
15214
15303
  children,
15215
15304
  target = "_blank",
15216
15305
  className
@@ -15221,6 +15310,8 @@ function AdsterraSmartlink({
15221
15310
  }
15222
15311
  let validatedHref;
15223
15312
  try {
15313
+ const href = context.plan.adsterra?.smartlink?.href;
15314
+ if (href === void 0) return null;
15224
15315
  validatedHref = validateSmartlinkUrl(href);
15225
15316
  } catch {
15226
15317
  return null;
@@ -15240,25 +15331,24 @@ function AdsterraSmartlink({
15240
15331
  // src/page-scripts.tsx
15241
15332
  import { useEffect as useEffect4 } from "react";
15242
15333
  import { jsx as jsx5 } from "react/jsx-runtime";
15243
- function AdsterraSocialBar(props) {
15244
- return /* @__PURE__ */ jsx5(PageScript, { ...props, format: "social-bar", target: "body" });
15334
+ function AdsterraSocialBar(_props) {
15335
+ return /* @__PURE__ */ jsx5(PageScript, { format: "social-bar", target: "body" });
15245
15336
  }
15246
- function AdsterraPopunder(props) {
15247
- return /* @__PURE__ */ jsx5(PageScript, { ...props, format: "popunder", target: "head" });
15337
+ function AdsterraPopunder(_props) {
15338
+ return /* @__PURE__ */ jsx5(PageScript, { format: "popunder", target: "head" });
15248
15339
  }
15249
- function PageScript({ format, slotId, scriptSrc, target }) {
15340
+ function PageScript({ format, target }) {
15250
15341
  const context = useAdsContext();
15342
+ const slotId = format === "social-bar" ? "global-social-bar" : "global-popunder";
15251
15343
  useEffect4(() => {
15252
15344
  if (context === null || !isFormatAllowed(context.plan.mode, format)) {
15253
15345
  return;
15254
15346
  }
15255
15347
  let validatedSrc;
15256
15348
  try {
15257
- validateSlotId(slotId);
15258
- validatedSrc = validateScriptUrl(
15259
- scriptSrc,
15260
- context.plan.allowedScriptHosts
15261
- );
15349
+ const managed = format === "social-bar" ? context.plan.adsterra?.socialBar : context.plan.adsterra?.popunder;
15350
+ if (managed === void 0) return;
15351
+ validatedSrc = validateComponentScriptUrl(managed.scriptSrc);
15262
15352
  } catch {
15263
15353
  return;
15264
15354
  }
@@ -15274,7 +15364,7 @@ function PageScript({ format, slotId, scriptSrc, target }) {
15274
15364
  script.nonce = context.nonce;
15275
15365
  }
15276
15366
  document[target].append(script);
15277
- }, [context, format, scriptSrc, slotId, target]);
15367
+ }, [context, format, slotId, target]);
15278
15368
  return null;
15279
15369
  }
15280
15370
  export {