diff --git a/config/babel-plugin/oakRouter.js b/config/babel-plugin/oakRouter.js index a6ecd99..de821a1 100644 --- a/config/babel-plugin/oakRouter.js +++ b/config/babel-plugin/oakRouter.js @@ -3,6 +3,7 @@ const { relative, join, resolve } = require('path'); const t = require('@babel/types'); const assert = require('assert'); const AppPaths = require('../web/paths'); +const { parseSync, transformFromAstSync } = require('@babel/core'); module.exports = () => { return { @@ -166,6 +167,10 @@ module.exports = () => { ) ) ); + + const { code } = transformFromAstSync(path.container); + + console.log(code); } }, }, diff --git a/config/babel-plugin/oakRouter2.js b/config/babel-plugin/oakRouter2.js new file mode 100644 index 0000000..5504910 --- /dev/null +++ b/config/babel-plugin/oakRouter2.js @@ -0,0 +1,218 @@ +const fs = require('fs'); +const { relative, join, resolve, parse } = require('path'); +const t = require('@babel/types'); +const assert = require('assert'); +const AppPaths = require('../web/paths'); +const { parseSync, transformFromAstSync } = require('@babel/core'); + +module.exports = () => { + return { + visitor: { + Program(path, state) { + const { cwd, filename } = state; + const rel = relative(cwd, filename).replace(/\\/g, '/'); + if ( + /([\\/]*[a-zA-Z0-9_-])*[\\/]src[\\/]app([\\/]*[a-zA-Z0-9_-])*[\\/]router[\\/]index.ts$/.test( + rel + ) && + rel.endsWith(`/router/index.ts`) + ) { + const { body } = path.node; + const appDir = rel.slice(0, rel.indexOf('/')); + const allRouters = []; + const namespaces = {}; + + // namespace从相应目录查询获取 + const dir = parse(filename).dir; + const namespaceDir = join(dir, '..', 'namespaces'); + const nss = fs.readdirSync(namespaceDir); + + const namespaceConfig = {}; + nss.forEach( + (ns) => { + const dir = join(namespaceDir, ns); + const stat = fs.statSync(dir); + if (stat.isDirectory()) { + namespaceConfig[ns] = {}; + const indexJsonFile = join(dir, 'index.json'); + if (fs.existsSync(indexJsonFile)) { + const json = require(indexJsonFile); + let { first, notFound, path } = json; + if (first) { + if (first.startsWith('/')) { + first = first.slice(1); + } + namespaceConfig[ns].first = first.replace(/\\/g, '/'); + } + if (notFound) { + if (notFound.startsWith('/')) { + notFound = notFound.slice(1); + } + namespaceConfig[ns].notFound = notFound.replace(/\\/g, '/'); + } + if (path) { + if (!path.startsWith('/')) { + path = `/${path}`; + } + namespaceConfig[ns].path = path.replace(/\\/g, '/'); + } + } + else { + namespaceConfig[ns].path = `/${ns}`; + } + } + } + ); + + // pages从相应目录遍历获得 + const pageSrcDir = join(AppPaths.appRootSrc, 'pages'); + + const pages = []; + const traverse = (dir, relativePath) => { + const files = fs.readdirSync(dir); + files.forEach( + (file) => { + const filepath = join(dir, file); + const stat = fs.statSync(filepath); + let added = false; + if (stat.isFile() && ['index.tsx', 'web.tsx', 'web.pc.tsx'].includes(file)) { + pages.push(relativePath.replace(/\\/g, '/')); + added = true; + } + else if (stat.isDirectory()) { + const dir2 = join(dir, file); + const relativePath2 = join(relativePath, file); + traverse(dir2, relativePath2); + } + } + ); + }; + traverse(pageSrcDir, ''); + + const node = body.find( + ele => t.isVariableDeclaration(ele) && t.isIdentifier(ele.declarations[0].id) && ele.declarations[0].id.name === 'allRouters' + ); + + assert(node, `${filename}中没有定义allRouters`); + const declaration = node.declarations[0]; + const { init } = declaration; + assert(t.isArrayExpression(init) && init.elements.length === 0); + + nss.forEach( + (ns) => { + const { path, notFound, first } = namespaceConfig[ns]; + + const children = t.arrayExpression( + pages.map( + (page) => { + return t.objectExpression( + [ + t.objectProperty( + t.identifier('path'), + t.stringLiteral(page) + ), + t.objectProperty( + t.identifier('namespace'), + t.stringLiteral(path), + ), + t.objectProperty( + t.identifier('Component'), + t.callExpression( + t.memberExpression(t.identifier('React'), t.identifier('lazy')), + [ + t.arrowFunctionExpression( + [], + t.callExpression(t.import(), [ + t.stringLiteral(join('@project', 'pages', page, 'index').replace(/\\/g, '/')) + ]) + ), + ] + ) + ), + t.objectProperty( + t.identifier('isFirst'), + t.booleanLiteral(first === page) + ) + ] + ) + } + ) + ); + if (notFound) { + children.elements.push( + t.objectExpression( + [ + t.objectProperty( + t.identifier('path'), + t.stringLiteral('*') + ), + t.objectProperty( + t.identifier('namespace'), + t.stringLiteral(path), + ), + t.objectProperty( + t.identifier('Component'), + t.callExpression( + t.memberExpression(t.identifier('React'), t.identifier('lazy')), + [ + t.arrowFunctionExpression( + [], + t.callExpression(t.import(), [ + t.stringLiteral(join('@project', 'pages', notFound, 'index').replace(/\\/g, '/')) + ]) + ), + ] + ) + ) + ] + ) + ) + } + + init.elements.push( + t.objectExpression([ + t.objectProperty( + t.identifier('path'), + t.stringLiteral(path), + ), + t.objectProperty( + t.identifier('namespace'), + t.stringLiteral(path), + ), + t.objectProperty( + t.identifier('Component'), + t.callExpression( + t.memberExpression(t.identifier('React'), t.identifier('lazy')), + [ + t.arrowFunctionExpression( + [], + t.callExpression(t.import(), [ + t.stringLiteral(join('.', '..', 'namespaces', ns).replace(/\\/g, '/')), + ]) + ), + ] + ) + ), + t.objectProperty( + t.identifier('children'), + children + ) + ]) + ); + } + ); + body.unshift( + t.importDeclaration( + [t.importDefaultSpecifier(t.identifier('React'))], + t.stringLiteral('react') + ) + ); + + const { code } = transformFromAstSync(path.container); + + console.log(code); + } + }, + }, + }; +}; \ No newline at end of file diff --git a/config/web/webpack.config.js b/config/web/webpack.config.js index 3809bf3..458683c 100644 --- a/config/web/webpack.config.js +++ b/config/web/webpack.config.js @@ -33,7 +33,7 @@ const createEnvironmentHash = require('./webpack/persistentCache/createEnvironme const oakPathTsxPlugin = require('../babel-plugin/oakPath'); const oakRenderTsxPlugin = require('../babel-plugin/oakRender'); -const oakRouterPlugin = require('../babel-plugin/oakRouter'); +const oakRouterPlugin = require('../babel-plugin/oakRouter2'); const oakI18nPlugin = require('../babel-plugin/oakI18n'); const oakStylePlugin = require('../babel-plugin/oakStyle'); const oakRpxToPxPlugin = require('../postcss-plugin/oakRpxToPx'); diff --git a/plugins/WechatMpPlugin.js b/plugins/WechatMpPlugin.js index 99a5e9c..a011225 100644 --- a/plugins/WechatMpPlugin.js +++ b/plugins/WechatMpPlugin.js @@ -601,6 +601,26 @@ class OakWeChatMpPlugin { } json.usingComponents = usingComponents; } + + // 将locales中的pageTitle复制到小程序中的navigationBarTitleText + const parsed = path.parse(assets); + if (parsed.name === 'index') { + const localeZhCnFile1 = path.join(parsed.dir, 'locales', 'zh-CN.json'); + const localeZhCnFile2 = path.join(parsed.dir, 'locales', 'zh_CN.json'); + if (fsExtra.existsSync(localeZhCnFile1)) { + const locales = require(localeZhCnFile1); + if (locales.pageTitle) { + json.navigationBarTitleText = locales.pageTitle; + } + } + else if (fsExtra.existsSync(localeZhCnFile2)) { + const locales = require(localeZhCnFile2); + if (locales.pageTitle) { + json.navigationBarTitleText = locales.pageTitle; + } + } + } + source = Buffer.from(JSON.stringify(json, null, 2)); size = source.length; }