diff --git a/package.json b/package.json
index e20de23264ba88133189b0411e7f18548e7eaadd..20f6b3cf0aed6c261d2ddc664c9bc8834ef9cbff 100644
--- a/package.json
+++ b/package.json
@@ -58,6 +58,7 @@
"lint-staged": "^10.5.3",
"mini-types": "^0.1.4",
"miniprogram-api-typings": "^3.2.0",
+ "module-alias": "^2.2.2",
"prettier": "^2.2.1",
"rollup": "^2.35.1",
"rollup-plugin-node-builtins": "^2.1.2",
diff --git a/packages/global.d.ts b/packages/global.d.ts
index 35df5576401cf8d76850221aa924cb532b421858..6c88bcf6a43a28ddc3264070ead04824d1bde70d 100644
--- a/packages/global.d.ts
+++ b/packages/global.d.ts
@@ -26,6 +26,7 @@ declare var __UNI_FEATURE_LEFTWINDOW__: boolean
declare var __UNI_FEATURE_RIGHTWINDOW__: boolean
declare var __UNI_FEATURE_RESPONSIVE__: boolean
declare var __UNI_FEATURE_PULL_DOWN_REFRESH__: boolean
+declare var __UNI_FEATURE_NAVIGATIONBAR_BUTTONS__: boolean
// TODO
declare var __uniRoutes: any
declare var __uniConfig: UniApp.UniConfig
diff --git a/packages/shims-uni-app.d.ts b/packages/shims-uni-app.d.ts
index fb9bf1b1bbbb5393f4a5a40bd0a5bb781a4bf703..bcb86dae5e45694e409e0d9fdd7f0822f606aa7f 100644
--- a/packages/shims-uni-app.d.ts
+++ b/packages/shims-uni-app.d.ts
@@ -1,13 +1,5 @@
declare namespace UniApp {
- type PLATFORM =
- | 'h5'
- | 'app-plus'
- | 'mp-alipay'
- | 'mp-baidu'
- | 'mp-qq'
- | 'mp-toutiao'
- | 'mp-weixin'
- | 'quickapp-webview'
+ type PLATFORM = keyof PagesJsonPagePlatformStyle
interface LayoutWindowOptions {
matchMedia?: {
minWidth?: number
@@ -28,16 +20,38 @@ declare namespace UniApp {
rightWindow?: LayoutWindowOptions
}
+ interface PageNavigationBarButton {
+ type?:
+ | 'none'
+ | 'forward'
+ | 'back'
+ | 'share'
+ | 'favorite'
+ | 'home'
+ | 'menu'
+ | 'close'
+ color?: string
+ background?: string
+ colorPressed?: string
+ float?: 'right' | 'left'
+ fontWeight?: string
+ fontSize?: string
+ fontSrc?: string
+ select?: boolean
+ text?: string
+ width?: string
+ }
interface PageNavigationBar {
- type: 'default' | 'transparent' | 'float' | 'none'
- titleText: string
- textStyle: 'black' | 'white'
- timingFunc: string
- duration: string
- backgroundColor: string
- titlePenetrate: 'YES' | 'NO'
- shadowColorType: 'grey' | 'blue' | 'green' | 'orange' | 'red' | 'yellow'
- backButton: boolean
+ type?: 'default' | 'transparent' | 'float' | 'none'
+ titleText?: string
+ textStyle?: 'black' | 'white'
+ timingFunc?: string
+ duration?: string
+ backgroundColor?: string
+ titlePenetrate?: 'YES' | 'NO'
+ shadowColorType?: 'grey' | 'blue' | 'green' | 'orange' | 'red' | 'yellow'
+ backButton?: boolean
+ buttons?: PageNavigationBarButton[]
}
interface PageRefreshOptions {
support: boolean
@@ -47,7 +61,24 @@ declare namespace UniApp {
range: number
offset: number
}
- interface PageRouteMeta {
+
+ interface PagesJsonPagePlatformStyle {
+ h5?: PagesJsonPageStyle
+ 'app-plus'?: PagesJsonPageStyle
+ 'mp-alipay'?: PagesJsonPageStyle
+ 'mp-baidu'?: PagesJsonPageStyle
+ 'mp-qq'?: PagesJsonPageStyle
+ 'mp-toutiao'?: PagesJsonPageStyle
+ 'mp-weixin'?: PagesJsonPageStyle
+ 'quickapp-webview'?: PagesJsonPageStyle
+ }
+
+ interface PagesJsonPageStyle extends PagesJsonPagePlatformStyle {
+ enablePullDownRefresh?: boolean
+ navigationBar: PageNavigationBar
+ refreshOptions?: PageRefreshOptions
+ }
+ interface PageRouteMeta extends PagesJsonPageStyle {
id: number
isQuit?: boolean
isEntry?: boolean
@@ -57,18 +88,11 @@ declare namespace UniApp {
topWindow?: boolean
leftWindow?: boolean
rightWindow?: boolean
- enablePullDownRefresh?: boolean
- navigationBar: PageNavigationBar
- refreshOptions?: PageRefreshOptions
- }
-
- interface PagesJsonPageStyle {
- enablePullDownRefresh?: boolean
}
interface PagesJsonPageOptions {
path: string
- style?: PagesJsonPageStyle
+ style: PagesJsonPageStyle
}
interface PagesJsonSubpackagesOptions {
root: string
diff --git a/packages/uni-h5/dist/uni-h5.esm.js b/packages/uni-h5/dist/uni-h5.esm.js
index 743499c2b60a66fe425d46b3a9a297a4785a3d39..690c2b59671b84ddba19ec3bfdd37b52d23692be 100644
--- a/packages/uni-h5/dist/uni-h5.esm.js
+++ b/packages/uni-h5/dist/uni-h5.esm.js
@@ -1,5 +1,5 @@
import {isFunction, extend, isPlainObject, hasOwn as hasOwn$1, hyphenate, isArray, isObject as isObject$1, capitalize, toRawType, makeMap as makeMap$1, isPromise} from "@vue/shared";
-import {injectHook, defineComponent, inject, provide, reactive, nextTick, computed, openBlock, createBlock, Fragment, withDirectives, createVNode, vShow, createCommentVNode, withCtx, KeepAlive, resolveDynamicComponent, resolveComponent, mergeProps, onMounted, ref, toDisplayString, toHandlers, renderSlot, withModifiers, vModelDynamic, renderList, vModelText, createTextVNode} from "vue";
+import {injectHook, defineComponent, inject, provide, reactive, nextTick, computed, withDirectives, createVNode, vShow, withCtx, openBlock, createBlock, KeepAlive, resolveDynamicComponent, resolveComponent, onMounted, ref, mergeProps, toDisplayString, toHandlers, renderSlot, createCommentVNode, withModifiers, vModelDynamic, Fragment, renderList, vModelText, createTextVNode} from "vue";
import {NAVBAR_HEIGHT, COMPONENT_NAME_PREFIX, isCustomElement, plusReady, debounce} from "@dcloudio/uni-shared";
import {createRouter, createWebHistory, createWebHashHistory, useRoute, RouterView} from "vue-router";
function applyOptions(options, instance2, publicThis) {
@@ -871,55 +871,48 @@ function useKeepAliveRoute() {
}
var Layout = defineComponent({
name: "Layout",
+ props: {
+ onChange: Function
+ },
emits: ["change"],
setup() {
- const route = __UNI_FEATURE_TABBAR__ ? useRoute() : null;
- const keepAliveRoute = __UNI_FEATURE_PAGES__ ? useKeepAliveRoute() : null;
- __UNI_FEATURE_TOPWINDOW__ ? useTopWindow() : null;
- __UNI_FEATURE_LEFTWINDOW__ ? useLeftWindow() : null;
- __UNI_FEATURE_RIGHTWINDOW__ ? useRightWindow() : null;
+ const route = __UNI_FEATURE_TABBAR__ && useRoute();
+ const keepAliveRoute = __UNI_FEATURE_PAGES__ && useKeepAliveRoute();
+ __UNI_FEATURE_TOPWINDOW__ && useTopWindow();
+ __UNI_FEATURE_LEFTWINDOW__ && useLeftWindow();
+ __UNI_FEATURE_RIGHTWINDOW__ && useRightWindow();
return () => {
- return openBlock(), createBlock(Fragment, null, [
- createLayoutVNode(keepAliveRoute),
- createTabBarVNode(route)
- ], 64);
+ const layoutTsx = createLayoutTsx(keepAliveRoute);
+ const tabBarTsx = __UNI_FEATURE_TABBAR__ && createTabBarTsx(route);
+ return [layoutTsx, tabBarTsx].filter(Boolean);
};
}
});
-function createLayoutVNode(keepAliveRoute, topWindow, leftWindow, rightWindow) {
+function createLayoutTsx(keepAliveRoute, topWindow, leftWindow, rightWindow) {
const routerVNode = __UNI_FEATURE_PAGES__ ? createRouterViewVNode(keepAliveRoute) : createPageVNode();
if (!__UNI_FEATURE_RESPONSIVE__) {
return routerVNode;
}
- const topWindowVNode = __UNI_FEATURE_TOPWINDOW__ ? createTopWindowVNode() : createCommentVNode("", true);
- const leftWindowVNode = __UNI_FEATURE_LEFTWINDOW__ ? createLeftWindowVNode() : createCommentVNode("", true);
- const rightWindowVNode = __UNI_FEATURE_RIGHTWINDOW__ ? createRightWindowVNode() : createCommentVNode("", true);
- return createVNode("uni-layout", null, [
- topWindowVNode,
- createVNode("uni-content", null, [
- createVNode("uni-main", null, [routerVNode]),
- leftWindowVNode,
- rightWindowVNode
- ])
- ]);
+ const topWindowTsx = __UNI_FEATURE_TOPWINDOW__ ? createTopWindowTsx() : null;
+ const leftWindowTsx = __UNI_FEATURE_LEFTWINDOW__ ? createLeftWindowTsx() : null;
+ const rightWindowTsx = __UNI_FEATURE_RIGHTWINDOW__ ? createRightWindowTsx() : null;
+ return createVNode("uni-layout", null, [topWindowTsx, createVNode("uni-content", null, [createVNode("uni-main", null, [routerVNode]), leftWindowTsx, rightWindowTsx])]);
}
-function createTabBarVNode(route) {
- return __UNI_FEATURE_TABBAR__ ? withDirectives(createVNode(TabBar, null, null, 512), [
- [vShow, route.meta.isTabBar]
- ]) : createCommentVNode("", true);
+function createTabBarTsx(route) {
+ return withDirectives(createVNode(TabBar, null, null, 512), [[vShow, route.meta.isTabBar]]);
}
function createPageVNode() {
return createVNode(__uniRoutes[1].component);
}
function createRouterViewVNode(keepAliveRoute) {
return createVNode(RouterView, null, {
- default: withCtx(({Component}) => [
- (openBlock(), createBlock(KeepAlive, {cache: keepAliveRoute.routeCache}, [
- (openBlock(), createBlock(resolveDynamicComponent(Component), {
- key: keepAliveRoute.routeKey.value
- }))
- ], 1032, ["cache"]))
- ]),
+ default: withCtx(({
+ Component
+ }) => [(openBlock(), createBlock(KeepAlive, {
+ cache: keepAliveRoute.routeCache
+ }, [(openBlock(), createBlock(resolveDynamicComponent(Component), {
+ key: keepAliveRoute.routeKey.value
+ }))], 1032, ["cache"]))]),
_: 1
});
}
@@ -948,53 +941,27 @@ function useRightWindow() {
height: 0
};
}
-function createTopWindowVNode(topWindow) {
- if (!__UNI_FEATURE_TOPWINDOW__) {
- return createCommentVNode("", true);
- }
- const {component, style, height, show} = useTopWindow();
- return withDirectives(createVNode("uni-top-window", null, [
- createVNode("div", {
- ref: "topWindow",
- class: "uni-top-window",
- style
- }, [
- createVNode(component, mergeProps({
- onVnodeMounted(vnode) {
- },
- "navigation-bar-title-text": ""
- }), null, 16, ["navigation-bar-title-text"])
- ], 4),
- createVNode("div", {
- class: "uni-top-window--placeholder",
- style: {height}
- }, null, 4)
- ], 512), [[vShow, show]]);
+function createTopWindowTsx(topWindow) {
}
-function createLeftWindowVNode(leftWindow) {
+function createLeftWindowTsx(leftWindow) {
}
-function createRightWindowVNode(leftWindow) {
+function createRightWindowTsx(leftWindow) {
}
-const CSS_VARS = [
- "--status-bar-height",
- "--top-window-height",
- "--window-left",
- "--window-right",
- "--window-margin"
-];
+const CSS_VARS = ["--status-bar-height", "--top-window-height", "--window-left", "--window-right", "--window-margin"];
var AppComponent = defineComponent({
name: "App",
setup() {
useCssVar();
useAppLifecycle();
- const {clazz, onChange: onChange2} = useAppClass();
- return () => (openBlock(), createBlock("uni-app", {
+ const {
+ clazz,
+ onChange: onChange2
+ } = useAppClass();
+ return () => createVNode("uni-app", {
class: clazz.value
- }, [
- createVNode(Layout, {
- onChange: onChange2
- }, null, 8, ["onChange"])
- ], 2));
+ }, [createVNode(Layout, {
+ onChange: onChange2
+ }, null, 8, ["onChange"])], 2);
}
});
function useCssVar() {
@@ -8074,17 +8041,16 @@ var PageHead = defineComponent({
clazz,
style
} = usePageHead(navigationBar);
- const backButtonJsx = createBackButtonJsx(navigationBar);
+ const backButtonJsx = __UNI_FEATURE_PAGES__ ? createBackButtonJsx(navigationBar) : null;
+ const leftButtonsJsx = __UNI_FEATURE_NAVIGATIONBAR_BUTTONS__ ? createButtonsJsx("left", navigationBar) : [];
return () => createVNode("uni-page-head", {
"uni-page-head-type": navigationBar.type
- }, {
- default: () => [createVNode("div", {
- class: clazz.value,
- style: style.value
- }, [createVNode("div", {
- class: "uni-page-head-hd"
- }, [backButtonJsx])], 6)]
- }, 8, ["uni-page-head-type"]);
+ }, [createVNode("div", {
+ class: clazz.value,
+ style: style.value
+ }, [createVNode("div", {
+ class: "uni-page-head-hd"
+ }, [backButtonJsx, ...leftButtonsJsx])], 6)], 8, ["uni-page-head-type"]);
}
});
function createBackButtonJsx(navigationBar) {
@@ -8092,11 +8058,19 @@ function createBackButtonJsx(navigationBar) {
return createVNode("div", {
class: "uni-page-head-btn"
}, [createVNode("i", {
- style: "{color:color,fontSize:'27px'}",
+ style: "fontSize:27px",
class: "uni-btn-icon"
}, [createTextVNode("\uE601")])]);
}
}
+function createButtonsJsx(float, navigationBar) {
+ if (isArray(navigationBar.buttons)) {
+ return navigationBar.buttons.filter((btn) => btn.float === float).map((btn, index2) => createVNode("div", {
+ key: index2
+ }, [createVNode("i", null, null)]));
+ }
+ return [];
+}
function usePageHead(navigationBar) {
const clazz = computed(() => {
const {
diff --git a/packages/uni-h5/lib/babel-plugin-jsx/README.md b/packages/uni-h5/lib/babel-plugin-jsx/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..aef7dc5e7682b2ff5992d8c4674368b352a98753
--- /dev/null
+++ b/packages/uni-h5/lib/babel-plugin-jsx/README.md
@@ -0,0 +1,334 @@
+# Babel Plugin JSX for Vue 3.0
+
+[![CircleCI](https://circleci.com/gh/vuejs/jsx-next.svg?style=svg)](https://circleci.com/gh/vuejs/vue-next) [![npm package](https://img.shields.io/npm/v/@vue/babel-plugin-jsx.svg?style=flat-square)](https://www.npmjs.com/package/@vue/babel-plugin-jsx)
+
+To add Vue JSX support.
+
+English | [简体中文](/packages/babel-plugin-jsx/README-zh_CN.md)
+
+## Installation
+
+Install the plugin with:
+
+```bash
+npm install @vue/babel-plugin-jsx -D
+```
+
+Then add the plugin to .babelrc:
+
+```js
+{
+ "plugins": ["@vue/babel-plugin-jsx"]
+}
+```
+
+## Usage
+
+### options
+
+#### transformOn
+
+Type: `boolean`
+
+Default: `false`
+
+transform `on: { click: xx }` to `onClick: xxx`
+
+#### optimize
+
+Type: `boolean`
+
+Default: `false`
+
+enable optimization or not. It's not recommended to enable it If you are not familiar with Vue 3.
+
+#### isCustomElement
+
+Type: `(tag: string) => boolean`
+
+Default: `undefined`
+
+configuring custom elements
+
+#### mergeProps
+
+Type: `boolean`
+
+Default: `true`
+
+merge static and dynamic class / style attributes / onXXX handlers
+
+#### enableObjectSlots
+
+Type: `boolean`
+
+Default: `true`
+
+Whether to enable `object slots` (mentioned below the document) syntax". It might be useful in JSX, but it will add a lot of `_isSlot` condition expressions which increase your bundle size. And `v-slots` is still available even if `enableObjectSlots` is turned off.
+
+## Syntax
+
+### Content
+
+functional component
+
+```jsx
+const App = () =>
Vue 3.0
;
+```
+
+with render
+
+```jsx
+const App = {
+ render() {
+ return Vue 3.0
;
+ },
+};
+```
+
+```jsx
+import { withModifiers, defineComponent } from "vue";
+
+const App = defineComponent({
+ setup() {
+ const count = ref(0);
+
+ const inc = () => {
+ count.value++;
+ };
+
+ return () => (
+ {count.value}
+ );
+ },
+});
+```
+
+Fragment
+
+```jsx
+const App = () => (
+ <>
+ I'm
+ Fragment
+ >
+);
+```
+
+### Attributes / Props
+
+```jsx
+const App = () => ;
+```
+
+with a dynamic binding:
+
+```jsx
+const placeholderText = "email";
+const App = () => ;
+```
+
+### Directives
+
+v-show
+
+```jsx
+const App = {
+ data() {
+ return { visible: true };
+ },
+ render() {
+ return ;
+ },
+};
+```
+
+v-model
+
+> Note: You should pass the second param as string for using `arg`.
+
+```jsx
+
+```
+
+```jsx
+
+```
+
+```jsx
+
+```
+
+Will compile to:
+
+```js
+h(A, {
+ argument: val,
+ argumentModifiers: {
+ modifier: true,
+ },
+ "onUpdate:argument": ($event) => (val = $event),
+});
+```
+
+v-models
+
+> Note: You should pass a Two-dimensional Arrays to v-models.
+
+```jsx
+
+```
+
+```jsx
+
+```
+
+```jsx
+
+```
+
+Will compile to:
+
+```js
+h(A, {
+ modelValue: foo,
+ modelModifiers: {
+ modifier: true,
+ },
+ "onUpdate:modelValue": ($event) => (foo = $event),
+ bar: bar,
+ barModifiers: {
+ modifier: true,
+ },
+ "onUpdate:bar": ($event) => (bar = $event),
+});
+```
+
+custom directive
+
+```jsx
+const App = {
+ directives: { custom: customDirective },
+ setup() {
+ return () => ;
+ },
+};
+```
+
+### Slot
+
+> Note: In `jsx`, _`v-slot`_ should be replace with **`v-slots`**
+
+```jsx
+const App = {
+ setup() {
+ const slots = {
+ foo: () => B,
+ };
+ return () => (
+
+ A
+
+ );
+ },
+};
+
+// or
+
+const App = {
+ setup() {
+ const slots = {
+ default: () => A
,
+ foo: () => B,
+ };
+ return () => ;
+ },
+};
+
+// or you can use object slots when `enableObjectSlots` is not false.
+const App = {
+ setup() {
+ return () => (
+ <>
+
+ {{
+ default: () => A
,
+ foo: () => B,
+ }}
+
+ {() => "foo"}
+ >
+ );
+ },
+};
+```
+
+### In TypeScript
+
+`tsconfig.json`:
+
+```json
+{
+ "compilerOptions": {
+ "jsx": "preserve"
+ }
+}
+```
+
+## Who is using
+
+
+
+## Compatibility
+
+This repo is only compatible with:
+
+- **Babel 7+**
+- **Vue 3+**
diff --git a/packages/uni-h5/lib/babel-plugin-jsx/dist/buildProps.d.ts b/packages/uni-h5/lib/babel-plugin-jsx/dist/buildProps.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..91679f42d54ae778d8aa27f37e1d83d7fe40a9db
--- /dev/null
+++ b/packages/uni-h5/lib/babel-plugin-jsx/dist/buildProps.d.ts
@@ -0,0 +1,14 @@
+import * as t from '@babel/types';
+import { NodePath } from '@babel/traverse';
+import { State } from '.';
+export declare type Slots = t.Identifier | t.ObjectExpression | null;
+declare const buildProps: (path: NodePath, state: State) => {
+ tag: t.CallExpression | t.Identifier | t.StringLiteral | t.MemberExpression;
+ props: t.Expression;
+ isComponent: boolean;
+ slots: null;
+ directives: t.ArrayExpression[];
+ patchFlag: number;
+ dynamicPropNames: Set;
+};
+export default buildProps;
diff --git a/packages/uni-h5/lib/babel-plugin-jsx/dist/buildProps.js b/packages/uni-h5/lib/babel-plugin-jsx/dist/buildProps.js
new file mode 100644
index 0000000000000000000000000000000000000000..77e66ab620d4694ae8a696d43edb498c24e19b1c
--- /dev/null
+++ b/packages/uni-h5/lib/babel-plugin-jsx/dist/buildProps.js
@@ -0,0 +1,293 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
+}) : (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ o[k2] = m[k];
+}));
+var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
+}) : function(o, v) {
+ o["default"] = v;
+});
+var __importStar = (this && this.__importStar) || function (mod) {
+ if (mod && mod.__esModule) return mod;
+ var result = {};
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
+ __setModuleDefault(result, mod);
+ return result;
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const t = __importStar(require("@babel/types"));
+const helper_module_imports_1 = require("@babel/helper-module-imports");
+const utils_1 = require("./utils");
+const parseDirectives_1 = __importDefault(require("./parseDirectives"));
+const transform_vue_jsx_1 = require("./transform-vue-jsx");
+const xlinkRE = /^xlink([A-Z])/;
+const onRE = /^on[^a-z]/;
+const isOn = (key) => onRE.test(key);
+const getJSXAttributeValue = (path, state) => {
+ const valuePath = path.get('value');
+ if (valuePath.isJSXElement()) {
+ return transform_vue_jsx_1.transformJSXElement(valuePath, state);
+ }
+ if (valuePath.isStringLiteral()) {
+ return valuePath.node;
+ }
+ if (valuePath.isJSXExpressionContainer()) {
+ return utils_1.transformJSXExpressionContainer(valuePath);
+ }
+ return null;
+};
+const transformJSXSpreadAttribute = (nodePath, path, mergeProps, args) => {
+ const argument = path.get('argument');
+ const { properties } = argument.node;
+ if (!properties) {
+ if (argument.isIdentifier()) {
+ utils_1.walksScope(nodePath, argument.name, 2 /* DYNAMIC */);
+ }
+ args.push(mergeProps ? argument.node : t.spreadElement(argument.node));
+ }
+ else if (mergeProps) {
+ args.push(t.objectExpression(properties));
+ }
+ else {
+ args.push(...properties);
+ }
+};
+const mergeAsArray = (existing, incoming) => {
+ if (t.isArrayExpression(existing.value)) {
+ existing.value.elements.push(incoming.value);
+ }
+ else {
+ existing.value = t.arrayExpression([
+ existing.value,
+ incoming.value,
+ ]);
+ }
+};
+const dedupeProperties = (properties = [], mergeProps) => {
+ if (!mergeProps) {
+ return properties;
+ }
+ const knownProps = new Map();
+ const deduped = [];
+ properties.forEach((prop) => {
+ const { value: name } = prop.key;
+ const existing = knownProps.get(name);
+ if (existing) {
+ if (name === 'style' || name === 'class' || name.startsWith('on')) {
+ mergeAsArray(existing, prop);
+ }
+ }
+ else {
+ knownProps.set(name, prop);
+ deduped.push(prop);
+ }
+ });
+ return deduped;
+};
+/**
+ * Check if an attribute value is constant
+ * @param node
+ * @returns boolean
+ */
+const isConstant = (node) => {
+ if (t.isIdentifier(node)) {
+ return node.name === 'undefined';
+ }
+ if (t.isArrayExpression(node)) {
+ const { elements } = node;
+ return elements.every((element) => element && isConstant(element));
+ }
+ if (t.isObjectExpression(node)) {
+ return node.properties.every((property) => isConstant(property.value));
+ }
+ if (t.isLiteral(node)) {
+ return true;
+ }
+ return false;
+};
+const buildProps = (path, state) => {
+ const tag = utils_1.getTag(path, state);
+ const isComponent = utils_1.checkIsComponent(path.get('openingElement'), state);
+ const props = path.get('openingElement').get('attributes');
+ const directives = [];
+ const dynamicPropNames = new Set();
+ let slots = null;
+ let patchFlag = 0;
+ if (props.length === 0) {
+ return {
+ tag,
+ isComponent,
+ slots,
+ props: t.nullLiteral(),
+ directives,
+ patchFlag,
+ dynamicPropNames,
+ };
+ }
+ let properties = [];
+ // patchFlag analysis
+ let hasRef = false;
+ let hasClassBinding = false;
+ let hasStyleBinding = false;
+ let hasHydrationEventBinding = false;
+ let hasDynamicKeys = false;
+ const mergeArgs = [];
+ const { mergeProps = true } = state.opts;
+ props
+ .forEach((prop) => {
+ if (prop.isJSXAttribute()) {
+ let name = utils_1.getJSXAttributeName(prop);
+ const attributeValue = getJSXAttributeValue(prop, state);
+ if (!isConstant(attributeValue) || name === 'ref') {
+ if (!isComponent
+ && isOn(name)
+ // omit the flag for click handlers becaues hydration gives click
+ // dedicated fast path.
+ && name.toLowerCase() !== 'onclick'
+ // omit v-model handlers
+ && name !== 'onUpdate:modelValue') {
+ hasHydrationEventBinding = true;
+ }
+ if (name === 'ref') {
+ hasRef = true;
+ }
+ else if (name === 'class' && !isComponent) {
+ hasClassBinding = true;
+ }
+ else if (name === 'style' && !isComponent) {
+ hasStyleBinding = true;
+ }
+ else if (name !== 'key'
+ && !utils_1.isDirective(name)
+ && name !== 'on') {
+ dynamicPropNames.add(name);
+ }
+ }
+ if (state.opts.transformOn && (name === 'on' || name === 'nativeOn')) {
+ if (!state.get('transformOn')) {
+ state.set('transformOn', helper_module_imports_1.addDefault(path, '@vue/babel-helper-vue-transform-on', { nameHint: '_transformOn' }));
+ }
+ mergeArgs.push(t.callExpression(state.get('transformOn'), [attributeValue || t.booleanLiteral(true)]));
+ return;
+ }
+ if (utils_1.isDirective(name)) {
+ const { directive, modifiers, values, args, directiveName, } = parseDirectives_1.default({
+ tag,
+ isComponent,
+ name,
+ path: prop,
+ state,
+ value: attributeValue,
+ });
+ if (directiveName === 'slots') {
+ slots = attributeValue;
+ return;
+ }
+ if (directive) {
+ directives.push(t.arrayExpression(directive));
+ }
+ else if (directiveName === 'html') {
+ properties.push(t.objectProperty(t.stringLiteral('innerHTML'), values[0]));
+ dynamicPropNames.add('innerHTML');
+ }
+ else if (directiveName === 'text') {
+ properties.push(t.objectProperty(t.stringLiteral('textContent'), values[0]));
+ dynamicPropNames.add('textContent');
+ }
+ if (['models', 'model'].includes(directiveName)) {
+ values.forEach((value, index) => {
+ var _a, _b;
+ const argVal = (_a = args[index]) === null || _a === void 0 ? void 0 : _a.value;
+ const propName = argVal || 'modelValue';
+ // must be v-model or v-models and is a component
+ if (!directive) {
+ properties.push(t.objectProperty(t.stringLiteral(propName), value));
+ dynamicPropNames.add(propName);
+ if ((_b = modifiers[index]) === null || _b === void 0 ? void 0 : _b.size) {
+ properties.push(t.objectProperty(t.stringLiteral(`${argVal || 'model'}Modifiers`), t.objectExpression([...modifiers[index]].map((modifier) => t.objectProperty(t.stringLiteral(modifier), t.booleanLiteral(true))))));
+ }
+ }
+ properties.push(t.objectProperty(t.stringLiteral(`onUpdate:${propName}`), t.arrowFunctionExpression([t.identifier('$event')], t.assignmentExpression('=', value, t.identifier('$event')))));
+ dynamicPropNames.add(`onUpdate:${propName}`);
+ });
+ }
+ }
+ else {
+ if (name.match(xlinkRE)) {
+ name = name.replace(xlinkRE, (_, firstCharacter) => `xlink:${firstCharacter.toLowerCase()}`);
+ }
+ properties.push(t.objectProperty(t.stringLiteral(name), attributeValue || t.booleanLiteral(true)));
+ }
+ }
+ else {
+ if (properties.length && mergeProps) {
+ mergeArgs.push(t.objectExpression(dedupeProperties(properties, mergeProps)));
+ properties = [];
+ }
+ // JSXSpreadAttribute
+ hasDynamicKeys = true;
+ transformJSXSpreadAttribute(path, prop, mergeProps, mergeProps ? mergeArgs : properties);
+ }
+ });
+ // patchFlag analysis
+ if (hasDynamicKeys) {
+ patchFlag |= 16 /* FULL_PROPS */;
+ }
+ else {
+ if (hasClassBinding) {
+ patchFlag |= 2 /* CLASS */;
+ }
+ if (hasStyleBinding) {
+ patchFlag |= 4 /* STYLE */;
+ }
+ if (dynamicPropNames.size) {
+ patchFlag |= 8 /* PROPS */;
+ }
+ if (hasHydrationEventBinding) {
+ patchFlag |= 32 /* HYDRATE_EVENTS */;
+ }
+ }
+ if ((patchFlag === 0 || patchFlag === 32 /* HYDRATE_EVENTS */)
+ && (hasRef || directives.length > 0)) {
+ patchFlag |= 512 /* NEED_PATCH */;
+ }
+ let propsExpression = t.nullLiteral();
+ if (mergeArgs.length) {
+ if (properties.length) {
+ mergeArgs.push(t.objectExpression(dedupeProperties(properties, mergeProps)));
+ }
+ if (mergeArgs.length > 1) {
+ propsExpression = t.callExpression(utils_1.createIdentifier(state, 'mergeProps'), mergeArgs);
+ }
+ else {
+ // single no need for a mergeProps call
+ propsExpression = mergeArgs[0];
+ }
+ }
+ else if (properties.length) {
+ // single no need for spread
+ if (properties.length === 1 && t.isSpreadElement(properties[0])) {
+ propsExpression = properties[0].argument;
+ }
+ else {
+ propsExpression = t.objectExpression(dedupeProperties(properties, mergeProps));
+ }
+ }
+ return {
+ tag,
+ props: propsExpression,
+ isComponent,
+ slots,
+ directives,
+ patchFlag,
+ dynamicPropNames,
+ };
+};
+exports.default = buildProps;
diff --git a/packages/uni-h5/lib/babel-plugin-jsx/dist/helpers.js b/packages/uni-h5/lib/babel-plugin-jsx/dist/helpers.js
new file mode 100644
index 0000000000000000000000000000000000000000..929b49e25ad492bf2a328a7337e109867caf6ed2
--- /dev/null
+++ b/packages/uni-h5/lib/babel-plugin-jsx/dist/helpers.js
@@ -0,0 +1,17 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const template_1 = __importDefault(require("@babel/template"));
+const helpers = Object.create(null);
+const helper = (tpl) => ({
+ ast: () => template_1.default.program.ast(tpl),
+});
+helpers.isSlot = helper `
+ import { isVNode } from 'vue';
+ export default function _isSlot(s) {
+ return typeof s === 'function' || (Object.prototype.toString.call(s) === '[object Object]' && !isVNode(s));
+ }
+`;
+exports.default = helpers;
diff --git a/packages/uni-h5/lib/babel-plugin-jsx/dist/index.d.ts b/packages/uni-h5/lib/babel-plugin-jsx/dist/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1cde9e6a10a317020b7d2cd6d20f3b32c227b310
--- /dev/null
+++ b/packages/uni-h5/lib/babel-plugin-jsx/dist/index.d.ts
@@ -0,0 +1,38 @@
+import * as t from '@babel/types';
+import * as BabelCore from '@babel/core';
+import { NodePath } from '@babel/traverse';
+export declare type State = {
+ get: (name: string) => any;
+ set: (name: string, value: any) => any;
+ opts: VueJSXPluginOptions;
+};
+export interface VueJSXPluginOptions {
+ /** transform `on: { click: xx }` to `onClick: xxx` */
+ transformOn?: boolean;
+ /** enable optimization or not. */
+ optimize?: boolean;
+ /** merge static and dynamic class / style attributes / onXXX handlers */
+ mergeProps?: boolean;
+ /** configuring custom elements */
+ isCustomElement?: (tag: string) => boolean;
+ /** enable object slots syntax */
+ enableObjectSlots?: boolean;
+}
+export declare type ExcludesBoolean = (x: T | false | true) => x is T;
+declare const _default: ({ types }: typeof BabelCore) => {
+ name: string;
+ inherits: any;
+ visitor: {
+ Program: {
+ enter(path: NodePath, state: State): void;
+ exit(path: NodePath): void;
+ };
+ JSXFragment: {
+ enter(path: BabelCore.NodePath, state: State): void;
+ };
+ JSXElement: {
+ exit(path: BabelCore.NodePath, state: State): void;
+ };
+ };
+};
+export default _default;
diff --git a/packages/uni-h5/lib/babel-plugin-jsx/dist/index.js b/packages/uni-h5/lib/babel-plugin-jsx/dist/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..d8fbbdcbe2ed3757f9093f392fdf16ad13f12835
--- /dev/null
+++ b/packages/uni-h5/lib/babel-plugin-jsx/dist/index.js
@@ -0,0 +1,145 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
+}) : (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ o[k2] = m[k];
+}));
+var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
+}) : function(o, v) {
+ o["default"] = v;
+});
+var __importStar = (this && this.__importStar) || function (mod) {
+ if (mod && mod.__esModule) return mod;
+ var result = {};
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
+ __setModuleDefault(result, mod);
+ return result;
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const t = __importStar(require("@babel/types"));
+const template_1 = __importDefault(require("@babel/template"));
+const plugin_syntax_jsx_1 = __importDefault(require("@babel/plugin-syntax-jsx"));
+const helper_module_imports_1 = require("@babel/helper-module-imports");
+const transform_vue_jsx_1 = __importDefault(require("./transform-vue-jsx"));
+const sugar_fragment_1 = __importDefault(require("./sugar-fragment"));
+const hasJSX = (parentPath) => {
+ let fileHasJSX = false;
+ parentPath.traverse({
+ JSXElement(path) {
+ fileHasJSX = true;
+ path.stop();
+ },
+ JSXFragment(path) {
+ fileHasJSX = true;
+ path.stop();
+ },
+ });
+ return fileHasJSX;
+};
+exports.default = ({ types }) => ({
+ name: 'babel-plugin-jsx',
+ inherits: plugin_syntax_jsx_1.default,
+ visitor: Object.assign(Object.assign(Object.assign({}, transform_vue_jsx_1.default), sugar_fragment_1.default), { Program: {
+ enter(path, state) {
+ if (hasJSX(path)) {
+ const importNames = [
+ 'createVNode',
+ 'Fragment',
+ 'resolveComponent',
+ 'withDirectives',
+ 'vShow',
+ 'vModelSelect',
+ 'vModelText',
+ 'vModelCheckbox',
+ 'vModelRadio',
+ 'vModelText',
+ 'vModelDynamic',
+ 'resolveDirective',
+ 'mergeProps',
+ 'createTextVNode',
+ 'isVNode',
+ ];
+ if (helper_module_imports_1.isModule(path)) {
+ // import { createVNode } from "vue";
+ const importMap = {};
+ importNames.forEach((name) => {
+ state.set(name, () => {
+ if (importMap[name]) {
+ return types.cloneNode(importMap[name]);
+ }
+ const identifier = helper_module_imports_1.addNamed(path, name, 'vue', {
+ ensureLiveReference: true,
+ });
+ importMap[name] = identifier;
+ return identifier;
+ });
+ });
+ const { enableObjectSlots = true } = state.opts;
+ if (enableObjectSlots) {
+ state.set('@vue/babel-plugin-jsx/runtimeIsSlot', () => {
+ if (importMap.runtimeIsSlot) {
+ return importMap.runtimeIsSlot;
+ }
+ const { name: isVNodeName } = state.get('isVNode')();
+ const isSlot = path.scope.generateUidIdentifier('isSlot');
+ const ast = template_1.default.ast `
+ function ${isSlot.name}(s) {
+ return typeof s === 'function' || (Object.prototype.toString.call(s) === '[object Object]' && !${isVNodeName}(s));
+ }
+ `;
+ const lastImport = path.get('body').filter((p) => p.isImportDeclaration()).pop();
+ if (lastImport) {
+ lastImport.insertAfter(ast);
+ }
+ importMap.runtimeIsSlot = isSlot;
+ return isSlot;
+ });
+ }
+ }
+ else {
+ // var _vue = require('vue');
+ let sourceName = '';
+ importNames.forEach((name) => {
+ state.set(name, () => {
+ if (!sourceName) {
+ sourceName = helper_module_imports_1.addNamespace(path, 'vue', {
+ ensureLiveReference: true,
+ }).name;
+ }
+ return t.memberExpression(t.identifier(sourceName), t.identifier(name));
+ });
+ });
+ }
+ }
+ },
+ exit(path) {
+ const body = path.get('body');
+ const specifiersMap = new Map();
+ body.filter((nodePath) => t.isImportDeclaration(nodePath.node)
+ && nodePath.node.source.value === 'vue')
+ .forEach((nodePath) => {
+ const { specifiers } = nodePath.node;
+ let shouldRemove = false;
+ specifiers.forEach((specifier) => {
+ if (!specifier.loc && t.isImportSpecifier(specifier) && t.isIdentifier(specifier.imported)) {
+ specifiersMap.set(specifier.imported.name, specifier);
+ shouldRemove = true;
+ }
+ });
+ if (shouldRemove) {
+ nodePath.remove();
+ }
+ });
+ const specifiers = [...specifiersMap.keys()].map((imported) => specifiersMap.get(imported));
+ if (specifiers.length) {
+ path.unshiftContainer('body', t.importDeclaration(specifiers, t.stringLiteral('vue')));
+ }
+ },
+ } }),
+});
diff --git a/packages/uni-h5/lib/babel-plugin-jsx/dist/parseDirectives.d.ts b/packages/uni-h5/lib/babel-plugin-jsx/dist/parseDirectives.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..046471ce1a2604cc93eb559e4de7bbb6fd407f7f
--- /dev/null
+++ b/packages/uni-h5/lib/babel-plugin-jsx/dist/parseDirectives.d.ts
@@ -0,0 +1,19 @@
+import * as t from '@babel/types';
+import { NodePath } from '@babel/traverse';
+import { State } from '.';
+export declare type Tag = t.Identifier | t.MemberExpression | t.StringLiteral | t.CallExpression;
+declare const parseDirectives: (params: {
+ name: string;
+ path: NodePath;
+ value: t.StringLiteral | t.Expression | null;
+ state: State;
+ tag: Tag;
+ isComponent: boolean;
+}) => {
+ directiveName: string;
+ modifiers: Set[];
+ values: (t.ArrayExpression | t.ArrowFunctionExpression | t.AssignmentExpression | t.AwaitExpression | t.BigIntLiteral | t.BinaryExpression | t.LogicalExpression | t.BindExpression | t.FunctionExpression | t.BooleanLiteral | t.CallExpression | t.ClassExpression | t.ConditionalExpression | t.DecimalLiteral | t.DoExpression | t.Identifier | t.StringLiteral | t.NumericLiteral | t.NullLiteral | t.RegExpLiteral | t.MemberExpression | t.NewExpression | t.ObjectExpression | t.SequenceExpression | t.ParenthesizedExpression | t.ThisExpression | t.UnaryExpression | t.UpdateExpression | t.MetaProperty | t.Super | t.TaggedTemplateExpression | t.TemplateLiteral | t.YieldExpression | t.Import | t.OptionalMemberExpression | t.OptionalCallExpression | t.TypeCastExpression | t.JSXElement | t.JSXFragment | t.PipelinePrimaryTopicReference | t.RecordExpression | t.TupleExpression | t.TSAsExpression | t.TSTypeAssertion | t.TSNonNullExpression | null)[];
+ args: (t.StringLiteral | t.NullLiteral)[];
+ directive: t.Expression[] | undefined;
+};
+export default parseDirectives;
diff --git a/packages/uni-h5/lib/babel-plugin-jsx/dist/parseDirectives.js b/packages/uni-h5/lib/babel-plugin-jsx/dist/parseDirectives.js
new file mode 100644
index 0000000000000000000000000000000000000000..4bf7d07a4dd3a75f7200448fd20a898598989037
--- /dev/null
+++ b/packages/uni-h5/lib/babel-plugin-jsx/dist/parseDirectives.js
@@ -0,0 +1,150 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
+}) : (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ o[k2] = m[k];
+}));
+var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
+}) : function(o, v) {
+ o["default"] = v;
+});
+var __importStar = (this && this.__importStar) || function (mod) {
+ if (mod && mod.__esModule) return mod;
+ var result = {};
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
+ __setModuleDefault(result, mod);
+ return result;
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const t = __importStar(require("@babel/types"));
+const utils_1 = require("./utils");
+/**
+ * Get JSX element type
+ *
+ * @param path Path
+ */
+const getType = (path) => {
+ const typePath = path
+ .get('attributes')
+ .find((attribute) => {
+ if (!t.isJSXAttribute(attribute)) {
+ return false;
+ }
+ return t.isJSXIdentifier(attribute.get('name'))
+ && attribute.get('name').node.name === 'type';
+ });
+ return typePath ? typePath.get('value').node : null;
+};
+const parseModifiers = (value) => (t.isArrayExpression(value)
+ ? value.elements
+ .map((el) => (t.isStringLiteral(el) ? el.value : ''))
+ .filter(Boolean)
+ : []);
+const parseDirectives = (params) => {
+ var _a, _b, _c;
+ const { name, path, value, state, tag, isComponent, } = params;
+ const args = [];
+ const vals = [];
+ const modifiersSet = [];
+ const underscoreModifiers = name.split('_');
+ const directiveName = ((_a = underscoreModifiers.shift()) === null || _a === void 0 ? void 0 : _a.replace(/^v/, '').replace(/^-/, '').replace(/^\S/, (s) => s.toLowerCase())) || '';
+ const isVModels = directiveName === 'models';
+ const isVModel = directiveName === 'model';
+ if (isVModel && !t.isJSXExpressionContainer(path.get('value'))) {
+ throw new Error('You have to use JSX Expression inside your v-model');
+ }
+ if (isVModels && !isComponent) {
+ throw new Error('v-models can only use in custom components');
+ }
+ const shouldResolve = !['html', 'text', 'model', 'models'].includes(directiveName)
+ || (isVModel && !isComponent);
+ if (['models', 'model'].includes(directiveName)) {
+ if (t.isArrayExpression(value)) {
+ const elementsList = isVModels ? value.elements : [value];
+ elementsList.forEach((element) => {
+ if (isVModels && !t.isArrayExpression(element)) {
+ throw new Error('You should pass a Two-dimensional Arrays to v-models');
+ }
+ const { elements } = element;
+ const [first, second, third] = elements;
+ let modifiers = underscoreModifiers;
+ if (t.isStringLiteral(second)) {
+ args.push(second);
+ modifiers = parseModifiers(third);
+ }
+ else if (t.isArrayExpression(second)) {
+ args.push(t.nullLiteral());
+ modifiers = parseModifiers(second);
+ }
+ else {
+ // work as v-model={[value]} or v-models={[[value]]}
+ args.push(t.nullLiteral());
+ }
+ modifiersSet.push(new Set(modifiers));
+ vals.push(first);
+ });
+ }
+ else if (isVModel) {
+ // work as v-model={value}
+ args.push(t.nullLiteral());
+ modifiersSet.push(new Set(underscoreModifiers));
+ }
+ }
+ else {
+ modifiersSet.push(new Set(underscoreModifiers));
+ }
+ return {
+ directiveName,
+ modifiers: modifiersSet,
+ values: vals.length ? vals : [value],
+ args,
+ directive: shouldResolve ? [
+ resolveDirective(path, state, tag, directiveName),
+ vals[0] || value,
+ !!((_b = modifiersSet[0]) === null || _b === void 0 ? void 0 : _b.size) && t.unaryExpression('void', t.numericLiteral(0), true),
+ !!((_c = modifiersSet[0]) === null || _c === void 0 ? void 0 : _c.size) && t.objectExpression([...modifiersSet[0]].map((modifier) => t.objectProperty(t.identifier(modifier), t.booleanLiteral(true)))),
+ ].filter(Boolean) : undefined,
+ };
+};
+const resolveDirective = (path, state, tag, directiveName) => {
+ var _a;
+ if (directiveName === 'show') {
+ return utils_1.createIdentifier(state, 'vShow');
+ }
+ if (directiveName === 'model') {
+ let modelToUse;
+ const type = getType(path.parentPath);
+ switch (tag.value) {
+ case 'select':
+ modelToUse = utils_1.createIdentifier(state, 'vModelSelect');
+ break;
+ case 'textarea':
+ modelToUse = utils_1.createIdentifier(state, 'vModelText');
+ break;
+ default:
+ if (t.isStringLiteral(type) || !type) {
+ switch ((_a = type) === null || _a === void 0 ? void 0 : _a.value) {
+ case 'checkbox':
+ modelToUse = utils_1.createIdentifier(state, 'vModelCheckbox');
+ break;
+ case 'radio':
+ modelToUse = utils_1.createIdentifier(state, 'vModelRadio');
+ break;
+ default:
+ modelToUse = utils_1.createIdentifier(state, 'vModelText');
+ }
+ }
+ else {
+ modelToUse = utils_1.createIdentifier(state, 'vModelDynamic');
+ }
+ }
+ return modelToUse;
+ }
+ return t.callExpression(utils_1.createIdentifier(state, 'resolveDirective'), [
+ t.stringLiteral(directiveName),
+ ]);
+};
+exports.default = parseDirectives;
diff --git a/packages/uni-h5/lib/babel-plugin-jsx/dist/patchFlags.d.ts b/packages/uni-h5/lib/babel-plugin-jsx/dist/patchFlags.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ba11ca7c60b6a083c8fa92644bbdab0339cb95f1
--- /dev/null
+++ b/packages/uni-h5/lib/babel-plugin-jsx/dist/patchFlags.d.ts
@@ -0,0 +1,18 @@
+export declare const enum PatchFlags {
+ TEXT = 1,
+ CLASS = 2,
+ STYLE = 4,
+ PROPS = 8,
+ FULL_PROPS = 16,
+ HYDRATE_EVENTS = 32,
+ STABLE_FRAGMENT = 64,
+ KEYED_FRAGMENT = 128,
+ UNKEYED_FRAGMENT = 256,
+ NEED_PATCH = 512,
+ DYNAMIC_SLOTS = 1024,
+ HOISTED = -1,
+ BAIL = -2
+}
+export declare const PatchFlagNames: {
+ [x: number]: string;
+};
diff --git a/packages/uni-h5/lib/babel-plugin-jsx/dist/patchFlags.js b/packages/uni-h5/lib/babel-plugin-jsx/dist/patchFlags.js
new file mode 100644
index 0000000000000000000000000000000000000000..e1b71b5e39346edc0b1fb04195923caae9ceeba9
--- /dev/null
+++ b/packages/uni-h5/lib/babel-plugin-jsx/dist/patchFlags.js
@@ -0,0 +1,19 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.PatchFlagNames = void 0;
+// dev only flag -> name mapping
+exports.PatchFlagNames = {
+ [1 /* TEXT */]: 'TEXT',
+ [2 /* CLASS */]: 'CLASS',
+ [4 /* STYLE */]: 'STYLE',
+ [8 /* PROPS */]: 'PROPS',
+ [16 /* FULL_PROPS */]: 'FULL_PROPS',
+ [32 /* HYDRATE_EVENTS */]: 'HYDRATE_EVENTS',
+ [64 /* STABLE_FRAGMENT */]: 'STABLE_FRAGMENT',
+ [128 /* KEYED_FRAGMENT */]: 'KEYED_FRAGMENT',
+ [256 /* UNKEYED_FRAGMENT */]: 'UNKEYED_FRAGMENT',
+ [1024 /* DYNAMIC_SLOTS */]: 'DYNAMIC_SLOTS',
+ [512 /* NEED_PATCH */]: 'NEED_PATCH',
+ [-1 /* HOISTED */]: 'HOISTED',
+ [-2 /* BAIL */]: 'BAIL',
+};
diff --git a/packages/uni-h5/lib/babel-plugin-jsx/dist/rumtime.js b/packages/uni-h5/lib/babel-plugin-jsx/dist/rumtime.js
new file mode 100644
index 0000000000000000000000000000000000000000..c8924fa698d62ae40b63c76f6aa44ceb06d186a3
--- /dev/null
+++ b/packages/uni-h5/lib/babel-plugin-jsx/dist/rumtime.js
@@ -0,0 +1,8 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.isSlot = void 0;
+const vue_1 = require("vue");
+const isFunction = (val) => typeof val === 'function';
+const isObject = (val) => Object.prototype.toString.call(val) === '[object Object]';
+const isSlot = (s) => isFunction(s) || (isObject(s) && !vue_1.isVNode(s));
+exports.isSlot = isSlot;
diff --git a/packages/uni-h5/lib/babel-plugin-jsx/dist/slotFlags.d.ts b/packages/uni-h5/lib/babel-plugin-jsx/dist/slotFlags.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..986e87ef214d9f329dc4097298f146fd2824f367
--- /dev/null
+++ b/packages/uni-h5/lib/babel-plugin-jsx/dist/slotFlags.d.ts
@@ -0,0 +1,22 @@
+declare const enum SlotFlags {
+ /**
+ * Stable slots that only reference slot props or context state. The slot
+ * can fully capture its own dependencies so when passed down the parent won't
+ * need to force the child to update.
+ */
+ STABLE = 1,
+ /**
+ * Slots that reference scope variables (v-for or an outer slot prop), or
+ * has conditional structure (v-if, v-for). The parent will need to force
+ * the child to update because the slot does not fully capture its dependencies.
+ */
+ DYNAMIC = 2,
+ /**
+ * `` being forwarded into a child component. Whether the parent needs
+ * to update the child is dependent on what kind of slots the parent itself
+ * received. This has to be refined at runtime, when the child's vnode
+ * is being created (in `normalizeChildren`)
+ */
+ FORWARDED = 3
+}
+export default SlotFlags;
diff --git a/packages/uni-h5/lib/babel-plugin-jsx/dist/slotFlags.js b/packages/uni-h5/lib/babel-plugin-jsx/dist/slotFlags.js
new file mode 100644
index 0000000000000000000000000000000000000000..c8ad2e549bdc6801e0d1c80b0308d4b9bd4985ce
--- /dev/null
+++ b/packages/uni-h5/lib/babel-plugin-jsx/dist/slotFlags.js
@@ -0,0 +1,2 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
diff --git a/packages/uni-h5/lib/babel-plugin-jsx/dist/sugar-fragment.d.ts b/packages/uni-h5/lib/babel-plugin-jsx/dist/sugar-fragment.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..acaac91dcf1bf05e54722f34a12a9b4c0d1031d2
--- /dev/null
+++ b/packages/uni-h5/lib/babel-plugin-jsx/dist/sugar-fragment.d.ts
@@ -0,0 +1,9 @@
+import * as t from '@babel/types';
+import { NodePath } from '@babel/traverse';
+import { State } from '.';
+declare const _default: {
+ JSXFragment: {
+ enter(path: NodePath, state: State): void;
+ };
+};
+export default _default;
diff --git a/packages/uni-h5/lib/babel-plugin-jsx/dist/sugar-fragment.js b/packages/uni-h5/lib/babel-plugin-jsx/dist/sugar-fragment.js
new file mode 100644
index 0000000000000000000000000000000000000000..18f1eb177a89d0ae22a25893565e5bc03b458ff5
--- /dev/null
+++ b/packages/uni-h5/lib/babel-plugin-jsx/dist/sugar-fragment.js
@@ -0,0 +1,37 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
+}) : (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ o[k2] = m[k];
+}));
+var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
+}) : function(o, v) {
+ o["default"] = v;
+});
+var __importStar = (this && this.__importStar) || function (mod) {
+ if (mod && mod.__esModule) return mod;
+ var result = {};
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
+ __setModuleDefault(result, mod);
+ return result;
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const t = __importStar(require("@babel/types"));
+const utils_1 = require("./utils");
+const transformFragment = (path, Fragment) => {
+ const children = path.get('children') || [];
+ return t.jsxElement(t.jsxOpeningElement(Fragment, []), t.jsxClosingElement(Fragment), children.map(({ node }) => node), false);
+};
+exports.default = ({
+ JSXFragment: {
+ enter(path, state) {
+ const fragmentCallee = utils_1.createIdentifier(state, utils_1.FRAGMENT);
+ path.replaceWith(transformFragment(path, t.isIdentifier(fragmentCallee)
+ ? t.jsxIdentifier(fragmentCallee.name)
+ : t.jsxMemberExpression(t.jsxIdentifier(fragmentCallee.object.name), t.jsxIdentifier(fragmentCallee.property.name))));
+ },
+ },
+});
diff --git a/packages/uni-h5/lib/babel-plugin-jsx/dist/transform-vue-jsx.d.ts b/packages/uni-h5/lib/babel-plugin-jsx/dist/transform-vue-jsx.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..45a0c7b8fb61a2e174800941f8c39546377e2150
--- /dev/null
+++ b/packages/uni-h5/lib/babel-plugin-jsx/dist/transform-vue-jsx.d.ts
@@ -0,0 +1,11 @@
+import * as t from '@babel/types';
+import { NodePath } from '@babel/traverse';
+import { State } from '.';
+declare const transformJSXElement: (path: NodePath, state: State) => t.CallExpression;
+export { transformJSXElement };
+declare const _default: {
+ JSXElement: {
+ exit(path: NodePath, state: State): void;
+ };
+};
+export default _default;
diff --git a/packages/uni-h5/lib/babel-plugin-jsx/dist/transform-vue-jsx.js b/packages/uni-h5/lib/babel-plugin-jsx/dist/transform-vue-jsx.js
new file mode 100644
index 0000000000000000000000000000000000000000..66ee20296a35981860d2a97f0a1a6b2446ed7c79
--- /dev/null
+++ b/packages/uni-h5/lib/babel-plugin-jsx/dist/transform-vue-jsx.js
@@ -0,0 +1,162 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
+}) : (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ o[k2] = m[k];
+}));
+var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
+}) : function(o, v) {
+ o["default"] = v;
+});
+var __importStar = (this && this.__importStar) || function (mod) {
+ if (mod && mod.__esModule) return mod;
+ var result = {};
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
+ __setModuleDefault(result, mod);
+ return result;
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.transformJSXElement = void 0;
+const t = __importStar(require("@babel/types"));
+const utils_1 = require("./utils");
+const buildProps_1 = __importDefault(require("./buildProps"));
+/**
+ * Get children from Array of JSX children
+ * @param paths Array
+ * @returns Array
+ */
+const getChildren = (paths, state) => paths
+ .map((path) => {
+ if (path.isJSXText()) {
+ const transformedText = utils_1.transformJSXText(path);
+ if (transformedText) {
+ return t.callExpression(utils_1.createIdentifier(state, 'createTextVNode'), [transformedText]);
+ }
+ return transformedText;
+ }
+ if (path.isJSXExpressionContainer()) {
+ const expression = utils_1.transformJSXExpressionContainer(path);
+ if (t.isIdentifier(expression)) {
+ const { name } = expression;
+ const { referencePaths = [] } = path.scope.getBinding(name) || {};
+ referencePaths.forEach((referencePath) => {
+ utils_1.walksScope(referencePath, name, 2 /* DYNAMIC */);
+ });
+ }
+ return expression;
+ }
+ if (t.isJSXSpreadChild(path)) {
+ return utils_1.transformJSXSpreadChild(path);
+ }
+ if (path.isCallExpression()) {
+ return path.node;
+ }
+ if (path.isJSXElement()) {
+ return transformJSXElement(path, state);
+ }
+ throw new Error(`getChildren: ${path.type} is not supported`);
+}).filter(((value) => (value !== undefined
+ && value !== null
+ && !t.isJSXEmptyExpression(value))));
+const transformJSXElement = (path, state) => {
+ const children = getChildren(path.get('children'), state);
+ const { tag, props, isComponent, directives, patchFlag, dynamicPropNames, slots, } = buildProps_1.default(path, state);
+ const { optimize = false } = state.opts;
+ const slotFlag = path.getData('slotFlag') || 1 /* STABLE */;
+ let VNodeChild;
+ if (children.length > 1 || slots) {
+ /*
+ {a}{b}
+ ---> {{ default: () => [a, b], ...slots }}
+ ---> {[a, b]}
+ */
+ VNodeChild = isComponent ? t.objectExpression([
+ !!children.length && t.objectProperty(t.identifier('default'), t.arrowFunctionExpression([], t.arrayExpression(utils_1.buildIIFE(path, children)))),
+ ...(slots ? (t.isObjectExpression(slots)
+ ? slots.properties
+ : [t.spreadElement(slots)]) : []),
+ optimize && t.objectProperty(t.identifier('_'), t.numericLiteral(slotFlag)),
+ ].filter(Boolean)) : t.arrayExpression(children);
+ }
+ else if (children.length === 1) {
+ /*
+ {a} or {() => a}
+ */
+ const { enableObjectSlots = true } = state.opts;
+ const child = children[0];
+ const objectExpression = t.objectExpression([
+ t.objectProperty(t.identifier('default'), t.arrowFunctionExpression([], t.arrayExpression(utils_1.buildIIFE(path, [child])))),
+ optimize && t.objectProperty(t.identifier('_'), t.numericLiteral(slotFlag)),
+ ].filter(Boolean));
+ if (t.isIdentifier(child) && isComponent) {
+ VNodeChild = enableObjectSlots ? t.conditionalExpression(t.callExpression(state.get('@vue/babel-plugin-jsx/runtimeIsSlot')(), [child]), child, objectExpression) : objectExpression;
+ }
+ else if (t.isCallExpression(child) && child.loc && isComponent) { // the element was generated and doesn't have location information
+ if (enableObjectSlots) {
+ const { scope } = path;
+ const slotId = scope.generateUidIdentifier('slot');
+ if (scope) {
+ scope.push({
+ id: slotId,
+ kind: 'let',
+ });
+ }
+ const alternate = t.objectExpression([
+ t.objectProperty(t.identifier('default'), t.arrowFunctionExpression([], t.arrayExpression(utils_1.buildIIFE(path, [slotId])))),
+ optimize && t.objectProperty(t.identifier('_'), t.numericLiteral(slotFlag)),
+ ].filter(Boolean));
+ const assignment = t.assignmentExpression('=', slotId, child);
+ const condition = t.callExpression(state.get('@vue/babel-plugin-jsx/runtimeIsSlot')(), [assignment]);
+ VNodeChild = t.conditionalExpression(condition, slotId, alternate);
+ }
+ else {
+ VNodeChild = objectExpression;
+ }
+ }
+ else if (t.isFunctionExpression(child) || t.isArrowFunctionExpression(child)) {
+ VNodeChild = t.objectExpression([
+ t.objectProperty(t.identifier('default'), child),
+ ]);
+ }
+ else if (t.isObjectExpression(child)) {
+ VNodeChild = t.objectExpression([
+ ...child.properties,
+ optimize && t.objectProperty(t.identifier('_'), t.numericLiteral(slotFlag)),
+ ].filter(Boolean));
+ }
+ else {
+ VNodeChild = isComponent ? t.objectExpression([
+ t.objectProperty(t.identifier('default'), t.arrowFunctionExpression([], t.arrayExpression([child]))),
+ ]) : t.arrayExpression([child]);
+ }
+ }
+ const createVNode = t.callExpression(utils_1.createIdentifier(state, 'createVNode'), [
+ tag,
+ props,
+ VNodeChild || t.nullLiteral(),
+ !!patchFlag && optimize && t.numericLiteral(patchFlag),
+ !!dynamicPropNames.size && optimize
+ && t.arrayExpression([...dynamicPropNames.keys()].map((name) => t.stringLiteral(name))),
+ ].filter(Boolean));
+ if (!directives.length) {
+ return createVNode;
+ }
+ return t.callExpression(utils_1.createIdentifier(state, 'withDirectives'), [
+ createVNode,
+ t.arrayExpression(directives),
+ ]);
+};
+exports.transformJSXElement = transformJSXElement;
+exports.default = ({
+ JSXElement: {
+ exit(path, state) {
+ path.replaceWith(transformJSXElement(path, state));
+ },
+ },
+});
diff --git a/packages/uni-h5/lib/babel-plugin-jsx/dist/utils.d.ts b/packages/uni-h5/lib/babel-plugin-jsx/dist/utils.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..861a33bca2b721f83d2de528e912f1f6aff00b0a
--- /dev/null
+++ b/packages/uni-h5/lib/babel-plugin-jsx/dist/utils.d.ts
@@ -0,0 +1,68 @@
+import * as t from '@babel/types';
+import { NodePath } from '@babel/traverse';
+import { State } from '.';
+import SlotFlags from './slotFlags';
+declare const JSX_HELPER_KEY = "JSX_HELPER_KEY";
+declare const FRAGMENT = "Fragment";
+/**
+ * create Identifier
+ * @param path NodePath
+ * @param state
+ * @param name string
+ * @returns MemberExpression
+ */
+declare const createIdentifier: (state: State, name: string) => t.Identifier | t.MemberExpression;
+/**
+ * Checks if string is describing a directive
+ * @param src string
+ */
+declare const isDirective: (src: string) => boolean;
+/**
+ * Should transformed to slots
+ * @param tag string
+ * @returns boolean
+ */
+declare const shouldTransformedToSlots: (tag: string) => boolean;
+/**
+ * Check if a Node is a component
+ *
+ * @param t
+ * @param path JSXOpeningElement
+ * @returns boolean
+ */
+declare const checkIsComponent: (path: NodePath) => boolean;
+/**
+ * Transform JSXMemberExpression to MemberExpression
+ * @param path JSXMemberExpression
+ * @returns MemberExpression
+ */
+declare const transformJSXMemberExpression: (path: NodePath) => t.MemberExpression;
+/**
+ * Get tag (first attribute for h) from JSXOpeningElement
+ * @param path JSXElement
+ * @param state State
+ * @returns Identifier | StringLiteral | MemberExpression | CallExpression
+ */
+declare const getTag: (path: NodePath, state: State) => t.Identifier | t.CallExpression | t.StringLiteral | t.MemberExpression;
+declare const getJSXAttributeName: (path: NodePath) => string;
+/**
+ * Transform JSXText to StringLiteral
+ * @param path JSXText
+ * @returns StringLiteral | null
+ */
+declare const transformJSXText: (path: NodePath) => t.StringLiteral | null;
+/**
+ * Transform JSXExpressionContainer to Expression
+ * @param path JSXExpressionContainer
+ * @returns Expression
+ */
+declare const transformJSXExpressionContainer: (path: NodePath) => (t.Expression);
+/**
+ * Transform JSXSpreadChild
+ * @param path JSXSpreadChild
+ * @returns SpreadElement
+ */
+declare const transformJSXSpreadChild: (path: NodePath) => t.SpreadElement;
+declare const walksScope: (path: NodePath, name: string, slotFlag: SlotFlags) => void;
+declare const buildIIFE: (path: NodePath, children: t.Expression[]) => t.Expression[];
+export { createIdentifier, isDirective, checkIsComponent, transformJSXMemberExpression, getTag, getJSXAttributeName, transformJSXText, transformJSXSpreadChild, transformJSXExpressionContainer, shouldTransformedToSlots, FRAGMENT, walksScope, buildIIFE, JSX_HELPER_KEY, };
diff --git a/packages/uni-h5/lib/babel-plugin-jsx/dist/utils.js b/packages/uni-h5/lib/babel-plugin-jsx/dist/utils.js
new file mode 100644
index 0000000000000000000000000000000000000000..8e4e84f58ded7818e8c646335f909a2eaec6b35d
--- /dev/null
+++ b/packages/uni-h5/lib/babel-plugin-jsx/dist/utils.js
@@ -0,0 +1,210 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
+}) : (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ o[k2] = m[k];
+}));
+var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
+}) : function(o, v) {
+ o["default"] = v;
+});
+var __importStar = (this && this.__importStar) || function (mod) {
+ if (mod && mod.__esModule) return mod;
+ var result = {};
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
+ __setModuleDefault(result, mod);
+ return result;
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.JSX_HELPER_KEY = exports.buildIIFE = exports.walksScope = exports.FRAGMENT = exports.shouldTransformedToSlots = exports.transformJSXExpressionContainer = exports.transformJSXSpreadChild = exports.transformJSXText = exports.getJSXAttributeName = exports.getTag = exports.transformJSXMemberExpression = exports.checkIsComponent = exports.isDirective = exports.createIdentifier = void 0;
+const t = __importStar(require("@babel/types"));
+const html_tags_1 = __importDefault(require("html-tags"));
+const svg_tags_1 = __importDefault(require("svg-tags"));
+const JSX_HELPER_KEY = 'JSX_HELPER_KEY';
+exports.JSX_HELPER_KEY = JSX_HELPER_KEY;
+const FRAGMENT = 'Fragment';
+exports.FRAGMENT = FRAGMENT;
+const KEEP_ALIVE = 'KeepAlive';
+/**
+ * create Identifier
+ * @param path NodePath
+ * @param state
+ * @param name string
+ * @returns MemberExpression
+ */
+const createIdentifier = (state, name) => state.get(name)();
+exports.createIdentifier = createIdentifier;
+/**
+ * Checks if string is describing a directive
+ * @param src string
+ */
+const isDirective = (src) => src.startsWith('v-')
+ || (src.startsWith('v') && src.length >= 2 && src[1] >= 'A' && src[1] <= 'Z');
+exports.isDirective = isDirective;
+/**
+ * Should transformed to slots
+ * @param tag string
+ * @returns boolean
+ */
+const shouldTransformedToSlots = (tag) => !(tag.endsWith(FRAGMENT) || tag === KEEP_ALIVE);
+exports.shouldTransformedToSlots = shouldTransformedToSlots;
+/**
+ * Check if a Node is a component
+ *
+ * @param t
+ * @param path JSXOpeningElement
+ * @returns boolean
+ */
+const checkIsComponent = (path, state) => {
+ const namePath = path.get('name');
+ if (namePath.isJSXMemberExpression()) {
+ return shouldTransformedToSlots(namePath.node.property.name); // For withCtx
+ }
+ const tag = namePath.node.name;
+ if(state.opts.isCustomElement && state.opts.isCustomElement(tag)){
+ return false
+ }
+ return shouldTransformedToSlots(tag) && !html_tags_1.default.includes(tag) && !svg_tags_1.default.includes(tag);
+};
+exports.checkIsComponent = checkIsComponent;
+/**
+ * Transform JSXMemberExpression to MemberExpression
+ * @param path JSXMemberExpression
+ * @returns MemberExpression
+ */
+const transformJSXMemberExpression = (path) => {
+ const objectPath = path.node.object;
+ const propertyPath = path.node.property;
+ const transformedObject = t.isJSXMemberExpression(objectPath)
+ ? transformJSXMemberExpression(path.get('object'))
+ : t.isJSXIdentifier(objectPath)
+ ? t.identifier(objectPath.name)
+ : t.nullLiteral();
+ const transformedProperty = t.identifier(propertyPath.name);
+ return t.memberExpression(transformedObject, transformedProperty);
+};
+exports.transformJSXMemberExpression = transformJSXMemberExpression;
+/**
+ * Get tag (first attribute for h) from JSXOpeningElement
+ * @param path JSXElement
+ * @param state State
+ * @returns Identifier | StringLiteral | MemberExpression | CallExpression
+ */
+const getTag = (path, state) => {
+ var _a, _b;
+ const namePath = path.get('openingElement').get('name');
+ if (namePath.isJSXIdentifier()) {
+ const { name } = namePath.node;
+ if (!html_tags_1.default.includes(name) && !svg_tags_1.default.includes(name)) {
+ return (name === FRAGMENT
+ ? createIdentifier(state, FRAGMENT)
+ : path.scope.hasBinding(name)
+ ? t.identifier(name)
+ : ((_b = (_a = state.opts).isCustomElement) === null || _b === void 0 ? void 0 : _b.call(_a, name)) ? t.stringLiteral(name)
+ : t.callExpression(createIdentifier(state, 'resolveComponent'), [t.stringLiteral(name)]));
+ }
+ return t.stringLiteral(name);
+ }
+ if (namePath.isJSXMemberExpression()) {
+ return transformJSXMemberExpression(namePath);
+ }
+ throw new Error(`getTag: ${namePath.type} is not supported`);
+};
+exports.getTag = getTag;
+const getJSXAttributeName = (path) => {
+ const nameNode = path.node.name;
+ if (t.isJSXIdentifier(nameNode)) {
+ return nameNode.name;
+ }
+ return `${nameNode.namespace.name}:${nameNode.name.name}`;
+};
+exports.getJSXAttributeName = getJSXAttributeName;
+/**
+ * Transform JSXText to StringLiteral
+ * @param path JSXText
+ * @returns StringLiteral | null
+ */
+const transformJSXText = (path) => {
+ const { node } = path;
+ const lines = node.value.split(/\r\n|\n|\r/);
+ let lastNonEmptyLine = 0;
+ for (let i = 0; i < lines.length; i++) {
+ if (lines[i].match(/[^ \t]/)) {
+ lastNonEmptyLine = i;
+ }
+ }
+ let str = '';
+ for (let i = 0; i < lines.length; i++) {
+ const line = lines[i];
+ const isFirstLine = i === 0;
+ const isLastLine = i === lines.length - 1;
+ const isLastNonEmptyLine = i === lastNonEmptyLine;
+ // replace rendered whitespace tabs with spaces
+ let trimmedLine = line.replace(/\t/g, ' ');
+ // trim whitespace touching a newline
+ if (!isFirstLine) {
+ trimmedLine = trimmedLine.replace(/^[ ]+/, '');
+ }
+ // trim whitespace touching an endline
+ if (!isLastLine) {
+ trimmedLine = trimmedLine.replace(/[ ]+$/, '');
+ }
+ if (trimmedLine) {
+ if (!isLastNonEmptyLine) {
+ trimmedLine += ' ';
+ }
+ str += trimmedLine;
+ }
+ }
+ return str !== '' ? t.stringLiteral(str) : null;
+};
+exports.transformJSXText = transformJSXText;
+/**
+ * Transform JSXExpressionContainer to Expression
+ * @param path JSXExpressionContainer
+ * @returns Expression
+ */
+const transformJSXExpressionContainer = (path) => path.get('expression').node;
+exports.transformJSXExpressionContainer = transformJSXExpressionContainer;
+/**
+ * Transform JSXSpreadChild
+ * @param path JSXSpreadChild
+ * @returns SpreadElement
+ */
+const transformJSXSpreadChild = (path) => t.spreadElement(path.get('expression').node);
+exports.transformJSXSpreadChild = transformJSXSpreadChild;
+const walksScope = (path, name, slotFlag) => {
+ if (path.scope.hasBinding(name) && path.parentPath) {
+ if (t.isJSXElement(path.parentPath.node)) {
+ path.parentPath.setData('slotFlag', slotFlag);
+ }
+ walksScope(path.parentPath, name, slotFlag);
+ }
+};
+exports.walksScope = walksScope;
+const buildIIFE = (path, children) => {
+ const { parentPath } = path;
+ if (t.isAssignmentExpression(parentPath)) {
+ const { left } = parentPath.node;
+ if (t.isIdentifier(left)) {
+ return children.map((child) => {
+ if (t.isIdentifier(child) && child.name === left.name) {
+ const insertName = path.scope.generateUidIdentifier(child.name);
+ parentPath.insertBefore(t.variableDeclaration('const', [
+ t.variableDeclarator(insertName, t.callExpression(t.functionExpression(null, [], t.blockStatement([t.returnStatement(child)])), [])),
+ ]));
+ return insertName;
+ }
+ return child;
+ });
+ }
+ }
+ return children;
+};
+exports.buildIIFE = buildIIFE;
diff --git a/packages/uni-h5/lib/babel-plugin-jsx/package.json b/packages/uni-h5/lib/babel-plugin-jsx/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..d40be471b128b324ec09f53835b507629bd1ab5e
--- /dev/null
+++ b/packages/uni-h5/lib/babel-plugin-jsx/package.json
@@ -0,0 +1,51 @@
+{
+ "name": "@vue/babel-plugin-jsx",
+ "version": "1.0.3",
+ "description": "Babel plugin for Vue 3.0 JSX",
+ "author": "Amour1688 ",
+ "homepage": "https://github.com/vuejs/jsx-next/tree/dev/packages/babel-plugin-jsx#readme",
+ "license": "MIT",
+ "main": "dist/index.js",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/vuejs/jsx-next.git"
+ },
+ "scripts": {
+ "build": "tsc",
+ "lint": "eslint 'src/*.ts'",
+ "test": "yarn build && jest --coverage",
+ "prepublishOnly": "yarn build"
+ },
+ "bugs": {
+ "url": "https://github.com/vuejs/jsx-next/issues"
+ },
+ "files": [
+ "dist"
+ ],
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.0.0",
+ "@babel/plugin-syntax-jsx": "^7.0.0",
+ "@babel/template": "^7.0.0",
+ "@babel/traverse": "^7.0.0",
+ "@babel/types": "^7.0.0",
+ "@vue/babel-helper-vue-transform-on": "^1.0.2",
+ "camelcase": "^6.0.0",
+ "html-tags": "^3.1.0",
+ "svg-tags": "^1.0.0"
+ },
+ "devDependencies": {
+ "@babel/core": "^7.0.0",
+ "@babel/preset-env": "^7.0.0",
+ "@types/jest": "^26.0.7",
+ "@types/svg-tags": "^1.0.0",
+ "@typescript-eslint/eslint-plugin": "^4.0.1",
+ "@typescript-eslint/parser": "^4.0.1",
+ "@vue/compiler-dom": "3.0.5",
+ "@vue/test-utils": "2.0.0-beta.2",
+ "jest": "^26.0.1",
+ "regenerator-runtime": "^0.13.5",
+ "ts-jest": "^26.1.3",
+ "typescript": "^4.0.2",
+ "vue": "3.0.5"
+ }
+}
diff --git a/packages/uni-h5/src/framework/components/app/index.ts b/packages/uni-h5/src/framework/components/app/index.tsx
similarity index 73%
rename from packages/uni-h5/src/framework/components/app/index.ts
rename to packages/uni-h5/src/framework/components/app/index.tsx
index dfcc43d503f90824ec615c1c3a9bebdb6dde8a3c..b3a940e8b0cbd3c28b201da948956f02f94f0e9d 100644
--- a/packages/uni-h5/src/framework/components/app/index.ts
+++ b/packages/uni-h5/src/framework/components/app/index.tsx
@@ -1,12 +1,4 @@
-import {
- ref,
- onMounted,
- computed,
- openBlock,
- createBlock,
- createVNode,
- defineComponent,
-} from 'vue'
+import { ref, computed, onMounted, defineComponent } from 'vue'
import Layout from './layout'
@@ -28,25 +20,9 @@ export default defineComponent({
const { clazz, onChange } = useAppClass()
return () => (
- openBlock(),
- createBlock(
- 'uni-app',
- {
- class: clazz.value,
- },
- [
- createVNode(
- Layout,
- {
- onChange,
- },
- null,
- 8 /* PROPS */,
- ['onChange']
- ),
- ],
- 2 /* CLASS */
- )
+
+
+
)
},
})
diff --git a/packages/uni-h5/src/framework/components/app/layout/index.ts b/packages/uni-h5/src/framework/components/app/layout/index.ts
deleted file mode 100644
index 2218405e4b36dcd22228f558e7b62a5643d295eb..0000000000000000000000000000000000000000
--- a/packages/uni-h5/src/framework/components/app/layout/index.ts
+++ /dev/null
@@ -1,203 +0,0 @@
-import {
- vShow,
- withCtx,
- Fragment,
- KeepAlive,
- openBlock,
- mergeProps,
- createBlock,
- createVNode,
- withDirectives,
- defineComponent,
- resolveComponent,
- ConcreteComponent,
- createCommentVNode,
- resolveDynamicComponent,
-} from 'vue'
-
-import { RouteLocationNormalizedLoaded, RouterView, useRoute } from 'vue-router'
-
-import TabBar from '../tabBar'
-
-import { useKeepAliveRoute } from '../../../plugin/page'
-
-type KeepAliveRoute = ReturnType
-
-export default defineComponent({
- name: 'Layout',
- emits: ['change'],
- setup() {
- const route = __UNI_FEATURE_TABBAR__ ? useRoute() : null
- const keepAliveRoute = __UNI_FEATURE_PAGES__ ? useKeepAliveRoute() : null
- const topWindow = __UNI_FEATURE_TOPWINDOW__ ? useTopWindow() : null
- const leftWindow = __UNI_FEATURE_LEFTWINDOW__ ? useLeftWindow() : null
- const rightWindow = __UNI_FEATURE_RIGHTWINDOW__ ? useRightWindow() : null
- return () => {
- return (
- openBlock(),
- createBlock(
- Fragment,
- null,
- [
- createLayoutVNode(
- keepAliveRoute,
- topWindow,
- leftWindow,
- rightWindow
- ),
- createTabBarVNode(route),
- ],
- 64 /* STABLE_FRAGMENT */
- )
- )
- }
- },
-})
-
-function createLayoutVNode(
- keepAliveRoute: KeepAliveRoute | null,
- topWindow: unknown,
- leftWindow: unknown,
- rightWindow: unknown
-) {
- const routerVNode = __UNI_FEATURE_PAGES__
- ? createRouterViewVNode(keepAliveRoute!)
- : createPageVNode()
- // 非响应式
- if (!__UNI_FEATURE_RESPONSIVE__) {
- return routerVNode
- }
- const topWindowVNode = __UNI_FEATURE_TOPWINDOW__
- ? createTopWindowVNode(topWindow)
- : createCommentVNode('', true)
- const leftWindowVNode = __UNI_FEATURE_LEFTWINDOW__
- ? createLeftWindowVNode(leftWindow)
- : createCommentVNode('', true)
- const rightWindowVNode = __UNI_FEATURE_RIGHTWINDOW__
- ? createRightWindowVNode(rightWindow)
- : createCommentVNode('', true)
- return createVNode('uni-layout', null, [
- topWindowVNode,
- createVNode('uni-content', null, [
- createVNode('uni-main', null, [routerVNode]),
- leftWindowVNode,
- rightWindowVNode,
- ]),
- ])
-}
-
-function createTabBarVNode(route: RouteLocationNormalizedLoaded | null) {
- return __UNI_FEATURE_TABBAR__
- ? withDirectives(createVNode(TabBar, null, null, 512 /* NEED_PATCH */), [
- [vShow, route!.meta.isTabBar], // TODO mediaQuery and api
- ])
- : createCommentVNode('', true)
-}
-
-function createPageVNode() {
- return createVNode(__uniRoutes[1].component)
-}
-
-function createRouterViewVNode(
- keepAliveRoute: ReturnType
-) {
- return createVNode(RouterView, null, {
- default: withCtx(({ Component }) => [
- (openBlock(),
- createBlock(
- KeepAlive,
- { cache: keepAliveRoute.routeCache },
- [
- (openBlock(),
- createBlock(resolveDynamicComponent(Component), {
- key: keepAliveRoute.routeKey.value,
- })),
- ],
- 1032 /* PROPS, DYNAMIC_SLOTS */,
- ['cache']
- )),
- ]),
- _: 1 /* STABLE */,
- })
-}
-
-function useTopWindow() {
- const component = resolveComponent('VUniTopWindow') as ConcreteComponent
- return {
- component,
- style: (component as any).style,
- height: 0,
- show: false,
- }
-}
-function useLeftWindow() {
- const component = resolveComponent('VUniLeftWindow') as ConcreteComponent
- return {
- component,
- style: (component as any).style,
- height: 0,
- }
-}
-function useRightWindow() {
- const component = resolveComponent('VUniRightWindow') as ConcreteComponent
- return {
- component,
- style: (component as any).style,
- height: 0,
- }
-}
-
-function createTopWindowVNode(topWindow: unknown) {
- if (!__UNI_FEATURE_TOPWINDOW__) {
- return createCommentVNode('', true)
- }
- const { component, style, height, show } = useTopWindow()
- return withDirectives(
- createVNode(
- 'uni-top-window',
- null,
- [
- createVNode(
- 'div',
- {
- ref: 'topWindow',
- class: 'uni-top-window',
- style,
- },
- [
- createVNode(
- component,
- mergeProps(
- {
- onVnodeMounted(vnode) {
- // update style.offsetHeight
- },
- 'navigation-bar-title-text': '',
- }
- //bindWindow
- ),
- null,
- 16 /* FULL_PROPS */,
- ['navigation-bar-title-text']
- ),
- ],
- 4 /* STYLE */
- ),
- createVNode(
- 'div',
- {
- class: 'uni-top-window--placeholder',
- style: { height },
- },
- null,
- 4 /* STYLE */
- ),
- ],
- 512 /* NEED_PATCH */
- ),
- [[vShow, show]]
- )
-}
-
-function createLeftWindowVNode(leftWindow: unknown) {}
-function createRightWindowVNode(leftWindow: unknown) {}
diff --git a/packages/uni-h5/src/framework/components/app/layout/index.tsx b/packages/uni-h5/src/framework/components/app/layout/index.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..5c5fb88bf510dc422adbb10587aab2fd4d8447b5
--- /dev/null
+++ b/packages/uni-h5/src/framework/components/app/layout/index.tsx
@@ -0,0 +1,141 @@
+import {
+ withCtx,
+ KeepAlive,
+ openBlock,
+ createBlock,
+ createVNode,
+ defineComponent,
+ resolveComponent,
+ ConcreteComponent,
+ resolveDynamicComponent,
+} from 'vue'
+
+import { RouteLocationNormalizedLoaded, RouterView, useRoute } from 'vue-router'
+
+import TabBar from '../tabBar'
+
+import { useKeepAliveRoute } from '../../../plugin/page'
+
+type KeepAliveRoute = ReturnType
+
+export default defineComponent({
+ name: 'Layout',
+ props: {
+ onChange: Function,
+ },
+ emits: ['change'],
+ setup() {
+ const route = __UNI_FEATURE_TABBAR__ && useRoute()
+ const keepAliveRoute = __UNI_FEATURE_PAGES__ && useKeepAliveRoute()
+ const topWindow = __UNI_FEATURE_TOPWINDOW__ && useTopWindow()
+ const leftWindow = __UNI_FEATURE_LEFTWINDOW__ && useLeftWindow()
+ const rightWindow = __UNI_FEATURE_RIGHTWINDOW__ && useRightWindow()
+ return () => {
+ const layoutTsx = createLayoutTsx(
+ keepAliveRoute,
+ topWindow,
+ leftWindow,
+ rightWindow
+ )
+ const tabBarTsx =
+ __UNI_FEATURE_TABBAR__ &&
+ createTabBarTsx(route as RouteLocationNormalizedLoaded)
+ return [layoutTsx, tabBarTsx].filter(Boolean)
+ }
+ },
+})
+
+function createLayoutTsx(
+ keepAliveRoute: KeepAliveRoute | false,
+ topWindow?: unknown,
+ leftWindow?: unknown,
+ rightWindow?: unknown
+) {
+ const routerVNode = __UNI_FEATURE_PAGES__
+ ? createRouterViewVNode(keepAliveRoute as KeepAliveRoute)
+ : createPageVNode()
+ // 非响应式
+ if (!__UNI_FEATURE_RESPONSIVE__) {
+ return routerVNode
+ }
+ const topWindowTsx = __UNI_FEATURE_TOPWINDOW__
+ ? createTopWindowTsx(topWindow)
+ : null
+ const leftWindowTsx = __UNI_FEATURE_LEFTWINDOW__
+ ? createLeftWindowTsx(leftWindow)
+ : null
+ const rightWindowTsx = __UNI_FEATURE_RIGHTWINDOW__
+ ? createRightWindowTsx(rightWindow)
+ : null
+ return (
+
+ {topWindowTsx}
+
+ {routerVNode}
+ {leftWindowTsx}
+ {rightWindowTsx}
+
+
+ )
+}
+
+function createTabBarTsx(route: RouteLocationNormalizedLoaded) {
+ return
+}
+
+function createPageVNode() {
+ return createVNode(__uniRoutes[1].component)
+}
+
+function createRouterViewVNode(
+ keepAliveRoute: ReturnType
+) {
+ return createVNode(RouterView, null, {
+ default: withCtx(({ Component }) => [
+ (openBlock(),
+ createBlock(
+ KeepAlive,
+ { cache: keepAliveRoute.routeCache },
+ [
+ (openBlock(),
+ createBlock(resolveDynamicComponent(Component), {
+ key: keepAliveRoute.routeKey.value,
+ })),
+ ],
+ 1032 /* PROPS, DYNAMIC_SLOTS */,
+ ['cache']
+ )),
+ ]),
+ _: 1 /* STABLE */,
+ })
+}
+
+function useTopWindow() {
+ const component = resolveComponent('VUniTopWindow') as ConcreteComponent
+ return {
+ component,
+ style: (component as any).style,
+ height: 0,
+ show: false,
+ }
+}
+function useLeftWindow() {
+ const component = resolveComponent('VUniLeftWindow') as ConcreteComponent
+ return {
+ component,
+ style: (component as any).style,
+ height: 0,
+ }
+}
+function useRightWindow() {
+ const component = resolveComponent('VUniRightWindow') as ConcreteComponent
+ return {
+ component,
+ style: (component as any).style,
+ height: 0,
+ }
+}
+
+function createTopWindowTsx(topWindow: unknown) {}
+function createLeftWindowTsx(leftWindow: unknown) {}
+function createRightWindowTsx(leftWindow: unknown) {}
diff --git a/packages/uni-h5/src/framework/components/page/pageHead.tsx b/packages/uni-h5/src/framework/components/page/pageHead.tsx
index 432901a217ed8d67e34a40badc139361d8117d57..47a8cc77e6a93ef85d0a8fabdd518fbf1dbafbb5 100644
--- a/packages/uni-h5/src/framework/components/page/pageHead.tsx
+++ b/packages/uni-h5/src/framework/components/page/pageHead.tsx
@@ -1,15 +1,5 @@
-import {
- computed,
- createBlock,
- // createCommentVNode,
- // createVNode,
- defineComponent,
- openBlock,
- // renderSlot,
- // SetupContext,
- // withCtx,
-} from 'vue'
-
+import { computed, defineComponent } from 'vue'
+import { isArray } from '@vue/shared'
import { usePageMeta } from '../../plugin/provide'
export default defineComponent({
@@ -19,11 +9,20 @@ export default defineComponent({
const navigationBar = pageMeta.navigationBar
UniServiceJSBridge.emit('onNavigationBarChange', navigationBar.titleText)
const { clazz, style } = usePageHead(navigationBar)
- const backButtonJsx = createBackButtonJsx(navigationBar)
+ // 单页面无需back按钮
+ const backButtonJsx = __UNI_FEATURE_PAGES__
+ ? createBackButtonJsx(navigationBar)
+ : null
+ const leftButtonsJsx = __UNI_FEATURE_NAVIGATIONBAR_BUTTONS__
+ ? createButtonsJsx('left', navigationBar)
+ : []
return () => (
-
{backButtonJsx}
+
+ {backButtonJsx}
+ {...leftButtonsJsx}
+
)
@@ -34,7 +33,7 @@ function createBackButtonJsx(navigationBar: UniApp.PageNavigationBar) {
if (navigationBar.backButton) {
return (
-
+
@@ -42,6 +41,22 @@ function createBackButtonJsx(navigationBar: UniApp.PageNavigationBar) {
}
}
+function createButtonsJsx(
+ float: 'left' | 'right',
+ navigationBar: UniApp.PageNavigationBar
+) {
+ if (isArray(navigationBar.buttons)) {
+ return navigationBar.buttons
+ .filter((btn) => btn.float === float)
+ .map((btn, index) => (
+
+
+
+ ))
+ }
+ return []
+}
+
function usePageHead(navigationBar: UniApp.PageNavigationBar) {
const clazz = computed(() => {
const { type, titlePenetrate, shadowColorType } = navigationBar
diff --git a/packages/uni-h5/vite.config.ts b/packages/uni-h5/vite.config.ts
index 7c04cdd1600de184a8bc203bbfa22560dec4d17c..65e6b97521187a1b28a5deb0aff691568479c69c 100644
--- a/packages/uni-h5/vite.config.ts
+++ b/packages/uni-h5/vite.config.ts
@@ -2,11 +2,17 @@ import path from 'path'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
-import vueJsx from '@vitejs/plugin-vue-jsx'
import replace from '@rollup/plugin-replace'
import { isCustomElement } from '../uni-shared'
+const moduleAlias = require('module-alias')
+moduleAlias.addAlias(
+ '@vue/babel-plugin-jsx',
+ path.join(__dirname, 'lib/babel-plugin-jsx')
+)
+const vueJsx = require('@vitejs/plugin-vue-jsx')
+
function resolve(file: string) {
return path.resolve(__dirname, file)
}
diff --git a/packages/vite-plugin-uni/src/handleHotUpdate/index.ts b/packages/vite-plugin-uni/src/handleHotUpdate/index.ts
index be058530aad435297e5dd2facb908556e7f3c333..b6a1aadcd69cccaa51cd98143466db63c6f8f6f1 100644
--- a/packages/vite-plugin-uni/src/handleHotUpdate/index.ts
+++ b/packages/vite-plugin-uni/src/handleHotUpdate/index.ts
@@ -8,16 +8,24 @@ import { getFeatures } from '../utils'
const debugHmr = debug('uni:hmr')
async function invalidate(file: string, moduleGraph: ModuleGraph) {
- const mod = await moduleGraph.getModuleById(slash(file))
- if (mod) {
- debugHmr('invalidate', mod.id)
- moduleGraph.invalidateModule(mod)
+ const mods = await moduleGraph.getModulesByFile(slash(file))
+ if (mods && mods.size) {
+ ;[...mods].forEach((mod) => {
+ debugHmr('invalidate', mod.id)
+ moduleGraph.invalidateModule(mod)
+ })
}
}
export function createHandleHotUpdate(
options: VitePluginUniResolvedOptions
): Plugin['handleHotUpdate'] {
+ const invalidateFiles = [
+ path.resolve(options.inputDir, 'pages.json.js'),
+ path.resolve(options.inputDir, 'manifest.json.js'),
+ require.resolve('@dcloudio/uni-h5/dist/uni-h5.esm.js'),
+ require.resolve('vite/dist/client/env.js'),
+ ]
return async function ({ file, server }) {
// TODO 目前简单处理,当pages.json,manifest.json发生变化,就直接刷新,理想情况下,应该区分变化的内容,仅必要时做整页面刷新
const isPagesJson = file.endsWith('pages.json')
@@ -36,15 +44,8 @@ export function createHandleHotUpdate(
)
debugHmr('define', server.config.define)
// 当pages.json,manifest.json发生变化时,作废pages.json.js缓存
- await invalidate(
- path.resolve(options.inputDir, 'pages.json.js'),
- server.moduleGraph
- )
- if (isManifestJson) {
- await invalidate(
- path.resolve(options.inputDir, 'manifest.json.js'),
- server.moduleGraph
- )
+ for (const file of invalidateFiles) {
+ await invalidate(file, server.moduleGraph)
}
return []
}
diff --git a/packages/vite-plugin-uni/src/utils/define.ts b/packages/vite-plugin-uni/src/utils/define.ts
index 1265a2b6f8eef598c0aed0f86d7b0427512addab..d5f875da5f817b972f3bacb45b9dc3cc2d28833e 100644
--- a/packages/vite-plugin-uni/src/utils/define.ts
+++ b/packages/vite-plugin-uni/src/utils/define.ts
@@ -2,7 +2,7 @@ import fs from 'fs'
import path from 'path'
import { ConfigEnv } from 'vite'
import { parse } from 'jsonc-parser'
-
+import { isArray } from '@vue/shared'
import { VitePluginUniResolvedOptions } from '..'
import { normalizePagesJson } from './pagesJson'
@@ -15,6 +15,7 @@ interface PagesFeatures {
leftWindow: boolean
rightWindow: boolean
pullDownRefresh: boolean
+ navigationBarButtons: boolean
}
interface ManifestFeatures {
wx: boolean
@@ -46,6 +47,7 @@ function resolvePagesFeature(
leftWindow: false, // 是否启用leftWindow
rightWindow: false, // 是否启用rightWindow
pullDownRefresh: false, // 是否启用下拉刷新
+ navigationBarButtons: true, // 是否启用标题按钮
}
const {
@@ -89,6 +91,15 @@ function resolvePagesFeature(
) {
features.nvue = false
}
+ if (
+ !pages.find(
+ (page) =>
+ isArray(page.style.navigationBar.buttons) &&
+ page.style.navigationBar.buttons.length
+ )
+ ) {
+ features.navigationBarButtons = false
+ }
}
return features
@@ -137,6 +148,7 @@ export function getFeatures(
leftWindow,
rightWindow,
pullDownRefresh,
+ navigationBarButtons,
} = Object.assign(
resolveManifestFeature(options),
resolvePagesFeature(options, command),
@@ -156,5 +168,6 @@ export function getFeatures(
__UNI_FEATURE_RIGHTWINDOW__: rightWindow,
__UNI_FEATURE_RESPONSIVE__: topWindow || leftWindow || rightWindow,
__UNI_FEATURE_PULL_DOWN_REFRESH__: pullDownRefresh,
+ __UNI_FEATURE_NAVIGATIONBAR_BUTTONS__: navigationBarButtons,
}
}
diff --git a/packages/vite-plugin-uni/src/utils/pagesJson.ts b/packages/vite-plugin-uni/src/utils/pagesJson.ts
index ff3b7cb04fdf9be081d77a70b936ce171dfe4514..004ca9cdda74670cbaa747de42096bedbe1990f8 100644
--- a/packages/vite-plugin-uni/src/utils/pagesJson.ts
+++ b/packages/vite-plugin-uni/src/utils/pagesJson.ts
@@ -55,7 +55,7 @@ function normalizeSubpackages(
if (Array.isArray(subpackages)) {
subpackages.forEach(({ root, pages: subPages }) => {
if (root && subPages.length) {
- subPages.forEach((subPage: { path: string }) => {
+ subPages.forEach((subPage) => {
subPage.path = slash(path.join(root, subPage.path))
pages.push(subPage)
})
@@ -66,7 +66,7 @@ function normalizeSubpackages(
}
function normalizePageStyle(
- pageStyle: Record,
+ pageStyle: UniApp.PagesJsonPageStyle,
platform: UniApp.PLATFORM
) {
if (pageStyle) {
@@ -118,10 +118,10 @@ function normalizeNavigationBar(
const platforms = ['h5', 'app-plus', 'mp-', 'quickapp']
-function removePlatformStyle(pageStyle: Record) {
+function removePlatformStyle(pageStyle: UniApp.PagesJsonPageStyle) {
Object.keys(pageStyle).forEach((name) => {
if (platforms.find((prefix) => name.startsWith(prefix))) {
- delete pageStyle[name]
+ delete pageStyle[name as UniApp.PLATFORM]
}
})
return pageStyle
diff --git a/yarn.lock b/yarn.lock
index 7c8234212ba4c2a4c72997150a1085c11bf3d6cf..dcb50505d96f9803213580e2820e1a05c584e0c8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -780,9 +780,9 @@
integrity sha512-XI3MGSejUQIJ3wzY0i5IHy5J3eb36M/ytgG8jIOssP08ovtRPcjpjXQqrx51AHBNBOisTS/NQNWJitI17+EwzQ==
"@types/estree@*":
- version "0.0.46"
- resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.46.tgz#0fb6bfbbeabd7a30880504993369c4bf1deab1fe"
- integrity sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg==
+ version "0.0.47"
+ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.47.tgz#d7a51db20f0650efec24cd04994f523d93172ed4"
+ integrity sha512-c5ciR06jK8u9BstrmJyO97m+klJrrhCf9u3rLu3DEAJBirxRqSCvDQoYKmxuYwQI5SZChAWu+tq9oVlGRuzPAg==
"@types/estree@0.0.39":
version "0.0.39"
@@ -4308,6 +4308,11 @@ mkdirp@1.x:
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
+module-alias@^2.2.2:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/module-alias/-/module-alias-2.2.2.tgz#151cdcecc24e25739ff0aa6e51e1c5716974c0e0"
+ integrity sha512-A/78XjoX2EmNvppVWEhM2oGk3x4lLxnkEA4jTbaK97QKSDjkIoOsKQlfylt/d3kKKi596Qy3NP5XrXJ6fZIC9Q==
+
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"