@playcraft/build 0.0.2
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/README.md +96 -0
- package/dist/base-builder.d.ts +66 -0
- package/dist/base-builder.js +415 -0
- package/dist/converter.d.ts +35 -0
- package/dist/converter.js +148 -0
- package/dist/generators/config-generator.d.ts +7 -0
- package/dist/generators/config-generator.js +122 -0
- package/dist/generators/settings-generator.d.ts +14 -0
- package/dist/generators/settings-generator.js +100 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +14 -0
- package/dist/loaders/playcanvas-loader.d.ts +10 -0
- package/dist/loaders/playcanvas-loader.js +18 -0
- package/dist/loaders/playcraft-loader.d.ts +10 -0
- package/dist/loaders/playcraft-loader.js +51 -0
- package/dist/platforms/applovin.d.ts +10 -0
- package/dist/platforms/applovin.js +67 -0
- package/dist/platforms/base.d.ts +29 -0
- package/dist/platforms/base.js +11 -0
- package/dist/platforms/bigo.d.ts +15 -0
- package/dist/platforms/bigo.js +77 -0
- package/dist/platforms/facebook.d.ts +9 -0
- package/dist/platforms/facebook.js +37 -0
- package/dist/platforms/google.d.ts +10 -0
- package/dist/platforms/google.js +53 -0
- package/dist/platforms/index.d.ts +14 -0
- package/dist/platforms/index.js +47 -0
- package/dist/platforms/ironsource.d.ts +10 -0
- package/dist/platforms/ironsource.js +71 -0
- package/dist/platforms/liftoff.d.ts +10 -0
- package/dist/platforms/liftoff.js +56 -0
- package/dist/platforms/moloco.d.ts +10 -0
- package/dist/platforms/moloco.js +53 -0
- package/dist/platforms/snapchat.d.ts +10 -0
- package/dist/platforms/snapchat.js +59 -0
- package/dist/platforms/tiktok.d.ts +15 -0
- package/dist/platforms/tiktok.js +65 -0
- package/dist/platforms/unity.d.ts +10 -0
- package/dist/platforms/unity.js +69 -0
- package/dist/playable-builder.d.ts +97 -0
- package/dist/playable-builder.js +590 -0
- package/dist/types.d.ts +90 -0
- package/dist/types.js +1 -0
- package/dist/vite/config-builder.d.ts +15 -0
- package/dist/vite/config-builder.js +212 -0
- package/dist/vite/platform-configs.d.ts +38 -0
- package/dist/vite/platform-configs.js +257 -0
- package/dist/vite/plugin-model-compression.d.ts +11 -0
- package/dist/vite/plugin-model-compression.js +63 -0
- package/dist/vite/plugin-platform.d.ts +17 -0
- package/dist/vite/plugin-platform.js +241 -0
- package/dist/vite/plugin-playcanvas.d.ts +18 -0
- package/dist/vite/plugin-playcanvas.js +711 -0
- package/dist/vite/plugin-source-builder.d.ts +15 -0
- package/dist/vite/plugin-source-builder.js +344 -0
- package/dist/vite-builder.d.ts +51 -0
- package/dist/vite-builder.js +122 -0
- package/package.json +51 -0
- package/templates/__loading__.js +100 -0
- package/templates/__modules__.js +47 -0
- package/templates/__settings__.template.js +20 -0
- package/templates/__start__.js +332 -0
- package/templates/index.html +18 -0
- package/templates/logo.png +0 -0
- package/templates/manifest.json +1 -0
- package/templates/patches/cannon.min.js +28 -0
- package/templates/patches/lz4.js +10 -0
- package/templates/patches/one-page-http-get.js +20 -0
- package/templates/patches/one-page-inline-game-scripts.js +20 -0
- package/templates/patches/one-page-mraid-resize-canvas.js +46 -0
- package/templates/patches/p2.min.js +27 -0
- package/templates/patches/playcraft-no-xhr.js +52 -0
- package/templates/playcanvas-stable.min.js +16363 -0
- package/templates/styles.css +43 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { PlatformAdapter } from './base.js';
|
|
2
|
+
export class BigoAdapter extends PlatformAdapter {
|
|
3
|
+
getName() {
|
|
4
|
+
return 'BIGO Ads';
|
|
5
|
+
}
|
|
6
|
+
getSizeLimit() {
|
|
7
|
+
// BIGO Ads: 5MB
|
|
8
|
+
return 5 * 1024 * 1024;
|
|
9
|
+
}
|
|
10
|
+
getDefaultFormat() {
|
|
11
|
+
return 'zip';
|
|
12
|
+
}
|
|
13
|
+
modifyHTML(html, assets) {
|
|
14
|
+
// BIGO Ads 需要 BIGO JS-SDK
|
|
15
|
+
const bigoScript = `
|
|
16
|
+
<script src="https://static-web.likeevideo.com/oss/material-ad/playable-ad-demo/bgy-mraid-sdk.js"></script>
|
|
17
|
+
<script>
|
|
18
|
+
// BIGO JS-SDK 桥接(如果 SDK 加载失败)
|
|
19
|
+
window.BGY_MRAID = window.BGY_MRAID || {
|
|
20
|
+
open: function(url) {
|
|
21
|
+
console.log('BIGO CTA: opening store');
|
|
22
|
+
window.open(url);
|
|
23
|
+
},
|
|
24
|
+
gameReady: function() {
|
|
25
|
+
console.log('BIGO: game ready');
|
|
26
|
+
},
|
|
27
|
+
gameEnd: function() {
|
|
28
|
+
console.log('BIGO: game end');
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
</script>
|
|
32
|
+
<!--
|
|
33
|
+
注意:
|
|
34
|
+
- BIGO Ads 要求 ZIP 格式,含 config.json
|
|
35
|
+
- config.json 需包含 orientation 字段:0=横或竖/1=仅竖/2=仅横
|
|
36
|
+
- 接入 BIGO JS-SDK
|
|
37
|
+
- CTA 使用 window.BGY_MRAID.open()
|
|
38
|
+
- 游戏结束调用 window.BGY_MRAID.gameEnd()
|
|
39
|
+
- 可选调用 gameReady()
|
|
40
|
+
- 素材不得为 mraid.js 格式
|
|
41
|
+
-->
|
|
42
|
+
`;
|
|
43
|
+
// 在 </head> 之前插入
|
|
44
|
+
return html.replace('</head>', `${bigoScript}</head>`);
|
|
45
|
+
}
|
|
46
|
+
getPlatformScript() {
|
|
47
|
+
return `
|
|
48
|
+
// BIGO Ads Playable
|
|
49
|
+
// 使用 BGY_MRAID SDK
|
|
50
|
+
|
|
51
|
+
if (typeof BGY_MRAID !== 'undefined') {
|
|
52
|
+
// 游戏准备就绪
|
|
53
|
+
BGY_MRAID.gameReady();
|
|
54
|
+
|
|
55
|
+
// CTA 跳转
|
|
56
|
+
// BGY_MRAID.open('https://play.google.com/store');
|
|
57
|
+
|
|
58
|
+
// 游戏结束
|
|
59
|
+
// BGY_MRAID.gameEnd();
|
|
60
|
+
}
|
|
61
|
+
`;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* 生成 config.json(BIGO 要求)
|
|
65
|
+
* @param orientation 0=横或竖, 1=仅竖屏, 2=仅横屏
|
|
66
|
+
*/
|
|
67
|
+
generateConfigJson(orientation = 0) {
|
|
68
|
+
return {
|
|
69
|
+
orientation: orientation,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
validateOptions() {
|
|
73
|
+
if (this.options.format && this.options.format !== 'zip') {
|
|
74
|
+
console.warn('警告: BIGO Ads 要求 ZIP 格式');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { PlatformAdapter } from './base.js';
|
|
2
|
+
import type { AssetInfo } from '../types.js';
|
|
3
|
+
export declare class FacebookAdapter extends PlatformAdapter {
|
|
4
|
+
getName(): string;
|
|
5
|
+
getSizeLimit(): number;
|
|
6
|
+
getDefaultFormat(): 'html' | 'zip';
|
|
7
|
+
modifyHTML(html: string, assets: AssetInfo[]): string;
|
|
8
|
+
getPlatformScript(): string;
|
|
9
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { PlatformAdapter } from './base.js';
|
|
2
|
+
export class FacebookAdapter extends PlatformAdapter {
|
|
3
|
+
getName() {
|
|
4
|
+
return 'Facebook';
|
|
5
|
+
}
|
|
6
|
+
getSizeLimit() {
|
|
7
|
+
// Facebook: HTML 5MB, ZIP 5MB(HTML 文件需 < 2MB 由校验处理)
|
|
8
|
+
return 5 * 1024 * 1024;
|
|
9
|
+
}
|
|
10
|
+
getDefaultFormat() {
|
|
11
|
+
return 'html';
|
|
12
|
+
}
|
|
13
|
+
modifyHTML(html, assets) {
|
|
14
|
+
// Facebook 需要 FbPlayableAd API
|
|
15
|
+
const fbScript = `
|
|
16
|
+
<script>
|
|
17
|
+
window.FbPlayableAd = window.FbPlayableAd || {
|
|
18
|
+
onCTAClick: function() {
|
|
19
|
+
console.log('Facebook CTA clicked');
|
|
20
|
+
// 这里会被 Facebook 替换为实际的跟踪代码
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
</script>
|
|
24
|
+
`;
|
|
25
|
+
// 在 </head> 之前插入
|
|
26
|
+
return html.replace('</head>', `${fbScript}</head>`);
|
|
27
|
+
}
|
|
28
|
+
getPlatformScript() {
|
|
29
|
+
return `
|
|
30
|
+
// Facebook Playable Ad API
|
|
31
|
+
if (typeof FbPlayableAd !== 'undefined') {
|
|
32
|
+
// 在 CTA 按钮点击时调用
|
|
33
|
+
// FbPlayableAd.onCTAClick();
|
|
34
|
+
}
|
|
35
|
+
`;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PlatformAdapter } from './base.js';
|
|
2
|
+
import type { AssetInfo } from '../types.js';
|
|
3
|
+
export declare class GoogleAdapter extends PlatformAdapter {
|
|
4
|
+
getName(): string;
|
|
5
|
+
getSizeLimit(): number;
|
|
6
|
+
getDefaultFormat(): 'html' | 'zip';
|
|
7
|
+
modifyHTML(html: string, assets: AssetInfo[]): string;
|
|
8
|
+
getPlatformScript(): string;
|
|
9
|
+
validateOptions(): void;
|
|
10
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { PlatformAdapter } from './base.js';
|
|
2
|
+
export class GoogleAdapter extends PlatformAdapter {
|
|
3
|
+
getName() {
|
|
4
|
+
return 'Google Ads';
|
|
5
|
+
}
|
|
6
|
+
getSizeLimit() {
|
|
7
|
+
// Google Ads: 5MB ZIP
|
|
8
|
+
return 5 * 1024 * 1024;
|
|
9
|
+
}
|
|
10
|
+
getDefaultFormat() {
|
|
11
|
+
return 'zip';
|
|
12
|
+
}
|
|
13
|
+
modifyHTML(html, assets) {
|
|
14
|
+
// Google Ads 需要 exitapi.js
|
|
15
|
+
const googleScript = `
|
|
16
|
+
<script>
|
|
17
|
+
// Google Ads Exit API
|
|
18
|
+
window.ExitApi = window.ExitApi || {
|
|
19
|
+
exit: function() {
|
|
20
|
+
console.log('Google Ads CTA: opening store');
|
|
21
|
+
// Google 会替换为实际的跟踪代码
|
|
22
|
+
window.open('https://play.google.com/store', '_blank');
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
</script>
|
|
26
|
+
<!--
|
|
27
|
+
注意:
|
|
28
|
+
- Google Ads 要求 ZIP 格式,最大 5MB,最多 512 文件
|
|
29
|
+
- 必须包含 <!DOCTYPE html> 和完整的 html/head/body 结构
|
|
30
|
+
- 使用 <meta name="ad.orientation" content="portrait|landscape"> 声明方向
|
|
31
|
+
- 支持 Google 托管库:Fonts/jQuery/Greensock/CreateJS
|
|
32
|
+
-->
|
|
33
|
+
<meta name="ad.size" content="320x480,480x320,768x1024,1024x768">
|
|
34
|
+
`;
|
|
35
|
+
// 在 </head> 之前插入
|
|
36
|
+
return html.replace('</head>', `${googleScript}</head>`);
|
|
37
|
+
}
|
|
38
|
+
getPlatformScript() {
|
|
39
|
+
return `
|
|
40
|
+
// Google Ads Playable
|
|
41
|
+
// 使用 ExitApi.exit() 跳转应用商店
|
|
42
|
+
|
|
43
|
+
if (typeof ExitApi !== 'undefined') {
|
|
44
|
+
console.log('Google ExitApi available');
|
|
45
|
+
}
|
|
46
|
+
`;
|
|
47
|
+
}
|
|
48
|
+
validateOptions() {
|
|
49
|
+
if (this.options.format && this.options.format !== 'zip') {
|
|
50
|
+
console.warn('警告: Google Ads 要求 ZIP 格式');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { PlatformAdapter } from './base.js';
|
|
2
|
+
import type { BuildOptions } from '../types.js';
|
|
3
|
+
export declare function createPlatformAdapter(options: BuildOptions): PlatformAdapter;
|
|
4
|
+
export { PlatformAdapter } from './base.js';
|
|
5
|
+
export { FacebookAdapter } from './facebook.js';
|
|
6
|
+
export { SnapchatAdapter } from './snapchat.js';
|
|
7
|
+
export { IronSourceAdapter } from './ironsource.js';
|
|
8
|
+
export { AppLovinAdapter } from './applovin.js';
|
|
9
|
+
export { GoogleAdapter } from './google.js';
|
|
10
|
+
export { TikTokAdapter } from './tiktok.js';
|
|
11
|
+
export { UnityAdapter } from './unity.js';
|
|
12
|
+
export { LiftoffAdapter } from './liftoff.js';
|
|
13
|
+
export { MolocoAdapter } from './moloco.js';
|
|
14
|
+
export { BigoAdapter } from './bigo.js';
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { FacebookAdapter } from './facebook.js';
|
|
2
|
+
import { SnapchatAdapter } from './snapchat.js';
|
|
3
|
+
import { IronSourceAdapter } from './ironsource.js';
|
|
4
|
+
import { AppLovinAdapter } from './applovin.js';
|
|
5
|
+
import { GoogleAdapter } from './google.js';
|
|
6
|
+
import { TikTokAdapter } from './tiktok.js';
|
|
7
|
+
import { UnityAdapter } from './unity.js';
|
|
8
|
+
import { LiftoffAdapter } from './liftoff.js';
|
|
9
|
+
import { MolocoAdapter } from './moloco.js';
|
|
10
|
+
import { BigoAdapter } from './bigo.js';
|
|
11
|
+
export function createPlatformAdapter(options) {
|
|
12
|
+
switch (options.platform) {
|
|
13
|
+
case 'facebook':
|
|
14
|
+
return new FacebookAdapter(options);
|
|
15
|
+
case 'snapchat':
|
|
16
|
+
return new SnapchatAdapter(options);
|
|
17
|
+
case 'ironsource':
|
|
18
|
+
return new IronSourceAdapter(options);
|
|
19
|
+
case 'applovin':
|
|
20
|
+
return new AppLovinAdapter(options);
|
|
21
|
+
case 'google':
|
|
22
|
+
return new GoogleAdapter(options);
|
|
23
|
+
case 'tiktok':
|
|
24
|
+
return new TikTokAdapter(options);
|
|
25
|
+
case 'unity':
|
|
26
|
+
return new UnityAdapter(options);
|
|
27
|
+
case 'liftoff':
|
|
28
|
+
return new LiftoffAdapter(options);
|
|
29
|
+
case 'moloco':
|
|
30
|
+
return new MolocoAdapter(options);
|
|
31
|
+
case 'bigo':
|
|
32
|
+
return new BigoAdapter(options);
|
|
33
|
+
default:
|
|
34
|
+
throw new Error(`Unsupported platform: ${options.platform}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export { PlatformAdapter } from './base.js';
|
|
38
|
+
export { FacebookAdapter } from './facebook.js';
|
|
39
|
+
export { SnapchatAdapter } from './snapchat.js';
|
|
40
|
+
export { IronSourceAdapter } from './ironsource.js';
|
|
41
|
+
export { AppLovinAdapter } from './applovin.js';
|
|
42
|
+
export { GoogleAdapter } from './google.js';
|
|
43
|
+
export { TikTokAdapter } from './tiktok.js';
|
|
44
|
+
export { UnityAdapter } from './unity.js';
|
|
45
|
+
export { LiftoffAdapter } from './liftoff.js';
|
|
46
|
+
export { MolocoAdapter } from './moloco.js';
|
|
47
|
+
export { BigoAdapter } from './bigo.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PlatformAdapter } from './base.js';
|
|
2
|
+
import type { AssetInfo } from '../types.js';
|
|
3
|
+
export declare class IronSourceAdapter extends PlatformAdapter {
|
|
4
|
+
getName(): string;
|
|
5
|
+
getSizeLimit(): number;
|
|
6
|
+
getDefaultFormat(): 'html' | 'zip';
|
|
7
|
+
modifyHTML(html: string, assets: AssetInfo[]): string;
|
|
8
|
+
getPlatformScript(): string;
|
|
9
|
+
validateOptions(): void;
|
|
10
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { PlatformAdapter } from './base.js';
|
|
2
|
+
export class IronSourceAdapter extends PlatformAdapter {
|
|
3
|
+
getName() {
|
|
4
|
+
return 'ironSource';
|
|
5
|
+
}
|
|
6
|
+
getSizeLimit() {
|
|
7
|
+
// ironSource: 5MB
|
|
8
|
+
return 5 * 1024 * 1024;
|
|
9
|
+
}
|
|
10
|
+
getDefaultFormat() {
|
|
11
|
+
return 'html';
|
|
12
|
+
}
|
|
13
|
+
modifyHTML(html, assets) {
|
|
14
|
+
// ironSource 需要 MRAID 和 dapi API
|
|
15
|
+
const ironSourceScript = `
|
|
16
|
+
<script>
|
|
17
|
+
// MRAID 2.0 API
|
|
18
|
+
window.mraid = window.mraid || {
|
|
19
|
+
getVersion: function() { return '2.0'; },
|
|
20
|
+
isReady: function() { return true; },
|
|
21
|
+
open: function(url) { window.open(url); },
|
|
22
|
+
close: function() {
|
|
23
|
+
console.log('ironSource: close() is handled by platform');
|
|
24
|
+
},
|
|
25
|
+
useCustomClose: function(useCustomClose) {
|
|
26
|
+
console.warn('ironSource: useCustomClose() is not allowed');
|
|
27
|
+
},
|
|
28
|
+
addEventListener: function(event, listener) {},
|
|
29
|
+
removeEventListener: function(event, listener) {},
|
|
30
|
+
getState: function() { return 'default'; },
|
|
31
|
+
getPlacementType: function() { return 'interstitial'; }
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// dapi API (ironSource specific)
|
|
35
|
+
window.dapi = window.dapi || {
|
|
36
|
+
isReady: function() { return true; },
|
|
37
|
+
addEventListener: function(event, callback) {
|
|
38
|
+
if (event === 'ready') {
|
|
39
|
+
setTimeout(callback, 0);
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
removeEventListener: function(event, callback) {}
|
|
43
|
+
};
|
|
44
|
+
</script>
|
|
45
|
+
<!--
|
|
46
|
+
注意:ironSource 要求预留四角约30x30px区域给平台UI
|
|
47
|
+
请确保游戏内容不会被遮挡
|
|
48
|
+
-->
|
|
49
|
+
`;
|
|
50
|
+
// 在 </head> 之前插入
|
|
51
|
+
return html.replace('</head>', `${ironSourceScript}</head>`);
|
|
52
|
+
}
|
|
53
|
+
getPlatformScript() {
|
|
54
|
+
return `
|
|
55
|
+
// ironSource Playable Ad
|
|
56
|
+
// 使用 mraid.open() 跳转应用商店
|
|
57
|
+
// 禁止使用 close() 或 useCustomClose()
|
|
58
|
+
|
|
59
|
+
if (typeof dapi !== 'undefined') {
|
|
60
|
+
dapi.addEventListener('ready', function() {
|
|
61
|
+
console.log('dapi ready');
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
`;
|
|
65
|
+
}
|
|
66
|
+
validateOptions() {
|
|
67
|
+
if (this.options.format && this.options.format !== 'html') {
|
|
68
|
+
console.warn('警告: ironSource 使用单文件 HTML 格式');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PlatformAdapter } from './base.js';
|
|
2
|
+
import type { AssetInfo } from '../types.js';
|
|
3
|
+
export declare class LiftoffAdapter extends PlatformAdapter {
|
|
4
|
+
getName(): string;
|
|
5
|
+
getSizeLimit(): number;
|
|
6
|
+
getDefaultFormat(): 'html' | 'zip';
|
|
7
|
+
modifyHTML(html: string, assets: AssetInfo[]): string;
|
|
8
|
+
getPlatformScript(): string;
|
|
9
|
+
validateOptions(): void;
|
|
10
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { PlatformAdapter } from './base.js';
|
|
2
|
+
export class LiftoffAdapter extends PlatformAdapter {
|
|
3
|
+
getName() {
|
|
4
|
+
return 'Liftoff';
|
|
5
|
+
}
|
|
6
|
+
getSizeLimit() {
|
|
7
|
+
// Liftoff: 建议 <5MB
|
|
8
|
+
return 5 * 1024 * 1024;
|
|
9
|
+
}
|
|
10
|
+
getDefaultFormat() {
|
|
11
|
+
return 'zip';
|
|
12
|
+
}
|
|
13
|
+
modifyHTML(html, assets) {
|
|
14
|
+
// Liftoff 支持 MRAID 或 window.open
|
|
15
|
+
const liftoffScript = `
|
|
16
|
+
<script>
|
|
17
|
+
// MRAID API(可选)
|
|
18
|
+
window.mraid = window.mraid || {
|
|
19
|
+
getVersion: function() { return '2.0'; },
|
|
20
|
+
isReady: function() { return true; },
|
|
21
|
+
open: function(url) {
|
|
22
|
+
console.log('Liftoff CTA: opening store');
|
|
23
|
+
window.open(url, '_blank');
|
|
24
|
+
},
|
|
25
|
+
addEventListener: function(event, listener) {},
|
|
26
|
+
removeEventListener: function(event, listener) {}
|
|
27
|
+
};
|
|
28
|
+
</script>
|
|
29
|
+
<!--
|
|
30
|
+
注意:
|
|
31
|
+
- Liftoff 要求 ZIP 格式
|
|
32
|
+
- 文件名必须为 ASCII(禁止 UTF-8)
|
|
33
|
+
- 大小写敏感
|
|
34
|
+
- 跳转使用 mraid.open() 或 window.open(),禁止 window.location
|
|
35
|
+
- 需用户交互后才能跳转
|
|
36
|
+
- 支持标准尺寸:320x480, 480x320, 768x1024, 1024x768, 320x50, 728x90, 300x250
|
|
37
|
+
- 关闭按钮由平台处理,可能遮挡角落 50x50px
|
|
38
|
+
-->
|
|
39
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
|
40
|
+
`;
|
|
41
|
+
// 在 </head> 之前插入
|
|
42
|
+
return html.replace('</head>', `${liftoffScript}</head>`);
|
|
43
|
+
}
|
|
44
|
+
getPlatformScript() {
|
|
45
|
+
return `
|
|
46
|
+
// Liftoff Playable Ad
|
|
47
|
+
// 使用 mraid.open() 或 window.open() 跳转
|
|
48
|
+
// 禁止 window.location 重定向
|
|
49
|
+
`;
|
|
50
|
+
}
|
|
51
|
+
validateOptions() {
|
|
52
|
+
if (this.options.format && this.options.format !== 'zip') {
|
|
53
|
+
console.warn('警告: Liftoff 要求 ZIP 格式');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PlatformAdapter } from './base.js';
|
|
2
|
+
import type { AssetInfo } from '../types.js';
|
|
3
|
+
export declare class MolocoAdapter extends PlatformAdapter {
|
|
4
|
+
getName(): string;
|
|
5
|
+
getSizeLimit(): number;
|
|
6
|
+
getDefaultFormat(): 'html' | 'zip';
|
|
7
|
+
modifyHTML(html: string, assets: AssetInfo[]): string;
|
|
8
|
+
getPlatformScript(): string;
|
|
9
|
+
validateOptions(): void;
|
|
10
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { PlatformAdapter } from './base.js';
|
|
2
|
+
export class MolocoAdapter extends PlatformAdapter {
|
|
3
|
+
getName() {
|
|
4
|
+
return 'Moloco';
|
|
5
|
+
}
|
|
6
|
+
getSizeLimit() {
|
|
7
|
+
// Moloco: 5MB
|
|
8
|
+
return 5 * 1024 * 1024;
|
|
9
|
+
}
|
|
10
|
+
getDefaultFormat() {
|
|
11
|
+
return 'html';
|
|
12
|
+
}
|
|
13
|
+
modifyHTML(html, assets) {
|
|
14
|
+
// Moloco 使用 FbPlayableAd API(与 Facebook 相同)
|
|
15
|
+
const molocoScript = `
|
|
16
|
+
<script>
|
|
17
|
+
// Moloco 使用 FbPlayableAd API
|
|
18
|
+
window.FbPlayableAd = window.FbPlayableAd || {
|
|
19
|
+
onCTAClick: function() {
|
|
20
|
+
console.log('Moloco CTA clicked');
|
|
21
|
+
// Moloco 要求:必须以"无参数"方式调用
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
</script>
|
|
25
|
+
<!--
|
|
26
|
+
注意:
|
|
27
|
+
- Moloco 使用单文件 HTML 格式,<5MB
|
|
28
|
+
- CTA 必须以"无参数"方式调用 FbPlayableAd.onCTAClick()
|
|
29
|
+
- 不得包含 mraid.js
|
|
30
|
+
- 不允许任何外部引用或 HTTP 动态加载
|
|
31
|
+
- 禁止 XMLHttpRequest 和 JS 重定向
|
|
32
|
+
-->
|
|
33
|
+
`;
|
|
34
|
+
// 在 </head> 之前插入
|
|
35
|
+
return html.replace('</head>', `${molocoScript}</head>`);
|
|
36
|
+
}
|
|
37
|
+
getPlatformScript() {
|
|
38
|
+
return `
|
|
39
|
+
// Moloco Playable Ad
|
|
40
|
+
// 使用 FbPlayableAd.onCTAClick() 跳转(无参数)
|
|
41
|
+
|
|
42
|
+
if (typeof FbPlayableAd !== 'undefined') {
|
|
43
|
+
// 在 CTA 按钮点击时调用
|
|
44
|
+
// FbPlayableAd.onCTAClick();
|
|
45
|
+
}
|
|
46
|
+
`;
|
|
47
|
+
}
|
|
48
|
+
validateOptions() {
|
|
49
|
+
if (this.options.format && this.options.format !== 'html') {
|
|
50
|
+
console.warn('警告: Moloco 使用单文件 HTML 格式');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PlatformAdapter } from './base.js';
|
|
2
|
+
import type { AssetInfo } from '../types.js';
|
|
3
|
+
export declare class SnapchatAdapter extends PlatformAdapter {
|
|
4
|
+
getName(): string;
|
|
5
|
+
getSizeLimit(): number;
|
|
6
|
+
getDefaultFormat(): 'html' | 'zip';
|
|
7
|
+
modifyHTML(html: string, assets: AssetInfo[]): string;
|
|
8
|
+
getPlatformScript(): string;
|
|
9
|
+
validateOptions(): void;
|
|
10
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { PlatformAdapter } from './base.js';
|
|
2
|
+
export class SnapchatAdapter extends PlatformAdapter {
|
|
3
|
+
getName() {
|
|
4
|
+
return 'Snapchat';
|
|
5
|
+
}
|
|
6
|
+
getSizeLimit() {
|
|
7
|
+
// Snapchat: 5MB (uncompressed)
|
|
8
|
+
return 5 * 1024 * 1024;
|
|
9
|
+
}
|
|
10
|
+
getDefaultFormat() {
|
|
11
|
+
return 'zip';
|
|
12
|
+
}
|
|
13
|
+
modifyHTML(html, assets) {
|
|
14
|
+
// Snapchat 需要 MRAID 2.0 和 snapchatCta 函数
|
|
15
|
+
const mraidScript = `
|
|
16
|
+
<script>
|
|
17
|
+
// MRAID 2.0 API
|
|
18
|
+
window.mraid = window.mraid || {
|
|
19
|
+
getVersion: function() { return '2.0'; },
|
|
20
|
+
isReady: function() { return true; },
|
|
21
|
+
open: function(url) { window.open(url); },
|
|
22
|
+
close: function() { window.close(); },
|
|
23
|
+
addEventListener: function(event, listener) {},
|
|
24
|
+
removeEventListener: function(event, listener) {},
|
|
25
|
+
getState: function() { return 'ready'; },
|
|
26
|
+
getPlacementType: function() { return 'interstitial'; }
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// Snapchat CTA function
|
|
30
|
+
window.snapchatCta = function() {
|
|
31
|
+
if (window.mraid && window.mraid.open) {
|
|
32
|
+
window.mraid.open('https://snapchat.com');
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
</script>
|
|
36
|
+
`;
|
|
37
|
+
return html.replace('</head>', `${mraidScript}</head>`);
|
|
38
|
+
}
|
|
39
|
+
getPlatformScript() {
|
|
40
|
+
return `
|
|
41
|
+
// Snapchat Playable Ad
|
|
42
|
+
if (typeof mraid !== 'undefined') {
|
|
43
|
+
mraid.addEventListener('ready', function() {
|
|
44
|
+
console.log('MRAID ready');
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// 在 CTA 按钮点击时调用
|
|
49
|
+
// snapchatCta();
|
|
50
|
+
`;
|
|
51
|
+
}
|
|
52
|
+
validateOptions() {
|
|
53
|
+
// Snapchat 默认使用 ZIP 格式,但不强制要求
|
|
54
|
+
// MRAID 支持会在 modifyHTML 中自动添加
|
|
55
|
+
if (this.options.format && this.options.format !== 'zip') {
|
|
56
|
+
console.warn('Warning: Snapchat typically uses ZIP format');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { PlatformAdapter } from './base.js';
|
|
2
|
+
import type { AssetInfo } from '../types.js';
|
|
3
|
+
export declare class TikTokAdapter extends PlatformAdapter {
|
|
4
|
+
getName(): string;
|
|
5
|
+
getSizeLimit(): number;
|
|
6
|
+
getDefaultFormat(): 'html' | 'zip';
|
|
7
|
+
modifyHTML(html: string, assets: AssetInfo[]): string;
|
|
8
|
+
getPlatformScript(): string;
|
|
9
|
+
/**
|
|
10
|
+
* 生成 config.json(TikTok/Pangle 要求)
|
|
11
|
+
* @param orientation 0=横竖均可, 1=仅竖屏, 2=仅横屏
|
|
12
|
+
*/
|
|
13
|
+
generateConfigJson(orientation?: 0 | 1 | 2): object;
|
|
14
|
+
validateOptions(): void;
|
|
15
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { PlatformAdapter } from './base.js';
|
|
2
|
+
export class TikTokAdapter extends PlatformAdapter {
|
|
3
|
+
getName() {
|
|
4
|
+
return 'TikTok/Pangle';
|
|
5
|
+
}
|
|
6
|
+
getSizeLimit() {
|
|
7
|
+
// TikTok/Pangle: 5MB
|
|
8
|
+
return 5 * 1024 * 1024;
|
|
9
|
+
}
|
|
10
|
+
getDefaultFormat() {
|
|
11
|
+
return 'zip';
|
|
12
|
+
}
|
|
13
|
+
modifyHTML(html, assets) {
|
|
14
|
+
// TikTok/Pangle 需要 Pangle JS-SDK
|
|
15
|
+
const pangleScript = `
|
|
16
|
+
<script>
|
|
17
|
+
// Pangle JS-SDK 桥接
|
|
18
|
+
window.Pangle = window.Pangle || {
|
|
19
|
+
open: function(url) {
|
|
20
|
+
console.log('Pangle CTA: opening store');
|
|
21
|
+
// Pangle SDK 会处理跳转
|
|
22
|
+
},
|
|
23
|
+
ready: function() {
|
|
24
|
+
console.log('Pangle SDK ready');
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// 不使用 mraid.js(TikTok要求)
|
|
29
|
+
</script>
|
|
30
|
+
<!--
|
|
31
|
+
注意:
|
|
32
|
+
- TikTok/Pangle 要求 ZIP 格式,含 config.json
|
|
33
|
+
- config.json 需包含 playable_orientation 字段:0=横竖均可/1=仅竖/2=仅横
|
|
34
|
+
- 不允许外部网络加载动态素材
|
|
35
|
+
- 不应使用 mraid.js
|
|
36
|
+
-->
|
|
37
|
+
`;
|
|
38
|
+
// 在 </head> 之前插入
|
|
39
|
+
return html.replace('</head>', `${pangleScript}</head>`);
|
|
40
|
+
}
|
|
41
|
+
getPlatformScript() {
|
|
42
|
+
return `
|
|
43
|
+
// TikTok/Pangle Playable Ad
|
|
44
|
+
// 使用 Pangle SDK 进行跳转
|
|
45
|
+
|
|
46
|
+
if (typeof Pangle !== 'undefined') {
|
|
47
|
+
Pangle.ready();
|
|
48
|
+
}
|
|
49
|
+
`;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 生成 config.json(TikTok/Pangle 要求)
|
|
53
|
+
* @param orientation 0=横竖均可, 1=仅竖屏, 2=仅横屏
|
|
54
|
+
*/
|
|
55
|
+
generateConfigJson(orientation = 0) {
|
|
56
|
+
return {
|
|
57
|
+
playable_orientation: orientation,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
validateOptions() {
|
|
61
|
+
if (this.options.format && this.options.format !== 'zip') {
|
|
62
|
+
console.warn('警告: TikTok/Pangle 要求 ZIP 格式');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PlatformAdapter } from './base.js';
|
|
2
|
+
import type { AssetInfo } from '../types.js';
|
|
3
|
+
export declare class UnityAdapter extends PlatformAdapter {
|
|
4
|
+
getName(): string;
|
|
5
|
+
getSizeLimit(): number;
|
|
6
|
+
getDefaultFormat(): 'html' | 'zip';
|
|
7
|
+
modifyHTML(html: string, assets: AssetInfo[]): string;
|
|
8
|
+
getPlatformScript(): string;
|
|
9
|
+
validateOptions(): void;
|
|
10
|
+
}
|