update playworks checker
This commit is contained in:
@@ -95,8 +95,8 @@ export function openPlayworksConverter(_context: vscode.ExtensionContext) {
|
||||
}
|
||||
|
||||
const ZIPPED_NETWORKS = new Set(['gg', 'vu', 'mtg']);
|
||||
const SUPPORTED_NETWORKS = new Set(['al', 'is', 'fb', 'gg', 'mo', 'vu', 'mtg', 'tt']);
|
||||
const MRAID_NETWORKS = new Set(['al', 'is']);
|
||||
const SUPPORTED_NETWORKS = new Set(['al', 'is', 'fb', 'gg', 'mo', 'vu', 'mtg', 'un', 'tt']);
|
||||
const MRAID_NETWORKS = new Set(['al', 'is', 'un']);
|
||||
const NETWORK_OUTPUT_FOLDERS: Record<string, string> = {
|
||||
al: 'Applovin',
|
||||
is: 'Ironsource',
|
||||
@@ -105,6 +105,7 @@ const NETWORK_OUTPUT_FOLDERS: Record<string, string> = {
|
||||
mo: 'Moloco',
|
||||
vu: 'Vungle',
|
||||
mtg: 'Mintegral',
|
||||
un: 'Unity',
|
||||
tt: 'TikTok',
|
||||
};
|
||||
|
||||
@@ -149,15 +150,15 @@ async function convertNetwork(html: string, opts: ConvertOptions, network: strin
|
||||
}
|
||||
|
||||
function transformHtml(html: string, network: string): string {
|
||||
let result = html;
|
||||
let result = sanitizePlayworksHtml(html);
|
||||
|
||||
// Inject into </head>: lifecycle stubs only (must register luna:build listener
|
||||
// BEFORE the Playworks bundle so our handler fires first), then any network SDK script.
|
||||
// Console restore stays at end-of-body — it must run AFTER the bundle overrides console.
|
||||
result = removeNetworkSdkScripts(result, network);
|
||||
result = removeNetworkSdkScripts(result);
|
||||
let headInject = buildLifecycleScript();
|
||||
if (MRAID_NETWORKS.has(network)) {
|
||||
headInject += '<script src="mraid.js"></script>';
|
||||
headInject += '<script src="mraid.js"></script>' + buildMraidComplianceScript();
|
||||
} else if (network === 'gg') {
|
||||
headInject += '<script src="exitapi.js"></script>';
|
||||
}
|
||||
@@ -175,16 +176,60 @@ function transformHtml(html: string, network: string): string {
|
||||
// Replace the CTA script
|
||||
result = replaceCTAScript(result, network);
|
||||
|
||||
return finalizeNetworkHtml(result, network);
|
||||
}
|
||||
|
||||
function sanitizePlayworksHtml(html: string): string {
|
||||
let result = cleanupPlayworksHtml(html);
|
||||
return removeNetworkSdkScripts(result);
|
||||
}
|
||||
|
||||
function cleanupPlayworksHtml(html: string): string {
|
||||
let result = html;
|
||||
result = trimAfterFirstHtmlClose(result);
|
||||
result = result.replace(/<script\b[^>]*>[\s\S]*?insertYourRemoteDebuggingTokenHere[\s\S]*?<\/script>\s*/gi, '');
|
||||
result = result.replace(/https:\/\/mrdoob\.github\.io\/stats\.js\/build\/stats\.min\.js/gi, 'data:text/javascript,');
|
||||
result = result.replace(/\s+crossorigin(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+))?/gi, '');
|
||||
result = result.replace(/\s+type\s*=\s*["']module["']/gi, '');
|
||||
result = result.replace(/\bconsole\.error\s*\(/g, 'console.warn(');
|
||||
return result;
|
||||
}
|
||||
|
||||
function removeNetworkSdkScripts(html: string, network: string): string {
|
||||
function trimAfterFirstHtmlClose(html: string): string {
|
||||
const idx = html.search(/<\/html\s*>/i);
|
||||
if (idx === -1) return html;
|
||||
const close = html.match(/<\/html\s*>/i);
|
||||
return close ? html.slice(0, idx + close[0].length) : html;
|
||||
}
|
||||
|
||||
function finalizeNetworkHtml(html: string, network: string): string {
|
||||
let result = cleanupPlayworksHtml(html);
|
||||
result = dedupeScriptSrc(result, 'mraid.js', MRAID_NETWORKS.has(network));
|
||||
result = dedupeScriptSrc(result, 'exitapi.js', network === 'gg');
|
||||
return result;
|
||||
}
|
||||
|
||||
function removeNetworkSdkScripts(html: string): string {
|
||||
let result = html;
|
||||
if (MRAID_NETWORKS.has(network)) {
|
||||
result = result.replace(/<script\b[^>]*\bsrc\s*=\s*["']mraid\.js["'][^>]*>\s*<\/script>\s*/gi, '');
|
||||
for (const src of ['mraid.js', 'exitapi.js']) {
|
||||
const escaped = src.replace('.', '\\.');
|
||||
result = result.replace(new RegExp(`<script\\b[^>]*\\bsrc\\s*=\\s*["']${escaped}["'][^>]*>\\s*<\\/script>\\s*`, 'gi'), '');
|
||||
}
|
||||
if (network === 'gg') {
|
||||
result = result.replace(/<script\b[^>]*\bsrc\s*=\s*["']exitapi\.js["'][^>]*>\s*<\/script>\s*/gi, '');
|
||||
return result;
|
||||
}
|
||||
|
||||
function dedupeScriptSrc(html: string, src: string, shouldExist: boolean): string {
|
||||
const escaped = src.replace('.', '\\.');
|
||||
let seen = false;
|
||||
let result = html.replace(new RegExp(`<script\\b[^>]*\\bsrc\\s*=\\s*["']${escaped}["'][^>]*>\\s*<\\/script>\\s*`, 'gi'), (match) => {
|
||||
if (shouldExist && !seen) {
|
||||
seen = true;
|
||||
return `<script src="${src}"></script>`;
|
||||
}
|
||||
return '';
|
||||
});
|
||||
if (shouldExist && !seen) {
|
||||
result = injectBeforeHeadClose(result, `<script src="${src}"></script>`);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -273,6 +318,28 @@ function buildLifecycleScript(): string {
|
||||
].join('');
|
||||
}
|
||||
|
||||
function buildMraidComplianceScript(): string {
|
||||
return [
|
||||
'<script>(function(){',
|
||||
'var m=null,scene=null,viewable=true,exposed=true,volume=null;',
|
||||
'function get(){return window.mraid||m;}',
|
||||
'function emit(name,detail){try{window.dispatchEvent(new CustomEvent(name,{detail:detail}));}catch(e){}}',
|
||||
'function apply(){emit("hpl:mraid:visibility",{viewable:viewable,exposed:exposed,hidden:!viewable||!exposed});if(scene&&scene.sound&&typeof scene.sound.setMute==="function")scene.sound.setMute(!viewable||!exposed);}',
|
||||
'function onViewable(v){viewable=!!v;apply();}',
|
||||
'function onExposure(p){if(typeof p==="number")exposed=p>0;apply();}',
|
||||
'function onVolume(v){if(typeof v==="number"){volume=v/100;emit("hpl:mraid:volume",volume);if(scene&&scene.sound&&typeof scene.sound.setVolume==="function")scene.sound.setVolume(volume);}}',
|
||||
'function add(name,fn){var x=get();try{if(x&&typeof x.addEventListener==="function")x.addEventListener(name,fn);}catch(e){}}',
|
||||
'function unload(){try{if(typeof mraid!=="undefined"&&typeof mraid.unload==="function")mraid.unload();}catch(e){}}',
|
||||
'window.__hplMraidUnload=unload;',
|
||||
'function setup(){var x=get();if(!x||setup.done)return;setup.done=true;m=x;try{if(typeof mraid!=="undefined"&&typeof mraid.isViewable==="function")viewable=!!mraid.isViewable();else if(typeof x.isViewable==="function")viewable=!!x.isViewable();}catch(e){}try{if(typeof mraid!=="undefined"&&typeof mraid.addEventListener==="function"){mraid.addEventListener("error",function(message,action){console.warn("[MRAID error]",{message:message,action:action});});mraid.addEventListener("stateChange",function(state){console.log("[MRAID stateChange]",state);});mraid.addEventListener("exposureChange",onExposure);mraid.addEventListener("viewableChange",onViewable);mraid.addEventListener("audioVolumeChange",onVolume);apply();return;}}catch(e){}add("error",function(message,action){console.warn("[MRAID error]",{message:message,action:action});});add("stateChange",function(state){console.log("[MRAID stateChange]",state);});add("exposureChange",onExposure);add("viewableChange",onViewable);add("audioVolumeChange",onVolume);apply();}',
|
||||
'function ready(){var x=get();if(!x)return false;try{if(typeof mraid!=="undefined"&&typeof mraid.getState==="function"&&mraid.getState()==="loading"){mraid.addEventListener("ready",setup);return true;}if(typeof x.getState==="function"&&x.getState()==="loading"){add("ready",setup);return true;}}catch(e){}setup();return true;}',
|
||||
'window.__hplMraidBindScene=function(s){scene=s;apply();if(typeof volume==="number"&&scene&&scene.sound&&typeof scene.sound.setVolume==="function")scene.sound.setVolume(volume);};',
|
||||
'if(!ready()){var end=Date.now()+500;(function poll(){if(ready()||Date.now()>end)return;setTimeout(poll,50);})();}',
|
||||
'setTimeout(setup,2000);',
|
||||
'})();</script>',
|
||||
].join('');
|
||||
}
|
||||
|
||||
function buildCTAScript(network: string): string {
|
||||
const urlSetup = `n=n||window.$environment.packageConfig.iosLink,i=i||window.$environment.packageConfig.androidLink;var o=/iphone|ipad|ipod|macintosh/i.test(window.navigator.userAgent.toLowerCase())?n:i;`;
|
||||
// gameClose must fire before every redirect
|
||||
@@ -282,6 +349,7 @@ function buildCTAScript(network: string): string {
|
||||
switch (network) {
|
||||
case 'al':
|
||||
case 'is':
|
||||
case 'un':
|
||||
// MRAID — mraid.js injected in <head>
|
||||
ctaLogic = `${closeCall}if(typeof mraid!=="undefined"&&typeof mraid.open==="function"){var s=typeof mraid.getState==="function"?mraid.getState():"default";if(s!=="loading"){mraid.open(o);return;}}window.open(o,"_blank");`;
|
||||
break;
|
||||
@@ -353,6 +421,7 @@ function getHtml(): string {
|
||||
{ tag: 'mo', label: 'Moloco', note: 'HTML + FbPlayableAd CTA' },
|
||||
{ tag: 'vu', label: 'Vungle', note: 'ZIP + __VUNGLE__ flag' },
|
||||
{ tag: 'mtg', label: 'Mintegral', note: 'ZIP + onload="gameReady()"' },
|
||||
{ tag: 'un', label: 'Unity', note: 'HTML + mraid.js in head' },
|
||||
{ tag: 'tt', label: 'TikTok', note: 'HTML + __TIKTOK__ flag' },
|
||||
];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user