@playcraft/devkit 1.0.31-beta.11 → 1.0.31-beta.14

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.
Files changed (101) hide show
  1. package/cli/bin/playable-scripts.js +6 -53
  2. package/cli/commands/build.js +32 -241
  3. package/cli/commands/builds.js +2 -13
  4. package/cli/commands/dev.js +1 -22
  5. package/cli/commands/pack.js +40 -320
  6. package/cli/commands/vite-dev.js +1 -7
  7. package/core/artifacts/emit-fonts.test.js +1 -0
  8. package/core/artifacts/emit.js +4 -98
  9. package/core/artifacts/fflate.js +1 -31
  10. package/core/artifacts/zip.js +1 -39
  11. package/core/batch-build.js +147 -1261
  12. package/core/constants.js +2 -20
  13. package/core/cos-uploader.js +23 -289
  14. package/core/engines/cocos/adapter-vfs-path.test.js +1 -0
  15. package/core/engines/cocos/clean-cache.js +5 -179
  16. package/core/engines/cocos/clean-cache.test.js +1 -75
  17. package/core/engines/cocos/cli-build.js +2 -116
  18. package/core/engines/cocos/cli.js +11 -38
  19. package/core/engines/cocos/constants.js +1 -21
  20. package/core/engines/cocos/creator-cli.js +1 -108
  21. package/core/engines/cocos/dev-server.js +4 -412
  22. package/core/engines/cocos/fs.js +1 -105
  23. package/core/engines/cocos/injects/3x/init.js +19 -438
  24. package/core/engines/cocos/injects/3x/main.js +2 -52
  25. package/core/engines/cocos/injects/libs/pako.js +1 -2
  26. package/core/engines/cocos/mcp-refresh.js +2 -76
  27. package/core/engines/cocos/merge-inline.test.js +1 -0
  28. package/core/engines/cocos/merge.js +9 -148
  29. package/core/engines/cocos/omit-playable-weight.js +10 -0
  30. package/core/engines/cocos/omit-playable-weight.test.js +2 -0
  31. package/core/engines/cocos/pack.js +1 -187
  32. package/core/engines/cocos/preview-cache.js +2 -48
  33. package/core/engines/cocos/preview-cache.test.js +1 -32
  34. package/core/engines/cocos/preview-concat.js +6 -189
  35. package/core/engines/cocos/preview-concat.test.js +1 -73
  36. package/core/engines/cocos/preview-json-hook.js +1 -200
  37. package/core/engines/cocos/preview-json-pack.js +3 -376
  38. package/core/engines/cocos/preview-json-pack.test.js +2 -226
  39. package/core/engines/cocos/preview-proxy.js +1 -132
  40. package/core/engines/cocos/rebundle-preview.js +2 -54
  41. package/core/engines/cocos/strip-social-share.js +3 -115
  42. package/core/engines/cocos/theme-assets.js +2 -161
  43. package/core/engines/cocos/theme-levels.js +1 -0
  44. package/core/engines/cocos/writable-cli.js +2 -248
  45. package/core/engines/cocos/writable-cli.test.js +1 -112
  46. package/core/engines/web/index.js +1 -20
  47. package/core/engines/web/vite.dev.js +17 -322
  48. package/core/engines/web/webpack.build.js +37 -522
  49. package/core/engines/web/webpack.common.js +11 -177
  50. package/core/engines/web/webpack.dev.js +6 -88
  51. package/core/index.js +7 -101
  52. package/core/injectors/apply.js +1 -94
  53. package/core/injectors/check-channel-matrix.js +2 -130
  54. package/core/injectors/spec.js +10 -217
  55. package/core/loaders/gltf-loader.js +28 -74
  56. package/core/options.js +16 -353
  57. package/core/plugins/AdikteevInjectorPlugin.js +4 -26
  58. package/core/plugins/BigoAdsInjectorPlugin.js +4 -21
  59. package/core/plugins/DAPIInjectorPlugin.js +2 -25
  60. package/core/plugins/DebuggerInjectionPlugin.js +3 -31
  61. package/core/plugins/ExitAPIInjectorPlugin.js +3 -56
  62. package/core/plugins/FflateCompressionPlugin.js +160 -307
  63. package/core/plugins/FflateCompressionPlugin.test.js +13 -0
  64. package/core/plugins/FontInjectionWebpackPlugin.js +4 -46
  65. package/core/plugins/LiftoffInjectorPlugin.js +4 -26
  66. package/core/plugins/MRAIDInjectorPlugin.js +2 -24
  67. package/core/plugins/MintegralInjectorPlugin.js +2 -25
  68. package/core/plugins/PangleInjectorPlugin.js +2 -24
  69. package/core/plugins/PlaycraftOrientationInjectorPlugin.js +3 -29
  70. package/core/plugins/SnapchatInjectorPlugin.js +4 -26
  71. package/core/plugins/SocialMediaInjectorPlugin.js +7 -119
  72. package/core/plugins/TikTokInjectorPlugin.js +2 -24
  73. package/core/plugins/UnityInjectorPlugin.js +8 -37
  74. package/core/plugins/ZipPlugin.js +20 -154
  75. package/core/plugins/socialMediaVitePlugin.js +2 -108
  76. package/core/utils/buildDefines.js +2 -30
  77. package/core/utils/buildTemplateString.js +5 -39
  78. package/core/utils/date.js +1 -16
  79. package/core/utils/fontRegistry.js +13 -81
  80. package/core/utils/fontResolver.js +37 -335
  81. package/core/utils/generateAdikteevHtmlWebpackPluginConfig.js +8 -42
  82. package/core/utils/generateBigabidHtmlWebpackPluginConfig.js +3 -30
  83. package/core/utils/generateInMobiHtmlWebpackPluginConfig.js +7 -43
  84. package/core/utils/getPlaycraftOrientationSuffix.js +2 -9
  85. package/core/utils/injectSDKPlugins.js +13 -68
  86. package/core/utils/logOptions.js +5 -46
  87. package/core/utils/mergeOptions.js +2 -21
  88. package/core/utils/obfuscateLevels.js +14 -0
  89. package/core/utils/obfuscateLevels.test.js +10 -0
  90. package/core/utils/parseArgvOptions.js +5 -125
  91. package/core/utils/resolveChannelFold2Zip.js +3 -15
  92. package/core/utils/validateThemeData.js +26 -227
  93. package/core/validators/pre-build-checker.js +25 -287
  94. package/core/validators/tracking-validator.js +40 -441
  95. package/core/validators/tracking-validator.test.js +2 -84
  96. package/core/vite.dev.js +1 -1
  97. package/core/webpack.build.js +1 -1
  98. package/core/webpack.common.js +1 -1
  99. package/core/webpack.dev.js +1 -1
  100. package/package.json +2 -3
  101. package/README.md +0 -262
