first commit

This commit is contained in:
2026-09-08 20:28:54 +08:00
commit 2ada8d3d5a
37380 changed files with 4886169 additions and 0 deletions
+202
View File
@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+251
View File
@@ -0,0 +1,251 @@
const fs = require('fs')
const path = require('path')
const loaderUtils = require('loader-utils')
const {
parsePages,
normalizePath,
parsePagesJson,
parseManifestJson
} = require('@dcloudio/uni-cli-shared')
const {
updateAppJson,
updatePageJson,
updateProjectJson
} = require('@dcloudio/uni-cli-shared/lib/cache')
const {
initTheme,
parseTheme,
darkmode
} = require('@dcloudio/uni-cli-shared/lib/theme')
const {
// pagesJsonJsFileName,
initAutoImportComponents
} = require('@dcloudio/uni-cli-shared/lib/pages')
const uniI18n = require('@dcloudio/uni-cli-i18n')
const parseStyle = require('./util').parseStyle
const {
initI18nOptions
} = require('@dcloudio/uni-cli-shared/lib/i18n')
const {
parseI18nJson
} = require('@dcloudio/uni-i18n')
// 将开发者手动设置的 usingComponents 调整名称,方便与自动解析到的 usingComponents 做最后合并
function renameUsingComponents (jsonObj) {
if (jsonObj.usingComponents || jsonObj.usingSwanComponents) {
// 暂定 usingComponents 优先级高于 usingSwanComponents
jsonObj.customUsingComponents = Object.assign({}, jsonObj.usingSwanComponents, jsonObj.usingComponents)
delete jsonObj.usingComponents
delete jsonObj.usingSwanComponents
}
return jsonObj
}
module.exports = function (content, map) {
this.cacheable && this.cacheable()
let isAppView = false
if (this.resourceQuery) {
const params = loaderUtils.parseQuery(this.resourceQuery)
isAppView = params.type === 'view'
}
// const pagesJsonJsPath = path.resolve(process.env.UNI_INPUT_DIR, pagesJsonJsFileName)
const manifestJsonPath = path.resolve(
process.env.UNI_INPUT_DIR,
'manifest.json'
)
const manifestJson = parseManifestJson(
fs.readFileSync(manifestJsonPath, 'utf8')
)
initTheme(manifestJson)
// this.addDependency(pagesJsonJsPath)
const localePath = path.resolve(process.env.UNI_INPUT_DIR, 'locale')
// 路径不存在时会触发 webpack5 差量编译
if (fs.existsSync(localePath)) {
this.addContextDependency(localePath)
}
this.addDependency(manifestJsonPath)
const pagesJson = parsePagesJson(content, {
addDependency: file => {
(process.UNI_PAGES_DEPS || (process.UNI_PAGES_DEPS = new Set())).add(
normalizePath(file)
)
this.addDependency(file)
}
})
if (!pagesJson.pages || pagesJson.pages.length === 0) {
console.error(uniI18n.__('pagesLoader.pagesNodeCannotNull'))
process.exit(0)
}
if (this.resourceQuery) {
const queryParam = loaderUtils.parseQuery(this.resourceQuery)
if (queryParam) {
if (queryParam.type === 'origin-pages-json') {
return `export default ${JSON.stringify(pagesJson)}`
}
}
}
const platformManifestJson = manifestJson[process.env.UNI_PLATFORM] || {}
if (global.uniPlugin.defaultTheme) {
this.addDependency(
path.resolve(
process.env.UNI_INPUT_DIR,
platformManifestJson.themeLocation || 'theme.json'
)
)
}
// 组件自动导入配置
process.UNI_AUTO_SCAN_COMPONENTS = !(
pagesJson.easycom && pagesJson.easycom.autoscan === false
)
initAutoImportComponents(pagesJson.easycom)
// TODO 与 usingComponents 放在一块读取设置
if (manifestJson.transformPx === false) {
process.UNI_TRANSFORM_PX = false
} else {
process.UNI_TRANSFORM_PX = true
}
if (
(process.env.UNI_PLATFORM.indexOf('mp') !== -1 && !darkmode()) ||
process.env.VUE_APP_DARK_MODE !== 'true'
) {
const { pages, globalStyle, tabBar } = parseTheme(pagesJson)
Object.assign(pagesJson, JSON.parse(JSON.stringify({ pages, globalStyle, tabBar })))
}
if (process.env.UNI_PLATFORM === 'h5') {
return this.callback(
null,
require('./platforms/h5')(
pagesJson,
manifestJson,
this
),
map
)
}
if (process.env.UNI_PLATFORM === 'quickapp-native') {
return this.callback(
null,
require('./platforms/quickapp-native')(pagesJson, manifestJson, this),
map
)
}
// 仅限小程序
if (process.env.UNI_PLATFORM !== 'app-plus') {
const i18nOptions = initI18nOptions(
process.env.UNI_PLATFORM,
process.env.UNI_INPUT_DIR,
true,
true
)
if (i18nOptions) {
const {
locale,
locales,
delimiters
} = i18nOptions
parseI18nJson(pagesJson, locales[locale], delimiters)
}
}
if (!process.env.UNI_USING_V3) {
parsePages(
pagesJson,
function (page) {
updatePageJson(
page.path,
renameUsingComponents(parseStyle(page.style))
)
},
function (root, page) {
updatePageJson(
normalizePath(path.join(root, page.path)),
renameUsingComponents(parseStyle(page.style, root))
)
}
)
}
const jsonFiles = require('./platforms/' + process.env.UNI_PLATFORM)(
pagesJson,
manifestJson,
isAppView
)
if (jsonFiles && jsonFiles.length) {
if (process.env.UNI_USING_V3) {
let appConfigContent = ''
jsonFiles.forEach(jsonFile => {
if (jsonFile) {
if (!isAppView && jsonFile.name === 'manifest.json') {
const content = JSON.parse(jsonFile.content)
if (
!content.launch_path &&
content.plus['uni-app'].nvueLaunchMode === 'fast'
) {
console.log(
uniI18n.__('pagesLoader.nvueFirstPageStartModeIsFast', {
0: 'https://ask.dcloud.net.cn/article/36749'
})
)
}
}
if (jsonFile.name === 'define-pages.js') {
appConfigContent = jsonFile.content
} else {
// app-view 不需要生成 app-config-service.js,manifest.json
!isAppView && this.emitFile(jsonFile.name, jsonFile.content)
}
}
})
return this.callback(null, appConfigContent, map)
}
if (process.env.UNI_USING_NATIVE || process.env.UNI_USING_V3_NATIVE) {
let appConfigContent = ''
jsonFiles.forEach(jsonFile => {
if (jsonFile) {
if (
jsonFile.name === 'app-config.js' ||
jsonFile.name === 'define-pages.js'
) {
appConfigContent = jsonFile.content
} else {
this.emitFile(jsonFile.name, jsonFile.content)
}
}
})
return this.callback(null, appConfigContent, map)
}
jsonFiles.forEach(jsonFile => {
if (jsonFile) {
if (jsonFile.name === 'app') {
updateAppJson(jsonFile.name, renameUsingComponents(jsonFile.content))
} else {
updateProjectJson(jsonFile.name, jsonFile.content)
}
}
})
}
this.callback(null, '', map)
}
+119
View File
@@ -0,0 +1,119 @@
const fs = require('fs')
const path = require('path')
const loaderUtils = require('loader-utils')
const {
parsePages,
normalizePath,
parsePagesJson,
parseManifestJson
} = require('@dcloudio/uni-cli-shared')
const {
getPagesJson
} = require('@dcloudio/uni-cli-shared/lib/cache')
const {
pagesJsonJsFileName
} = require('@dcloudio/uni-cli-shared/lib/pages')
const parseStyle = require('./util').parseStyle
const emitFileCaches = {}
function checkEmitFile (filePath, jsonObj, changedEmitFiles) {
const content = JSON.stringify(jsonObj, null, 2)
if (emitFileCaches[filePath] !== content) {
changedEmitFiles.push(filePath)
emitFileCaches[filePath] = content
}
}
module.exports = function (content, map) {
// content = JSON.stringify(require('@dcloudio/uni-cli-shared/lib/uni_modules').getPagesJson(content))
let queryParam
if (this.resourceQuery) {
queryParam = loaderUtils.parseQuery(this.resourceQuery)
if (queryParam) {
if (queryParam.type === 'style') {
return `export default ${JSON.stringify(getPagesJson())}`
} else if (queryParam.type === 'stat') {
return `export default ${JSON.stringify(process.UNI_STAT_CONFIG || {})}`
}
}
}
// add deps
// global.uniModules.forEach(module => {
// const uniModulePagesJsonPath = path.resolve(process.env.UNI_INPUT_DIR, 'uni_modules', module, 'pages.json')
// if (fs.existsSync(uniModulePagesJsonPath)) {
// this.addDependency(uniModulePagesJsonPath)
// }
// })
if (
process.env.UNI_USING_COMPONENTS ||
process.env.UNI_PLATFORM === 'h5' ||
process.env.UNI_PLATFORM === 'quickapp-native'
) {
return require('./index-new').call(this, content, map)
}
this.cacheable && this.cacheable()
const manifestJsonPath = path.resolve(process.env.UNI_INPUT_DIR, 'manifest.json')
const pagesJsonJsPath = path.resolve(process.env.UNI_INPUT_DIR, pagesJsonJsFileName)
const manifestJson = parseManifestJson(fs.readFileSync(manifestJsonPath, 'utf8'))
this.addDependency(manifestJsonPath)
this.addDependency(pagesJsonJsPath)
const pagesJson = parsePagesJson(content, {
addDependency: (file) => {
(process.UNI_PAGES_DEPS || (process.UNI_PAGES_DEPS = new Set())).add(normalizePath(file))
this.addDependency(file)
}
})
if (this.resourceQuery && queryParam) {
if (queryParam) {
if (queryParam.type === 'origin-pages-json') {
return `export default ${JSON.stringify(pagesJson)}`
}
}
}
if (manifestJson.transformPx === false) {
process.UNI_TRANSFORM_PX = false
} else {
process.UNI_TRANSFORM_PX = true
}
if (process.env.UNI_PLATFORM === 'h5') {
return require('./platforms/h5')(pagesJson, manifestJson)
}
const changedEmitFiles = []
function checkPageEmitFile (pagePath, pageStyle) {
checkEmitFile(pagePath, parseStyle(pageStyle), changedEmitFiles)
}
parsePages(pagesJson, function (page) {
checkPageEmitFile(page.path, page.style)
}, function (root, page) {
checkPageEmitFile(normalizePath(path.join(root, page.path)), page.style)
})
const jsonFiles = require('./platforms/' + process.env.UNI_PLATFORM)(pagesJson, manifestJson)
if (jsonFiles && jsonFiles.length) {
jsonFiles.forEach(jsonFile => {
jsonFile && checkEmitFile(jsonFile.name, jsonFile.content, changedEmitFiles)
})
}
changedEmitFiles.forEach(name => {
this.emitFile(name + '.json', emitFileCaches[name])
})
this.callback(null, '', map)
}
@@ -0,0 +1,96 @@
const {
initI18nOptions
} = require('@dcloudio/uni-cli-shared/lib/i18n')
function parseRoutes (config) {
const __uniRoutes = []
/* eslint-disable no-mixed-operators */
const tabBarList = ((config.tabBar && config.tabBar.list) || []).map(
item => item.pagePath
)
Object.keys(config.page).forEach(function (pagePath) {
const isTabBar = tabBarList.indexOf(pagePath) !== -1
const isQuit = isTabBar || config.pages[0] === pagePath
const isNVue = !!config.page[pagePath].nvue
const route = {
path: '/' + pagePath,
meta: {},
window: config.page[pagePath].window || {}
}
if (isQuit) {
route.meta.isQuit = true
}
if (isNVue) {
route.meta.isNVue = true
}
if (isTabBar) {
route.meta.isTabBar = true
}
__uniRoutes.push(route)
})
return __uniRoutes
}
const GLOBALS = [
'global',
'window',
'document',
'frames',
'self',
'location',
'navigator',
'localStorage',
'history',
'Caches',
'screen',
'alert',
'confirm',
'prompt',
'fetch',
'XMLHttpRequest',
'WebSocket',
'webkit',
'print'
]
const globalStatement = GLOBALS.map(g => `${g}:void 0`).join(',')
module.exports = function definePages (appJson) {
const __uniRoutes = parseRoutes(appJson)
delete appJson.page
delete appJson.usingComponents
// 保留nvueCompiler
// delete appJson.nvueCompiler
// 保留renderer
// delete appJson.renderer
if (process.env.UNI_AUTOMATOR_WS_ENDPOINT) {
appJson.automator = true
}
const i18nOptions = initI18nOptions(
process.env.UNI_PLATFORM,
process.env.UNI_INPUT_DIR,
false,
true
)
if (i18nOptions) {
appJson.locale = ''
appJson.fallbackLocale = i18nOptions.locale
appJson.locales = i18nOptions.locales
}
return {
name: 'app-config-service.js',
content: `
var isReady=false;var onReadyCallbacks=[];
var isServiceReady=false;var onServiceReadyCallbacks=[];
var __uniConfig = ${JSON.stringify(appJson, null)};
var __uniRoutes = ${JSON.stringify(__uniRoutes)};
__uniConfig.onReady=function(callback){if(__uniConfig.ready){callback()}else{onReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"ready",{get:function(){return isReady},set:function(val){isReady=val;if(!isReady){return}const callbacks=onReadyCallbacks.slice(0);onReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
__uniConfig.onServiceReady=function(callback){if(__uniConfig.serviceReady){callback()}else{onServiceReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"serviceReady",{get:function(){return isServiceReady},set:function(val){isServiceReady=val;if(!isServiceReady){return}const callbacks=onServiceReadyCallbacks.slice(0);onServiceReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
service.register("uni-app-config",{create(a,b,c){if(!__uniConfig.viewport){var d=b.weex.config.env.scale,e=b.weex.config.env.deviceWidth,f=Math.ceil(e/d);Object.assign(__uniConfig,{viewport:f,defaultFontSize:Math.round(f/20)})}return{instance:{__uniConfig:__uniConfig,__uniRoutes:__uniRoutes,${globalStatement}}}}});
`
}
}
@@ -0,0 +1,40 @@
const fs = require('fs')
const {
parseTheme
} = require('@dcloudio/uni-cli-shared/lib/theme')
function generatePageCode (pages, pageOptions) {
return pages.map(pagePath => {
if (pageOptions[pagePath].nvue) {
return ''
}
return `__definePage('${pagePath}',function(){return Vue.extend(require('${pagePath}.vue?mpType=page').default)})`
}).join('\n')
}
function generateUniConfig (appJson, isAppView) {
return isAppView ? `window.__uniConfig = ${JSON.stringify(
{
window: parseTheme(appJson.window),
darkmode: appJson.darkmode
}
, null)};` : ''
}
function generatePolyfill () {
return fs.readFileSync(require.resolve('@dcloudio/uni-cli-shared/lib/uni-polyfill.js'), { encoding: 'utf8' })
}
module.exports = function definePages (appJson, isAppView) {
return {
name: 'define-pages.js',
content: `
${generatePolyfill()}
${generateUniConfig(appJson, isAppView)}
if(uni.restoreGlobal){
uni.restoreGlobal(weex,plus,setTimeout,clearTimeout,setInterval,clearInterval)
}
${generatePageCode(appJson.pages, appJson.page)}
`
}
}
@@ -0,0 +1,689 @@
const fs = require('fs')
const fsExtra = require('fs-extra')
const path = require('path')
const merge = require('merge')
const {
normalizePath,
getFlexDirection
} = require('@dcloudio/uni-cli-shared')
const {
getTheme,
hasTheme,
parseTheme
} = require('@dcloudio/uni-cli-shared/lib/theme')
const {
compileI18nJsonStr
} = require('@dcloudio/uni-i18n')
const {
initI18nOptions
} = require('@dcloudio/uni-cli-shared/lib/i18n')
const {
hasOwn,
parseStyle
} = require('../../util')
const wxPageOrientationMapping = {
auto: [
'portrait-primary',
'portrait-secondary',
'landscape-primary',
'landscape-secondary'
],
portrait: ['portrait-primary', 'portrait-secondary'],
landscape: ['landscape-primary', 'landscape-secondary']
}
function parseConfig (appJson) {
return {
name: 'app-config.js',
content: `__registerConfig(${JSON.stringify(appJson)});`
}
}
const _toString = Object.prototype.toString
function isPlainObject (obj) {
return _toString.call(obj) === '[object Object]'
}
function normalizeNetworkTimeout (appJson) {
if (!isPlainObject(appJson.networkTimeout)) {
appJson.networkTimeout = {
request: 60000,
connectSocket: 60000,
uploadFile: 60000,
downloadFile: 60000
}
} else {
if (typeof appJson.networkTimeout.request === 'undefined') {
appJson.networkTimeout.request = 60000
}
if (typeof appJson.networkTimeout.connectSocket === 'undefined') {
appJson.networkTimeout.connectSocket = 60000
}
if (typeof appJson.networkTimeout.uploadFile === 'undefined') {
appJson.networkTimeout.uploadFile = 60000
}
if (typeof appJson.networkTimeout.downloadFile === 'undefined') {
appJson.networkTimeout.downloadFile = 60000
}
}
}
function updateFileFlag (appJson) {
// 已经不再根据文件识别,理论可废弃此处的逻辑
if (process.env.UNI_USING_V3 || process.env.UNI_USING_V3_NATIVE) {
return
}
const nvueCompilerFilePath = path.resolve(
process.env.UNI_OUTPUT_DIR,
'__uniappnvuecompiler.js'
)
const nvueCompilerExists = fs.existsSync(nvueCompilerFilePath)
if (appJson.nvueCompiler === 'uni-app') {
if (!nvueCompilerExists) {
fsExtra.outputFile(nvueCompilerFilePath, '')
}
} else {
if (nvueCompilerExists) {
fs.unlinkSync(nvueCompilerFilePath)
}
}
const rendererFilePath = path.resolve(
process.env.UNI_OUTPUT_DIR,
'__uniapprenderer.js'
)
const rendererExists = fs.existsSync(rendererFilePath)
if (appJson.renderer === 'native') {
if (!rendererExists) {
fsExtra.outputFile(rendererFilePath, '')
}
} else {
if (rendererExists) {
fs.unlinkSync(rendererFilePath)
}
}
}
function _initTheme (appJson, userManifestJson) {
const manifestJson = userManifestJson[process.env.UNI_PLATFORM] || {}
appJson.darkmode = manifestJson.darkmode || false
const themeLocation = manifestJson.themeLocation || 'theme.json'
if (themeLocation && hasTheme(themeLocation)) {
appJson.themeConfig = getTheme()
}
return appJson
}
module.exports = function (pagesJson, userManifestJson, isAppView) {
const {
app
} = require('../mp')(pagesJson, userManifestJson)
const manifest = {
name: 'manifest'
}
const appJson = app.content
_initTheme(appJson, userManifestJson)
const parsedThemeAppJsonWindow = parseTheme(appJson.window)
const navigationBarTextStyle =
(pagesJson.pages[0].style && pagesJson.pages[0].style.navigationBarTextStyle) ||
(pagesJson.globalStyle && pagesJson.globalStyle.navigationBarTextStyle) ||
'black'
const navigationBarBackgroundColor = (parsedThemeAppJsonWindow && parsedThemeAppJsonWindow.navigationBarBackgroundColor) || '#000000'
const TABBAR_HEIGHT = 50
let manifestJson = JSON.parse(
fs.readFileSync(path.resolve(__dirname, './manifest.json'), 'utf8')
)
// 状态栏
manifestJson.plus.statusbar = {
immersed: 'supportedDevice',
style: navigationBarTextStyle === 'white' ? 'light' : 'dark',
background: navigationBarBackgroundColor
}
// 用户配置覆盖默认配置
manifestJson = merge.recursive(
true,
manifestJson, {
id: userManifestJson.appid || '',
name: userManifestJson.name || '',
description: userManifestJson.description || '',
version: {
name: userManifestJson.versionName,
code: userManifestJson.versionCode
},
locale: userManifestJson.locale,
uniStatistics: userManifestJson.uniStatistics
}, {
plus: userManifestJson['app-plus']
}
)
initUniStatistics(manifestJson)
const splashscreenOptions =
userManifestJson['app-plus'] && userManifestJson['app-plus'].splashscreen
const hasAlwaysShowBeforeRender =
splashscreenOptions &&
hasOwn(splashscreenOptions, 'alwaysShowBeforeRender')
// 转换为老版本配置
if (manifestJson.plus.modules) {
manifestJson.permissions = manifestJson.plus.modules
delete manifestJson.plus.modules
}
const distribute = manifestJson.plus.distribute
if (distribute) {
if (distribute.android) {
manifestJson.plus.distribute.google = distribute.android
delete manifestJson.plus.distribute.android
}
if (distribute.ios) {
manifestJson.plus.distribute.apple = distribute.ios
delete manifestJson.plus.distribute.ios
}
if (distribute.sdkConfigs) {
manifestJson.plus.distribute.plugins = distribute.sdkConfigs
delete manifestJson.plus.distribute.sdkConfigs
}
if (manifestJson.plus.darkmode) {
if (!(distribute.google || (distribute.google = {})).defaultNightMode) {
distribute.google.defaultNightMode = 'auto'
}
if (!(distribute.apple || (distribute.apple = {})).UIUserInterfaceStyle) {
distribute.apple.UIUserInterfaceStyle = 'Automatic'
}
}
}
// 屏幕启动方向
if (manifestJson.plus.screenOrientation) {
// app平台优先使用 manifest 配置
manifestJson.screenOrientation = manifestJson.plus.screenOrientation
delete manifestJson.plus.screenOrientation
} else if (appJson.window && appJson.window.pageOrientation) {
// 兼容微信小程序
const pageOrientationValue =
wxPageOrientationMapping[appJson.window.pageOrientation]
if (pageOrientationValue) {
manifestJson.screenOrientation = pageOrientationValue
}
}
// 全屏配置
manifestJson.fullscreen = manifestJson.plus.fullscreen
// 地图坐标系
if (manifestJson.permissions && manifestJson.permissions.Maps) {
manifestJson.permissions.Maps.coordType = 'gcj02'
}
if (!manifestJson.permissions) {
manifestJson.permissions = {}
}
const nvuePages = process.env.UNI_USING_V3_NATIVE
? pagesJson.pages
: pagesJson.nvue && pagesJson.nvue.pages
if (nvuePages && nvuePages.length) {
const pages = {}
nvuePages.forEach(({
path,
style
}) => {
pages[path] = {
window: parseStyle(style),
nvue: true
}
})
appJson.nvue = {
pages
}
if (process.env.UNI_USING_V3_NATIVE) {
appJson.nvue.entryPagePath = nvuePages[0]
} else if (pagesJson.nvue.entryPagePath) {
appJson.nvue.entryPagePath = pagesJson.nvue.entryPagePath
}
// nvue 权限
manifestJson.permissions.UniNView = {
description: 'UniNView原生渲染'
}
} else if (process.env.UNI_USING_V8) {
// nvue 权限
manifestJson.permissions.UniNView = {
description: 'UniNView原生渲染'
}
}
// 启动页面配置
if (process.env.NODE_ENV === 'development') {
const condition = pagesJson.condition
if (condition && Array.isArray(condition.list) && condition.list.length) {
const list = condition.list
let current = parseInt(condition.current) || 0
if (current < 0) {
current = 0
}
if (current >= list.length) {
current = 0
}
manifestJson.plus.arguments = JSON.stringify(list[current])
}
}
// 允许内联播放视频
manifestJson.plus.allowsInlineMediaPlayback = true
const addRenderAlways = function () {
// "render": "always"
if (!manifestJson.plus.launchwebview) {
manifestJson.plus.launchwebview = {
render: 'always'
}
} else if (!manifestJson.plus.launchwebview.render) {
manifestJson.plus.launchwebview.render = 'always'
}
}
if (appJson.tabBar && appJson.tabBar.list && appJson.tabBar.list.length) {
// 安全区配置 仅包含 tabBar 的时候才配置
if (!manifestJson.plus.safearea) {
manifestJson.plus.safearea = {
background: parseTheme(appJson.tabBar).backgroundColor || '#FFFFFF',
bottom: {
offset: 'auto'
}
}
}
if (!process.env.UNI_USING_COMPONENTS) {
// 非自定义组件模式下,仍旧添加 render always
addRenderAlways()
}
} else {
addRenderAlways()
}
let flexDir = false
if (process.env.UNI_USING_NVUE_COMPILER) {
appJson.nvueCompiler = 'uni-app'
flexDir = getFlexDirection(manifestJson.plus)
} else {
appJson.nvueCompiler = 'weex'
}
appJson.nvueStyleCompiler = process.env.UNI_USING_NVUE_STYLE_COMPILER
? 'uni-app'
: 'weex'
if (manifestJson.plus.renderer === 'native') {
appJson.renderer = 'native'
} else {
appJson.renderer = 'auto'
}
updateFileFlag(appJson)
appJson.splashscreen = {
alwaysShowBeforeRender: false, // 是否启用白屏检测 关闭 splash
autoclose: false // 是否 uni-app 框架关闭 splash
}
// 强制白屏检测
if (manifestJson.plus.splashscreen) {
if (
!hasAlwaysShowBeforeRender &&
manifestJson.plus.splashscreen.autoclose === false
) {
// 兼容旧版本仅配置了 autoclose 为 false
manifestJson.plus.splashscreen.alwaysShowBeforeRender = false
}
if (manifestJson.plus.splashscreen.alwaysShowBeforeRender) {
// 白屏检测
if (!manifestJson.plus.splashscreen.target) {
manifestJson.plus.splashscreen.target = 'id:1'
}
manifestJson.plus.splashscreen.autoclose = true
manifestJson.plus.splashscreen.delay = 0
appJson.splashscreen.alwaysShowBeforeRender = true
} else {
// 不启用白屏检测
delete manifestJson.plus.splashscreen.target
if (manifestJson.plus.splashscreen.autoclose) {
// 启用 uni-app 框架关闭 splash
manifestJson.plus.splashscreen.autoclose = false // 原 5+ autoclose 改为 false
appJson.splashscreen.autoclose = true
}
}
delete manifestJson.plus.splashscreen.alwaysShowBeforeRender
}
appJson.appname = manifestJson.name
if (!manifestJson.plus.distribute) {
manifestJson.plus.distribute = {
plugins: {}
}
}
if (!manifestJson.plus.distribute.plugins) {
manifestJson.plus.distribute.plugins = {}
}
// 录音支持 mp3
manifestJson.plus.distribute.plugins.audio = {
mp3: {
description: 'Android平台录音支持MP3格式文件'
}
}
// 有效值为 close,none
if (!['close', 'none'].includes(manifestJson.plus.popGesture + '')) {
manifestJson.plus.popGesture = 'close'
}
// 检查原生混淆选项
const confusion = manifestJson.plus.confusion
if (confusion && confusion.resources) {
const resources = {}
const nvuePages = (appJson.nvue && appJson.nvue.pages) || {}
for (const key in confusion.resources) {
if (path.extname(key) === '.js') {
// 支持 js 混淆,过滤掉
// 静态 js 文件
if (
key.indexOf('hybrid/html') === 0 ||
key.indexOf('static/') === 0 ||
key.indexOf('/static/') !== -1
) {
resources[key] = confusion.resources[key]
}
continue
}
if (!/\.nvue$/.test(key)) {
throw new Error(`原生混淆仅支持 nvue 页面,错误的页面路径:${key}`)
} else {
resources[key.replace(/\.nvue$/, '.js')] = confusion.resources[key]
}
if (
!Object.keys(nvuePages).find(path => {
const subNVues = nvuePages[path].window.subNVues || []
// TODO
return (
path.replace(/\.html$/, '.nvue') === key ||
path.replace(/\.html$/, '.nvue') + '.nvue' === key ||
subNVues.find(({
path
}) => path === key.replace(/\.nvue$/, ''))
)
}) &&
!pagesJson.pages.find(({
style = {}
}) => {
style = Object.assign(style, style['app-plus'])
const subNVues = style.subNVues || []
return subNVues.find(
({
path
}) => path === key.replace(/\.nvue$/, '')
)
})
) {
throw new Error(`原生混淆页面未在项目内使用,错误的页面路径:${key}`)
}
}
confusion.resources = resources
}
// uni-app
const uniApp = require('../../../package.json')['uni-app']
manifestJson.plus['uni-app'] = uniApp
// 控制页类型
const control =
process.env.UNI_USING_V3 || process.env.UNI_USING_V3_NATIVE
? 'uni-v3'
: process.env.UNI_USING_V8
? 'v8'
: 'webview'
manifestJson.plus['uni-app'].control = control
manifestJson.plus['uni-app'].nvueCompiler = appJson.nvueCompiler
// v3 + native 时强制 auto
manifestJson.plus['uni-app'].renderer = process.env.UNI_USING_V3_NATIVE
? 'auto'
: appJson.renderer
if (flexDir) {
manifestJson.plus['uni-app'].nvue = {
'flex-direction': flexDir
}
}
// 检查 webview 版本 || 下载 X5 后启动
const plusWebview = manifestJson.plus.webView
if (plusWebview) {
manifestJson.plus['uni-app'].webView = plusWebview
delete manifestJson.plus.webView
}
// 记录编译器版本号
appJson.compilerVersion = uniApp.compilerVersion
if (process.env.UNI_USING_V8) {
let entryPagePath = appJson.pages[0]
let conditionPagePath = false
if (manifestJson.plus.arguments) {
try {
const args = JSON.parse(manifestJson.plus.arguments)
if (args && (args.path || args.pathName)) {
entryPagePath = conditionPagePath = args.path || args.pathName
}
} catch (e) { }
}
let isNVueEntryPage = appJson.nvue && appJson.nvue.entryPagePath
conditionPagePath =
process.env.UNI_CLI_LAUNCH_PAGE_PATH || conditionPagePath
if (conditionPagePath && appJson.nvue) {
isNVueEntryPage = `${conditionPagePath}.html` in appJson.nvue.pages
}
manifestJson.plus.useragent.value = 'uni-app'
manifestJson.launch_path = '__uniappview.html'
Object.assign(manifestJson.plus.launchwebview, {
id: '1',
kernel: 'WKWebview',
'uni-app': 'auto'
})
if (process.env.UNI_USING_NATIVE) {
appJson.entryPagePath = appJson.nvue.entryPagePath
// networkTimeout
normalizeNetworkTimeout(appJson)
appJson.page = Object.create(null)
appJson.pages = Object.keys(appJson.nvue.pages).map(pagePath => {
const newPagePath = pagePath.replace('.html', '')
appJson.page[newPagePath] = {
window: appJson.nvue.pages[pagePath].window,
nvue: true
}
return newPagePath
})
delete appJson.nvue
delete manifestJson.plus.launchwebview.kernel
manifestJson.launch_path = ''
Object.assign(manifestJson.plus.launchwebview, {
uniNView: {
path: appJson.entryPagePath
}
})
} else if (isNVueEntryPage) {
// 非纯 nvue 项目首页为 nvue 页面
manifestJson.plus.launchwebview.id = '2'
manifestJson.plus.launchwebview.render = 'always'
}
// 带 tab
if (
pagesJson.tabBar &&
pagesJson.tabBar.list &&
pagesJson.tabBar.list.length
) {
const tabBar = (manifestJson.plus.tabBar = Object.assign({},
parseTheme(pagesJson.tabBar)
))
const borderStyles = {
black: 'rgba(0,0,0,0.4)',
white: 'rgba(255,255,255,0.4)'
}
let borderStyle = tabBar.borderStyle
if (!borderStyle) {
borderStyle = 'black'
}
if (borderStyle in borderStyles) {
tabBar.borderStyle = borderStyles[borderStyle]
}
if (!tabBar.selectedColor) {
tabBar.selectedColor = '#0062cc'
}
tabBar.height = `${parseFloat(tabBar.height) || TABBAR_HEIGHT}px`
// 非纯 nvue 项目首页为 nvue 页面
if (!process.env.UNI_USING_NATIVE && isNVueEntryPage) {
manifestJson.plus.launchwebview.id = '2'
} else {
// 首页是 tabBar 页面
const item = tabBar.list.find(
page =>
page.pagePath ===
(process.env.UNI_USING_NATIVE
? appJson.entryPagePath
: entryPagePath)
)
if (item) {
tabBar.child = ['lauchwebview']
tabBar.selected = tabBar.list.indexOf(item)
}
}
const i18nOptions = initI18nOptions(
process.env.UNI_PLATFORM,
process.env.UNI_INPUT_DIR,
true,
true
)
if (i18nOptions) {
manifestJson = JSON.parse(
compileI18nJsonStr(JSON.stringify(manifestJson), i18nOptions)
)
manifestJson.fallbackLocale = i18nOptions.locale
}
}
}
if (!process.env.UNI_USING_COMPONENTS) {
manifestJson.plus.launchwebview.kernel = 'UIWebview'
}
manifest.content = manifestJson
const subPackages = []
// 分包合并
if (appJson.subPackages && appJson.subPackages.length) {
appJson.subPackages.forEach(subPackage => {
if (subPackage.pages && subPackage.pages.length) {
subPackage.pages.forEach(page => {
appJson.pages.push(normalizePath(path.join(subPackage.root, page)))
})
subPackages.push({
root: subPackage.root
})
}
})
}
delete appJson.subPackages
// TODO 处理纯原生
if (process.env.UNI_USING_NATIVE) {
manifest.name = 'manifest.json'
manifest.content = JSON.stringify(manifest.content)
return [manifest, parseConfig(appJson)]
}
if (process.env.UNI_USING_V3 || process.env.UNI_USING_V3_NATIVE) {
if (process.env.UNI_USING_V3 && process.env.UNI_OPT_SUBPACKAGES) {
appJson.subPackages = subPackages
}
return require('./index.v3')(
appJson,
manifestJson, {
manifest,
pagesJson,
normalizeNetworkTimeout
},
isAppView
)
}
return [app, manifest]
}
function initUniStatistics (manifestJson) {
// 根节点配置了统计
if (manifestJson.uniStatistics) {
manifestJson.plus.uniStatistics = merge.recursive(
true,
manifestJson.uniStatistics,
manifestJson.plus.uniStatistics
)
delete manifestJson.uniStatistics
}
if (!process.env.UNI_CLOUD_PROVIDER) {
return
}
let spaces = []
try {
spaces = JSON.parse(process.env.UNI_CLOUD_PROVIDER)
} catch (e) { }
if (!Array.isArray(spaces) || !spaces.length) {
return
}
const space = spaces[0]
if (!space) {
return
}
const uniStatistics = manifestJson.plus && manifestJson.plus.uniStatistics
if (!uniStatistics) {
return
}
if (uniStatistics.version === 2 || uniStatistics.version === '2') {
if (uniStatistics.uniCloud && uniStatistics.uniCloud.spaceId) {
return
}
uniStatistics.uniCloud = {
provider: space.provider,
spaceId: space.spaceId,
clientSecret: space.clientSecret,
endpoint: space.endpoint
}
}
}
@@ -0,0 +1,113 @@
const path = require('path')
const {
normalizePath
} = require('@dcloudio/uni-cli-shared')
const {
parsePages,
addPageUsingComponents
} = require('@dcloudio/uni-cli-shared/lib/pages')
const {
parseStyle
} = require('../../util')
const definePages = require('./define-pages')
const appConfigService = require('./app-config-service')
function getTabBarPages (appJson) {
return appJson.tabBar &&
appJson.tabBar.list &&
appJson.tabBar.list.length &&
appJson.tabBar.list
}
function isTabBarPage (pathName, tabBarPages) {
return Array.isArray(tabBarPages) && tabBarPages.find(item => item.pagePath === pathName)
}
function parseEntryPagePath (appJson, manifestJson) {
const argsJsonStr = manifestJson.plus.arguments
if (argsJsonStr) {
try {
const args = JSON.parse(argsJsonStr)
const pathName = args.path || args.pathName
const entryPageQuery = (args.query ? ('?' + args.query) : '')
if (pathName && appJson.pages[0] !== pathName) {
appJson.entryPagePath = pathName
appJson.entryPageQuery = entryPageQuery
if (!isTabBarPage(pathName, getTabBarPages(appJson))) {
appJson.realEntryPagePath = appJson.pages[0]
}
}
} catch (e) {}
}
if (!appJson.entryPagePath) {
appJson.entryPagePath = appJson.pages[0]
}
}
module.exports = function (appJson, manifestJson, {
pagesJson,
manifest,
normalizeNetworkTimeout
}, isAppView) {
parseEntryPagePath(appJson, manifestJson)
// timeout
normalizeNetworkTimeout(appJson)
appJson.page = Object.create(null)
const addPage = function (pagePath, windowOptions, nvue) {
// 缓存页面级usingComponents
addPageUsingComponents(pagePath, windowOptions.usingComponents)
delete windowOptions.usingComponents
appJson.page[pagePath] = {
window: windowOptions,
nvue
}
}
parsePages(pagesJson, function (page) {
addPage(page.path, parseStyle(page.style), !!page.nvue)
}, function (root, page) {
addPage(normalizePath(path.join(root, page.path)), parseStyle(page.style, root), !!page.nvue)
})
// nvue 权限
manifestJson.permissions.UniNView = {
description: 'UniNView原生渲染'
}
manifestJson.plus.launchwebview.id = '1' // 首页 id 固定 为 1
// 删除首页 style 中的 uni-app 配置(不注入 app-view.js
delete manifestJson.plus.launchwebview['uni-app']
const entryPagePath = appJson.entryPagePath
if (!appJson.page[entryPagePath]) {
console.error(
`pages.json condition['list'][current]['path']: ${entryPagePath} 需在 pages 数组中`
)
process.exit(0)
}
if (appJson.page[entryPagePath].nvue) { // 首页是 nvue
manifestJson.launch_path = '' // 首页地址为空
manifestJson.plus.launchwebview.uniNView = {
path: entryPagePath + '.js' + (appJson.entryPageQuery || '')
}
const tabBar = manifestJson.plus.tabBar
if (tabBar && isTabBarPage(entryPagePath, tabBar.list)) {
tabBar.child = ['lauchwebview']
}
} else {
manifestJson.plus.launch_path = '__uniappview.html' // 首页地址固定
}
// nvue 首页启动模式
manifestJson.plus['uni-app'].nvueLaunchMode = manifestJson.plus.nvueLaunchMode === 'fast' ? 'fast' : 'normal'
delete manifestJson.plus.nvueLaunchMode
manifest.name = 'manifest.json'
manifest.content = JSON.stringify(manifest.content)
delete appJson.nvue
return [manifest, definePages(appJson, isAppView), appConfigService(appJson)]
}
@@ -0,0 +1,35 @@
{
"@platforms": [
"android",
"iPhone",
"iPad"
],
"id": "__WEAPP_ID",
"name": "__WEAPP_NAME",
"version": {
"name": "1.0",
"code": ""
},
"description": "",
"launch_path": "__uniappservice.html",
"developer": {
"name": "",
"email": "",
"url": ""
},
"permissions": {},
"plus": {
"useragent": {
"value": "uni-app appservice",
"concatenate": true
},
"splashscreen": {
"target":"id:1",
"autoclose": true,
"waiting": true,
"alwaysShowBeforeRender":true
},
"popGesture": "close",
"launchwebview": {}
}
}
@@ -0,0 +1,3 @@
module.exports = function createTabBarNView () {
}
+471
View File
@@ -0,0 +1,471 @@
const fs = require('fs')
const path = require('path')
const {
hasOwn,
getPlatforms,
getH5Options,
getFlexDirection,
getNetworkTimeout,
normalizePath
} = require('@dcloudio/uni-cli-shared')
const {
addPageUsingComponents
} = require('@dcloudio/uni-cli-shared/lib/pages')
const {
getTheme
} = require('@dcloudio/uni-cli-shared/lib/theme')
const compilerVersion = require('@dcloudio/webpack-uni-pages-loader/package.json')['uni-app'].compilerVersion
const PLATFORMS = getPlatforms()
const removePlatformStyle = function (style) {
Object.keys(style).forEach(name => {
if (PLATFORMS.includes(name)) {
delete style[name]
}
})
delete style.app
delete style.web
}
const getPageComponents = function (inputDir, pagesJson) {
const firstPagePath = pagesJson.pages[0].path
const pages = pagesJson.pages
// 解析分包
if (pagesJson.subPackages && pagesJson.subPackages.length) {
pagesJson.subPackages.forEach(({
root,
pages: subPages
}) => {
if (root && subPages.length) {
subPages.forEach(subPage => {
subPage.path = normalizePath(path.join(root, subPage.path))
pages.push(subPage)
})
}
})
}
const tabBarList = (pagesJson.tabBar && pagesJson.tabBar.list) || []
tabBarList.forEach(item => { // 添加全部属性,方便 Vue 响应式
item.text = item.text || ''
item.iconPath = item.iconPath || ''
item.selectedIconPath = item.selectedIconPath || ''
item.redDot = false
item.badge = ''
})
if (tabBarList.length) { // 添加全部属性,方便 Vue 响应式
pagesJson.tabBar.color = pagesJson.tabBar.color || '#999'
pagesJson.tabBar.selectedColor = pagesJson.tabBar.selectedColor || '#007aff'
pagesJson.tabBar.backgroundColor = pagesJson.tabBar.backgroundColor || ''
pagesJson.tabBar.borderStyle = pagesJson.tabBar.borderStyle || 'black'
}
const globalStyle = Object.assign({}, pagesJson.globalStyle || {})
Object.assign(
globalStyle,
globalStyle.app || globalStyle['app-plus'] || {},
globalStyle.web || globalStyle.h5 || {}
)
if (process.env.UNI_SUB_PLATFORM) {
Object.assign(globalStyle, globalStyle[process.env.UNI_SUB_PLATFORM] || {})
}
process.UNI_H5_PAGES_JSON = {
pages: {},
globalStyle
}
removePlatformStyle(process.UNI_H5_PAGES_JSON.globalStyle)
return pages.map(page => {
const name = page.path.replace(/\//g, '-')
const pagePath = normalizePath(path.resolve(inputDir, page.path))
const props = page.style || {}
const isEntry = firstPagePath === page.path
const tabBarIndex = tabBarList.findIndex(tabBarPage => tabBarPage.pagePath === page.path)
const isTabBar = tabBarIndex !== -1
let isNVue = false
if (process.env.UNI_USING_NVUE_COMPILER) {
if (!fs.existsSync(pagePath + '.vue') && fs.existsSync(pagePath + '.nvue')) {
isNVue = true
}
}
// 解析 titleNViewpullToRefresh
const h5Options = Object.assign({}, props.app || props['app-plus'] || {}, props.web || props.h5 || {})
if (process.env.UNI_SUB_PLATFORM) {
Object.assign(h5Options, props[process.env.UNI_SUB_PLATFORM] || {})
Object.assign(props, props[process.env.UNI_SUB_PLATFORM] || {})
}
removePlatformStyle(h5Options)
if (hasOwn(h5Options, 'titleNView')) {
props.titleNView = h5Options.titleNView
}
if (hasOwn(h5Options, 'pullToRefresh')) {
props.pullToRefresh = h5Options.pullToRefresh
}
let windowTop = 44
const pageStyle = Object.assign({}, globalStyle, props)
const titleNViewTypeList = {
none: 'default',
auto: 'transparent',
always: 'float'
}
let titleNView = pageStyle.titleNView
titleNView = Object.assign({}, {
type: pageStyle.navigationStyle === 'custom' ? 'none' : 'default'
},
pageStyle.transparentTitle in titleNViewTypeList ? {
type: titleNViewTypeList[pageStyle.transparentTitle],
backgroundColor: 'rgba(0,0,0,0)'
}
: null,
typeof titleNView === 'object'
? titleNView
: (
typeof titleNView === 'boolean' ? {
type: titleNView ? 'default' : 'none'
}
: null
)
)
if (titleNView.type === 'none' || titleNView.type === 'transparent') {
windowTop = 0
}
// 删除 app-plus 平台配置
delete props.app
delete props['app-plus']
delete props.web
delete props.h5
if (process.env.UNI_SUB_PLATFORM) {
delete props[process.env.UNI_SUB_PLATFORM]
}
process.UNI_H5_PAGES_JSON.pages[page.path] = props
// 缓存usingComponents
addPageUsingComponents(page.path, props.usingComponents)
return {
name,
route: page.path,
path: pagePath,
props,
isNVue,
isEntry,
isTabBar,
tabBarIndex,
isQuit: isEntry || isTabBar,
windowTop,
topWindow: pageStyle.topWindow,
leftWindow: pageStyle.leftWindow,
rightWindow: pageStyle.rightWindow,
maxWidth: pageStyle.maxWidth
}
}).filter(pageComponents => !!pageComponents)
}
const genRegisterPageVueComponentsCode = function (pageComponents) {
return pageComponents
.map(({
name,
path,
isNVue,
isQuit,
isEntry,
isTabBar
}) => {
const ext = isNVue ? '.nvue' : '.vue'
return `Vue.component('${name}', resolve=>{
const component = {
component:require.ensure([], () => resolve(require(${JSON.stringify(path)}+'${ext}')), '${name}'),
delay:__uniConfig['async'].delay,
timeout: __uniConfig['async'].timeout
}
if(__uniConfig['async']['loading']){
component.loading={
name:'SystemAsyncLoading',
render(createElement){
return createElement(__uniConfig['async']['loading'])
}
}
}
if(__uniConfig['async']['error']){
component.error={
name:'SystemAsyncError',
render(createElement){
return createElement(__uniConfig['async']['error'])
}
}
}
return component
})`
})
.join('\n')
}
const genPageRoutes = function (pageComponents) {
let id = 1
return pageComponents
.map(({
name,
route,
props,
isNVue,
isQuit,
isEntry,
isTabBar,
windowTop,
tabBarIndex,
topWindow,
leftWindow,
rightWindow,
maxWidth
}) => {
return `
{
path: '/${isEntry ? '' : route}',${isEntry ? '\nalias:\'/' + route + '\',' : ''}
component: {
render (createElement) {
return createElement(
'Page',
{
props: Object.assign({
${isQuit ? 'isQuit:true,\n' : ''}${isEntry ? 'isEntry:true,\n' : ''}${isTabBar ? 'isTabBar:true,\n' : ''}
${topWindow === false ? 'topWindow:false,\n' : ''}${leftWindow === false ? 'leftWindow:false,\n' : ''}${rightWindow === false ? 'rightWindow:false,\n' : ''}
${isTabBar ? ('tabBarIndex:' + tabBarIndex) : ''}
},__uniConfig.globalStyle,${JSON.stringify(props)})
},
[
createElement('${name}', {
slot: 'page'
})
]
)
}
},
meta:{${isQuit ? '\nid:' + (id++) + ',' : ''}
name:'${name}',
isNVue:${isNVue},maxWidth:${maxWidth || 0},${topWindow === false ? 'topWindow:false,\n' : ''}${leftWindow === false ? 'leftWindow:false,\n' : ''}${rightWindow === false ? 'rightWindow:false,\n' : ''}
pagePath:'${route}'${isQuit ? ',\nisQuit:true' : ''}${isEntry ? ',\nisEntry:true' : ''}${isTabBar ? ',\nisTabBar:true' : ''}${tabBarIndex !== -1 ? (',\ntabBarIndex:' + tabBarIndex) : ''},
windowTop:${windowTop}
}
}`
})
}
const genSystemRoutes = function () {
return [
`
{
path: '/choose-location',
component: {
render (createElement) {
return createElement(
'Page',
{
props:{
navigationStyle:'custom'
}
},
[
createElement('system-choose-location', {
slot: 'page'
})
]
)
}
},
meta:{
name:'choose-location',
pagePath:'/choose-location'
}
}
`,
`
{
path: '/open-location',
component: {
render (createElement) {
return createElement(
'Page',
{
props:{
navigationStyle:'custom'
}
},
[
createElement('system-open-location', {
slot: 'page'
})
]
)
}
},
meta:{
name:'open-location',
pagePath:'/open-location'
}
}
`
]
}
function filterPages (pagesJson, includes) {
const pages = []
let subPackages = pagesJson.subPackages || []
if (!Array.isArray(subPackages)) {
subPackages = []
}
includes.forEach(includePagePath => {
let page = pagesJson.pages.find(page => page.path === includePagePath)
if (!page) {
for (let i = 0; i < subPackages.length; i++) {
const {
root,
pages: subPages
} = subPackages[i]
page = subPages.find(subPage => normalizePath(path.join(root, subPage.path)) === includePagePath)
if (page) {
break
}
}
}
if (!page) {
console.error(`${includePagePath} is not found`)
}
pages.push(page)
})
pagesJson.pages = pages
}
function genLayoutComponentsCode (pagesJson) {
const code = []
const {
topWindow,
leftWindow,
rightWindow
} = pagesJson
if (topWindow && topWindow.path) {
code.push(
`import TopWindow from './${topWindow.path}';
${topWindow.style ? ('TopWindow.style=' + JSON.stringify(topWindow.style)) : ''}
Vue.component('VUniTopWindow',TopWindow);`
)
}
if (leftWindow && leftWindow.path) {
code.push(
`import LeftWindow from './${leftWindow.path}';
${leftWindow.style ? ('LeftWindow.style=' + JSON.stringify(leftWindow.style)) : ''}
Vue.component('VUniLeftWindow',LeftWindow);`
)
}
if (rightWindow && rightWindow.path) {
code.push(
`
import RightWindow from './${rightWindow.path}';
${rightWindow.style ? ('RightWindow.style=' + JSON.stringify(rightWindow.style)) : ''}
Vue.component('VUniRightWindow',RightWindow);`
)
}
return code.join('\n')
}
module.exports = function (pagesJson, manifestJson, loader) {
const inputDir = process.env.UNI_INPUT_DIR
global.uniPlugin.configurePages.forEach(configurePages => {
configurePages(pagesJson, manifestJson, loader)
})
if (loader.resourceQuery) {
const loaderUtils = require('loader-utils')
const params = loaderUtils.parseQuery(loader.resourceQuery)
if (params.pages) {
try {
const pages = JSON.parse(params.pages)
if (Array.isArray(pages)) {
filterPages(pagesJson, pages)
}
} catch (e) {}
}
}
const pageComponents = getPageComponents(inputDir, pagesJson)
pagesJson.globalStyle = process.UNI_H5_PAGES_JSON.globalStyle
delete pagesJson.pages
delete pagesJson.subPackages
const h5 = getH5Options(manifestJson)
const networkTimeoutConfig = getNetworkTimeout(manifestJson)
const sdkConfigs = h5.sdkConfigs || {}
const tempTencentMapKey = sdkConfigs.maps && sdkConfigs.maps.tencent && sdkConfigs.maps.tencent.key
const tempQQMapKey = sdkConfigs.maps && sdkConfigs.maps.qqmap && sdkConfigs.maps.qqmap.key
const qqMapKey = tempTencentMapKey || tempQQMapKey
const googleMapKey = sdkConfigs.maps && sdkConfigs.maps.google && sdkConfigs.maps.google.key
const aMapKey = sdkConfigs.maps && sdkConfigs.maps.amap && sdkConfigs.maps.amap.key
const aMapSecurityJsCode =
sdkConfigs.maps && sdkConfigs.maps.amap && sdkConfigs.maps.amap.securityJsCode
const aMapServiceHost =
sdkConfigs.maps && sdkConfigs.maps.amap && sdkConfigs.maps.amap.serviceHost
let locale = manifestJson.locale
locale = locale && locale.toUpperCase() !== 'AUTO' ? locale : ''
return `
import Vue from 'vue'
${genLayoutComponentsCode(pagesJson)}
const locales = ${fs.existsSync(path.resolve(process.env.UNI_INPUT_DIR, 'locale')) ? 'require.context(\'./locale\', false, /.json$/)' : '{keys(){return []}}'}
global['____${h5.appid}____'] = true;
delete global['____${h5.appid}____'];
global.__uniConfig = ${JSON.stringify(pagesJson)};
global.__uniConfig.compilerVersion = '${compilerVersion}';
global.__uniConfig.darkmode = ${JSON.stringify(h5.darkmode || false)};
global.__uniConfig.themeConfig = ${JSON.stringify(getTheme())};
global.__uniConfig.uniPlatform = '${process.env.UNI_PLATFORM}';
global.__uniConfig.appId = '${process.env.UNI_APP_ID}';
global.__uniConfig.appName = '${process.env.UNI_APP_NAME}';
global.__uniConfig.appVersion = '${process.env.UNI_APP_VERSION_NAME}';
global.__uniConfig.appVersionCode = '${process.env.UNI_APP_VERSION_CODE}';
global.__uniConfig.router = ${JSON.stringify(h5.router)};
global.__uniConfig.publicPath = ${JSON.stringify(h5.publicPath)};
global.__uniConfig['async'] = ${JSON.stringify(h5.async)};
global.__uniConfig.debug = ${manifestJson.debug === true};
global.__uniConfig.networkTimeout = ${JSON.stringify(networkTimeoutConfig)};
global.__uniConfig.sdkConfigs = ${JSON.stringify(sdkConfigs)};
global.__uniConfig.qqMapKey = ${JSON.stringify(qqMapKey)};
global.__uniConfig.googleMapKey = ${JSON.stringify(googleMapKey)};
global.__uniConfig.aMapKey = ${JSON.stringify(aMapKey)};
global.__uniConfig.aMapSecurityJsCode = ${JSON.stringify(aMapSecurityJsCode)};
global.__uniConfig.aMapServiceHost = ${JSON.stringify(aMapServiceHost)};
global.__uniConfig.locale = ${JSON.stringify(locale)};
global.__uniConfig.fallbackLocale = ${JSON.stringify(manifestJson.fallbackLocale)};
global.__uniConfig.locales = locales.keys().reduce((res,key)=>{const locale=key.replace(/\\.\\/(uni-app.)?(.*).json/,'$2');const messages = locales(key);Object.assign(res[locale]||(res[locale]={}),messages.common||messages);return res},{});
global.__uniConfig.nvue = ${JSON.stringify({ 'flex-direction': getFlexDirection(manifestJson['app-plus']) })}
global.__uniConfig.__webpack_chunk_load__ = __webpack_chunk_load__
${genRegisterPageVueComponentsCode(pageComponents)}
global.__uniRoutes=[${genPageRoutes(pageComponents).concat(genSystemRoutes()).join(',')}]
global.UniApp && new global.UniApp();
`
}
@@ -0,0 +1,148 @@
const fs = require('fs')
const path = require('path')
const {
parsePages,
getPlatformProject
} = require('@dcloudio/uni-cli-shared')
const {
updateAppJsonUsingComponents
} = require('@dcloudio/uni-cli-shared/lib/cache')
const {
hasOwn,
parseStyle,
parseTabBar,
NON_APP_JSON_KEYS
} = require('../util')
function defaultCopy (name, value, json) {
json[name] = value
}
const pagesJson2AppJson = {
globalStyle: function (name, value, json) {
json.window = parseStyle(value)
if (json.window.usingComponents) {
json.usingComponents = json.window.usingComponents
delete json.window.usingComponents
}
},
tabBar: function (name, value, json) {
json.tabBar = parseTabBar(value)
},
preloadRule: defaultCopy,
entryPagePath: defaultCopy
}
function copyToJson (json, fromJson, options) {
Object.keys(options).forEach(name => {
if (hasOwn(fromJson, name)) {
options[name](name, fromJson[name], json)
}
})
}
function parseCondition (pagesJson) {
const condition = pagesJson.condition
const launchPagePath = process.env.UNI_CLI_LAUNCH_PAGE_PATH || ''
const launchPageQuery = process.env.UNI_CLI_LAUNCH_PAGE_QUERY || ''
const launchPageOptions = {
title: launchPagePath,
page: launchPagePath,
pageQuery: launchPageQuery
}
const compileModeJson = {
modes: []
}
if (condition && Array.isArray(condition.list) && condition.list.length) {
compileModeJson.modes = condition.list.map(item => {
return {
title: item.name,
page: item.path,
pageQuery: item.query
}
})
delete pagesJson.condition
}
if (launchPagePath) {
compileModeJson.modes = [launchPageOptions]
}
const miniIdeDir = path.join(process.env.UNI_OUTPUT_DIR, '.mini-ide')
if (!fs.existsSync(miniIdeDir)) {
fs.mkdirSync(miniIdeDir, { recursive: true })
fs.writeFileSync(
path.join(miniIdeDir, 'compileMode.json'),
JSON.stringify(compileModeJson, null, 2)
)
}
}
const projectKeys = ['component2', 'enableAppxNg']
module.exports = function (pagesJson, manifestJson) {
const app = {
pages: [],
subPackages: []
}
const subPackages = {}
parsePages(pagesJson, function (page) {
app.pages.push(page.path)
}, function (root, page, subPackage) {
if (!subPackages[root]) {
subPackages[root] = {
root,
pages: []
}
Object.keys(subPackage).forEach(name => {
if (['root', 'pages'].indexOf(name) === -1) {
subPackages[root][name] = subPackage[name]
}
})
}
subPackages[root].pages.push(page.path)
})
Object.keys(subPackages).forEach(root => {
app.subPackages.push(subPackages[root])
})
copyToJson(app, pagesJson, pagesJson2AppJson)
const platformJson = manifestJson['mp-alipay'] || {}
Object.keys(platformJson).forEach(key => {
if (!projectKeys.includes(key) && !NON_APP_JSON_KEYS.includes(key)) {
// usingComponents 是编译模式开关,需要过滤,不能拷贝到 app
app[key] = platformJson[key]
}
})
if (app.usingComponents) {
updateAppJsonUsingComponents(app.usingComponents)
}
const projectName = getPlatformProject()
let project = {}
const projectPath = path.resolve(process.env.UNI_INPUT_DIR, projectName)
if (fs.existsSync(projectPath)) {
project = require(projectPath)
} else {
project.component2 = hasOwn(platformJson, 'component2') ? platformJson.component2 : true
project.enableAppxNg = hasOwn(platformJson, 'enableAppxNg') ? platformJson.enableAppxNg : true
}
parseCondition(pagesJson)
return [{
name: 'app',
content: app
}, {
name: 'mini.project',
content: project
}]
}
@@ -0,0 +1,29 @@
module.exports = function (pagesJson, manifestJson) {
const {
app,
project
} = require('../mp')(pagesJson, manifestJson, require('./project.swan.json'))
const content = project.content
const miniprogram = content.condition && content.condition.miniprogram
if (miniprogram && Array.isArray(miniprogram.list) && miniprogram.list.length) {
content['compilation-args'].options = miniprogram.list.map((item) => {
return {
id: item.id,
text: item.name,
extra: {
index: item.pathName,
query: item.query
}
}
})
delete content.condition
}
project.name = 'project.swan'
return [
app,
project
]
}
@@ -0,0 +1,13 @@
{
"appid": "",
"compilation-args": {
"selected": -3
},
"appInfo": {},
"appkey": "",
"condition": {},
"setting": {
"urlCheck": true
},
"libVersion": ""
}
@@ -0,0 +1,10 @@
module.exports = function (pagesJson, manifestJson) {
const {
app,
project
} = require('../mp')(pagesJson, manifestJson, require('./project.config.json'))
const [key, value] = ['component2', true]
app.content = app.content || {}
app.content[key] = key in pagesJson ? pagesJson[key] : value
return [app, project]
}
@@ -0,0 +1,11 @@
{
"setting": {
"urlCheck": true,
"es6": false,
"postcss": false,
"minified": false,
"newFeature": true
},
"appid": "testAppId",
"projectname": ""
}
@@ -0,0 +1,11 @@
module.exports = function (pagesJson, manifestJson) {
const {
app,
project
} = require('../mp')(pagesJson, manifestJson, require('./project.config.json'))
// 暂不支持分包,兼容引擎判断
if (app.content.subPackages && !app.content.subPackages.length) {
delete app.content.subPackages
}
return [app, project]
}
@@ -0,0 +1,11 @@
{
"setting": {
"urlCheck": true,
"es6": false,
"postcss": false,
"minified": false,
"newFeature": true
},
"appid": "testAppId",
"projectname": ""
}
@@ -0,0 +1,7 @@
module.exports = function (pagesJson, manifestJson) {
const {
app,
project
} = require('../mp')(pagesJson, manifestJson, require('./project.config.json'))
return [app, project]
}
@@ -0,0 +1,6 @@
{
"description": "项目配置文件。",
"libVersion": "0.6.0",
"appid": "touristappid",
"projectname": ""
}
@@ -0,0 +1,7 @@
module.exports = function (pagesJson, manifestJson) {
const {
app,
project
} = require('../mp')(pagesJson, manifestJson, require('./project.config.json'))
return [app, project]
}
@@ -0,0 +1,11 @@
{
"setting": {
"urlCheck": true,
"es6": false,
"postcss": false,
"minified": false,
"newFeature": true
},
"appid": "testAppId",
"projectname": ""
}
@@ -0,0 +1,17 @@
module.exports = function (pagesJson, manifestJson) {
const {
app,
project
} = require('../mp')(pagesJson, manifestJson, require('./project.config.json'))
if (app.content && app.content.subPackages && app.content.subPackages.length === 0) {
delete app.content.subPackages
}
if (project) {
project.content.qqappid = project.content.appid
project.content.qqLibVersion = project.content.libVersion
delete project.content.appid
delete project.content.libVersion
}
return [app, project]
}
@@ -0,0 +1,36 @@
{
"description": "项目配置文件。",
"packOptions": {
"ignore": []
},
"setting": {
"urlCheck": true,
"es6": false,
"postcss": false,
"minified": false,
"newFeature": true,
"nodeModules": false
},
"compileType": "miniprogram",
"libVersion": "1.6.3",
"appid": "touristappid",
"projectname": "",
"condition": {
"search": {
"current": -1,
"list": []
},
"conversation": {
"current": -1,
"list": []
},
"game": {
"current": -1,
"list": []
},
"miniprogram": {
"current": -1,
"list": []
}
}
}
@@ -0,0 +1,10 @@
module.exports = function (pagesJson, manifestJson) {
const {
app,
project
} = require('../mp')(pagesJson, manifestJson, require('./project.config.json'))
const [key, value] = ['component2', true]
app.content = app.content || {}
app.content[key] = key in pagesJson ? pagesJson[key] : value
return [app, project]
}
@@ -0,0 +1,11 @@
{
"setting": {
"urlCheck": true,
"es6": false,
"postcss": false,
"minified": false,
"newFeature": true
},
"appid": "testAppId",
"projectname": ""
}
@@ -0,0 +1,7 @@
module.exports = function (pagesJson, manifestJson) {
const {
app,
project
} = require('../mp')(pagesJson, manifestJson, require('./project.config.json'))
return [app, project]
}
@@ -0,0 +1,36 @@
{
"description": "项目配置文件。",
"packOptions": {
"ignore": []
},
"setting": {
"urlCheck": true,
"es6": false,
"postcss": false,
"minified": false,
"newFeature": true,
"bigPackageSizeSupport": true
},
"compileType": "miniprogram",
"libVersion": "",
"appid": "touristappid",
"projectname": "",
"condition": {
"search": {
"current": -1,
"list": []
},
"conversation": {
"current": -1,
"list": []
},
"game": {
"current": -1,
"list": []
},
"miniprogram": {
"current": -1,
"list": []
}
}
}
@@ -0,0 +1,7 @@
module.exports = function (pagesJson, manifestJson) {
const {
app,
project
} = require('../mp')(pagesJson, manifestJson, require('./project.config.json'))
return [app, project]
}
@@ -0,0 +1,11 @@
{
"setting": {
"urlCheck": true,
"es6": false,
"postcss": false,
"minified": false,
"newFeature": true
},
"appid": "testAppId",
"projectname": ""
}
+396
View File
@@ -0,0 +1,396 @@
const fs = require('fs')
const path = require('path')
const merge = require('merge')
const {
parsePages,
normalizePath,
getPlatformProject,
isSupportSubPackages
} = require('@dcloudio/uni-cli-shared')
const {
updateAppJsonUsingComponents
} = require('@dcloudio/uni-cli-shared/lib/cache')
const {
darkmode,
hasTheme
} = require('@dcloudio/uni-cli-shared/lib/theme')
const {
hasOwn,
parseStyle,
trimMPJson,
NON_APP_JSON_KEYS
} = require('../util')
const uniI18n = require('@dcloudio/uni-cli-i18n')
function defaultCopy (name, value, json) {
json[name] = value
}
function isPlainObject (a) {
if (a === null) {
return false
}
return typeof a === 'object'
}
function deepCopy (name, value, json) {
if (isPlainObject(value) && isPlainObject(json[name])) {
json[name] = merge.recursive(true, json[name], value)
} else {
defaultCopy(name, value, json)
}
}
const pagesJson2AppJson = {
globalStyle: function (name, value, json) {
json.window = parseStyle(value)
if (json.window.usingComponents || json.window.usingSwanComponents) {
// 暂定 usingComponents 优先级高于 usingSwanComponents
json.usingComponents = Object.assign({}, json.window.usingSwanComponents, json.window.usingComponents)
delete json.window.usingComponents
delete json.window.usingSwanComponents
} else {
json.usingComponents = {}
}
},
tabBar: function (name, value, json, fromJson) {
if (value && value.list && value.list.length) {
if (value.list.length < 2) {
console.error(
uniI18n.__('pagesLoader.pagesTabbarMinItem2', {
0: 'tabBar.list'
})
)
}
const pages = json.pages
value.list.forEach((page, index) => {
if (!pages.includes(page.pagePath)) {
if (
!(
fromJson &&
fromJson.nvue &&
fromJson.nvue.pages &&
fromJson.nvue.pages.find(
({
path
}) => path === page.pagePath + '.html'
)
)
) {
console.error(
uniI18n.__('pagesLoader.needInPagesNode', {
0: `pages.json tabBar['list'][${index}]['pagePath'] "${page.pagePath}"`
})
)
}
}
})
}
json[name] = value
},
preloadRule: defaultCopy,
workers: defaultCopy,
plugins: defaultCopy,
entryPagePath: defaultCopy
}
const manifestJson2AppJson = {
networkTimeout: defaultCopy,
debug: defaultCopy
}
function parseCondition (projectJson, pagesJson) {
if (process.env.NODE_ENV === 'development') {
// 仅开发期间 condition 生效
// 启动Condition
const condition = getCondition(pagesJson)
if (condition) {
if (!projectJson.condition) {
projectJson.condition = {}
}
projectJson.condition.miniprogram = condition
}
}
}
const pagesJson2ProjectJson = {}
const manifestJson2ProjectJson = {
name: function (name, value, json) {
if (!value) {
value = path.basename(process.env.UNI_INPUT_DIR)
if (value === 'src') {
value = path.basename(path.dirname(process.env.UNI_INPUT_DIR))
}
}
json.projectname = value
}
}
const platformJson2ProjectJson = {
appid: defaultCopy,
setting: deepCopy,
miniprogramRoot: defaultCopy,
cloudfunctionRoot: defaultCopy,
qcloudRoot: defaultCopy,
pluginRoot: defaultCopy,
compileType: defaultCopy,
libVersion: defaultCopy,
projectname: defaultCopy,
packOptions: deepCopy,
debugOptions: deepCopy,
scripts: deepCopy,
cloudbaseRoot: defaultCopy
}
function copyToJson (json, fromJson, options) {
Object.keys(options).forEach(name => {
if (hasOwn(fromJson, name)) {
options[name](name, fromJson[name], json, fromJson)
}
})
}
function getCondition (pagesJson) {
const condition = pagesJson.condition
const launchPagePath = process.env.UNI_CLI_LAUNCH_PAGE_PATH || ''
const launchPageQuery = process.env.UNI_CLI_LAUNCH_PAGE_QUERY || ''
const launchPageOptions = {
id: 0,
name: launchPagePath, // 模式名称
pathName: launchPagePath, // 启动页面,必选
query: launchPageQuery // 启动参数,在页面的onLoad函数里面得到。
}
if (condition) {
let current = -1
if (Array.isArray(condition.list) && condition.list.length) {
condition.list.forEach(function (item, index) {
item.id = item.id || index
if (item.path) {
item.pathName = item.path
delete item.path
}
if (launchPagePath) {
if (
item.pathName === launchPagePath &&
item.query === launchPageQuery
) {
// 指定了入口页
current = index
}
}
})
if (launchPagePath) {
if (current !== -1) {
// 已存在
condition.current = current
} else {
// 不存在
condition.list.push(
Object.assign(launchPageOptions, {
id: condition.list.length
})
)
condition.current = condition.list.length - 1
}
}
return condition
}
}
if (launchPagePath) {
pagesJson.condition = {
current: 0,
list: [launchPageOptions]
}
return pagesJson.condition
}
return false
}
function weixinSkyline (config) {
return config.renderer === 'skyline' && config.lazyCodeLoading === 'requiredComponents'
}
function openES62ES5 (config) {
if (!config.setting) {
config.setting = {}
}
if (!config.setting.es6) {
config.setting.es6 = true
}
}
module.exports = function (pagesJson, manifestJson, project = {}) {
const app = {
pages: [],
subPackages: []
}
const subPackages = {}
parsePages(
pagesJson,
function (page) {
app.pages.push(page.path)
},
function (root, page, subPackage) {
if (!isSupportSubPackages()) {
// 不支持分包
app.pages.push(normalizePath(path.join(root, page.path)))
} else {
if (!subPackages[root]) {
subPackages[root] = {
root,
pages: []
}
Object.keys(subPackage).forEach(name => {
if (['root', 'pages'].indexOf(name) === -1) {
subPackages[root][name] = subPackage[name]
}
})
}
subPackages[root].pages.push(page.path)
}
}
)
Object.keys(subPackages).forEach(root => {
app.subPackages.push(subPackages[root])
})
copyToJson(app, pagesJson, pagesJson2AppJson)
copyToJson(app, manifestJson, manifestJson2AppJson)
if (app.usingComponents) {
updateAppJsonUsingComponents(app.usingComponents)
}
const themeLocation = (manifestJson[process.env.UNI_PLATFORM] || {}).themeLocation
if (darkmode() && hasTheme(themeLocation)) {
app.themeLocation = themeLocation || 'theme.json'
}
const projectName = getPlatformProject()
const projectPath =
projectName &&
path.resolve(process.env.VUE_CLI_CONTEXT || process.cwd(), projectName)
if (projectPath && fs.existsSync(projectPath)) {
// 自定义 project.config.json
const platform = process.env.UNI_PLATFORM
// app-plus时不需要处理平台配置到 app 中
if (platform !== 'app-plus' && hasOwn(manifestJson, platform)) {
const platformJson = manifestJson[platform] || {}
const projectKeys = Object.keys(platformJson2ProjectJson)
Object.keys(platformJson).forEach(key => {
if (
!projectKeys.includes(key) && !NON_APP_JSON_KEYS.includes(key)
) {
// usingComponents 是编译模式开关,需要过滤,不能拷贝到 app
app[key] = platformJson[key]
}
})
}
if (
platform === 'mp-weixin' ||
platform === 'mp-qq'
) {
// 微信不需要生成,其他平台做拷贝
return {
app: {
name: 'app',
content: trimMPJson(app)
}
}
}
return {
app: {
name: 'app',
content: trimMPJson(app)
},
project: {
name: 'project.config',
content: require(projectPath)
}
}
} else {
parseCondition(project, pagesJson)
copyToJson(project, pagesJson, pagesJson2ProjectJson)
copyToJson(project, manifestJson, manifestJson2ProjectJson)
const platform = process.env.UNI_PLATFORM
// app-plus时不需要处理平台配置到 app 中
if (platform !== 'app-plus' && hasOwn(manifestJson, platform)) {
const platformJson = manifestJson[platform] || {}
copyToJson(project, platformJson, platformJson2ProjectJson)
const projectKeys = Object.keys(platformJson2ProjectJson)
Object.keys(platformJson).forEach(key => {
if (
!projectKeys.includes(key) && !NON_APP_JSON_KEYS.includes(key)
) {
// usingComponents 是编译模式开关,需要过滤,不能拷贝到 app
app[key] = platformJson[key]
}
})
}
// 引用了原生小程序组件,自动开启 ES6=>ES5
const wxcomponentsPath = path.resolve(
process.env.UNI_INPUT_DIR,
'./wxcomponents'
)
if (fs.existsSync(wxcomponentsPath)) {
const wxcomponentsFiles = fs.readdirSync(wxcomponentsPath)
if (wxcomponentsFiles.length) {
if (!project.setting) {
project.setting = {}
}
project.setting.es6 = true
}
}
// 使用了微信小程序手势系统,自动开启 ES6=>ES5
platform === 'mp-weixin' && weixinSkyline(manifestJson[platform]) && openES62ES5(project)
if (process.env.UNI_AUTOMATOR_WS_ENDPOINT) {
if (!project.setting) {
project.setting = {}
}
// automator时,强制不检测域名
project.setting.urlCheck = false
}
if (!project.appid) {
project.appid = 'touristappid'
}
return {
app: {
name: 'app',
content: trimMPJson(app)
},
project: {
name: 'project.config',
content: project
}
}
}
}
@@ -0,0 +1,3 @@
module.exports = function (pagesJson, manifestJson, loader) {
return require('@dcloudio/uni-quickapp-native/lib/manifest')(pagesJson, manifestJson, loader)
}
@@ -0,0 +1,36 @@
/**
* webpack-uni-pages-loader 待重构,需要将平台特有逻辑,收敛到各自包内
* @param {Object} pagesJson
* @param {Object} manifestJson
*/
module.exports = function (pagesJson, manifestJson) {
const {
app,
project
} = require('../mp')(pagesJson, manifestJson, require('./project.config.json'))
const baseJson = {
appType: 'webapp', // 华为IDE V3.0.2+ 需要此属性,否则无法导入
minPlatformVersion: 1070
}
manifestJson.name && (baseJson.name = manifestJson.name)
manifestJson.versionName && (baseJson.versionName = manifestJson.versionName)
manifestJson.versionCode && (baseJson.versionCode = manifestJson.versionCode)
const options = Object.assign({}, manifestJson['quickapp-webview'] || {})
if (process.env.UNI_SUB_PLATFORM) {
Object.assign(options, manifestJson[process.env.UNI_SUB_PLATFORM] || {})
}
Object.assign(app.content, baseJson, options)
if (!app.content.package) {
app.content.package = manifestJson.name
}
project.name = 'quickapp.config'
return [
app,
project
]
}
@@ -0,0 +1,36 @@
{
"description": "项目配置文件。",
"packOptions": {
"ignore": []
},
"setting": {
"urlCheck": true,
"es6": false,
"postcss": false,
"minified": false,
"newFeature": true
},
"compileType": "miniprogram",
"libVersion": "",
"appid": "touristappid",
"projectname": "",
"quickappRoot": "./",
"condition": {
"search": {
"current": -1,
"list": []
},
"conversation": {
"current": -1,
"list": []
},
"game": {
"current": -1,
"list": []
},
"miniprogram": {
"current": -1,
"list": []
}
}
}
+171
View File
@@ -0,0 +1,171 @@
const path = require('path')
const {
getPlatforms,
normalizePath
} = require('@dcloudio/uni-cli-shared')
const PLATFORMS = getPlatforms()
const alipayWindowMap = {
defaultTitle: 'navigationBarTitleText',
pullRefresh: 'enablePullDownRefresh',
allowsBounceVertical: 'allowsBounceVertical',
titleBarColor: 'navigationBarBackgroundColor',
optionMenu: 'optionMenu',
backgroundColor: 'backgroundColor',
usingComponents: 'usingComponents',
navigationBarShadow: 'navigationBarShadow',
titleImage: 'titleImage',
transparentTitle: 'transparentTitle',
titlePenetrate: 'titlePenetrate',
barButtonTheme: {
key: 'navigationBarTextStyle',
transform: function (value) {
}
}
}
const alipayTabBarMap = {
customize: 'customize',
textColor: 'color',
selectedColor: 'selectedColor',
backgroundColor: 'backgroundColor',
items: 'list'
}
const alipayTabBarItemMap = {
pagePath: 'pagePath',
name: 'text',
icon: 'iconPath',
activeIcon: 'selectedIconPath'
}
const _hasOwnProperty = Object.prototype.hasOwnProperty
function hasOwn (obj, key) {
return _hasOwnProperty.call(obj, key)
}
function trimMPJson (json) {
delete json.maxWidth
delete json.topWindow
delete json.leftWindow
delete json.rightWindow
if (json.tabBar) {
delete json.tabBar.matchMedia
}
return json
}
function parseStyle (style = {}, root = '') {
// TODO pages.json 触发了两次,需要排查
style = trimMPJson(JSON.parse(JSON.stringify(style)))
let platformStyle = {}
Object.keys(style).forEach(name => {
if (name === 'app') {
name = 'app-plus'
} else if (name === 'web') {
name = 'h5'
}
if (PLATFORMS.includes(name)) {
if (name === process.env.UNI_PLATFORM) {
if (name === 'app-plus') {
platformStyle = style.app || style[name] || {}
} else if (name === 'h5') {
platformStyle = style.web || style[name] || {}
} else {
platformStyle = style[name] || {}
}
}
delete style[name]
}
})
delete style.app
delete style.web
if (process.env.UNI_PLATFORM === 'app-plus') {
if (root && Array.isArray(platformStyle.subNVues) && platformStyle.subNVues.length) { // 处理分包逻辑
platformStyle.subNVues.forEach(subNVue => {
subNVue.path = normalizePath(path.join(root, subNVue.path))
})
}
style.disableSwipeBack === true
? platformStyle.popGesture = 'none'
: delete platformStyle.popGesture
delete style.disableSwipeBack
}
if (process.env.UNI_PLATFORM === 'mp-alipay') {
const windowOptions = {}
Object.keys(alipayWindowMap).forEach(key => {
if (hasOwn(style, alipayWindowMap[key])) {
windowOptions[key] = style[alipayWindowMap[key]]
}
})
return Object.assign(windowOptions, platformStyle)
}
if (
style.navigationBarTextStyle &&
(
style.navigationBarTextStyle !== 'black' &&
style.navigationBarTextStyle.indexOf('@') !== 0
)
) {
style.navigationBarTextStyle = 'white'
}
return Object.assign({
usingComponents: {}
}, style, platformStyle)
}
function parseTabBar (style = {}) {
if (process.env.UNI_PLATFORM === 'mp-alipay') {
const tabBarOptions = {}
Object.keys(alipayTabBarMap).forEach(key => {
if (hasOwn(style, alipayTabBarMap[key])) {
tabBarOptions[key] = style[alipayTabBarMap[key]]
}
})
if (Array.isArray(tabBarOptions.items) && tabBarOptions.items.length) {
tabBarOptions.items = tabBarOptions.items.map(itemOptions => {
const tabBarItemOptions = {}
Object.keys(alipayTabBarItemMap).forEach(key => {
if (hasOwn(itemOptions, alipayTabBarItemMap[key])) {
tabBarItemOptions[key] = itemOptions[alipayTabBarItemMap[key]]
}
})
return tabBarItemOptions
})
}
return tabBarOptions
}
return style
}
const NON_APP_JSON_KEYS = [
'appid',
'unipush',
'secureNetwork',
'usingComponents',
'optimization',
'scopedSlotsCompiler',
'slotMultipleInstance',
'uniStatistics',
'mergeVirtualHostAttributes',
'styleIsolation'
]
module.exports = {
hasOwn,
parseStyle,
parseTabBar,
trimMPJson,
NON_APP_JSON_KEYS
}
+1
View File
@@ -0,0 +1 @@
[https://dcloud.io/license/uni-app.html](https://dcloud.io/license/uni-app.html)
+27
View File
@@ -0,0 +1,27 @@
{
"name": "@dcloudio/webpack-uni-pages-loader",
"version": "2.0.2-4070620250821001",
"description": "uni-app pages.json loader",
"main": "lib/index.js",
"repository": {
"type": "git",
"url": "git+https://github.com/dcloudio/uni-app.git",
"directory": "packages/webpack-uni-pages-loader"
},
"files": [
"lib"
],
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "fxy060608",
"license": "Apache-2.0",
"dependencies": {
"merge": "^2.1.1",
"strip-json-comments": "^2.0.1"
},
"uni-app": {
"compilerVersion": "4.76"
},
"gitHead": "83322ec9f7cc592b2052ff78370e12f4689f5966"
}