0.1.6
- cleanup per network folder for playworks converter - loosen mraid checker file and folder scanning
This commit is contained in:
BIN
dist/hpl-toolbox-0.1.6.exe
vendored
BIN
dist/hpl-toolbox-0.1.6.exe
vendored
Binary file not shown.
BIN
dist/hpl-toolbox-0.1.6.vsix
vendored
BIN
dist/hpl-toolbox-0.1.6.vsix
vendored
Binary file not shown.
@@ -80,15 +80,21 @@ export function openMraidChecker(_context: vscode.ExtensionContext) {
|
|||||||
let targets: string[] = [];
|
let targets: string[] = [];
|
||||||
let baseDir = '';
|
let baseDir = '';
|
||||||
let skipped = 0;
|
let skipped = 0;
|
||||||
|
let skippedReason = '';
|
||||||
|
let noTargetsError = 'No HTML files were found.';
|
||||||
if (files && files.length) {
|
if (files && files.length) {
|
||||||
const existing = files.filter(f => fs.existsSync(f));
|
const existing = files.filter(f => fs.existsSync(f));
|
||||||
targets = existing.filter(isSupportedMraidBuild);
|
targets = existing;
|
||||||
skipped = existing.length - targets.length;
|
skipped = files.length - existing.length;
|
||||||
|
skippedReason = 'missing file(s).';
|
||||||
|
noTargetsError = 'No selected HTML files were found.';
|
||||||
baseDir = targets.length ? commonBaseDir(targets) : '';
|
baseDir = targets.length ? commonBaseDir(targets) : '';
|
||||||
} else if (folder && fs.existsSync(folder)) {
|
} else if (folder && fs.existsSync(folder)) {
|
||||||
const allHtmlFiles = await collectHtmlFiles(folder);
|
const allHtmlFiles = await collectHtmlFiles(folder);
|
||||||
targets = allHtmlFiles.filter(isSupportedMraidBuild);
|
targets = allHtmlFiles.filter(isInSupportedMraidFolderPath);
|
||||||
skipped = allHtmlFiles.length - targets.length;
|
skipped = allHtmlFiles.length - targets.length;
|
||||||
|
skippedReason = 'HTML file(s) outside AppLovin/ironSource/Unity folders.';
|
||||||
|
noTargetsError = 'No AppLovin, ironSource, or Unity folder HTML files were found.';
|
||||||
baseDir = folder;
|
baseDir = folder;
|
||||||
} else {
|
} else {
|
||||||
panel.webview.postMessage({ type: 'results', results: [], error: 'Pick a folder or files first' });
|
panel.webview.postMessage({ type: 'results', results: [], error: 'Pick a folder or files first' });
|
||||||
@@ -100,7 +106,8 @@ export function openMraidChecker(_context: vscode.ExtensionContext) {
|
|||||||
type: 'results',
|
type: 'results',
|
||||||
results: [],
|
results: [],
|
||||||
skipped,
|
skipped,
|
||||||
error: 'No AppLovin, ironSource, or Unity HTML builds were found.',
|
skippedReason,
|
||||||
|
error: noTargetsError,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -116,7 +123,7 @@ export function openMraidChecker(_context: vscode.ExtensionContext) {
|
|||||||
// Skip unreadable files, matching the scanner pattern used elsewhere.
|
// Skip unreadable files, matching the scanner pattern used elsewhere.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panel.webview.postMessage({ type: 'results', results, skipped });
|
panel.webview.postMessage({ type: 'results', results, skipped, skippedReason });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -193,9 +200,24 @@ function collectMraidCallLines(html: string): Map<string, number> {
|
|||||||
return calls;
|
return calls;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isSupportedMraidBuild(filePath: string): boolean {
|
function isInSupportedMraidFolderPath(filePath: string): boolean {
|
||||||
const normalized = filePath.toLowerCase().replace(/\\/g, '/');
|
const folderParts = path.dirname(filePath)
|
||||||
return /(^|[\/._ -])(al|applovin|app-lovin|is|iron.?source|un|unity|unityads|unity-ads)([\/._ -]|$)/i.test(normalized);
|
.split(/[\\/]+/)
|
||||||
|
.map(part => part.toLowerCase());
|
||||||
|
return folderParts.some(part => [
|
||||||
|
'al',
|
||||||
|
'applovin',
|
||||||
|
'app-lovin',
|
||||||
|
'is',
|
||||||
|
'ironsource',
|
||||||
|
'iron-source',
|
||||||
|
'iron_source',
|
||||||
|
'un',
|
||||||
|
'unity',
|
||||||
|
'unityads',
|
||||||
|
'unity-ads',
|
||||||
|
'unity_ads',
|
||||||
|
].includes(part));
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasMraidReference(ctx: ScanContext): boolean {
|
function hasMraidReference(ctx: ScanContext): boolean {
|
||||||
@@ -387,7 +409,7 @@ function getHtml(): string {
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h2>MRAID Checker</h2>
|
<h2>MRAID Checker</h2>
|
||||||
<div class="docs">Static checks for AppLovin, ironSource, and Unity HTML builds based on MRAID 3.0 requirements and best practices from mraidDocuments/.</div>
|
<div class="docs">Static checks for AppLovin, ironSource, and Unity folder HTML builds based on MRAID 3.0 requirements and best practices from mraidDocuments/.</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<input id="folder" type="text" placeholder="Folder to scan recursively..." />
|
<input id="folder" type="text" placeholder="Folder to scan recursively..." />
|
||||||
<button id="pick">Browse Folder...</button>
|
<button id="pick">Browse Folder...</button>
|
||||||
@@ -457,8 +479,9 @@ function getHtml(): string {
|
|||||||
const requirements = msg.results.reduce((n, r) => n + r.issues.filter(i => i.severity === 'requirement').length, 0);
|
const requirements = msg.results.reduce((n, r) => n + r.issues.filter(i => i.severity === 'requirement').length, 0);
|
||||||
const bestPractices = msg.results.reduce((n, r) => n + r.issues.filter(i => i.severity === 'best-practice').length, 0);
|
const bestPractices = msg.results.reduce((n, r) => n + r.issues.filter(i => i.severity === 'best-practice').length, 0);
|
||||||
const skipped = Number(msg.skipped || 0);
|
const skipped = Number(msg.skipped || 0);
|
||||||
const skippedText = skipped ? ' Skipped ' + skipped + ' non-target HTML file(s).' : '';
|
const skippedReason = msg.skippedReason || 'file(s).';
|
||||||
statusEl.innerHTML = '<div class="summary">Scanned ' + total + ' AppLovin/ironSource/Unity HTML file(s). ' + withIssues + ' file(s) need review. ' + requirements + ' requirement issue(s), ' + bestPractices + ' best-practice warning(s).' + skippedText + '</div>';
|
const skippedText = skipped ? ' Skipped ' + skipped + ' ' + skippedReason : '';
|
||||||
|
statusEl.innerHTML = '<div class="summary">Scanned ' + total + ' HTML file(s). ' + withIssues + ' file(s) need review. ' + requirements + ' requirement issue(s), ' + bestPractices + ' best-practice warning(s).' + skippedText + '</div>';
|
||||||
resultsEl.innerHTML = '';
|
resultsEl.innerHTML = '';
|
||||||
for (const r of msg.results) {
|
for (const r of msg.results) {
|
||||||
const requirementsForFile = r.issues.filter(i => i.severity === 'requirement').length;
|
const requirementsForFile = r.issues.filter(i => i.severity === 'requirement').length;
|
||||||
|
|||||||
@@ -94,6 +94,17 @@ export function openPlayworksConverter(_context: vscode.ExtensionContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ZIPPED_NETWORKS = new Set(['gg', 'vu', 'mtg']);
|
const ZIPPED_NETWORKS = new Set(['gg', 'vu', 'mtg']);
|
||||||
|
const NETWORK_OUTPUT_FOLDERS: Record<string, string> = {
|
||||||
|
al: 'Applovin',
|
||||||
|
is: 'Ironsource',
|
||||||
|
un: 'Unity',
|
||||||
|
fb: 'Facebook',
|
||||||
|
gg: 'GoogleAds',
|
||||||
|
mo: 'Moloco',
|
||||||
|
vu: 'Vungle',
|
||||||
|
mtg: 'Mintegral',
|
||||||
|
tt: 'TikTok',
|
||||||
|
};
|
||||||
|
|
||||||
function sourceBaseName(sourcePath: string): string {
|
function sourceBaseName(sourcePath: string): string {
|
||||||
return path.basename(sourcePath, path.extname(sourcePath))
|
return path.basename(sourcePath, path.extname(sourcePath))
|
||||||
@@ -105,10 +116,12 @@ async function convertNetwork(html: string, opts: ConvertOptions, network: strin
|
|||||||
const needsZip = ZIPPED_NETWORKS.has(network);
|
const needsZip = ZIPPED_NETWORKS.has(network);
|
||||||
const baseName = sourceBaseName(opts.sourcePath);
|
const baseName = sourceBaseName(opts.sourcePath);
|
||||||
const htmlFileName = `${baseName}_${network}.html`;
|
const htmlFileName = `${baseName}_${network}.html`;
|
||||||
|
const outputDir = path.join(opts.outputDir, NETWORK_OUTPUT_FOLDERS[network] ?? network);
|
||||||
|
fs.mkdirSync(outputDir, { recursive: true });
|
||||||
|
|
||||||
if (needsZip) {
|
if (needsZip) {
|
||||||
const tmpPath = path.join(opts.outputDir, `_tmp_${Date.now()}_${network}.html`);
|
const tmpPath = path.join(outputDir, `_tmp_${Date.now()}_${network}.html`);
|
||||||
const zipPath = path.join(opts.outputDir, `${baseName}_${network}.zip`);
|
const zipPath = path.join(outputDir, `${baseName}_${network}.zip`);
|
||||||
fs.writeFileSync(tmpPath, transformed, 'utf8');
|
fs.writeFileSync(tmpPath, transformed, 'utf8');
|
||||||
try {
|
try {
|
||||||
await createZip(tmpPath, 'index.html', zipPath);
|
await createZip(tmpPath, 'index.html', zipPath);
|
||||||
@@ -118,7 +131,7 @@ async function convertNetwork(html: string, opts: ConvertOptions, network: strin
|
|||||||
return zipPath;
|
return zipPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
const outPath = path.join(opts.outputDir, htmlFileName);
|
const outPath = path.join(outputDir, htmlFileName);
|
||||||
fs.writeFileSync(outPath, transformed, 'utf8');
|
fs.writeFileSync(outPath, transformed, 'utf8');
|
||||||
return outPath;
|
return outPath;
|
||||||
}
|
}
|
||||||
@@ -431,6 +444,11 @@ function getHtml(): string {
|
|||||||
if (outputDir) vscode.postMessage({ type: 'openOutput', dir: outputDir });
|
if (outputDir) vscode.postMessage({ type: 'openOutput', dir: outputDir });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function outputDisplayName(file) {
|
||||||
|
const parts = file.split(/[\\\\/]/).filter(Boolean);
|
||||||
|
return parts.slice(-2).join('/');
|
||||||
|
}
|
||||||
|
|
||||||
document.getElementById('convert').addEventListener('click', () => {
|
document.getElementById('convert').addEventListener('click', () => {
|
||||||
const networks = [...document.querySelectorAll('.net-cb')]
|
const networks = [...document.querySelectorAll('.net-cb')]
|
||||||
.filter(c => c.checked).map(c => c.dataset.tag);
|
.filter(c => c.checked).map(c => c.dataset.tag);
|
||||||
@@ -484,7 +502,7 @@ function getHtml(): string {
|
|||||||
const detail = document.createElement('span');
|
const detail = document.createElement('span');
|
||||||
if (r.ok) {
|
if (r.ok) {
|
||||||
detail.className = 'res-file';
|
detail.className = 'res-file';
|
||||||
detail.textContent = r.file.split(/[\\\\/]/).pop();
|
detail.textContent = outputDisplayName(r.file);
|
||||||
} else {
|
} else {
|
||||||
detail.className = 'res-err';
|
detail.className = 'res-err';
|
||||||
detail.textContent = r.error || 'Unknown error';
|
detail.textContent = r.error || 'Unknown error';
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ type mraidContext struct {
|
|||||||
func MraidPage(w http.ResponseWriter, r *http.Request) {
|
func MraidPage(w http.ResponseWriter, r *http.Request) {
|
||||||
body := `
|
body := `
|
||||||
<h2>MRAID Checker</h2>
|
<h2>MRAID Checker</h2>
|
||||||
<p class="hint">Static checks for AppLovin, ironSource, and Unity HTML builds based on MRAID 3.0 requirements and best practices from mraidDocuments/.</p>
|
<p class="hint">Static checks for AppLovin, ironSource, and Unity folder HTML builds based on MRAID 3.0 requirements and best practices from mraidDocuments/.</p>
|
||||||
<div style="display:flex;gap:8px;align-items:center;margin-bottom:8px;">
|
<div style="display:flex;gap:8px;align-items:center;margin-bottom:8px;">
|
||||||
<input id="folder" type="text" placeholder="Folder to scan recursively..." style="flex:1;" />
|
<input id="folder" type="text" placeholder="Folder to scan recursively..." style="flex:1;" />
|
||||||
<button id="pickFolder">Browse Folder...</button>
|
<button id="pickFolder">Browse Folder...</button>
|
||||||
@@ -112,8 +112,9 @@ document.getElementById('scan').addEventListener('click', async () => {
|
|||||||
const requirements = j.results.reduce((n, r) => n + r.issues.filter(i => i.severity === 'requirement').length, 0);
|
const requirements = j.results.reduce((n, r) => n + r.issues.filter(i => i.severity === 'requirement').length, 0);
|
||||||
const bestPractices = j.results.reduce((n, r) => n + r.issues.filter(i => i.severity === 'best-practice').length, 0);
|
const bestPractices = j.results.reduce((n, r) => n + r.issues.filter(i => i.severity === 'best-practice').length, 0);
|
||||||
const skipped = Number(j.skipped || 0);
|
const skipped = Number(j.skipped || 0);
|
||||||
const skippedText = skipped ? ' Skipped ' + skipped + ' non-target HTML file(s).' : '';
|
const skippedReason = j.skippedReason || 'file(s).';
|
||||||
statusEl.innerHTML = '<div class="summary">Scanned ' + total + ' AppLovin/ironSource/Unity HTML file(s). ' + withIssues + ' file(s) need review. ' + requirements + ' requirement issue(s), ' + bestPractices + ' best-practice warning(s).' + skippedText + '</div>';
|
const skippedText = skipped ? ' Skipped ' + skipped + ' ' + skippedReason : '';
|
||||||
|
statusEl.innerHTML = '<div class="summary">Scanned ' + total + ' HTML file(s). ' + withIssues + ' file(s) need review. ' + requirements + ' requirement issue(s), ' + bestPractices + ' best-practice warning(s).' + skippedText + '</div>';
|
||||||
resultsEl.innerHTML = '';
|
resultsEl.innerHTML = '';
|
||||||
for (const rr of j.results) {
|
for (const rr of j.results) {
|
||||||
const reqCount = rr.issues.filter(i => i.severity === 'requirement').length;
|
const reqCount = rr.issues.filter(i => i.severity === 'requirement').length;
|
||||||
@@ -164,6 +165,8 @@ func MraidScan(w http.ResponseWriter, r *http.Request) {
|
|||||||
var targets []string
|
var targets []string
|
||||||
var baseDir string
|
var baseDir string
|
||||||
skipped := 0
|
skipped := 0
|
||||||
|
skippedReason := ""
|
||||||
|
noTargetsError := "No HTML files were found."
|
||||||
if len(req.Files) > 0 {
|
if len(req.Files) > 0 {
|
||||||
var existing []string
|
var existing []string
|
||||||
for _, f := range req.Files {
|
for _, f := range req.Files {
|
||||||
@@ -171,30 +174,30 @@ func MraidScan(w http.ResponseWriter, r *http.Request) {
|
|||||||
existing = append(existing, f)
|
existing = append(existing, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, f := range existing {
|
targets = existing
|
||||||
if isSupportedMraidBuild(f) {
|
skipped = len(req.Files) - len(existing)
|
||||||
targets = append(targets, f)
|
skippedReason = "missing file(s)."
|
||||||
}
|
noTargetsError = "No selected HTML files were found."
|
||||||
}
|
|
||||||
skipped = len(existing) - len(targets)
|
|
||||||
if len(targets) > 0 {
|
if len(targets) > 0 {
|
||||||
baseDir = commonBaseDir(targets)
|
baseDir = commonBaseDir(targets)
|
||||||
}
|
}
|
||||||
} else if req.Folder != "" && fileExists(req.Folder) {
|
} else if req.Folder != "" && fileExists(req.Folder) {
|
||||||
all := collectHTMLFiles(req.Folder)
|
all := collectHTMLFiles(req.Folder)
|
||||||
for _, f := range all {
|
for _, f := range all {
|
||||||
if isSupportedMraidBuild(f) {
|
if isInSupportedMraidFolderPath(f) {
|
||||||
targets = append(targets, f)
|
targets = append(targets, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
skipped = len(all) - len(targets)
|
skipped = len(all) - len(targets)
|
||||||
|
skippedReason = "HTML file(s) outside AppLovin/ironSource/Unity folders."
|
||||||
|
noTargetsError = "No AppLovin, ironSource, or Unity folder HTML files were found."
|
||||||
baseDir = req.Folder
|
baseDir = req.Folder
|
||||||
} else {
|
} else {
|
||||||
writeJSON(w, map[string]any{"results": []mraidResult{}, "error": "Pick a folder or files first"})
|
writeJSON(w, map[string]any{"results": []mraidResult{}, "error": "Pick a folder or files first"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(targets) == 0 {
|
if len(targets) == 0 {
|
||||||
writeJSON(w, map[string]any{"results": []mraidResult{}, "skipped": skipped, "error": "No AppLovin, ironSource, or Unity HTML builds were found."})
|
writeJSON(w, map[string]any{"results": []mraidResult{}, "skipped": skipped, "skippedReason": skippedReason, "error": noTargetsError})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,13 +218,12 @@ func MraidScan(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
results = append(results, mraidResult{File: display, OK: len(issues) == 0, Issues: issues})
|
results = append(results, mraidResult{File: display, OK: len(issues) == 0, Issues: issues})
|
||||||
}
|
}
|
||||||
writeJSON(w, map[string]any{"results": results, "skipped": skipped})
|
writeJSON(w, map[string]any{"results": results, "skipped": skipped, "skippedReason": skippedReason})
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
mraidScriptRx = regexp.MustCompile(`(?is)<script\b[^>]*>(.*?)</script>`)
|
mraidScriptRx = regexp.MustCompile(`(?is)<script\b[^>]*>(.*?)</script>`)
|
||||||
mraidCallRx = regexp.MustCompile(`(?i)\bmraid\s*\.\s*([a-zA-Z_$][\w$]*)\s*\(`)
|
mraidCallRx = regexp.MustCompile(`(?i)\bmraid\s*\.\s*([a-zA-Z_$][\w$]*)\s*\(`)
|
||||||
mraidBuildNameRx = regexp.MustCompile(`(?i)(^|[/._ -])(al|applovin|app-lovin|is|iron.?source|un|unity|unityads|unity-ads)([/._ -]|$)`)
|
|
||||||
mraidReferenceRx = regexp.MustCompile(`(?i)\bmraid\b`)
|
mraidReferenceRx = regexp.MustCompile(`(?i)\bmraid\b`)
|
||||||
mraidWindowOpenRx = regexp.MustCompile(`(?i)\bwindow\s*\.\s*open\s*\(`)
|
mraidWindowOpenRx = regexp.MustCompile(`(?i)\bwindow\s*\.\s*open\s*\(`)
|
||||||
mraidLocationNavRx = regexp.MustCompile(`(?i)\blocation\s*\.\s*(href|assign|replace)\b`)
|
mraidLocationNavRx = regexp.MustCompile(`(?i)\blocation\s*\.\s*(href|assign|replace)\b`)
|
||||||
@@ -232,9 +234,30 @@ var (
|
|||||||
|
|
||||||
const mraidReference = "MRAID 3.0 specification and MRAID 3.0 Best Practices Guide in mraidDocuments/"
|
const mraidReference = "MRAID 3.0 specification and MRAID 3.0 Best Practices Guide in mraidDocuments/"
|
||||||
|
|
||||||
func isSupportedMraidBuild(filePath string) bool {
|
func isInSupportedMraidFolderPath(filePath string) bool {
|
||||||
normalized := strings.ReplaceAll(strings.ToLower(filePath), `\`, `/`)
|
supported := map[string]bool{
|
||||||
return mraidBuildNameRx.MatchString(normalized)
|
"al": true,
|
||||||
|
"applovin": true,
|
||||||
|
"app-lovin": true,
|
||||||
|
"is": true,
|
||||||
|
"ironsource": true,
|
||||||
|
"iron-source": true,
|
||||||
|
"iron_source": true,
|
||||||
|
"un": true,
|
||||||
|
"unity": true,
|
||||||
|
"unityads": true,
|
||||||
|
"unity-ads": true,
|
||||||
|
"unity_ads": true,
|
||||||
|
}
|
||||||
|
parts := strings.FieldsFunc(strings.ToLower(filepath.Dir(filePath)), func(r rune) bool {
|
||||||
|
return r == '/' || r == '\\'
|
||||||
|
})
|
||||||
|
for _, part := range parts {
|
||||||
|
if supported[part] {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkMraid(htmlSrc string) []mraidIssue {
|
func checkMraid(htmlSrc string) []mraidIssue {
|
||||||
|
|||||||
@@ -139,6 +139,11 @@ openOutBtn.addEventListener('click', () => {
|
|||||||
if (outputDir) fetch('/api/open', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ url: outputDir }) });
|
if (outputDir) fetch('/api/open', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ url: outputDir }) });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function outputDisplayName(file) {
|
||||||
|
const parts = file.split(/[\\\\/]/).filter(Boolean);
|
||||||
|
return parts.slice(-2).join('/');
|
||||||
|
}
|
||||||
|
|
||||||
document.getElementById('convert').addEventListener('click', async () => {
|
document.getElementById('convert').addEventListener('click', async () => {
|
||||||
const networks = [...document.querySelectorAll('.net-cb')].filter(c => c.checked).map(c => c.dataset.tag);
|
const networks = [...document.querySelectorAll('.net-cb')].filter(c => c.checked).map(c => c.dataset.tag);
|
||||||
statusEl.textContent = 'Converting...';
|
statusEl.textContent = 'Converting...';
|
||||||
@@ -170,7 +175,7 @@ document.getElementById('convert').addEventListener('click', async () => {
|
|||||||
const detail = document.createElement('span');
|
const detail = document.createElement('span');
|
||||||
if (r.ok) {
|
if (r.ok) {
|
||||||
detail.className = 'res-file';
|
detail.className = 'res-file';
|
||||||
detail.textContent = r.file.split(/[\\\\/]/).pop();
|
detail.textContent = outputDisplayName(r.file);
|
||||||
} else {
|
} else {
|
||||||
detail.className = 'res-err';
|
detail.className = 'res-err';
|
||||||
detail.textContent = r.error || 'Unknown error';
|
detail.textContent = r.error || 'Unknown error';
|
||||||
@@ -242,22 +247,51 @@ func convertPlayworksNetwork(htmlSrc string, opts playworksConvertOptions, netwo
|
|||||||
transformed := transformPlayworksHTML(htmlSrc, network)
|
transformed := transformPlayworksHTML(htmlSrc, network)
|
||||||
baseName := playworksSourceBaseName(opts.SourcePath)
|
baseName := playworksSourceBaseName(opts.SourcePath)
|
||||||
htmlFileName := fmt.Sprintf("%s_%s.html", baseName, network)
|
htmlFileName := fmt.Sprintf("%s_%s.html", baseName, network)
|
||||||
|
outputDir := filepath.Join(opts.OutputDir, playworksNetworkOutputFolder(network))
|
||||||
|
if err := os.MkdirAll(outputDir, 0755); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
if playworksNeedsZip(network) {
|
if playworksNeedsZip(network) {
|
||||||
zipPath := filepath.Join(opts.OutputDir, fmt.Sprintf("%s_%s.zip", baseName, network))
|
zipPath := filepath.Join(outputDir, fmt.Sprintf("%s_%s.zip", baseName, network))
|
||||||
if err := createSingleFileZip([]byte(transformed), "index.html", zipPath); err != nil {
|
if err := createSingleFileZip([]byte(transformed), "index.html", zipPath); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return zipPath, nil
|
return zipPath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
outPath := filepath.Join(opts.OutputDir, htmlFileName)
|
outPath := filepath.Join(outputDir, htmlFileName)
|
||||||
if err := os.WriteFile(outPath, []byte(transformed), 0644); err != nil {
|
if err := os.WriteFile(outPath, []byte(transformed), 0644); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return outPath, nil
|
return outPath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func playworksNetworkOutputFolder(network string) string {
|
||||||
|
switch network {
|
||||||
|
case "al":
|
||||||
|
return "Applovin"
|
||||||
|
case "is":
|
||||||
|
return "Ironsource"
|
||||||
|
case "un":
|
||||||
|
return "Unity"
|
||||||
|
case "fb":
|
||||||
|
return "Facebook"
|
||||||
|
case "gg":
|
||||||
|
return "GoogleAds"
|
||||||
|
case "mo":
|
||||||
|
return "Moloco"
|
||||||
|
case "vu":
|
||||||
|
return "Vungle"
|
||||||
|
case "mtg":
|
||||||
|
return "Mintegral"
|
||||||
|
case "tt":
|
||||||
|
return "TikTok"
|
||||||
|
default:
|
||||||
|
return network
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func playworksNeedsZip(network string) bool {
|
func playworksNeedsZip(network string) bool {
|
||||||
return network == "gg" || network == "vu" || network == "mtg"
|
return network == "gg" || network == "vu" || network == "mtg"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user