pages.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. Object.defineProperty(exports, "__esModule", { value: true });
  6. exports.filterPlatformPages = exports.parseSubpackagesRootOnce = exports.normalizePagesRoute = exports.removePlatformStyle = exports.validatePages = exports.normalizePagesJson = exports.parsePagesJsonOnce = exports.parsePagesJson = exports.isUniPageSfcFile = exports.isUniPageSetupAndTs = exports.isUniPageFile = void 0;
  7. const fs_1 = __importDefault(require("fs"));
  8. const path_1 = __importDefault(require("path"));
  9. const shared_1 = require("@vue/shared");
  10. const uni_shared_1 = require("@dcloudio/uni-shared");
  11. const utils_1 = require("../utils");
  12. const json_1 = require("./json");
  13. const utils_2 = require("../vue/utils");
  14. const vite_1 = require("../vite");
  15. const constants_1 = require("../constants");
  16. const theme_1 = require("./theme");
  17. const manifest_1 = require("./manifest");
  18. const pagesCacheSet = new Set();
  19. function isUniPageFile(file, inputDir = process.env.UNI_INPUT_DIR) {
  20. if (inputDir && path_1.default.isAbsolute(file)) {
  21. file = (0, utils_1.normalizePath)(path_1.default.relative(inputDir, file));
  22. }
  23. return pagesCacheSet.has((0, utils_1.removeExt)(file));
  24. }
  25. exports.isUniPageFile = isUniPageFile;
  26. function isUniPageSetupAndTs(file) {
  27. const { filename, query } = (0, vite_1.parseVueRequest)(file);
  28. return !!(query.vue &&
  29. query.setup &&
  30. (0, shared_1.hasOwn)(query, 'lang.ts') &&
  31. constants_1.EXTNAME_VUE_RE.test(filename));
  32. }
  33. exports.isUniPageSetupAndTs = isUniPageSetupAndTs;
  34. function isUniPageSfcFile(file, inputDir = process.env.UNI_INPUT_DIR) {
  35. return (0, utils_2.isVueSfcFile)(file) && isUniPageFile(file, inputDir);
  36. }
  37. exports.isUniPageSfcFile = isUniPageSfcFile;
  38. /**
  39. * 小程序平台慎用,因为该解析不支持 subpackages
  40. * @param inputDir
  41. * @param platform
  42. * @param normalize
  43. * @returns
  44. */
  45. const parsePagesJson = (inputDir, platform, normalize = true) => {
  46. const jsonStr = fs_1.default.readFileSync(path_1.default.join(inputDir, 'pages.json'), 'utf8');
  47. if (normalize) {
  48. return normalizePagesJson(jsonStr, platform);
  49. }
  50. return (0, json_1.parseJson)(jsonStr, true);
  51. };
  52. exports.parsePagesJson = parsePagesJson;
  53. /**
  54. * 该方法解析出来的是不支持 subpackages,会被合并入 pages
  55. */
  56. exports.parsePagesJsonOnce = (0, uni_shared_1.once)(exports.parsePagesJson);
  57. /**
  58. * 目前 App 和 H5 使用了该方法
  59. * @param jsonStr
  60. * @param platform
  61. * @param param2
  62. * @returns
  63. */
  64. function normalizePagesJson(jsonStr, platform, { subpackages, } = { subpackages: false }) {
  65. let pagesJson = {
  66. pages: [],
  67. globalStyle: {
  68. navigationBar: {},
  69. },
  70. };
  71. // preprocess
  72. try {
  73. pagesJson = (0, json_1.parseJson)(jsonStr, true);
  74. }
  75. catch (e) {
  76. console.error(`[vite] Error: pages.json parse failed.\n`, jsonStr, e);
  77. }
  78. // pages
  79. validatePages(pagesJson, jsonStr);
  80. pagesJson.subPackages = pagesJson.subPackages || pagesJson.subpackages;
  81. delete pagesJson.subpackages;
  82. // subpackages
  83. if (pagesJson.subPackages) {
  84. if (subpackages) {
  85. pagesJson.subPackages.forEach(({ pages }) => {
  86. pages && normalizePages(pages, platform);
  87. });
  88. }
  89. else {
  90. pagesJson.pages.push(...normalizeSubpackages(pagesJson.subPackages));
  91. delete pagesJson.subPackages;
  92. }
  93. }
  94. else {
  95. delete pagesJson.subPackages;
  96. }
  97. // pageStyle
  98. normalizePages(pagesJson.pages, platform);
  99. // globalStyle
  100. pagesJson.globalStyle = normalizePageStyle(null, pagesJson.globalStyle, platform);
  101. // tabBar
  102. if (pagesJson.tabBar) {
  103. const tabBar = normalizeTabBar(pagesJson.tabBar, platform);
  104. if (tabBar) {
  105. pagesJson.tabBar = tabBar;
  106. }
  107. else {
  108. delete pagesJson.tabBar;
  109. }
  110. }
  111. // 过滤平台page
  112. filterPlatformPages(platform, pagesJson);
  113. // 缓存页面列表
  114. pagesCacheSet.clear();
  115. pagesJson.pages.forEach((page) => pagesCacheSet.add(page.path));
  116. const manifestJsonPlatform = (0, manifest_1.getPlatformManifestJsonOnce)();
  117. if (!manifestJsonPlatform.darkmode) {
  118. const { pages, globalStyle, tabBar } = (0, theme_1.initTheme)(manifestJsonPlatform, pagesJson);
  119. (0, shared_1.extend)(pagesJson, { pages, globalStyle, tabBar });
  120. }
  121. return pagesJson;
  122. }
  123. exports.normalizePagesJson = normalizePagesJson;
  124. function validatePages(pagesJson, jsonStr) {
  125. if (!(0, shared_1.isArray)(pagesJson.pages)) {
  126. pagesJson.pages = [];
  127. console.error(`[uni-app] Error: pages.json->pages parse failed.`);
  128. process.exit(0);
  129. }
  130. else if (!pagesJson.pages.length) {
  131. console.error(`[uni-app] Error: pages.json->pages must contain at least 1 page.`);
  132. process.exit(0);
  133. }
  134. else {
  135. const pages = [];
  136. pagesJson.pages.forEach((page) => {
  137. if (pages.indexOf(page.path) !== -1) {
  138. console.error(`[uni-app] Error: pages.json->${page.path} duplication.`);
  139. process.exit(0);
  140. }
  141. pages.push(page.path);
  142. });
  143. }
  144. }
  145. exports.validatePages = validatePages;
  146. function normalizePages(pages, platform) {
  147. pages.forEach((page) => {
  148. page.style = normalizePageStyle(page.path, page.style, platform);
  149. });
  150. if (platform !== 'app') {
  151. return;
  152. }
  153. const subNVuePages = [];
  154. // subNVues
  155. pages.forEach(({ style: { subNVues } }) => {
  156. if (!(0, shared_1.isArray)(subNVues)) {
  157. return;
  158. }
  159. subNVues.forEach((subNVue) => {
  160. if (subNVue && subNVue.path) {
  161. subNVuePages.push({
  162. path: subNVue.path,
  163. style: { isSubNVue: true, isNVue: true, navigationBar: {} },
  164. });
  165. }
  166. });
  167. });
  168. if (subNVuePages.length) {
  169. pages.push(...subNVuePages);
  170. }
  171. }
  172. function normalizeSubpackages(subpackages) {
  173. const pages = [];
  174. if ((0, shared_1.isArray)(subpackages)) {
  175. subpackages.forEach(({ root, pages: subPages }) => {
  176. if (root && subPages.length) {
  177. subPages.forEach((subPage) => {
  178. subPage.path = (0, utils_1.normalizePath)(path_1.default.join(root, subPage.path));
  179. subPage.style = normalizeSubpackageSubNVues(root, subPage.style);
  180. pages.push(subPage);
  181. });
  182. }
  183. });
  184. }
  185. return pages;
  186. }
  187. function normalizeSubpackageSubNVues(root, style = { navigationBar: {} }) {
  188. const platformStyle = style['app'] || style['app-plus'];
  189. if (!platformStyle) {
  190. return style;
  191. }
  192. if ((0, shared_1.isArray)(platformStyle.subNVues)) {
  193. platformStyle.subNVues.forEach((subNVue) => {
  194. if (subNVue.path) {
  195. subNVue.path = (0, utils_1.normalizePath)(path_1.default.join(root, subNVue.path));
  196. }
  197. });
  198. }
  199. return style;
  200. }
  201. function normalizePageStyle(pagePath, pageStyle, platform) {
  202. let isNVue = false;
  203. if (process.env.UNI_APP_X === 'true') {
  204. isNVue = undefined;
  205. }
  206. else {
  207. const hasNVue = pagePath &&
  208. process.env.UNI_INPUT_DIR &&
  209. fs_1.default.existsSync(path_1.default.join(process.env.UNI_INPUT_DIR, pagePath + '.nvue'))
  210. ? true
  211. : undefined;
  212. if (hasNVue) {
  213. const hasVue = fs_1.default.existsSync(path_1.default.join(process.env.UNI_INPUT_DIR, pagePath + '.vue'));
  214. if (hasVue) {
  215. if (platform === 'app') {
  216. if (process.env.UNI_NVUE_COMPILER !== 'vue') {
  217. isNVue = true;
  218. }
  219. }
  220. }
  221. else {
  222. isNVue = true;
  223. }
  224. }
  225. }
  226. if (pageStyle) {
  227. if (platform === 'h5') {
  228. (0, shared_1.extend)(pageStyle, pageStyle['app'] || pageStyle['app-plus'], pageStyle['web'] || pageStyle['h5']);
  229. }
  230. else if (platform === 'app') {
  231. (0, shared_1.extend)(pageStyle, pageStyle['app'] || pageStyle['app-plus']);
  232. }
  233. else {
  234. (0, shared_1.extend)(pageStyle, pageStyle[platform]);
  235. }
  236. if (['h5', 'app'].includes(platform)) {
  237. pageStyle.navigationBar = normalizeNavigationBar(pageStyle);
  238. if (isEnablePullDownRefresh(pageStyle)) {
  239. pageStyle.enablePullDownRefresh = true;
  240. pageStyle.pullToRefresh = normalizePullToRefresh(pageStyle);
  241. }
  242. if (platform === 'app') {
  243. pageStyle.disableSwipeBack === true
  244. ? (pageStyle.popGesture = 'none')
  245. : delete pageStyle.popGesture;
  246. delete pageStyle.disableSwipeBack;
  247. }
  248. }
  249. pageStyle.isNVue = isNVue;
  250. removePlatformStyle(pageStyle);
  251. return pageStyle;
  252. }
  253. return { navigationBar: {}, isNVue };
  254. }
  255. const navigationBarMaps = {
  256. navigationBarBackgroundColor: 'backgroundColor',
  257. navigationBarTextStyle: 'textStyle',
  258. navigationBarTitleText: 'titleText',
  259. navigationStyle: 'style',
  260. titleImage: 'titleImage',
  261. titlePenetrate: 'titlePenetrate',
  262. transparentTitle: 'transparentTitle',
  263. };
  264. function normalizeNavigationBar(pageStyle) {
  265. const navigationBar = Object.create(null);
  266. Object.keys(navigationBarMaps).forEach((name) => {
  267. if ((0, shared_1.hasOwn)(pageStyle, name)) {
  268. navigationBar[navigationBarMaps[name]] =
  269. pageStyle[name];
  270. delete pageStyle[name];
  271. }
  272. });
  273. navigationBar.type = navigationBar.type || 'default';
  274. const { titleNView } = pageStyle;
  275. if ((0, shared_1.isPlainObject)(titleNView)) {
  276. (0, shared_1.extend)(navigationBar, titleNView);
  277. delete pageStyle.titleNView;
  278. }
  279. else if (titleNView === false) {
  280. navigationBar.style = 'custom';
  281. }
  282. if ((0, shared_1.hasOwn)(navigationBar, 'transparentTitle')) {
  283. const transparentTitle = navigationBar.transparentTitle;
  284. if (transparentTitle === 'always') {
  285. navigationBar.style = 'custom';
  286. navigationBar.type = 'float';
  287. }
  288. else if (transparentTitle === 'auto') {
  289. navigationBar.type = 'transparent';
  290. }
  291. else {
  292. navigationBar.type = 'default';
  293. }
  294. delete navigationBar.transparentTitle;
  295. }
  296. if (navigationBar.titleImage && navigationBar.titleText) {
  297. delete navigationBar.titleText;
  298. }
  299. if (!navigationBar.titleColor && (0, shared_1.hasOwn)(navigationBar, 'textStyle')) {
  300. const textStyle = navigationBar.textStyle;
  301. if (constants_1.TEXT_STYLE.includes(textStyle)) {
  302. navigationBar.titleColor = (0, uni_shared_1.normalizeTitleColor)(textStyle);
  303. }
  304. else {
  305. navigationBar.titleColor = navigationBar.textStyle;
  306. }
  307. delete navigationBar.textStyle;
  308. }
  309. if (pageStyle.navigationBarShadow &&
  310. pageStyle.navigationBarShadow.colorType) {
  311. navigationBar.shadowColorType = pageStyle.navigationBarShadow.colorType;
  312. delete pageStyle.navigationBarShadow;
  313. }
  314. const parsedNavigationBar = (0, theme_1.initTheme)((0, manifest_1.getPlatformManifestJsonOnce)(), navigationBar);
  315. if ((0, shared_1.isArray)(navigationBar.buttons)) {
  316. navigationBar.buttons = navigationBar.buttons.map((btn) => normalizeNavigationBarButton(btn, navigationBar.type, parsedNavigationBar.titleColor));
  317. }
  318. if ((0, shared_1.isPlainObject)(navigationBar.searchInput)) {
  319. navigationBar.searchInput = normalizeNavigationBarSearchInput(navigationBar.searchInput);
  320. }
  321. if (navigationBar.type === 'transparent') {
  322. navigationBar.coverage = navigationBar.coverage || '132px';
  323. }
  324. return navigationBar;
  325. }
  326. function normalizeNavigationBarButton(btn, type, titleColor) {
  327. btn.color = btn.color || titleColor;
  328. if (!btn.fontSize) {
  329. btn.fontSize =
  330. type === 'transparent' || (btn.text && /\\u/.test(btn.text))
  331. ? '22px'
  332. : '27px';
  333. }
  334. else if (/\d$/.test(btn.fontSize)) {
  335. btn.fontSize += 'px';
  336. }
  337. btn.text = btn.text || '';
  338. return btn;
  339. }
  340. function normalizeNavigationBarSearchInput(searchInput) {
  341. return (0, shared_1.extend)({
  342. autoFocus: false,
  343. align: 'center',
  344. color: '#000',
  345. backgroundColor: 'rgba(255,255,255,0.5)',
  346. borderRadius: '0px',
  347. placeholder: '',
  348. placeholderColor: '#CCCCCC',
  349. disabled: false,
  350. }, searchInput);
  351. }
  352. const DEFAULT_TAB_BAR = {
  353. position: 'bottom',
  354. color: '#999',
  355. selectedColor: '#007aff',
  356. borderStyle: 'black',
  357. blurEffect: 'none',
  358. fontSize: '10px',
  359. iconWidth: '24px',
  360. spacing: '3px',
  361. height: uni_shared_1.TABBAR_HEIGHT + 'px',
  362. };
  363. function normalizeTabBar(tabBar, platform) {
  364. const { list, midButton } = tabBar;
  365. if (!list || !list.length) {
  366. return;
  367. }
  368. tabBar = (0, shared_1.extend)({}, DEFAULT_TAB_BAR, tabBar);
  369. list.forEach((item) => {
  370. if (item.iconPath) {
  371. item.iconPath = normalizeFilepath(item.iconPath);
  372. }
  373. if (item.selectedIconPath) {
  374. item.selectedIconPath = normalizeFilepath(item.selectedIconPath);
  375. }
  376. });
  377. if (midButton && midButton.backgroundImage) {
  378. midButton.backgroundImage = normalizeFilepath(midButton.backgroundImage);
  379. }
  380. tabBar.selectedIndex = 0;
  381. tabBar.shown = true;
  382. return tabBar;
  383. }
  384. const SCHEME_RE = /^([a-z-]+:)?\/\//i;
  385. const DATA_RE = /^data:.*,.*/;
  386. function normalizeFilepath(filepath) {
  387. const themeConfig = (0, theme_1.normalizeThemeConfigOnce)()['light'] || {};
  388. if (themeConfig[filepath.replace('@', '')])
  389. return filepath;
  390. if (!(SCHEME_RE.test(filepath) || DATA_RE.test(filepath)) &&
  391. filepath.indexOf('/') !== 0) {
  392. return (0, uni_shared_1.addLeadingSlash)(filepath);
  393. }
  394. return filepath;
  395. }
  396. const platforms = ['h5', 'app', 'mp-', 'quickapp', 'web'];
  397. function removePlatformStyle(pageStyle) {
  398. Object.keys(pageStyle).forEach((name) => {
  399. if (platforms.find((prefix) => name.startsWith(prefix))) {
  400. delete pageStyle[name];
  401. }
  402. });
  403. return pageStyle;
  404. }
  405. exports.removePlatformStyle = removePlatformStyle;
  406. function normalizePagesRoute(pagesJson) {
  407. const firstPagePath = pagesJson.pages[0].path;
  408. const tabBarList = (pagesJson.tabBar && pagesJson.tabBar.list) || [];
  409. return pagesJson.pages.map((pageOptions) => {
  410. const pagePath = pageOptions.path;
  411. const isEntry = firstPagePath === pagePath ? true : undefined;
  412. const tabBarIndex = tabBarList.findIndex((tabBarPage) => tabBarPage.pagePath === pagePath);
  413. const isTabBar = tabBarIndex !== -1 ? true : undefined;
  414. let windowTop = 0;
  415. const meta = (0, shared_1.extend)({
  416. isQuit: isEntry || isTabBar ? true : undefined,
  417. isEntry: isEntry || undefined,
  418. isTabBar: isTabBar || undefined,
  419. tabBarIndex: isTabBar ? tabBarIndex : undefined,
  420. windowTop: windowTop || undefined,
  421. }, pageOptions.style);
  422. return {
  423. path: pageOptions.path,
  424. meta,
  425. };
  426. });
  427. }
  428. exports.normalizePagesRoute = normalizePagesRoute;
  429. function isEnablePullDownRefresh(pageStyle) {
  430. return pageStyle.enablePullDownRefresh || pageStyle.pullToRefresh?.support;
  431. }
  432. function normalizePullToRefresh(pageStyle) {
  433. return pageStyle.pullToRefresh;
  434. }
  435. function parseSubpackagesRoot(inputDir, platform) {
  436. const pagesJson = (0, exports.parsePagesJson)(inputDir, platform, false);
  437. const subpackages = pagesJson.subPackages || pagesJson.subpackages;
  438. const roots = [];
  439. if ((0, shared_1.isArray)(subpackages)) {
  440. subpackages.forEach(({ root }) => {
  441. if (root) {
  442. roots.push(root);
  443. }
  444. });
  445. }
  446. return roots;
  447. }
  448. exports.parseSubpackagesRootOnce = (0, uni_shared_1.once)(parseSubpackagesRoot);
  449. let isInvalidPagesWarned = false;
  450. function filterPlatformPages(platform, pagesJson) {
  451. const invalidPages = [];
  452. pagesJson.pages = pagesJson.pages.filter(({ path }) => {
  453. if (isPlatformPage(platform, path)) {
  454. return true;
  455. }
  456. invalidPages.push(path);
  457. return false;
  458. });
  459. if (pagesJson.subPackages) {
  460. pagesJson.subPackages.forEach((subPackage) => {
  461. if (subPackage.pages) {
  462. subPackage.pages = subPackage.pages.filter(({ path }) => {
  463. const pagePath = subPackage.root + '/' + path;
  464. if (isPlatformPage(platform, pagePath)) {
  465. return true;
  466. }
  467. invalidPages.push(pagePath);
  468. return false;
  469. });
  470. }
  471. });
  472. }
  473. if (pagesJson.subpackages) {
  474. pagesJson.subpackages.forEach((subPackage) => {
  475. if (subPackage.pages) {
  476. subPackage.pages = subPackage.pages.filter(({ path }) => {
  477. const pagePath = subPackage.root + '/' + path;
  478. if (isPlatformPage(platform, pagePath)) {
  479. return true;
  480. }
  481. invalidPages.push(pagePath);
  482. return false;
  483. });
  484. }
  485. });
  486. }
  487. // 目前仅启动的时候警告一次,该方法可能会被调用很多次
  488. if (invalidPages.length) {
  489. if (!isInvalidPagesWarned) {
  490. isInvalidPagesWarned = true;
  491. console.log(`已忽略页面:${invalidPages.join('、')}。详见:https://uniapp.dcloud.net.cn/tutorial/platform.html#platforms`);
  492. }
  493. }
  494. }
  495. exports.filterPlatformPages = filterPlatformPages;
  496. function isPlatformPage(platform, pagePath) {
  497. if (pagePath.startsWith('platforms/')) {
  498. if (platform === 'app' || platform === 'app-plus') {
  499. return (pagePath.startsWith('platforms/app/') ||
  500. pagePath.startsWith('platforms/app-plus/'));
  501. }
  502. else if (platform === 'h5' || platform === 'web') {
  503. return (pagePath.startsWith('platforms/h5/') ||
  504. pagePath.startsWith('platforms/web/'));
  505. }
  506. return pagePath.startsWith('platforms/' + platform + '/');
  507. }
  508. return true;
  509. }