@@ -1,110 +1,4 @@
1
- 'use strict';
2
-
3
- /**
1
+ "use strict";/**
4
2
  * Vite dev 模式:social_media 渠道的 OG / Twitter meta 注入。
5
3
  * 与 SocialMediaInjectorPlugin.js 输出完全一致,仅 hook 形态不同。
6
- */
7
-
8
- const path = require('path');
9
- const fs = require('fs');
10
- const JSON5 = require('json5');
11
-
12
- /** 把 shareMeta 渲染成 <meta> 标签字符串(与 webpack plugin 完全一致) */
13
- function buildMetaTags(meta) {
14
- if (!meta) return [];
15
- const esc = (s) => String(s)
16
- .replace(/&/g, '&amp;')
17
- .replace(/"/g, '&quot;')
18
- .replace(/</g, '&lt;')
19
- .replace(/>/g, '&gt;');
20
-
21
- const tags = [];
22
- const { title, description, imageUrl, pageUrl, siteName } = meta;
23
- const t = (title || '').trim();
24
- const d = (description || '').trim();
25
- const i = (imageUrl || '').trim();
26
- const u = (pageUrl || '').trim();
27
- const s = (siteName || '').trim();
28
-
29
- if (t) tags.push({ tag: 'meta', injectTo: 'head', attrs: { property: 'og:title', content: t } });
30
- if (d) tags.push({ tag: 'meta', injectTo: 'head', attrs: { property: 'og:description', content: d } });
31
- if (i) tags.push({ tag: 'meta', injectTo: 'head', attrs: { property: 'og:image', content: i } });
32
- if (u) tags.push({ tag: 'meta', injectTo: 'head', attrs: { property: 'og:url', content: u } });
33
- if (s) tags.push({ tag: 'meta', injectTo: 'head', attrs: { property: 'og:site_name', content: s } });
34
- tags.push({ tag: 'meta', injectTo: 'head', attrs: { property: 'og:type', content: 'website' } });
35
-
36
- tags.push({ tag: 'meta', injectTo: 'head', attrs: { name: 'twitter:card', content: 'summary_large_image' } });
37
- if (t) tags.push({ tag: 'meta', injectTo: 'head', attrs: { name: 'twitter:title', content: t } });
38
- if (d) tags.push({ tag: 'meta', injectTo: 'head', attrs: { name: 'twitter:description', content: d } });
39
- if (i) tags.push({ tag: 'meta', injectTo: 'head', attrs: { name: 'twitter:image', content: i } });
40
- return tags;
41
- }
42
-
43
- /** 检测主题名(与 fontFamilyPlugin 逻辑保持一致) */
44
- function detectTheme() {
45
- const root = process.cwd();
46
- const buildsConfigPath = path.join(root, 'builds.config.js');
47
- let config = { sourceDir: 'src/theme', entryFile: 'src/theme/index.ts' };
48
- if (fs.existsSync(buildsConfigPath)) {
49
- try {
50
- delete require.cache[require.resolve(buildsConfigPath)];
51
- const bc = require(buildsConfigPath);
52
- if (bc.themes) config = { ...config, ...bc.themes };
53
- } catch (_) { /* ignore */ }
54
- }
55
- let name = null;
56
- const entryPath = path.join(root, config.entryFile);
57
- if (fs.existsSync(entryPath)) {
58
- const content = fs.readFileSync(entryPath, 'utf8');
59
- const m = content.match(/from\s+['"]\.\/([^'"]+)['"]/);
60
- if (m) name = m[1];
61
- }
62
- return { themeName: name, themeConfig: config };
63
- }
64
-
65
- /** 读取 shareMeta,缓存以避免 transformIndexHtml 多次触发时反复读盘 */
66
- let _cache = { key: null, value: null };
67
-
68
- function loadShareMeta() {
69
- const { themeName, themeConfig } = detectTheme();
70
- if (!themeName) return null;
71
- const root = process.cwd();
72
- const dataPath = path.join(
73
- root,
74
- themeConfig.sourceDir || 'src/theme',
75
- themeName,
76
- 'theme.data.json5'
77
- );
78
- if (!fs.existsSync(dataPath)) return null;
79
- const stat = fs.statSync(dataPath);
80
- const key = `${dataPath}::${stat.mtimeMs}`;
81
- if (_cache.key === key) return _cache.value;
82
- try {
83
- const raw = fs.readFileSync(dataPath, 'utf8');
84
- const parsed = JSON5.parse(raw);
85
- const value = parsed && parsed.gamePlay && parsed.gamePlay.shareMeta
86
- ? parsed.gamePlay.shareMeta
87
- : null;
88
- _cache = { key, value };
89
- return value;
90
- } catch (e) {
91
- console.warn('[socialMediaVitePlugin] Failed to read theme.data.json5:', e.message);
92
- return null;
93
- }
94
- }
95
-
96
- function socialMediaVitePlugin() {
97
- return {
98
- name: 'vite-plugin-social-media',
99
- apply: 'serve',
100
- transformIndexHtml: {
101
- order: 'pre',
102
- handler() {
103
- const meta = loadShareMeta();
104
- return buildMetaTags(meta);
105
- },
106
- },
107
- };
108
- }
109
-
110
- module.exports = { socialMediaVitePlugin, buildMetaTags };
4
+ */const path=require("path");const fs=require("fs");const JSON5=require("json5");/** 把 shareMeta 渲染成 <meta> 标签字符串(与 webpack plugin 完全一致) */function buildMetaTags(meta){if(!meta)return[];const esc=s=>String(s).replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;");const tags=[];const{title,description,imageUrl,pageUrl,siteName}=meta;const t=(title||"").trim();const d=(description||"").trim();const i=(imageUrl||"").trim();const u=(pageUrl||"").trim();const s=(siteName||"").trim();if(t)tags.push({tag:"meta",injectTo:"head",attrs:{property:"og:title",content:t}});if(d)tags.push({tag:"meta",injectTo:"head",attrs:{property:"og:description",content:d}});if(i)tags.push({tag:"meta",injectTo:"head",attrs:{property:"og:image",content:i}});if(u)tags.push({tag:"meta",injectTo:"head",attrs:{property:"og:url",content:u}});if(s)tags.push({tag:"meta",injectTo:"head",attrs:{property:"og:site_name",content:s}});tags.push({tag:"meta",injectTo:"head",attrs:{property:"og:type",content:"website"}});tags.push({tag:"meta",injectTo:"head",attrs:{name:"twitter:card",content:"summary_large_image"}});if(t)tags.push({tag:"meta",injectTo:"head",attrs:{name:"twitter:title",content:t}});if(d)tags.push({tag:"meta",injectTo:"head",attrs:{name:"twitter:description",content:d}});if(i)tags.push({tag:"meta",injectTo:"head",attrs:{name:"twitter:image",content:i}});return tags}/** 检测主题名(与 fontFamilyPlugin 逻辑保持一致) */function detectTheme(){const root=process.cwd();const buildsConfigPath=path.join(root,"builds.config.js");let config={sourceDir:"src/theme",entryFile:"src/theme/index.ts"};if(fs.existsSync(buildsConfigPath)){try{delete require.cache[require.resolve(buildsConfigPath)];const bc=require(buildsConfigPath);if(bc.themes)config={...config,...bc.themes}}catch(_){/* ignore */}}let name=null;const entryPath=path.join(root,config.entryFile);if(fs.existsSync(entryPath)){const content=fs.readFileSync(entryPath,"utf8");const m=content.match(/from\s+['"]\.\/([^'"]+)['"]/);if(m)name=m[1]}return{themeName:name,themeConfig:config}}/** 读取 shareMeta,缓存以避免 transformIndexHtml 多次触发时反复读盘 */let _cache={key:null,value:null};function loadShareMeta(){const{themeName,themeConfig}=detectTheme();if(!themeName)return null;const root=process.cwd();const dataPath=path.join(root,themeConfig.sourceDir||"src/theme",themeName,"theme.data.json5");if(!fs.existsSync(dataPath))return null;const stat=fs.statSync(dataPath);const key=`${dataPath}::${stat.mtimeMs}`;if(_cache.key===key)return _cache.value;try{const raw=fs.readFileSync(dataPath,"utf8");const parsed=JSON5.parse(raw);const value=parsed&&parsed.gamePlay&&parsed.gamePlay.shareMeta?parsed.gamePlay.shareMeta:null;_cache={key,value};return value}catch(e){console.warn("[socialMediaVitePlugin] Failed to read theme.data.json5:",e.message);return null}}function socialMediaVitePlugin(){return{name:"vite-plugin-social-media",apply:"serve",transformIndexHtml:{order:"pre",handler(){const meta=loadShareMeta();return buildMetaTags(meta)}}}}module.exports={socialMediaVitePlugin,buildMetaTags};
@@ -1,32 +1,4 @@
1
- const { options } = require('../options');
2
-
3
- /**
1
+ "use strict";const{options}=require("../options");/**
4
2
  * Build's default defines list for dev & prod builds
5
3
  * @param {import('../index').CLIOptions} [customOptions] - 合并后的当前构建选项(用于读取会随单次构建变化的字段,如 playcraftOrientationValue);未提供时回退到全局 options
6
- */
7
- exports.buildDefines = function buildDefines(customOptions) {
8
- const opts = customOptions || options;
9
- const defines = {
10
- __DEV__: JSON.stringify(opts['dev'] === undefined ? false : opts['dev']),
11
- GOOGLE_PLAY_URL: JSON.stringify(opts.googlePlayUrl),
12
- APP_STORE_URL: JSON.stringify(opts.appStoreUrl),
13
- AD_NETWORK: JSON.stringify(opts['network']),
14
- AD_PROTOCOL: JSON.stringify(opts['protocol']),
15
- APP: JSON.stringify(opts.app),
16
- NAME: JSON.stringify(opts.name),
17
- VERSION: JSON.stringify(opts.version),
18
- BUILD_HASH: JSON.stringify((+new Date()).toString(36)),
19
- LANGUAGE: JSON.stringify(opts.language),
20
- PLAYCRAFT_ORIENTATION: JSON.stringify(opts.playcraftOrientationValue || 'both')
21
- };
22
-
23
- /** @type {AD_NETWORK} */
24
- let adNetworkDefine = opts['network'];
25
-
26
- if (adNetworkDefine === 'pangle') adNetworkDefine = 'tiktok';
27
- if (adNetworkDefine === 'mytarget' || adNetworkDefine === 'moloco') adNetworkDefine = 'facebook';
28
-
29
- defines['AD_NETWORK'] = JSON.stringify(adNetworkDefine);
30
-
31
- return defines;
32
- };
4
+ */exports.buildDefines=function buildDefines(customOptions){const opts=customOptions||options;const defines={__DEV__:JSON.stringify(opts["dev"]===undefined?false:opts["dev"]),GOOGLE_PLAY_URL:JSON.stringify(opts.googlePlayUrl),APP_STORE_URL:JSON.stringify(opts.appStoreUrl),AD_NETWORK:JSON.stringify(opts["network"]),AD_PROTOCOL:JSON.stringify(opts["protocol"]),APP:JSON.stringify(opts.app),NAME:JSON.stringify(opts.name),VERSION:JSON.stringify(opts.version),BUILD_HASH:JSON.stringify((+new Date).toString(36)),LANGUAGE:JSON.stringify(opts.language),PLAYCRAFT_ORIENTATION:JSON.stringify(opts.playcraftOrientationValue||"both")};/** @type {AD_NETWORK} */let adNetworkDefine=opts["network"];if(adNetworkDefine==="pangle")adNetworkDefine="tiktok";if(adNetworkDefine==="mytarget"||adNetworkDefine==="moloco")adNetworkDefine="facebook";defines["AD_NETWORK"]=JSON.stringify(adNetworkDefine);return defines};
@@ -1,40 +1,6 @@
1
- const { options } = require('../options');
2
- const { getCurrentDateFormatted } = require('./date');
3
- const path = require('path');
4
-
5
- /** @type {Record<string, string>} Mapping of ad network identifiers to their display names in filenames */
6
- const adNetworkFileNameMap = {
7
- preview: 'Preview',
8
- bigoads: 'bigo'
9
- };
10
-
11
- /**
1
+ "use strict";const{options}=require("../options");const{getCurrentDateFormatted}=require("./date");const path=require("path");/** @type {Record<string, string>} Mapping of ad network identifiers to their display names in filenames */const adNetworkFileNameMap={preview:"Preview",bigoads:"bigo"};/**
12
2
  * Build's result string from template. Used for outDir or filename
13
- */
14
- exports.buildTemplateString = function buildTemplateString(template, customOptions) {
15
- customOptions = customOptions || options;
16
-
17
- /** @type {AD_NETWORK} */
18
- const adNetwork = customOptions['network'];
19
-
20
- /** @type {AD_PROTOCOL} */
21
- // const adProtocol = customOptions['protocol'];
22
-
23
- let networkName = customOptions.adNetworkNames[adNetwork] || adNetworkFileNameMap[adNetwork] || adNetwork;
24
- // if (adProtocol === 'dapi') networkName += '_DAPI';
25
-
26
- // 如果是绝对路径,直接返回,不做模板替换
27
- if (path.isAbsolute(template)) {
28
- return template;
29
- }
30
-
31
- template = template.replaceAll('{app}', customOptions.app);
32
- template = template.replaceAll('{name}', customOptions.name);
33
- template = template.replaceAll('{version}', customOptions.version);
34
- template = template.replaceAll('{date}', getCurrentDateFormatted());
35
- template = template.replaceAll('{language}', customOptions.language);
36
- template = template.replaceAll('{network}', networkName.toLowerCase());
37
- template = template.replaceAll('{hash}', '[fullhash:6]');
38
-
39
- return template;
40
- };
3
+ */exports.buildTemplateString=function buildTemplateString(template,customOptions){customOptions=customOptions||options;/** @type {AD_NETWORK} */const adNetwork=customOptions["network"];/** @type {AD_PROTOCOL} */// const adProtocol = customOptions['protocol'];
4
+ let networkName=customOptions.adNetworkNames[adNetwork]||adNetworkFileNameMap[adNetwork]||adNetwork;// if (adProtocol === 'dapi') networkName += '_DAPI';
5
+ // 如果是绝对路径,直接返回,不做模板替换
6
+ if(path.isAbsolute(template)){return template}template=template.replaceAll("{app}",customOptions.app);template=template.replaceAll("{name}",customOptions.name);template=template.replaceAll("{version}",customOptions.version);template=template.replaceAll("{date}",getCurrentDateFormatted());template=template.replaceAll("{language}",customOptions.language);template=template.replaceAll("{network}",networkName.toLowerCase());template=template.replaceAll("{hash}","[fullhash:6]");return template};
@@ -1,16 +1 @@
1
- exports.getCurrentDateFormatted = function getCurrentDateFormatted(includeTime) {
2
- const date = new Date();
3
- const year = date.getFullYear();
4
- const month = (date.getMonth() + 1).toString().padStart(2, '0');
5
- const day = date.getDate().toString().padStart(2, '0');
6
-
7
- if (includeTime) {
8
- const hour = date.getHours().toString().padStart(2, '0');
9
- const minute = date.getMinutes().toString().padStart(2, '0');
10
- const second = date.getSeconds().toString().padStart(2, '0');
11
-
12
- return `${year}${month}${day}-${hour}${minute}${second}`;
13
- }
14
-
15
- return `${year}${month}${day}`;
16
- };
1
+ "use strict";exports.getCurrentDateFormatted=function getCurrentDateFormatted(includeTime){const date=new Date;const year=date.getFullYear();const month=(date.getMonth()+1).toString().padStart(2,"0");const day=date.getDate().toString().padStart(2,"0");if(includeTime){const hour=date.getHours().toString().padStart(2,"0");const minute=date.getMinutes().toString().padStart(2,"0");const second=date.getSeconds().toString().padStart(2,"0");return`${year}${month}${day}-${hour}${minute}${second}`}return`${year}${month}${day}`};
@@ -1,6 +1,4 @@
1
- 'use strict';
2
-
3
- /**
1
+ "use strict";/**
4
2
  * 平台预置字体字典。
5
3
  *
6
4
  * 所有字体文件内置于 playable-scripts/core/resources/fonts/ 目录下。
@@ -11,87 +9,21 @@
11
9
  * - builtin=false: 需要从本地字体文件读取并 base64 内联到产物中
12
10
  *
13
11
  * key 命名规范:与 theme.schema.json5 中 fontFamily 的 enum 值一一对应。
14
- */
15
-
16
- const path = require('path');
17
-
18
- /** 字体资源目录(随 npm 包发布) */
19
- const FONTS_DIR = path.join(__dirname, '..', 'resources', 'fonts');
20
-
21
- const FONT_REGISTRY = {
22
- // ===== 系统自带字体(无需注入) =====
23
- system: {
24
- builtin: true,
25
- fallback: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
26
- },
27
- Arial: {
28
- builtin: true,
29
- fallback: 'Arial, Helvetica, sans-serif',
30
- },
31
- monaco: {
32
- builtin: true,
33
- fallback: 'Monaco, "Courier New", monospace',
34
- },
35
-
36
- // ===== 平台内置字体(base64 内联注入) =====
37
- // key 必须与 theme.schema.json5 fontFamily.enum 值完全一致
38
-
39
- // Google Fonts 字体:单文件 woff2
40
- Poppins: {
41
- builtin: false,
42
- fontFileName: 'poppins-regular.woff2',
43
- cssFamily: 'Poppins, sans-serif',
44
- },
45
- 'Noto Sans SC': {
46
- builtin: false,
47
- fontFileName: 'noto-sans-sc-regular.woff2',
48
- cssFamily: '"Noto Sans SC", sans-serif',
49
- },
50
-
51
- // 本地 ttf 种子字体(单文件 woff2,由 download-fonts.js 用 pyftsubset 生成)
52
- 'Pangmen Zhengdao': {
53
- builtin: false,
54
- fontFileName: 'pangmen-regular.woff2', // 由 pangmen-biaoti.ttf subset 生成
55
- cssFamily: '"Pangmen Zhengdao", sans-serif',
56
- },
57
-
58
- // ZeoSeven 字体:unicode-range 子集(build 时按需筛选)
59
- 'Maoken Zhuyuan Ti': {
60
- builtin: false,
61
- subsetsDir: 'maoken',
62
- fontFileName: 'maoken-regular.woff2',
63
- cssFamily: '"Maoken Zhuyuan Ti", sans-serif',
64
- },
65
- };
66
-
67
- /**
12
+ */const path=require("path");/** 字体资源目录(随 npm 包发布) */const FONTS_DIR=path.join(__dirname,"..","resources","fonts");const FONT_REGISTRY={// ===== 系统自带字体(无需注入) =====
13
+ system:{builtin:true,fallback:"system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif"},Arial:{builtin:true,fallback:"Arial, Helvetica, sans-serif"},monaco:{builtin:true,fallback:"Monaco, \"Courier New\", monospace"},// ===== 平台内置字体(base64 内联注入) =====
14
+ // key 必须与 theme.schema.json5 fontFamily.enum 值完全一致
15
+ // Google Fonts 字体:单文件 woff2
16
+ Poppins:{builtin:false,fontFileName:"poppins-regular.woff2",cssFamily:"Poppins, sans-serif"},"Noto Sans SC":{builtin:false,fontFileName:"noto-sans-sc-regular.woff2",cssFamily:"\"Noto Sans SC\", sans-serif"},// 本地 ttf 种子字体(单文件 woff2,由 download-fonts.js 用 pyftsubset 生成)
17
+ "Pangmen Zhengdao":{builtin:false,fontFileName:"pangmen-regular.woff2",// 由 pangmen-biaoti.ttf subset 生成
18
+ cssFamily:"\"Pangmen Zhengdao\", sans-serif"},// ZeoSeven 字体:unicode-range 子集(build 时按需筛选)
19
+ "Maoken Zhuyuan Ti":{builtin:false,subsetsDir:"maoken",fontFileName:"maoken-regular.woff2",cssFamily:"\"Maoken Zhuyuan Ti\", sans-serif"}};/**
68
20
  * @returns {string[]} 所有已注册的字体 key 列表
69
- */
70
- function getRegisteredFontKeys() {
71
- return Object.keys(FONT_REGISTRY);
72
- }
73
-
74
- /**
21
+ */function getRegisteredFontKeys(){return Object.keys(FONT_REGISTRY)}/**
75
22
  * @param {string} key - 字体 key
76
23
  * @returns {boolean} 是否为系统自带字体
77
- */
78
- function isBuiltin(key) {
79
- return !!(FONT_REGISTRY[key] && FONT_REGISTRY[key].builtin);
80
- }
81
-
82
- /**
24
+ */function isBuiltin(key){return!!(FONT_REGISTRY[key]&&FONT_REGISTRY[key].builtin)}/**
83
25
  * @param {string} key - 字体 key
84
26
  * @returns {object|null} 字体配置对象,未注册返回 null
85
- */
86
- function getFontEntry(key) {
87
- return FONT_REGISTRY[key] || null;
88
- }
89
-
90
- /**
27
+ */function getFontEntry(key){return FONT_REGISTRY[key]||null}/**
91
28
  * @returns {string} 字体资源目录绝对路径
92
- */
93
- function getFontsDir() {
94
- return FONTS_DIR;
95
- }
96
-
97
- module.exports = { FONT_REGISTRY, getRegisteredFontKeys, isBuiltin, getFontEntry, getFontsDir };
29
+ */function getFontsDir(){return FONTS_DIR}module.exports={FONT_REGISTRY,getRegisteredFontKeys,isBuiltin,getFontEntry,getFontsDir};