@moneko/core 3.58.0 → 3.58.1-bate.1
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/lib/config.d.mts +1 -1
- package/lib/config.mjs +1 -1
- package/lib/dev.mjs +2 -2
- package/lib/index.d.mts +1 -1
- package/lib/index.mjs +1 -1
- package/lib/plugin/manifest/index.d.mts +10 -0
- package/lib/plugin/manifest/index.mjs +1 -0
- package/lib/plugin/manifest/types.d.mts +577 -0
- package/lib/plugin/manifest/types.mjs +1 -0
- package/lib/plugins.config.mjs +1 -1
- package/package.json +1 -1
- package/lib/plugin/manifest.d.mts +0 -90
- package/lib/plugin/manifest.mjs +0 -1
package/lib/config.d.mts
CHANGED
package/lib/config.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{join as e,relative as o}from"node:path";import t from"node:process";import{merge as n}from"webpack-merge";import
|
|
1
|
+
import{join as e,relative as o}from"node:path";import t from"node:process";import{merge as n}from"webpack-merge";import a from"./commom/paths.mjs";import r from"./commom/setup-env.mjs";import s from"./options/jsx-dom-expressions.mjs";import i from"./options/split-chunk.mjs";import{getConfigWithTypescript as l,isFunction as m,node_modules as p,resolveProgram as c}from"./utils/index.mjs";import{APPTYPE as u,FRAMEWORK as d,frameworkVersion as f,isCI as h,isDev as g,isLibrary as v,isMobile as x,isReact as C,jsxImportSource as P,mainDirectory as j,NODE_ENV as b,PACKAGENAME as k}from"./process-env.mjs";let w=["@app","@moneko","neko-ui",".cache/http/data","@element-plus","ant-design-vue","element-plus","element-ui","ng-zorro-antd","@mui","@du","@fontsource","@fortawesome","font-pingfang-sc","font-pingfang-tc","katex","react-markdown-editor-lite","react-photo-view","schema-design","monaco-editor"];export async function getConfig(e){let o=l(e).default;return(m(o)?await o(t):o)??{}}let I=await r(b,u,d,[],"true"===t.env.IS_BUILD),[O,S]=await Promise.all([getConfig(a.configPath),getConfig(a.customConfigPath)]),y={mode:b,strict:!1,devtool:"true"!==t.env.IS_BUILD&&g?"eval-cheap-module-source-map":"cheap-module-source-map",seo:!1,bundleAnalyzer:!1,polyfill:!1,entry:{},minifier:{},sourceMap:{filename:"[file].map",publicPath:"",namespace:k,moduleFilenameTemplate:"moneko://[namespace]/[resource-path]?[loaders]",fallbackModuleFilenameTemplate:"moneko://[namespace]/[resource-path]?[loaders]"},env:I,basename:"/",publicPath:"auto",rem:{designSize:x?375:1920},fallbackCompPath:null,modifyVars:{},prefixCls:"n",alias:Object.assign({"@":c(j)},C&&f<18?{"react/package.json":p("react/package.json"),"react/jsx-runtime":p("react/jsx-runtime.js"),"react/jsx-dev-runtime":p("react/jsx-dev-runtime.js")}:{}),moduleRules:[],prefixJsLoader:[],cssModules:[],cssModuleDefinition:!0,importOnDemand:{},proxy:{},devServer:{host:"localhost",port:3e3,open:!0},htmlPluginOption:{title:k.toLocaleUpperCase(),favicon:o(a.programPath,`${a.corePath}/options/favicon.ico`)},copy:{},routerMode:"browser",fixBrowserRouter:!1,plugins:[],resolvePlugins:[],overrideResolve:!1,splitChunk:i,runtimeChunk:"single",moduleFederation:[],rulesInclude:{css:w,js:w,media:w,font:w,wasm:[]},mdx:{jsx:!1,development:g,jsxImportSource:P,providerImportSource:`@moneko/${d}/mdx`},jsxDomExpressions:s,bar:{name:"Client",nameColor:"68",msgColor:"242",barBgColor:"15",barColor:"69",quiet:h},normalizeCss:!0,externalsPresets:{},buildHttp:void 0,virtualModule:{},cssExtract:{},externals:["@swc/core"],lazyCompilation:!1,performance:!1,refresh:"solid"!==d,bundleId:"com.moneko.bid",bundles:[],stylelint:{},eslint:{lintDirtyModulesOnly:!1},minChunkSize:1e3,compression:"true"!==t.env.IS_BUILD,manifest:{filename:"site.webmanifest"},corepack:!0,reactJsxRuntime:"automatic"};v&&(y.alias=Object.assign(y.alias,{"@pkg":a.componentsPath,[k]:a.componentsPath}));let M=y;(!1===(M=n(M,O,S)).devtool||!1===M.sourceMap)&&(M.sourceMap=!1,M.devtool=!1),"true"===t.env.CODESPACES&&(M.devServer.https=!1),!1===M.devServer.https&&"darwin"===t.platform&&(M.devServer.open=!1),M.htmlPluginOption&&(M.htmlPluginOption.tags||(M.htmlPluginOption.tags=[]),M.fixBrowserRouter&&M.htmlPluginOption.tags.push({textContent:"(function(l) {if (l.search[1] === '/' ) {var decoded = l.search.slice(1).split('&').map(function(s) {return s.replace(/~and~/g, '&')}).join('?');window.history.replaceState(null, null,l.pathname.slice(0, -1) + decoded + l.hash);}}(window.location))"}),M.manifest&&M.htmlPluginOption.tags.push({href:e(M.basename,M.manifest.filename).replaceAll(/\\/g,"/"),tag:"link",rel:"manifest"}));export const CONFIG=M;export const PUBLICPATH="auto"===CONFIG.publicPath?"":CONFIG.publicPath;
|
package/lib/dev.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{exec as e,spawn as t}from"node:child_process";import{watchFile as o}from"node:fs";import{
|
|
2
|
-
`):(
|
|
1
|
+
import{exec as e,spawn as t}from"node:child_process";import{watchFile as o}from"node:fs";import{relative as r}from"node:path";import i from"node:process";import{URL as s}from"node:url";import{ink as n,print as a,println as m,progressBar as l}from"@moneko/utils";import p from"webpack";import c from"webpack-hot-middleware";import{merge as h}from"webpack-merge";import{diffObject as f}from"./commom/diff-object.mjs";import d,{config_files as u}from"./commom/paths.mjs";import g from"./commom/sigint-exit.mjs";import{devLog as w,PORT as y}from"./dev/config.mjs";import $ from"./dev/generate-progress-html.mjs";import j from"./dev/server.mjs";import v from"./options/reslove.mjs";import{ESLintPlugin as b}from"./plugin/eslint.mjs";import{StylelintPlugin as x}from"./plugin/stylelint.mjs";import{empty as C}from"./utils/index.mjs";import{CONFIG as _,getConfig as P}from"./config.mjs";import{createDevelopmentConfiguration as S}from"./create-development-configuration.mjs";import{outputFileSystem as k}from"./file-system.mjs";import{isLibrary as E,refresh as B}from"./process-env.mjs";let H=!1,I="/____progress____",O={percentage:0,info:""},T="/__hmr__",q=new URLSearchParams({name:"client",path:T.substring(1),dynamicPublicPath:!0,timeout:2e3,reload:!B,quiet:!0,noInfo:!0,overlay:!1,autoConnect:!0}).toString(),G=await S({watchOptions:{stdin:!0,aggregateTimeout:300,ignored:/node_modules\/(?!(@app)\/)/},entry:{main:[`${v.hotMiddlewareClient}?${q}`]},plugins:[new p.WatchIgnorePlugin({paths:[/node_modules\/(?!(@app)\/)/,/\.d\.ts$/]}),new p.ProgressPlugin({handler(e,t,...o){let r=o.length?`[${t}] ${o.join(" ")}`:" ";H||(O.info=r,O.percentage=e,H=1===e);let s=_.bar;if(s){let t=s.name||"Build";s.quiet?i.stdout.write(`${r}
|
|
2
|
+
`):(l(e||0,1,{msg:r,name:t,barColor:s.barColor,nameColor:s.nameColor,barBgColor:s.barBgColor,msgColor:s.msgColor}),1===e&&i.stdout.write("\r\x1b[2K"))}}})]});function L(e){let t=e.join(","),o=[r(d.programPath,`${_.alias["@"]}/**/*.{${t}}`).replace(/\\/g,"/")];return E&&o.push(r(d.programPath,`${_.alias["@pkg"]}/**/*.{${t}}`).replace(/\\/g,"/")),o}_.eslint&&G.plugins.push(new b({fix:!0,cache:!0,cacheLocation:`${d.lintCachePath}/.eslintcache`,cacheStrategy:"metadata",files:L(["js","jsx","ts","tsx","json","html","vue"]),..._.eslint})),_.stylelint&&G.plugins.push(new x({fix:!0,cache:!0,cacheLocation:`${d.lintCachePath}/.stylelintcache`,files:L(["css","scss","sass","less","ts","tsx","js","jsx"]),..._.stylelint}));let U=p(G);if(!U)throw Error("无法创建编译器");U.outputFileSystem=k;let F=U.watch(U.options.watchOptions,w);if(!F)throw Error("无法创建监视器");U.hooks.done.tap("client-log",e=>{w(null,e)});let N=`${_.basename}/${T}`.replace(/\/+/g,"/"),R=c(U,{log:!1,path:N,heartbeat:2e3}),J=await j({port:y,root_dir:U.options.output.path,fileSystem:U.outputFileSystem,headers:_.devServer.headers,https:_.devServer.https,host:_.devServer.host,open:_.devServer.open,basename:_.basename,onRequest(e,t){if(!t.writableEnded){if("GET"===e.method){let o=new s(`${_.devServer.https?"https":"http"}://${e.headers.host}${e.url}`);if(o.pathname===I)return t.writeHead(200,{"Content-Type":"application/json; charset=utf-8","Cache-Control":"no-store"}),t.end(JSON.stringify(O)),!0;if(!H)return t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end($(I,O)),!0;if(o.pathname===N&&"text/event-stream"===e.headers.accept)return R(e,t,C),!0}return!1}}});function K(){i.exit(0)}J.on("close",()=>{F.close(C),R.close()});let M=await Promise.all(u.map(P)),W=h(M[0]||{},M[1]||{});u.forEach(function(t){o(t,async function(){var o;let[r,s]=await Promise.all(u.map(P)),l=h(r||{},s||{}),p=f(W,l);1===Object.keys(p).length&&"proxy"in p?(a(n(`代理更新中...`,"yellow"),!0),a(n(`代理更新完成...`,"green"),!0),_.proxy=l.proxy,W.proxy=l.proxy,W=l):(W=l,m(n(`检测到工程配置${n(`[${t}]`,"blue")}变更, 程序即将重启...`,"yellow"),!0),o=y,e(z?`netstat -ano | findstr :${o}`:`lsof -i :${o} -t`,(e,t)=>{if(e){m(n(`查找端口 ${o} 时发生错误: ${e.message}`,"red")),m(n("请尝试手动重启程序","yellow"));return}let r=t.trim().replace(/\r\n/g,"\n").split("\n").filter(Boolean),s=z?r[0]?.split(/\s+/).pop()?.trim():r[0]?.trim();if(!s)return void m(n(`未找到占用端口 ${o} 的进程, 请尝试手动重启程序`,"yellow"));try{i.kill(Number(s),"SIGHUP")}catch(e){m(n(`终止进程 ${s} 时发生错误: ${e.message}`,"red"))}}))})});let z="win32"===i.platform;i.on("SIGHUP",function(){J.close(C);let e=t(i.argv[0],i.argv.slice(1),{detached:!1,stdio:"inherit"});e.unref(),e.on("close",K)}),i.on("exit",function(){J.close(C)}),g(K);
|
package/lib/index.d.mts
CHANGED
|
@@ -16,7 +16,7 @@ export { type JsxDomExpressions, default as jsxDomExpressions, } from './options
|
|
|
16
16
|
export { type OptimizationSplitChunksOptions, default as splitChunk, } from './options/split-chunk.mjs';
|
|
17
17
|
export type { CompressionPluginOptions } from './plugin/compression.mjs';
|
|
18
18
|
export type { HtmlMeta, HtmlPluginOption } from './plugin/html-plugin.mjs';
|
|
19
|
-
export
|
|
19
|
+
export * from './plugin/manifest/index.mjs';
|
|
20
20
|
export type { OverrideResolverOption } from './plugin/override-resolve.mjs';
|
|
21
21
|
export type { VirtualModulePluginOption } from './plugin/virtual-module.mjs';
|
|
22
22
|
export { APPTYPE, coreName, FRAMEWORK, isCI, isDev, isLibrary, isMicro, mainDirectory, packageJson, PACKAGENAME, } from './process-env.mjs';
|
package/lib/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{default as hasPkg}from"./commom/has-pkg.mjs";export{getIPv4,getPort}from"./commom/net.mjs";export{default as open}from"./commom/open.mjs";export{default as parseArgs}from"./commom/parse-args.mjs";export{CUSTOMCONFIG,default as paths,routeDir,yarnArgv}from"./commom/paths.mjs";export{default as printLog}from"./commom/print-log.mjs";export{default as require}from"./commom/require.mjs";export{default as Rule}from"./commom/rule.mjs";export{default as timer}from"./commom/timer.mjs";export{yApiMock,yApiSchemaMock}from"./dev/mock.mjs";export{default as jsxDomExpressions}from"./options/jsx-dom-expressions.mjs";export{default as splitChunk}from"./options/split-chunk.mjs";export{APPTYPE,coreName,FRAMEWORK,isCI,isDev,isLibrary,isMicro,mainDirectory,packageJson,PACKAGENAME}from"./process-env.mjs";export*from"./type/types.mjs";export{digest,md5,node_modules,resolveProgram,toCamelCase}from"./utils/index.mjs";export*from"@moneko/mdx";export*from"@moneko/utils";import o from"webpack";export{o as webpack};
|
|
1
|
+
export{default as hasPkg}from"./commom/has-pkg.mjs";export{getIPv4,getPort}from"./commom/net.mjs";export{default as open}from"./commom/open.mjs";export{default as parseArgs}from"./commom/parse-args.mjs";export{CUSTOMCONFIG,default as paths,routeDir,yarnArgv}from"./commom/paths.mjs";export{default as printLog}from"./commom/print-log.mjs";export{default as require}from"./commom/require.mjs";export{default as Rule}from"./commom/rule.mjs";export{default as timer}from"./commom/timer.mjs";export{yApiMock,yApiSchemaMock}from"./dev/mock.mjs";export{default as jsxDomExpressions}from"./options/jsx-dom-expressions.mjs";export{default as splitChunk}from"./options/split-chunk.mjs";export*from"./plugin/manifest/index.mjs";export{APPTYPE,coreName,FRAMEWORK,isCI,isDev,isLibrary,isMicro,mainDirectory,packageJson,PACKAGENAME}from"./process-env.mjs";export*from"./type/types.mjs";export{digest,md5,node_modules,resolveProgram,toCamelCase}from"./utils/index.mjs";export*from"@moneko/mdx";export*from"@moneko/utils";import o from"webpack";export{o as webpack};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type Compilation, type Compiler } from 'webpack';
|
|
2
|
+
import type { ManifestPluginOption } from './types.mjs';
|
|
3
|
+
export * from './types.mjs';
|
|
4
|
+
export declare class ManifestPlugin {
|
|
5
|
+
private name;
|
|
6
|
+
private options;
|
|
7
|
+
constructor(options?: Partial<ManifestPluginOption>);
|
|
8
|
+
getPublicPath(compilation: Compilation): string;
|
|
9
|
+
apply(compiler: Compiler): void;
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{existsSync as s,readFileSync as t}from"node:fs";import{basename as o,relative as e,resolve as i}from"node:path";import r from"webpack";import a from"../../commom/paths.mjs";import{CONFIG as n}from"../../config.mjs";import{packageJson as p}from"../../process-env.mjs";export*from"./types.mjs";export class ManifestPlugin{constructor(s){this.name="ManifestPlugin",this.options={filename:"site.webmanifest",name:p.name,short_name:p.shortName,description:p.description,start_url:p.startUrl??"/?source=pwa",scope:"/",display:p.display??"standalone",background_color:p.backgroundColor??"#fff",theme_color:p.themeColor,icons:[{src:e(a.programPath,`${a.corePath}/options/icon.webp`),type:"image/webp",sizes:"512x512"}]},this.options={...this.options,...s}}getPublicPath(s){let t=s.getAssetPath(s.outputOptions.publicPath,{hash:s.hash}),o="auto"===t?"/":t;return"/"===o&&(o=n.basename),o.length&&!o.endsWith("/")&&(o+="/"),o}apply(e){let a=this.name,{filename:n,...c}=this.options;e.hooks.compilation.tap(a,m=>{m.hooks.processAssets.tap({name:a,stage:r.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL},()=>{let a={...c,icons:c.icons?.map(a=>{let n={...a};if(n.src&&!n.src.startsWith("http")){let a=i(e.context,n.src);if(s(a)){let s=o(n.src),e=t(a);m.emitAsset(s,new r.sources.RawSource(e),{javascriptModule:!1}),n.src=this.getPublicPath(m)+s}else m.warnings.push(new r.WebpackError(`Icon file ${a} does not exist`))}return n}),version:`${p.version}(${m.fullHash})`,hash:m.fullHash};m.emitAsset(n,new e.webpack.sources.RawSource(JSON.stringify(a)),{javascriptModule:!1})})})}}
|
|
@@ -0,0 +1,577 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 表示网页应用的屏幕截图
|
|
3
|
+
* 用于在应用商店、安装提示等场景中展示应用的外观和功能
|
|
4
|
+
* @see https://docs.pwabuilder.com/#/builder/manifest?id=screenshots
|
|
5
|
+
*/
|
|
6
|
+
interface Screenshot {
|
|
7
|
+
/**
|
|
8
|
+
* 截图图像的URL地址
|
|
9
|
+
* 可以是相对路径或绝对URL
|
|
10
|
+
* @example "/screenshots/homepage-wide.png"
|
|
11
|
+
* @example "https://example.com/screenshots/app.png"
|
|
12
|
+
*/
|
|
13
|
+
src: string;
|
|
14
|
+
/**
|
|
15
|
+
* 图像的MIME类型
|
|
16
|
+
* 用于浏览器识别图像格式
|
|
17
|
+
* @example "image/png"
|
|
18
|
+
* @example "image/jpeg"
|
|
19
|
+
*/
|
|
20
|
+
type: string;
|
|
21
|
+
/**
|
|
22
|
+
* 图像尺寸,遵循srcset规范
|
|
23
|
+
* 格式为 "宽度x高度",多个尺寸用空格分隔
|
|
24
|
+
* @example "1280x720"
|
|
25
|
+
* @example "1920x1080 1280x720"
|
|
26
|
+
*/
|
|
27
|
+
sizes: string;
|
|
28
|
+
/**
|
|
29
|
+
* 截图适用的平台类型
|
|
30
|
+
* - 'wide': 宽屏设备(如桌面、平板横屏)
|
|
31
|
+
* - 'narrow': 窄屏设备(如手机)
|
|
32
|
+
* 如果不指定,截图可用于所有平台
|
|
33
|
+
* @example "wide"
|
|
34
|
+
* @example "narrow"
|
|
35
|
+
*/
|
|
36
|
+
platform?: 'wide' | 'narrow' | string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* 表示各种尺寸和格式的应用图标
|
|
40
|
+
* 应用图标用于在主屏幕、启动画面、任务栏等位置显示
|
|
41
|
+
* 建议提供多种尺寸以确保在不同设备上都有良好的显示效果
|
|
42
|
+
* @see https://docs.pwabuilder.com/#/builder/manifest?id=icons
|
|
43
|
+
*/
|
|
44
|
+
interface Icon {
|
|
45
|
+
/**
|
|
46
|
+
* 图标图像的URL地址
|
|
47
|
+
* 可以是相对路径或绝对URL
|
|
48
|
+
* @example "/icons/icon-192x192.png"
|
|
49
|
+
* @example "https://example.com/icons/app-icon.png"
|
|
50
|
+
*/
|
|
51
|
+
src: string;
|
|
52
|
+
/**
|
|
53
|
+
* 图像的MIME类型
|
|
54
|
+
* 用于浏览器识别图像格式,建议使用 PNG 或 SVG
|
|
55
|
+
* @example "image/png"
|
|
56
|
+
* @example "image/svg+xml"
|
|
57
|
+
*/
|
|
58
|
+
type: string;
|
|
59
|
+
/**
|
|
60
|
+
* 图标尺寸,格式为 "宽度x高度"
|
|
61
|
+
* 建议提供 192x192 和 512x512 两种尺寸
|
|
62
|
+
* 多个尺寸用空格分隔
|
|
63
|
+
* @example "192x192"
|
|
64
|
+
* @example "512x512"
|
|
65
|
+
* @example "192x192 512x512"
|
|
66
|
+
*/
|
|
67
|
+
sizes: string;
|
|
68
|
+
/**
|
|
69
|
+
* 图标的用途类型
|
|
70
|
+
* - 'any': 任意场景使用(默认值)
|
|
71
|
+
* - 'maskable': 可适应不同形状的图标(如 Android 自适应图标)
|
|
72
|
+
* - 'monochrome': 单色图标(用于某些系统UI场景)
|
|
73
|
+
* 可以组合使用,如 "any maskable"
|
|
74
|
+
* @default "any"
|
|
75
|
+
* @example "any"
|
|
76
|
+
* @example "maskable"
|
|
77
|
+
* @example "any maskable"
|
|
78
|
+
*/
|
|
79
|
+
purpose?: 'any' | 'maskable' | 'monochrome' | string;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* 描述网页应用所属的分类
|
|
83
|
+
* 用于应用商店分类、搜索优化和应用发现
|
|
84
|
+
* 可以指定多个分类,帮助用户更容易找到你的应用
|
|
85
|
+
* @see https://docs.pwabuilder.com/#/builder/manifest?id=categories
|
|
86
|
+
*/
|
|
87
|
+
type Categories = 'books' /** 图书 - 电子书、阅读应用 */ | 'business' /** 商业 - 商务工具、企业应用 */ | 'education' /** 教育 - 学习、教学应用 */ | 'entertainment' /** 娱乐 - 视频、音乐、娱乐内容 */ | 'finance' /** 金融 - 银行、投资、支付应用 */ | 'fitness' /** 健身 - 运动、健康追踪 */ | 'food' /** 美食 - 餐厅、食谱、外卖 */ | 'games' /** 游戏 - 各种类型的游戏 */ | 'government' /** 政府 - 政府服务、公共信息 */ | 'health' /** 健康 - 医疗、健康管理 */ | 'kids' /** 儿童 - 儿童教育、娱乐应用 */ | 'lifestyle' /** 生活方式 - 时尚、美容、生活服务 */ | 'magazines' /** 杂志 - 期刊、杂志阅读 */ | 'medical' /** 医疗 - 医疗信息、诊断工具 */ | 'music' /** 音乐 - 音乐播放、创作 */ | 'navigation' /** 导航 - 地图、路线规划 */ | 'news' /** 新闻 - 新闻阅读、资讯 */ | 'personalization' /** 个性化 - 主题、壁纸、个性化设置 */ | 'photo' /** 照片 - 图片编辑、相册 */ | 'politics' /** 政治 - 政治新闻、投票 */ | 'productivity' /** 生产力 - 办公、效率工具 */ | 'security' /** 安全 - 安全工具、密码管理 */ | 'shopping' /** 购物 - 电商、购物应用 */ | 'social' /** 社交 - 社交媒体、聊天 */ | 'sports' /** 体育 - 体育新闻、赛事 */ | 'travel' /** 旅行 - 旅游、酒店、航班 */ | 'utilities' /** 工具 - 实用工具、系统工具 */ | 'weather'; /** 天气 - 天气预报、气象信息 */
|
|
88
|
+
/**
|
|
89
|
+
* 表示应用的快速快捷方式,指向特定功能或页面
|
|
90
|
+
* 用户可以在应用图标上长按(或右键)看到这些快捷方式,快速访问常用功能
|
|
91
|
+
* 例如:音乐应用可以添加"播放列表"、"搜索"等快捷方式
|
|
92
|
+
* @see https://docs.pwabuilder.com/#/builder/manifest?id=shortcuts
|
|
93
|
+
*/
|
|
94
|
+
interface Shortcut {
|
|
95
|
+
/**
|
|
96
|
+
* 快捷方式的显示名称
|
|
97
|
+
* 这是用户看到的主要文本,建议简短明了
|
|
98
|
+
* @example "新建笔记"
|
|
99
|
+
* @example "播放列表"
|
|
100
|
+
* @example "搜索"
|
|
101
|
+
*/
|
|
102
|
+
name: string;
|
|
103
|
+
/**
|
|
104
|
+
* 快捷方式打开的URL地址
|
|
105
|
+
* 可以是相对路径或绝对URL,应该指向应用作用域内的页面
|
|
106
|
+
* @example "/notes/new"
|
|
107
|
+
* @example "/playlist"
|
|
108
|
+
* @example "https://example.com/search"
|
|
109
|
+
*/
|
|
110
|
+
url: string;
|
|
111
|
+
/**
|
|
112
|
+
* 简短名称,当空间有限时使用
|
|
113
|
+
* 如果未提供,将使用 name 字段
|
|
114
|
+
* @example "新建"
|
|
115
|
+
* @example "列表"
|
|
116
|
+
*/
|
|
117
|
+
short_name?: string;
|
|
118
|
+
/**
|
|
119
|
+
* 快捷方式的描述信息
|
|
120
|
+
* 用于向用户说明该快捷方式的功能
|
|
121
|
+
* @example "快速创建新的笔记"
|
|
122
|
+
* @example "查看我的播放列表"
|
|
123
|
+
*/
|
|
124
|
+
description?: string;
|
|
125
|
+
/**
|
|
126
|
+
* 快捷方式关联的图标列表
|
|
127
|
+
* 建议提供 96x96 或更大的图标
|
|
128
|
+
* 如果不提供,将使用应用的默认图标
|
|
129
|
+
* @example [{ src: "/icons/shortcut-new.png", sizes: "96x96", type: "image/png" }]
|
|
130
|
+
*/
|
|
131
|
+
icons?: Icon[];
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* 定义应用处理的协议处理器
|
|
135
|
+
* 允许你的应用注册为特定 URL 协议的处理程序
|
|
136
|
+
* 例如:注册 "mailto:" 协议后,用户点击邮件链接时会打开你的应用
|
|
137
|
+
* @see https://docs.pwabuilder.com/#/builder/manifest?id=protocol_handlers
|
|
138
|
+
*/
|
|
139
|
+
interface ProtocolHandler {
|
|
140
|
+
/**
|
|
141
|
+
* 要处理的协议名称
|
|
142
|
+
* 标准协议:如 "mailto"、"tel"、"sms"
|
|
143
|
+
* 自定义协议:必须以 "web+" 开头,如 "web+music"、"web+notes"
|
|
144
|
+
* @example "mailto"
|
|
145
|
+
* @example "web+music"
|
|
146
|
+
* @example "tel"
|
|
147
|
+
*/
|
|
148
|
+
protocol: string;
|
|
149
|
+
/**
|
|
150
|
+
* 处理协议请求的URL模板
|
|
151
|
+
* 使用 "%s" 作为协议参数的占位符
|
|
152
|
+
* @example "/handle?url=%s"
|
|
153
|
+
* @example "https://example.com/open?url=%s"
|
|
154
|
+
*/
|
|
155
|
+
url: string;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* 表示相关的原生应用
|
|
159
|
+
* 用于链接到应用商店中的原生应用版本
|
|
160
|
+
* 通常与 prefer_related_applications 配合使用
|
|
161
|
+
* @see https://docs.pwabuilder.com/#/builder/manifest?id=related_applications
|
|
162
|
+
*/
|
|
163
|
+
interface RelatedApplication {
|
|
164
|
+
/**
|
|
165
|
+
* 应用平台标识符
|
|
166
|
+
* - "play": Google Play Store (Android)
|
|
167
|
+
* - "itunes": Apple App Store (iOS)
|
|
168
|
+
* - "windows": Microsoft Store (Windows)
|
|
169
|
+
* - "webapp": 其他 Web 应用
|
|
170
|
+
* @example "play"
|
|
171
|
+
* @example "itunes"
|
|
172
|
+
* @example "windows"
|
|
173
|
+
*/
|
|
174
|
+
platform?: string;
|
|
175
|
+
/**
|
|
176
|
+
* 应用商店或下载页面的URL
|
|
177
|
+
* 用户点击后会跳转到此URL
|
|
178
|
+
* @example "https://play.google.com/store/apps/details?id=com.example.app"
|
|
179
|
+
* @example "https://apps.apple.com/app/id123456789"
|
|
180
|
+
*/
|
|
181
|
+
url?: string;
|
|
182
|
+
/**
|
|
183
|
+
* 应用在商店中的唯一标识符
|
|
184
|
+
* - Google Play: 包名,如 "com.example.app"
|
|
185
|
+
* - App Store: 数字ID,如 "123456789"
|
|
186
|
+
* - Microsoft Store: 应用ID
|
|
187
|
+
* @example "com.example.app"
|
|
188
|
+
* @example "123456789"
|
|
189
|
+
*/
|
|
190
|
+
id?: string;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* 分享参数配置
|
|
194
|
+
* 定义应用接收分享数据时的参数映射
|
|
195
|
+
* 用于将系统分享的数据映射到你的应用处理逻辑
|
|
196
|
+
*/
|
|
197
|
+
interface ShareTargetParams {
|
|
198
|
+
/**
|
|
199
|
+
* 分享的标题参数名
|
|
200
|
+
* 指定接收标题数据的表单字段名或URL参数名
|
|
201
|
+
* @example "title"
|
|
202
|
+
* @example "subject"
|
|
203
|
+
*/
|
|
204
|
+
title?: string;
|
|
205
|
+
/**
|
|
206
|
+
* 分享的URL参数名
|
|
207
|
+
* 指定接收URL数据的表单字段名或URL参数名
|
|
208
|
+
* @example "url"
|
|
209
|
+
* @example "link"
|
|
210
|
+
*/
|
|
211
|
+
url?: string;
|
|
212
|
+
/**
|
|
213
|
+
* 分享的文本参数名
|
|
214
|
+
* 指定接收文本内容的表单字段名或URL参数名
|
|
215
|
+
* @example "text"
|
|
216
|
+
* @example "content"
|
|
217
|
+
*/
|
|
218
|
+
text?: string;
|
|
219
|
+
/**
|
|
220
|
+
* 文件分享配置数组
|
|
221
|
+
* 定义应用可以接收的文件类型和参数名
|
|
222
|
+
* 每个对象表示一种文件类型配置
|
|
223
|
+
* @example [{ name: "images", accept: ["image/*"] }]
|
|
224
|
+
* @example [{ name: "files", accept: ["text/plain", "application/pdf"] }]
|
|
225
|
+
*/
|
|
226
|
+
files?: {
|
|
227
|
+
/**
|
|
228
|
+
* 文件参数名
|
|
229
|
+
* 指定接收文件的表单字段名
|
|
230
|
+
* @example "images"
|
|
231
|
+
* @example "attachments"
|
|
232
|
+
*/
|
|
233
|
+
name?: string;
|
|
234
|
+
/**
|
|
235
|
+
* 接受的MIME类型数组
|
|
236
|
+
* 使用 "*" 表示接受所有类型,使用 "image/*" 表示所有图片类型
|
|
237
|
+
* @example ["image/*"]
|
|
238
|
+
* @example ["text/plain", "application/pdf"]
|
|
239
|
+
* @example ["video/mp4", "video/quicktime"]
|
|
240
|
+
*/
|
|
241
|
+
accept?: string[];
|
|
242
|
+
}[];
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* 定义应用如何处理分享目标
|
|
246
|
+
* 允许你的应用出现在系统的分享菜单中,接收来自其他应用的内容
|
|
247
|
+
* 例如:用户可以在图片应用中分享图片到你的应用
|
|
248
|
+
* @see https://docs.pwabuilder.com/#/builder/manifest?id=share_target
|
|
249
|
+
*/
|
|
250
|
+
interface ShareTarget {
|
|
251
|
+
/**
|
|
252
|
+
* 处理分享数据的URL地址
|
|
253
|
+
* 分享的数据会被发送到此URL
|
|
254
|
+
* 应该是应用作用域内的相对路径或绝对URL
|
|
255
|
+
* @example "/share"
|
|
256
|
+
* @example "/handle-share"
|
|
257
|
+
*/
|
|
258
|
+
action: string;
|
|
259
|
+
/**
|
|
260
|
+
* HTTP请求方法
|
|
261
|
+
* - "GET": 数据通过URL参数传递(适合简单数据)
|
|
262
|
+
* - "POST": 数据通过请求体传递(适合文件和大数据)
|
|
263
|
+
* @default "GET"
|
|
264
|
+
* @example "GET"
|
|
265
|
+
* @example "POST"
|
|
266
|
+
*/
|
|
267
|
+
method?: 'GET' | 'POST';
|
|
268
|
+
/**
|
|
269
|
+
* 编码类型,仅在 method 为 "POST" 时使用
|
|
270
|
+
* - "application/x-www-form-urlencoded": 标准表单编码(默认)
|
|
271
|
+
* - "multipart/form-data": 多部分表单编码(用于文件上传)
|
|
272
|
+
* @default "application/x-www-form-urlencoded"
|
|
273
|
+
* @example "multipart/form-data"
|
|
274
|
+
*/
|
|
275
|
+
enctype?: string;
|
|
276
|
+
/**
|
|
277
|
+
* 分享参数配置
|
|
278
|
+
* 定义如何将分享的数据映射到请求参数
|
|
279
|
+
* @example { title: "title", text: "text", url: "url" }
|
|
280
|
+
*/
|
|
281
|
+
params: ShareTargetParams;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Microsoft Edge侧边栏配置
|
|
285
|
+
* 用于配置应用在 Microsoft Edge 浏览器侧边栏中的显示方式
|
|
286
|
+
* 这是 Edge 浏览器特有的扩展功能
|
|
287
|
+
* @see https://docs.pwabuilder.com/#/builder/manifest?id=edge_side_panel
|
|
288
|
+
*/
|
|
289
|
+
interface EdgeSidePanel {
|
|
290
|
+
/**
|
|
291
|
+
* 侧边栏的首选宽度(像素)
|
|
292
|
+
* 建议值:320-1024 像素
|
|
293
|
+
* 如果未指定,浏览器将使用默认宽度
|
|
294
|
+
* @example 400
|
|
295
|
+
* @example 600
|
|
296
|
+
*/
|
|
297
|
+
preferred_width?: number;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* 定义网页应用的方向约束
|
|
301
|
+
* 控制应用在设备上的屏幕方向锁定
|
|
302
|
+
* 用于确保应用在特定方向上获得最佳体验
|
|
303
|
+
* @see https://docs.pwabuilder.com/#/builder/manifest?id=orientation
|
|
304
|
+
*/
|
|
305
|
+
type Orientation = 'any' /** 任意方向 - 允许用户自由旋转屏幕(默认) */ | 'natural' /** 自然方向 - 使用设备的自然方向 */ | 'portrait' /** 竖屏 - 锁定为竖屏方向(任意竖屏方向) */ | 'landscape' /** 横屏 - 锁定为横屏方向(任意横屏方向) */ | 'portrait-primary' /** 主要竖屏方向 - 锁定为设备的主要竖屏方向 */ | 'portrait-secondary' /** 次要竖屏方向 - 锁定为设备的次要竖屏方向(倒置) */ | 'landscape-primary' /** 主要横屏方向 - 锁定为设备的主要横屏方向 */ | 'landscape-secondary'; /** 次要横屏方向 - 锁定为设备的次要横屏方向(反向) */
|
|
306
|
+
/**
|
|
307
|
+
* 显示模式覆盖设置
|
|
308
|
+
* 按优先级顺序尝试的显示模式列表
|
|
309
|
+
* 浏览器会按顺序尝试这些模式,使用第一个支持的模式
|
|
310
|
+
* 这是 display 字段的增强版本,提供更细粒度的控制
|
|
311
|
+
* @see https://docs.pwabuilder.com/#/builder/manifest?id=display_override
|
|
312
|
+
*/
|
|
313
|
+
type DisplayOverride = 'window-controls-overlay' /** 窗口控件叠加 - 应用内容覆盖系统窗口控件(如标题栏) */ | 'standalone' /** 独立应用 - 类似原生应用的体验,无浏览器UI */ | 'minimal-ui' /** 最小UI - 保留最小浏览器UI(如地址栏) */ | 'fullscreen' /** 全屏 - 完全全屏显示,无任何UI */ | 'browser'; /** 浏览器 - 标准浏览器窗口 */
|
|
314
|
+
/**
|
|
315
|
+
* 应用文本方向
|
|
316
|
+
* 控制应用界面的文本阅读方向
|
|
317
|
+
* 影响布局、对齐和文本流方向
|
|
318
|
+
* @see https://docs.pwabuilder.com/#/builder/manifest?id=dir
|
|
319
|
+
*/
|
|
320
|
+
type Dir = 'auto' /** 自动检测 - 根据 lang 字段或系统设置自动确定方向 */ | 'ltr' /** 从左到右 - 适用于大多数语言(如中文、英文) */ | 'rtl'; /** 从右到左 - 适用于阿拉伯语、希伯来语等 */
|
|
321
|
+
/**
|
|
322
|
+
* 网页应用清单配置,遵循W3C标准并包含PWABuilder扩展
|
|
323
|
+
* 这是PWA(渐进式Web应用)的核心配置文件,定义了应用在用户设备上安装时的行为方式。
|
|
324
|
+
* 包括应用的名称、图标、启动URL、显示模式、主题颜色等关键信息。
|
|
325
|
+
* 使用示例:
|
|
326
|
+
* ```json
|
|
327
|
+
* {
|
|
328
|
+
* "name": "我的应用",
|
|
329
|
+
* "short_name": "应用",
|
|
330
|
+
* "start_url": "/",
|
|
331
|
+
* "display": "standalone",
|
|
332
|
+
* "theme_color": "#000000",
|
|
333
|
+
* "background_color": "#ffffff",
|
|
334
|
+
* "icons": [
|
|
335
|
+
* {
|
|
336
|
+
* "src": "/icons/icon-192x192.png",
|
|
337
|
+
* "sizes": "192x192",
|
|
338
|
+
* "type": "image/png"
|
|
339
|
+
* }
|
|
340
|
+
* ]
|
|
341
|
+
* }
|
|
342
|
+
* ```
|
|
343
|
+
* @see https://docs.pwabuilder.com/#/builder/manifest
|
|
344
|
+
*/
|
|
345
|
+
export interface WebManifest {
|
|
346
|
+
/**
|
|
347
|
+
* 应用的唯一标识符
|
|
348
|
+
* 用于区分不同的应用实例,通常使用URL格式
|
|
349
|
+
* 如果不提供,浏览器会使用 start_url 作为默认值
|
|
350
|
+
* @example "https://example.com/app"
|
|
351
|
+
* @example "/app"
|
|
352
|
+
*/
|
|
353
|
+
id?: string;
|
|
354
|
+
/**
|
|
355
|
+
* 应用的完整名称
|
|
356
|
+
* 这是用户在主屏幕、启动画面等位置看到的应用名称
|
|
357
|
+
* 建议长度不超过45个字符,以确保在各种设备上都能完整显示
|
|
358
|
+
* @example "我的超级应用"
|
|
359
|
+
* @example "Awesome PWA App"
|
|
360
|
+
*/
|
|
361
|
+
name?: string;
|
|
362
|
+
/**
|
|
363
|
+
* 应用版本号
|
|
364
|
+
* 用于标识应用的版本,可以是语义化版本号或任意字符串
|
|
365
|
+
* 主要用于版本管理和更新检测
|
|
366
|
+
* @example "1.0.0"
|
|
367
|
+
* @example "v2.3.1"
|
|
368
|
+
*/
|
|
369
|
+
version?: string;
|
|
370
|
+
/**
|
|
371
|
+
* 应用的简短名称,空间有限时显示
|
|
372
|
+
* 当主屏幕图标下方空间不足时,会使用此名称替代 name
|
|
373
|
+
* 建议长度不超过12个字符
|
|
374
|
+
* @example "我的应用"
|
|
375
|
+
* @example "App"
|
|
376
|
+
*/
|
|
377
|
+
short_name?: string;
|
|
378
|
+
/**
|
|
379
|
+
* 应用描述
|
|
380
|
+
* 简要说明应用的功能和用途
|
|
381
|
+
* 用于应用商店展示、安装提示等场景
|
|
382
|
+
* @example "一个功能强大的任务管理应用"
|
|
383
|
+
* @example "帮助您高效管理日常任务和待办事项"
|
|
384
|
+
*/
|
|
385
|
+
description?: string;
|
|
386
|
+
/**
|
|
387
|
+
* 应用启动时打开的URL地址
|
|
388
|
+
* 用户从主屏幕启动应用时,会导航到此URL
|
|
389
|
+
* 可以是相对路径(相对于manifest.json的位置)或绝对URL
|
|
390
|
+
* 如果以 "/" 开头,相对于manifest.json的域名
|
|
391
|
+
* @example "/"
|
|
392
|
+
* @example "/index.html"
|
|
393
|
+
* @example "https://example.com/home"
|
|
394
|
+
*/
|
|
395
|
+
start_url?: string;
|
|
396
|
+
/**
|
|
397
|
+
* 应用的作用域,定义应用导航的范围
|
|
398
|
+
* 指定应用可以控制的URL范围,超出此范围的链接会在浏览器中打开
|
|
399
|
+
* 如果不提供,默认为包含 manifest.json 的目录
|
|
400
|
+
* 必须以 "/" 开头
|
|
401
|
+
* @example "/"
|
|
402
|
+
* @example "/app/"
|
|
403
|
+
* @example "https://example.com/app/"
|
|
404
|
+
*/
|
|
405
|
+
scope?: string;
|
|
406
|
+
/**
|
|
407
|
+
* 文本方向
|
|
408
|
+
* 控制应用界面的文本阅读方向
|
|
409
|
+
* - 'auto': 自动检测(根据 lang 或系统设置)
|
|
410
|
+
* - 'ltr': 从左到右(适用于大多数语言)
|
|
411
|
+
* - 'rtl': 从右到左(适用于阿拉伯语、希伯来语等)
|
|
412
|
+
* @default "auto"
|
|
413
|
+
* @example "ltr"
|
|
414
|
+
* @example "rtl"
|
|
415
|
+
*/
|
|
416
|
+
dir?: Dir;
|
|
417
|
+
/**
|
|
418
|
+
* 显示模式
|
|
419
|
+
* @description 控制应用在用户设备上的呈现方式
|
|
420
|
+
* @value 'browser': 标准浏览器窗口
|
|
421
|
+
* @value 'minimal-ui': 最小浏览器UI
|
|
422
|
+
* @value 'standalone': 独立应用模式(推荐用于PWA)
|
|
423
|
+
* @value 'fullscreen': 全屏模式
|
|
424
|
+
* @default "standalone"
|
|
425
|
+
*/
|
|
426
|
+
display?: 'browser' | 'minimal-ui' | 'standalone' | 'fullscreen';
|
|
427
|
+
/**
|
|
428
|
+
* 显示模式覆盖,按优先级排序的显示模式数组
|
|
429
|
+
* 浏览器会按顺序尝试这些模式,使用第一个支持的模式
|
|
430
|
+
* 这是 display 字段的增强版本,提供更细粒度的控制
|
|
431
|
+
* @example ["window-controls-overlay", "standalone"]
|
|
432
|
+
* @example ["standalone", "minimal-ui", "browser"]
|
|
433
|
+
*/
|
|
434
|
+
display_override?: DisplayOverride[];
|
|
435
|
+
/**
|
|
436
|
+
* 屏幕方向约束
|
|
437
|
+
* 锁定应用在特定方向上显示
|
|
438
|
+
* 如果不指定,允许用户自由旋转屏幕
|
|
439
|
+
* @example "portrait"
|
|
440
|
+
* @example "landscape"
|
|
441
|
+
* @example "portrait-primary"
|
|
442
|
+
*/
|
|
443
|
+
orientation?: Orientation;
|
|
444
|
+
/**
|
|
445
|
+
* 应用的主要语言
|
|
446
|
+
* 使用BCP 47语言标签格式
|
|
447
|
+
* 影响文本方向、日期格式等本地化设置
|
|
448
|
+
* @example "zh-CN"
|
|
449
|
+
*/
|
|
450
|
+
lang?: string;
|
|
451
|
+
/**
|
|
452
|
+
* IARC内容评级ID
|
|
453
|
+
* 用于应用商店的内容评级系统
|
|
454
|
+
* 从 IARC(International Age Rating Coalition)获取
|
|
455
|
+
* @example "e84b072d-71b3-4d3e-86ae-31a8ce4e53b7"
|
|
456
|
+
*/
|
|
457
|
+
iarc_rating_id?: string;
|
|
458
|
+
/**
|
|
459
|
+
* 启动前的背景颜色
|
|
460
|
+
* 在应用启动时,在内容加载完成前显示的背景颜色
|
|
461
|
+
* 建议与主题颜色协调,使用十六进制颜色值
|
|
462
|
+
* 用于改善启动体验,避免白屏闪烁
|
|
463
|
+
* @example "#ffffff"
|
|
464
|
+
* @example "#000000"
|
|
465
|
+
* @example "#2196F3"
|
|
466
|
+
*/
|
|
467
|
+
background_color?: string;
|
|
468
|
+
/**
|
|
469
|
+
* 主题颜色,影响状态栏等系统UI
|
|
470
|
+
* 用于设置浏览器地址栏、状态栏、任务栏等系统UI的颜色
|
|
471
|
+
* 建议使用十六进制颜色值,与应用的视觉风格保持一致
|
|
472
|
+
* @example "#2196F3"
|
|
473
|
+
* @example "#000000"
|
|
474
|
+
* @example "#ffffff"
|
|
475
|
+
*/
|
|
476
|
+
theme_color?: string;
|
|
477
|
+
/**
|
|
478
|
+
* 相关的原生应用列表
|
|
479
|
+
* 用于链接到应用商店中的原生应用版本
|
|
480
|
+
* 通常与 prefer_related_applications 配合使用
|
|
481
|
+
* @example [{ platform: "play", url: "https://play.google.com/...", id: "com.example.app" }]
|
|
482
|
+
*/
|
|
483
|
+
related_applications?: RelatedApplication[];
|
|
484
|
+
/**
|
|
485
|
+
* 是否优先推荐相关原生应用
|
|
486
|
+
* 如果为 true,浏览器可能会提示用户安装原生应用而不是PWA
|
|
487
|
+
* 通常设置为 false,除非你希望引导用户使用原生应用
|
|
488
|
+
* @default false
|
|
489
|
+
* @example false
|
|
490
|
+
* @example true
|
|
491
|
+
*/
|
|
492
|
+
prefer_related_applications?: boolean;
|
|
493
|
+
/**
|
|
494
|
+
* 应用图标列表
|
|
495
|
+
* 提供不同尺寸和格式的图标,用于主屏幕、启动画面、任务栏等
|
|
496
|
+
* 建议至少提供 192x192 和 512x512 两种尺寸
|
|
497
|
+
* 图标应该是正方形,支持 PNG、SVG 等格式
|
|
498
|
+
* @example [
|
|
499
|
+
* { src: "/icons/icon-192x192.png", sizes: "192x192", type: "image/png" },
|
|
500
|
+
* { src: "/icons/icon-512x512.png", sizes: "512x512", type: "image/png" }
|
|
501
|
+
* ]
|
|
502
|
+
*/
|
|
503
|
+
icons?: Icon[];
|
|
504
|
+
/**
|
|
505
|
+
* 应用快捷方式列表
|
|
506
|
+
* 用户可以在应用图标上长按(或右键)看到这些快捷方式
|
|
507
|
+
* 最多支持4个快捷方式,每个快捷方式可以指向特定功能或页面
|
|
508
|
+
* @example [
|
|
509
|
+
* { name: "新建笔记", url: "/notes/new", icons: [...] },
|
|
510
|
+
* { name: "搜索", url: "/search" }
|
|
511
|
+
* ]
|
|
512
|
+
*/
|
|
513
|
+
shortcuts?: Shortcut[];
|
|
514
|
+
/**
|
|
515
|
+
* 协议处理器列表
|
|
516
|
+
* 允许应用注册为特定 URL 协议的处理程序
|
|
517
|
+
* 例如:注册 "mailto:" 协议后,用户点击邮件链接时会打开你的应用
|
|
518
|
+
* @example [
|
|
519
|
+
* { protocol: "mailto", url: "/handle?url=%s" },
|
|
520
|
+
* { protocol: "web+music", url: "/play?url=%s" }
|
|
521
|
+
* ]
|
|
522
|
+
*/
|
|
523
|
+
protocol_handlers?: ProtocolHandler[];
|
|
524
|
+
/**
|
|
525
|
+
* 应用分类列表
|
|
526
|
+
* 用于应用商店分类、搜索优化和应用发现
|
|
527
|
+
* 可以指定多个分类,帮助用户更容易找到你的应用
|
|
528
|
+
* @example ["productivity", "utilities"]
|
|
529
|
+
* @example ["games", "entertainment"]
|
|
530
|
+
*/
|
|
531
|
+
categories?: Categories[];
|
|
532
|
+
/**
|
|
533
|
+
* 应用截图列表,用于应用商店展示
|
|
534
|
+
* 在应用商店、安装提示等场景中展示应用的外观和功能
|
|
535
|
+
* 建议提供不同尺寸和平台的截图
|
|
536
|
+
* @example [
|
|
537
|
+
* { src: "/screenshots/wide.png", sizes: "1280x720", type: "image/png", platform: "wide" }
|
|
538
|
+
* ]
|
|
539
|
+
*/
|
|
540
|
+
screenshots?: Screenshot[];
|
|
541
|
+
/**
|
|
542
|
+
* 内容资源列表
|
|
543
|
+
* PWABuilder扩展字段,用于指定应用的内容资源
|
|
544
|
+
* 通常用于离线缓存或预加载
|
|
545
|
+
* @example ["/offline.html", "/styles.css"]
|
|
546
|
+
*/
|
|
547
|
+
content_assets?: string[];
|
|
548
|
+
/**
|
|
549
|
+
* Edge侧边栏配置
|
|
550
|
+
* Microsoft Edge浏览器特有的扩展功能
|
|
551
|
+
* 用于配置应用在Edge浏览器侧边栏中的显示方式
|
|
552
|
+
* @example { preferred_width: 400 }
|
|
553
|
+
*/
|
|
554
|
+
edge_side_panel?: EdgeSidePanel;
|
|
555
|
+
/**
|
|
556
|
+
* 分享目标配置
|
|
557
|
+
* 允许应用出现在系统的分享菜单中,接收来自其他应用的内容
|
|
558
|
+
* 例如:用户可以在图片应用中分享图片到你的应用
|
|
559
|
+
* @example {
|
|
560
|
+
* action: "/share",
|
|
561
|
+
* method: "POST",
|
|
562
|
+
* enctype: "multipart/form-data",
|
|
563
|
+
* params: { title: "title", text: "text", files: [{ name: "images", accept: ["image/*"] }] }
|
|
564
|
+
* }
|
|
565
|
+
*/
|
|
566
|
+
share_target?: ShareTarget;
|
|
567
|
+
/**
|
|
568
|
+
* 扩展字段
|
|
569
|
+
* 允许添加自定义字段,用于特定平台或框架的扩展功能
|
|
570
|
+
* 这些字段不会影响标准的PWA行为
|
|
571
|
+
*/
|
|
572
|
+
[key: string]: unknown;
|
|
573
|
+
}
|
|
574
|
+
export interface ManifestPluginOption extends WebManifest {
|
|
575
|
+
filename: string;
|
|
576
|
+
}
|
|
577
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{};
|
package/lib/plugins.config.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"webpack";import{CompressionPlugin as t}from"./plugin/compression.mjs";import{CopyPlugin as
|
|
1
|
+
import e from"webpack";import{CompressionPlugin as t}from"./plugin/compression.mjs";import{CopyPlugin as i}from"./plugin/copy.mjs";import{HtmlPlugin as o}from"./plugin/html-plugin.mjs";import{ManifestPlugin as r}from"./plugin/manifest/index.mjs";import n from"./plugin/module-federation.mjs";import{VirtualModuleWebpackPlugin as p}from"./plugin/virtual-module.mjs";import{CONFIG as l}from"./config.mjs";import{packageJson as s}from"./process-env.mjs";let a="object"==typeof l.compression?l.compression:{},m=[...n,new p(l.virtualModule),new i(l.copy),new e.DefinePlugin({"process.env":JSON.stringify(l.env)}),new e.IgnorePlugin({resourceRegExp:/\/(__(tests|mocks)__|test|spec|e2e)\//}),...l.plugins].filter(Boolean);if(l.compression&&m.push(new t({algorithm:l.devServer.https?"brotli":"gzip",test:/\.(js|css|html|svg|ttf|woff|woff2|png|jpg|jpeg)$/,...a})),l.manifest&&m.push(new r(l.manifest)),l.htmlPluginOption){let e={charset:"UTF-8","X-UA-Compatible":{"http-equiv":"X-UA-Compatible",content:"IE=edge,Chrome=1"},HandheldFriendly:"true",MobileOptimized:"320","screen-orientation":"portrait","x5-orientation":"portrait",browsermode:"application","x5-page-mode":"app","msapplication-tap-highlight":"no","mobile-web-app-capable":"yes",renderer:"webkit",description:s.description,keywords:Array.isArray(s.keywords)?s.keywords.toString():"","http-equiv":"refresh",viewport:"width=device-width, initial-scale=1"};l.seo&&(e.relCanonical={rel:"canonical",href:`https://${l.seo.domain}${l.basename}`}),l.htmlPluginOption.meta&&Object.assign(e,l.htmlPluginOption.meta),m.push(new o({...l.htmlPluginOption,meta:e}))}if(l.fixBrowserRouter){let e=l.basename.split("/").filter(Boolean).length,t=`${Array(e).fill("..").join("/")+(e?"/":"")}404.html`,i=l.fixBrowserRouter.pathSegmentsToKeep??e;m.push(new o({filename:l.fixBrowserRouter.path??t,inject:!1,templateContent:()=>`<html lang="en"><head><title>Redirect</title><script>const pathKeep = ${i};const l = window.location;l.replace(l.protocol + '//' + l.hostname + (l.port ? ':' + l.port : '') + l.pathname.split('/').slice(0, 1 + pathKeep).join('/') + '/?/' + l.pathname.slice(1).split('/').slice(pathKeep).join('/').replace(/&/g, '~and~') + (l.search ? '&' + l.search.slice(1).replace(/&/g, '~and~') : '') + l.hash);</script></head><body></body></html>`}))}l.sourceMap&&m.push(new e.SourceMapDevToolPlugin(l.sourceMap));export default m;
|
package/package.json
CHANGED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { type Compilation, type Compiler } from 'webpack';
|
|
2
|
-
interface Screenshot {
|
|
3
|
-
src: string;
|
|
4
|
-
type: string;
|
|
5
|
-
sizes: string;
|
|
6
|
-
platform?: 'wide' | string;
|
|
7
|
-
}
|
|
8
|
-
interface Icon {
|
|
9
|
-
src: string;
|
|
10
|
-
type: string;
|
|
11
|
-
sizes: string;
|
|
12
|
-
purpose?: 'any' | 'maskable' | string;
|
|
13
|
-
}
|
|
14
|
-
type Categories = 'books' | 'business' | 'education' | 'entertainment' | 'finance' | 'fitness' | 'food' | 'games' | 'government' | 'health' | 'kids' | 'lifestyle' | 'magazines' | 'medical' | 'music' | 'navigation' | 'news' | 'personalization' | 'photo' | 'politics' | 'productivity' | 'security' | 'shopping' | 'social' | 'sports' | 'travel' | 'utilities' | 'weather';
|
|
15
|
-
interface Shortcut {
|
|
16
|
-
name: string;
|
|
17
|
-
url: string;
|
|
18
|
-
short_name?: string;
|
|
19
|
-
description?: string;
|
|
20
|
-
icons?: Icon[];
|
|
21
|
-
}
|
|
22
|
-
interface ProtocolHandler {
|
|
23
|
-
protocol: string;
|
|
24
|
-
url: string;
|
|
25
|
-
}
|
|
26
|
-
interface RelatedApplication {
|
|
27
|
-
platform?: string;
|
|
28
|
-
url?: string;
|
|
29
|
-
id?: string;
|
|
30
|
-
}
|
|
31
|
-
interface ShareTarget {
|
|
32
|
-
action: string;
|
|
33
|
-
method?: 'GET' | 'POST';
|
|
34
|
-
enctype?: string;
|
|
35
|
-
params: {
|
|
36
|
-
title?: string;
|
|
37
|
-
url?: string;
|
|
38
|
-
text?: string;
|
|
39
|
-
files?: {
|
|
40
|
-
name?: string;
|
|
41
|
-
accept?: string[];
|
|
42
|
-
}[];
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
interface EdgeSidePanel {
|
|
46
|
-
preferred_width?: number;
|
|
47
|
-
}
|
|
48
|
-
type Orientation = 'any' | 'natural' | 'portrait' | 'landscape' | 'portrait-primary' | 'portrait-secondary' | 'landscape-primary' | 'landscape-secondary';
|
|
49
|
-
type DisplayOverride = 'window-controls-overlay' | 'standalone' | 'browser';
|
|
50
|
-
type Dir = 'auto' | 'ltr' | 'rtl';
|
|
51
|
-
type Display = 'browser' | 'minimal-ui' | 'standalone' | 'fullscreen';
|
|
52
|
-
export interface WebManifest {
|
|
53
|
-
id?: string;
|
|
54
|
-
name?: string;
|
|
55
|
-
version?: string;
|
|
56
|
-
short_name?: string;
|
|
57
|
-
description?: string;
|
|
58
|
-
start_url?: string;
|
|
59
|
-
scope?: string;
|
|
60
|
-
dir?: Dir;
|
|
61
|
-
display?: Display;
|
|
62
|
-
display_override?: DisplayOverride[];
|
|
63
|
-
orientation?: Orientation;
|
|
64
|
-
lang?: string;
|
|
65
|
-
iarc_rating_id?: string;
|
|
66
|
-
background_color?: string;
|
|
67
|
-
theme_color?: string;
|
|
68
|
-
related_applications?: RelatedApplication[];
|
|
69
|
-
prefer_related_applications?: boolean;
|
|
70
|
-
icons?: Icon[];
|
|
71
|
-
shortcuts?: Shortcut[];
|
|
72
|
-
protocol_handlers?: ProtocolHandler[];
|
|
73
|
-
categories?: Categories[];
|
|
74
|
-
screenshots?: Screenshot[];
|
|
75
|
-
content_assets?: string[];
|
|
76
|
-
edge_side_panel?: EdgeSidePanel;
|
|
77
|
-
share_target?: ShareTarget;
|
|
78
|
-
[key: string]: unknown;
|
|
79
|
-
}
|
|
80
|
-
export interface ManifestPluginOption extends WebManifest {
|
|
81
|
-
filename: string;
|
|
82
|
-
}
|
|
83
|
-
export declare class ManifestPlugin {
|
|
84
|
-
private name;
|
|
85
|
-
private options;
|
|
86
|
-
constructor(options?: Partial<ManifestPluginOption>);
|
|
87
|
-
getPublicPath(compilation: Compilation): string;
|
|
88
|
-
apply(compiler: Compiler): void;
|
|
89
|
-
}
|
|
90
|
-
export {};
|
package/lib/plugin/manifest.mjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{existsSync as s,readFileSync as t}from"node:fs";import{basename as o,relative as e,resolve as i}from"node:path";import r from"webpack";import a from"../commom/paths.mjs";import{packageJson as n}from"../process-env.mjs";export class ManifestPlugin{constructor(s){this.name="ManifestPlugin",this.options={filename:"site.webmanifest",name:n.name,short_name:n.shortName,description:n.description,start_url:n.startUrl??"/?source=pwa",scope:"/",display:n.display??"standalone",background_color:n.backgroundColor??"#fff",theme_color:n.themeColor,icons:[{src:e(a.programPath,`${a.corePath}/options/icon.webp`),type:"image/webp",sizes:"512x512"}]},this.options={...this.options,...s}}getPublicPath(s){let t=s.getAssetPath(s.outputOptions.publicPath,{hash:s.hash}),o="auto"===t?"/":t;return o.length&&!o.endsWith("/")&&(o+="/"),o}apply(e){let a=this.name,{filename:p,...c}=this.options;e.hooks.compilation.tap(a,h=>{h.hooks.processAssets.tap({name:a,stage:r.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL},()=>{let a={...c,icons:c.icons?.map(a=>{let n={...a};if(n.src&&!n.src.startsWith("http")){let a=i(e.context,n.src);if(s(a)){let s=o(n.src),e=t(a);h.emitAsset(s,new r.sources.RawSource(e),{javascriptModule:!1}),n.src=this.getPublicPath(h)+s}else h.warnings.push(new r.WebpackError(`Icon file ${a} does not exist`))}return n}),version:`${n.version}(${h.fullHash})`,hash:h.fullHash};h.emitAsset(p,new e.webpack.sources.RawSource(JSON.stringify(a)),{javascriptModule:!1})})})}}
|