diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 934db8c12431..07aa7c9e5a01 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -9,6 +9,8 @@ assignees: '' > Feature Request 请提到 [FeatHub](https://feathub.com/NervJS/taro) +> Taro 使用上的问题请提到 [Taro 社区——让每一次交流被沉淀](https://taro-club.jd.com/) + 如果是提交 bug,请搜索文档和 issue,确认以下事项: * 该问题没有在其他 issue 和文档讨论到,不属于重复内容 diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e4108d0e3c0..4bfd5e3fec62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,222 @@ -# [](https://github.com/NervJS/taro/compare/v1.3.0...v) (2019-06-11) +# [](https://github.com/NervJS/taro/compare/v1.3.7...v) (2019-07-10) + + + + +## [1.3.7](https://github.com/NervJS/taro/compare/v1.3.6...v1.3.7) (2019-07-10) + + +### Bug Fixes + +* **cli:** h5端支持alias到src下的目录了, fix [#2866](https://github.com/NervJS/taro/issues/2866) ([3e4e89c](https://github.com/NervJS/taro/commit/3e4e89c)) +* **components:** 修复快应用 WebView 问题。 close [#3451](https://github.com/NervJS/taro/issues/3451), [#3724](https://github.com/NervJS/taro/issues/3724) ([397b017](https://github.com/NervJS/taro/commit/397b017)) +* **taro:** 为 Taro.request 类型定义添加 abort 方法,完善注释 [#3654](https://github.com/NervJS/taro/issues/3654) ([#3715](https://github.com/NervJS/taro/issues/3715)) ([b007a49](https://github.com/NervJS/taro/commit/b007a49)) +* **taro-alipay:** 修复支付宝分包问题。close [#3445](https://github.com/NervJS/taro/issues/3445) ([d904a79](https://github.com/NervJS/taro/commit/d904a79)) +* **taro-alipay:** 修复支付宝分包问题。close [#3703](https://github.com/NervJS/taro/issues/3703) ([2b8f024](https://github.com/NervJS/taro/commit/2b8f024)) +* **taro-quickapp:** 快应用获取页面参数时增加容错 ([12c9998](https://github.com/NervJS/taro/commit/12c9998)) +* **taro-rn:** 修复showLoading没有使用title属性 ([8d0b1df](https://github.com/NervJS/taro/commit/8d0b1df)) +* **taro-router-rn:** 修复RN端触发不了下拉刷新事件 ([dbfabf2](https://github.com/NervJS/taro/commit/dbfabf2)) +* **taro-utils:** 优化 Object.is 判断 ([49bef9e](https://github.com/NervJS/taro/commit/49bef9e)) +* **transformer:** opt.isNormal 不需要走自定义 babel 插件 ([0945248](https://github.com/NervJS/taro/commit/0945248)), closes [#3731](https://github.com/NervJS/taro/issues/3731) +* **transformer:** 修复 0945248e2faf2a2d0f7fcf5f0e52473c85c5d073 重复添加插件 ([2b8180b](https://github.com/NervJS/taro/commit/2b8180b)) + + +### Features + +* **cli:** transformer 增加参数 alias ([2890b8c](https://github.com/NervJS/taro/commit/2890b8c)) +* **cli:** 优化对快应用系统包的判断与提醒 ([c9ae6b1](https://github.com/NervJS/taro/commit/c9ae6b1)) +* **cli:** 支持对 npm 包中文件进行转换 ([49a97e9](https://github.com/NervJS/taro/commit/49a97e9)) + + + + +## [1.3.6](https://github.com/NervJS/taro/compare/v1.3.5...v1.3.6) (2019-07-08) + + +### Bug Fixes + +* **cli:** 快应用支持多端组件,close [#3685](https://github.com/NervJS/taro/issues/3685) ([adf68af](https://github.com/NervJS/taro/commit/adf68af)) +* **component:** 修复 Swiper 组件指示标初始为 false ,更新不显示问题, close [#3676](https://github.com/NervJS/taro/issues/3676) ([0ecb399](https://github.com/NervJS/taro/commit/0ecb399)) +* **components:** H5 不支持 camera 组件,修改文档 ([697c74b](https://github.com/NervJS/taro/commit/697c74b)) +* **h5:** Page组件增加$component对象,与微信小程序统一 ([cd54061](https://github.com/NervJS/taro/commit/cd54061)) +* **quickapp:** 快应用支持 Block 标签,close [#3686](https://github.com/NervJS/taro/issues/3686) ([2dfeafe](https://github.com/NervJS/taro/commit/2dfeafe)) +* **router:** 解决getCurrentPages有时候只能获取长度但没有内容的问题 ([#3669](https://github.com/NervJS/taro/issues/3669)) ([a88225e](https://github.com/NervJS/taro/commit/a88225e)) +* **taro:** interceptor 暴露 request 返回的 requestTask。close [#3654](https://github.com/NervJS/taro/issues/3654) ([2ada5a2](https://github.com/NervJS/taro/commit/2ada5a2)) +* **taro:** 修复 this.$router 类型错误 close [#3650](https://github.com/NervJS/taro/issues/3650) ([#3653](https://github.com/NervJS/taro/issues/3653)) ([557938e](https://github.com/NervJS/taro/commit/557938e)) +* **taro-cli:** 添加 json 文件缺失的逗号 ([#3707](https://github.com/NervJS/taro/issues/3707)) ([b6c3be9](https://github.com/NervJS/taro/commit/b6c3be9)) +* **taro-quickapp:** 修复快应用 tabBar 图标显示问题 ([81cbdf7](https://github.com/NervJS/taro/commit/81cbdf7)) +* **taroize:** 加强对对象扩展运算符的支持,close [#3632](https://github.com/NervJS/taro/issues/3632) ([e3c638e](https://github.com/NervJS/taro/commit/e3c638e)) +* **transformer:** 使用 spread/rest 语法生成匿名函数 ([75fc37a](https://github.com/NervJS/taro/commit/75fc37a)), closes [#3577](https://github.com/NervJS/taro/issues/3577) +* **transformer:** 修复 11964f8 对 JSX 属性判断错误,close [#3697](https://github.com/NervJS/taro/issues/3697) ([24e717f](https://github.com/NervJS/taro/commit/24e717f)) +* **transformer:** 修复 46604f5 导致 indexKey 没有加入循环中 ([61c54c6](https://github.com/NervJS/taro/commit/61c54c6)), closes [#3665](https://github.com/NervJS/taro/issues/3665) +* **transformer:** 匿名变量生成位置错误 ([c3086ae](https://github.com/NervJS/taro/commit/c3086ae)) +* **transformer:** 如果循环在三元表达式中没有被 JSX 包裹住解析出错 ([f879bf6](https://github.com/NervJS/taro/commit/f879bf6)), closes [#3646](https://github.com/NervJS/taro/issues/3646) + + +### Features + +* **mobx:** 提供 Mobx Hooks API ([#3599](https://github.com/NervJS/taro/issues/3599)) ([3a3bbdb](https://github.com/NervJS/taro/commit/3a3bbdb)) +* **quickapp:** 新增快应用的一些 api 及组件 ([ddf279b](https://github.com/NervJS/taro/commit/ddf279b)) +* **taroize:** 生命周期函数支持 async/await, close [#3477](https://github.com/NervJS/taro/issues/3477) ([c7b76ab](https://github.com/NervJS/taro/commit/c7b76ab)) +* **transformer:** 支持普通函数表达式定义组件,close [#3682](https://github.com/NervJS/taro/issues/3682) ([e16e671](https://github.com/NervJS/taro/commit/e16e671)) + + + + +## [1.3.5](https://github.com/NervJS/taro/compare/v1.3.4...v1.3.5) (2019-07-03) + + +### Bug Fixes + +* **cli:** 修复项目目录带'src'时编译报错的问题, fix [#3431](https://github.com/NervJS/taro/issues/3431) ([14b135a](https://github.com/NervJS/taro/commit/14b135a)) +* **cli:** 小程序用到的静态资源走CDN 和 防止node_modules/xxxx包被taro再次编译的bug ([#3508](https://github.com/NervJS/taro/issues/3508)) ([cdd9c81](https://github.com/NervJS/taro/commit/cdd9c81)) +* **cli:** 当页面或组件没有引用样式时生成模板不需要生成插入样式代码 ([3220f5d](https://github.com/NervJS/taro/commit/3220f5d)) +* **cli:** 更新快应用 manifest ([b09c4d6](https://github.com/NervJS/taro/commit/b09c4d6)) +* **cli:** 更新快应用原生包识别逻辑 ([3cda7bb](https://github.com/NervJS/taro/commit/3cda7bb)) +* **cli:** 组件文件不需要插入 taro-page 组件引用 ([c3b6bbe](https://github.com/NervJS/taro/commit/c3b6bbe)) +* **components:** 修复 Video 组件 poster 失效问题 close [#3526](https://github.com/NervJS/taro/issues/3526) ([b69232d](https://github.com/NervJS/taro/commit/b69232d)) +* **components-qa:** 快应用 tabBar 图片需占位 ([7e7c07e](https://github.com/NervJS/taro/commit/7e7c07e)) +* **docs:** 案例中的taro-redux引用路径错误 ([#3522](https://github.com/NervJS/taro/issues/3522)) ([8ae96c2](https://github.com/NervJS/taro/commit/8ae96c2)) +* **h5:** h5的chooseImage在count设置为1时取消了multiple属性, fix [#3401](https://github.com/NervJS/taro/issues/3401) ([08aa12d](https://github.com/NervJS/taro/commit/08aa12d)) +* **h5:** 修复build模式下h5 api的样式被treeshake掉的问题, fix [#3497](https://github.com/NervJS/taro/issues/3497) ([775c953](https://github.com/NervJS/taro/commit/775c953)) +* **h5:** 修复h5 setClipboardData api调用出错的问题, fix [#3539](https://github.com/NervJS/taro/issues/3539) ([e6fe90f](https://github.com/NervJS/taro/commit/e6fe90f)) +* **h5:** 修复previewImage的点透问题, fix [#3071](https://github.com/NervJS/taro/issues/3071) ([11a8fd2](https://github.com/NervJS/taro/commit/11a8fd2)) +* **movableview.d.ts:** 修正 关于 y 轴和 onVTouchMove 事件注释错误的问题 ([#2924](https://github.com/NervJS/taro/issues/2924)) ([c5fc256](https://github.com/NervJS/taro/commit/c5fc256)) +* **rn:** 导出 hooks 相关接口,以解决 RN 端接口未定义问题 ([#3579](https://github.com/NervJS/taro/issues/3579)) ([7ea3f37](https://github.com/NervJS/taro/commit/7ea3f37)) +* **router:** 修复设置alias到'/'时出现页面重叠的问题, fix [#3597](https://github.com/NervJS/taro/issues/3597) ([2660b9b](https://github.com/NervJS/taro/commit/2660b9b)) +* **taro:** 在memo中增加对state的浅判断 ([#3563](https://github.com/NervJS/taro/issues/3563)) ([19eef47](https://github.com/NervJS/taro/commit/19eef47)), closes [#3527](https://github.com/NervJS/taro/issues/3527) +* **taro-cli:** 修复小程序端非生产模式下不应用 csso 配置问题 close [#3622](https://github.com/NervJS/taro/issues/3622) ([#3623](https://github.com/NervJS/taro/issues/3623)) ([40cba83](https://github.com/NervJS/taro/commit/40cba83)) +* **taro-cli:** 尽早设置watch下的NODE_ENV为development ([#3583](https://github.com/NervJS/taro/issues/3583)) ([d9d9f68](https://github.com/NervJS/taro/commit/d9d9f68)) +* **taro-quickapp:** 修复事件传参绑定 ([4af3659](https://github.com/NervJS/taro/commit/4af3659)) +* **taro-quickapp:** 修复路由传参的问题,close [#3620](https://github.com/NervJS/taro/issues/3620) ([c0c5cb2](https://github.com/NervJS/taro/commit/c0c5cb2)) +* **taro-quickapp:** 快应用属性处理 ([dbc9b6b](https://github.com/NervJS/taro/commit/dbc9b6b)) +* **taro-weapp/qq/tt/swan/alipay:** 循环 ref 问题。close [#3455](https://github.com/NervJS/taro/issues/3455) ([975084f](https://github.com/NervJS/taro/commit/975084f)) +* memo对state的判断应该用逻辑或 ([#3600](https://github.com/NervJS/taro/issues/3600)) ([552e868](https://github.com/NervJS/taro/commit/552e868)) +* **taroize:** catch 事件填空字符串报错 ([dad3ae4](https://github.com/NervJS/taro/commit/dad3ae4)) +* **taroize:** 字母集从a-j调整为b-k ([#3569](https://github.com/NervJS/taro/issues/3569)) ([b826b11](https://github.com/NervJS/taro/commit/b826b11)) +* **transformer:** children 从 this.props 解构会删除赋值语句 ([260360f](https://github.com/NervJS/taro/commit/260360f)) +* **transformer:** 函数式组件支持 bind,close [#3534](https://github.com/NervJS/taro/issues/3534) ([ed361db](https://github.com/NervJS/taro/commit/ed361db)) +* **transformer:** 只有在快应用时再删除多余的 $usedState ([fa7c227](https://github.com/NervJS/taro/commit/fa7c227)) +* **transformer:** 循环中使用对象展开符报错,close [#3547](https://github.com/NervJS/taro/issues/3547) ([527ae89](https://github.com/NervJS/taro/commit/527ae89)) +* **transformer:** 循环没有写 return 生成匿名函数错误,close [#3536](https://github.com/NervJS/taro/issues/3536) ([46604f5](https://github.com/NervJS/taro/commit/46604f5)) +* **transformer:** 某些情况解析 ...props 错误,close [#3647](https://github.com/NervJS/taro/issues/3647) ([11964f8](https://github.com/NervJS/taro/commit/11964f8)) + + +### Features + +* **cli:** 修复weapp转换项目后Nerv未定义的问题 ([9632436](https://github.com/NervJS/taro/commit/9632436)) +* **cli:** 增加对华为原子服务定义文件的规范检查 ([#3571](https://github.com/NervJS/taro/issues/3571)) ([d78ee16](https://github.com/NervJS/taro/commit/d78ee16)) +* **cli:** 新版本快应用编译器模块内容调整 ([a51bf63](https://github.com/NervJS/taro/commit/a51bf63)) +* **taro-components:** 完善 Form 组件的类型定义 ([#2951](https://github.com/NervJS/taro/issues/2951)) ([16b2613](https://github.com/NervJS/taro/commit/16b2613)) +* **taro-quickapp:** 快应用支持设置 tabBar ([0e673ad](https://github.com/NervJS/taro/commit/0e673ad)) +* **transformer:** 使用类函数式组件不再要求以 render 开头命名 ([ea1e43e](https://github.com/NervJS/taro/commit/ea1e43e)) +* **transformer:** 支持 children 与其它变量同时从 props 中解构 ([b6d1d45](https://github.com/NervJS/taro/commit/b6d1d45)), closes [#3530](https://github.com/NervJS/taro/issues/3530) +* **transformer:** 支持 render props ([eda6750](https://github.com/NervJS/taro/commit/eda6750)) +* **typings:** add the type definition of FunctionComponent and Taro.memo ([#3517](https://github.com/NervJS/taro/issues/3517)) ([7c8edd2](https://github.com/NervJS/taro/commit/7c8edd2)) +* **weapp:** 把 `shallowEqual` 导出到各程序端 API ([279becb](https://github.com/NervJS/taro/commit/279becb)) +* **webpack-runner:** mainFields补上了browser字段, close [#3415](https://github.com/NervJS/taro/issues/3415) ([3ef3d5b](https://github.com/NervJS/taro/commit/3ef3d5b)) + + +### Performance Improvements + +* **transformer:** 组件卸载时清理事件订阅 ([7284946](https://github.com/NervJS/taro/commit/7284946)) + + + + +## [1.3.4](https://github.com/NervJS/taro/compare/v1.3.3...v1.3.4) (2019-06-25) + + +### Bug Fixes + +* **transformer:** 在 hooks 会把 return 替换,close [#3469](https://github.com/NervJS/taro/issues/3469) ([beb21f0](https://github.com/NervJS/taro/commit/beb21f0)) +* **transformer:** 嵌套循环判断使用上级变量编译错误,close [#3462](https://github.com/NervJS/taro/issues/3462) ([6b525c2](https://github.com/NervJS/taro/commit/6b525c2)) +* **transformer:** 自定义组件支持外部类,close [#3080](https://github.com/NervJS/taro/issues/3080) ([96573c1](https://github.com/NervJS/taro/commit/96573c1)) +* **weapp:** 修复 extraProps 判断 bug。 ([3288436](https://github.com/NervJS/taro/commit/3288436)) +* **weapp:** 修复 mobx 下 extraProps 判断 bug。close [#3513](https://github.com/NervJS/taro/issues/3513) ([3deb1a7](https://github.com/NervJS/taro/commit/3deb1a7)) + + +### Features + +* **components-rn:** ScrollView, 支持 FlatList 来代替 ScrollView ([6714e24](https://github.com/NervJS/taro/commit/6714e24)) +* **transformer:** 支持在快应用循环中使用匿名函数,[#3495](https://github.com/NervJS/taro/issues/3495) ([0a66dbd](https://github.com/NervJS/taro/commit/0a66dbd)) +* **transformer:** 循环中可以直接 return JSX 引用,close [#3504](https://github.com/NervJS/taro/issues/3504) ([38a38ce](https://github.com/NervJS/taro/commit/38a38ce)) + + + + +## [1.3.3](https://github.com/NervJS/taro/compare/v1.3.2...v1.3.3) (2019-06-24) + + +### Bug Fixes + +* **alipay:** 修复在支付宝分包中状态管理工具不可用的问题,fix [#3445](https://github.com/NervJS/taro/issues/3445) ([a6f4c0a](https://github.com/NervJS/taro/commit/a6f4c0a)) +* **cli:** 修复快应用编译报错,快应用依赖安装问题 ([15bed06](https://github.com/NervJS/taro/commit/15bed06)) +* **cli:** 引入json包含null的问题,close [#3505](https://github.com/NervJS/taro/issues/3505) ([849999d](https://github.com/NervJS/taro/commit/849999d)) +* **router:** 修复偶尔页面隐藏失败的情况 ([b9f708a](https://github.com/NervJS/taro/commit/b9f708a)) +* **taro:** 增加 Taro.getAccountInfoSync 类型定义 ([#3433](https://github.com/NervJS/taro/issues/3433)) ([2f33f56](https://github.com/NervJS/taro/commit/2f33f56)) +* **taro-weapp:** 微信小程序能通过 extraProps 接收外部 props ([506ca02](https://github.com/NervJS/taro/commit/506ca02)) +* **taro-weapp/tt/swan/qq/alipay:** 拦截器添加 cleanInterceptors 方法 ([22edff9](https://github.com/NervJS/taro/commit/22edff9)) +* **weapp:** 初始 ref 获取改到 didmount 阶段 ([0d2bb53](https://github.com/NervJS/taro/commit/0d2bb53)) + + +### Features + +* **taro-components:** add borderRadius for Progress Component ([4484546](https://github.com/NervJS/taro/commit/4484546)) + + + + +## [1.3.2](https://github.com/NervJS/taro/compare/v1.3.1...v1.3.2) (2019-06-17) + + +### Bug Fixes + +* **components-rn:** Clickable android, 绑定 onClick 的组件让 ScrollView 无法滑动了 ([16cf886](https://github.com/NervJS/taro/commit/16cf886)) +* **components-rn:** react-native-swiper 修复并更新相关代码样式 ([7494c41](https://github.com/NervJS/taro/commit/7494c41)) +* **transformer:** mobx 不需要 import ReduxContext, close [#3453](https://github.com/NervJS/taro/issues/3453) ([8d99a2b](https://github.com/NervJS/taro/commit/8d99a2b)) +* **transformer:** 使用 spread props 导致报错,close [#3439](https://github.com/NervJS/taro/issues/3439) ([bf85def](https://github.com/NervJS/taro/commit/bf85def)) +* **transformer:** 使用异步订阅 redux 更新 ([1ab6123](https://github.com/NervJS/taro/commit/1ab6123)), closes [#3456](https://github.com/NervJS/taro/issues/3456) +* **transformer:** 误报解构警告,close [#3450](https://github.com/NervJS/taro/issues/3450) ([f38e13b](https://github.com/NervJS/taro/commit/f38e13b)) + + +### Features + +* **components:** 组件 Image 新增 lazyLoad 属性 ([6d03f64](https://github.com/NervJS/taro/commit/6d03f64)) +* **components-rn:** Swiper, 可以直接从样式传入 width, height 和 margin*,之前需要套 View, margin* 作用在内层导致样式有误 ([3646ec8](https://github.com/NervJS/taro/commit/3646ec8)) +* **components-rn:** 将 react-native-swiper 内嵌到项目中 ([91a27e0](https://github.com/NervJS/taro/commit/91a27e0)) +* **taro:** 新增 defineProperties polyfill ([6666f40](https://github.com/NervJS/taro/commit/6666f40)) + + + + +## [1.3.1](https://github.com/NervJS/taro/compare/v1.3.0...v1.3.1) (2019-06-16) + + +### Bug Fixes + +* **cli:** 修正页面创建时页面命名等问题 ([247b0c0](https://github.com/NervJS/taro/commit/247b0c0)) +* **mobx-h5:** 修复inject组件的componentDidShow内获取不到组件this的问题, fix [#3333](https://github.com/NervJS/taro/issues/3333) ([322f258](https://github.com/NervJS/taro/commit/322f258)) +* 优化h5 下 ScrollView 标签,提供 onTouchMove 方法 ([44b730a](https://github.com/NervJS/taro/commit/44b730a)) +* **rn:** [RN]Taro.getCurrentPages方法不存在 close [#3224](https://github.com/NervJS/taro/issues/3224) ([a9b8fa7](https://github.com/NervJS/taro/commit/a9b8fa7)) +* **taro-tt:** 修复头条小程序事件不带 type 参数的问题,fix [#3382](https://github.com/NervJS/taro/issues/3382) ([1977062](https://github.com/NervJS/taro/commit/1977062)) +* **transformer:**   在第一个直接时会被无视, close [#3406](https://github.com/NervJS/taro/issues/3406) ([4d14dd7](https://github.com/NervJS/taro/commit/4d14dd7)) +* **transformer:** 在类函数的 JSX循环无法使用 this.state 来循环 ([0401fd0](https://github.com/NervJS/taro/commit/0401fd0)) +* **transformer:** 多个 if block 有同名变量编译错误,close [#3388](https://github.com/NervJS/taro/issues/3388) ([6df5d8d](https://github.com/NervJS/taro/commit/6df5d8d)) +* **transformer:** 循环中的 wx:else 也需要用 block 包裹 ([b2ba05d](https://github.com/NervJS/taro/commit/b2ba05d)), closes [#3410](https://github.com/NervJS/taro/issues/3410) + + +### Features + +* **components-rn:** [@ant-design](https://github.com/ant-design)/react-native 按需引入 ([d24b5f6](https://github.com/NervJS/taro/commit/d24b5f6)) +* **components-rn:** ScrollView 允许传入部分 RN 自己的参数 ([4116344](https://github.com/NervJS/taro/commit/4116344)) +* **redux:** useSelector, useStore, useDispatch typing ([dd18aa9](https://github.com/NervJS/taro/commit/dd18aa9)) +* **redux:** 支持 useSelector, useDispatch, useStore ([bc6bc47](https://github.com/NervJS/taro/commit/bc6bc47)) +* **rn:** rn 的 router 和 API 添加构建,API 改造TS ([93388cc](https://github.com/NervJS/taro/commit/93388cc)) +* **taro:** 增加 createRef 的 typings ([e9b74ef](https://github.com/NervJS/taro/commit/e9b74ef)) +* **transformer:** 可以找到普通函数是否阻止冒泡, close [#3379](https://github.com/NervJS/taro/issues/3379) ([dfcf62b](https://github.com/NervJS/taro/commit/dfcf62b)) +* **transformer:** 支持导出匿名函数声明组件 ([caf66df](https://github.com/NervJS/taro/commit/caf66df)) @@ -13,6 +230,8 @@ * **cli:** 修复 taro convert 报错问题 ([d9b3d0c](https://github.com/NervJS/taro/commit/d9b3d0c)) * **h5:** 修复showLoading显示上一个showToast内容的问题, fix [#3367](https://github.com/NervJS/taro/issues/3367) ([897c2eb](https://github.com/NervJS/taro/commit/897c2eb)) * **mobx:** close [#3218](https://github.com/NervJS/taro/issues/3218) ([c2e08c4](https://github.com/NervJS/taro/commit/c2e08c4)) +* **rn:** this.$router增加path属性,与形式小程序同步 ([af0236e](https://github.com/NervJS/taro/commit/af0236e)) +* **rn:** this.$router增加path属性,与形式小程序同步 ([0175da5](https://github.com/NervJS/taro/commit/0175da5)) * **taro:** 添加百度 setPageInfo api, close [#3206](https://github.com/NervJS/taro/issues/3206) ([2ef11ff](https://github.com/NervJS/taro/commit/2ef11ff)) * **taro-h5:** 去掉 es6 方法调用 ([3282707](https://github.com/NervJS/taro/commit/3282707)) diff --git a/docs/apis/multimedia/images/chooseImage.md b/docs/apis/multimedia/images/chooseImage.md index e9a85b977c0b..7e4fab2d5225 100644 --- a/docs/apis/multimedia/images/chooseImage.md +++ b/docs/apis/multimedia/images/chooseImage.md @@ -8,6 +8,28 @@ sidebar_label: chooseImage 注:RN 端该 API 不支持 `count` 属性;不支持相机与相册同时选择,只会取 `sourceType` 数组里的第一个值。默认从相册选取图片。 +## 参数 + +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| object | Object | | 参数 | +| [object.sourceType] | Array.<string> | ['album', 'camera'] | 选择图片的来源(h5端未实现) | +| [object.sizeType] | Array.<string> | ['original', 'compressed'] | 所选的图片的尺寸(h5端未实现) | +| [object.count] | number | 9 | 最多可以选择的图片张数 | +| [object.success] | function | | 接口调用成功的回调函数 | +| [object.fail] | function | | 接口调用失败的回调函数 | +| [object.complete] | function | | 接口调用结束的回调函数(调用成功、失败都会执行) | +| [object.imageId] | string | | 用来上传的input元素ID(仅h5端) | + +## 返回值 + +### Promise <object res> + +| Name | Type | Description | +| --- | --- | --- | +| res.tempFilePaths | Array. | 图片的本地临时文件路径列表 +| res.tempFiles | Array. | 图片的本地临时文件列表 + ## 示例代码 ```jsx diff --git a/docs/apis/network/request/request.md b/docs/apis/network/request/request.md index 34f6ae20f2a9..e0dc36122199 100644 --- a/docs/apis/network/request/request.md +++ b/docs/apis/network/request/request.md @@ -3,9 +3,10 @@ title: Taro.request(OBJECT) sidebar_label: request --- - 发起网络请求,支持 `Promise` 化使用。 +> 暂不支持使用 [RequestTask.onHeadersReceived(function callback)](https://developers.weixin.qq.com/miniprogram/dev/api/network/request/RequestTask.onHeadersReceived.html) 和 [RequestTask.offHeadersReceived(function callback)](https://developers.weixin.qq.com/miniprogram/dev/api/network/request/RequestTask.offHeadersReceived.html) 方法。 + **OBJECT 参数说明:** | 参数 | 类型 | 必填 | 默认值 | 说明 | @@ -56,12 +57,27 @@ Taro.request({ .then(res => console.log(res.data)) ``` +## 小程序端使用 RequestTask.abort() +```jsx +const requestTask = Taro.request({ + url: 'test.php', //仅为示例,并非真实的接口地址 + data: { + x: '' , + y: '' + }, + header: { + 'content-type': 'application/json' + }, + success (res) { + console.log(res.data) + } +}) +requestTask.abort() // 取消请求任务 +``` ## API支持度 - | API | 微信小程序 | H5 | React Native | 支付宝小程序 | 百度小程序 | 头条小程序 | QQ 轻应用 | | :-: | :-: | :-: | :-: | :-: | :-: | :-: | :-: | | Taro.request | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | - diff --git a/docs/best-practice.md b/docs/best-practice.md index dbe59e9e57cd..05c6cde20b04 100644 --- a/docs/best-practice.md +++ b/docs/best-practice.md @@ -172,7 +172,7 @@ class App extends Component { ### 组件 `state` 与 `props` 里字段重名的问题 -不要在 `state` 与 `props` 上用同名的字段,因为这些被字段在微信小程序中都会挂在 `data` 上。 +不要在 `state` 与 `props` 上用同名的字段,因为这些字段在微信小程序中都会挂在 `data` 上。 ### 小程序中页面生命周期 `componentWillMount` 不一致问题 @@ -234,6 +234,26 @@ if (process.env.NODE_ENV === 'development') { `this.$componentType` 可能取值分别为 `PAGE` 和 `COMPONENT`,开发者可以根据此变量的取值分别采取不同逻辑。 +### 原生小程序组件传递 props 给 Taro 组件 + +**Taro v1.3+** 对 props 系统进行了改造,使得不能兼容原生组件通过 properties 传入的属性。 + +目前可以通过把所有需要传入 Taro 组件的 props,通过借助 `extraProps` 属性来解决。 + +```js +// 小程序组件常规 props 传递 + + +// 原生小程序组件调用 Taro 组件时需要改造成以下形式: +this.setData({ + extraProps: { + name, + desc + } +}) + +``` + ## 全局变量 在 Taro 中推荐使用 `Redux` 来进行全局变量的管理,但是对于一些小型的应用, `Redux` 就可能显得比较重了,这时候如果想使用全局变量,推荐如下使用。 diff --git a/docs/components/media/camera.md b/docs/components/media/camera.md index 0c545a97aadb..b93890725d16 100755 --- a/docs/components/media/camera.md +++ b/docs/components/media/camera.md @@ -9,9 +9,9 @@ sidebar_label: Camera | H5 | ReactNative| 属性名 | 类型 | 默认值 | 说明 | | :-: | :-: | :- | :- | :- | :- | -| √ | | devicePosition | String | back | 前置或后置,值为 front, back | -| √ | | onStop | EventHandle | | 摄像头在非正常终止时触发,如退出后台等情况 | -| √ | | onError | EventHandle | | 用户不允许使用摄像头时触发 | +| | | devicePosition | String | back | 前置或后置,值为 front, back | +| | | onStop | EventHandle | | 摄像头在非正常终止时触发,如退出后台等情况 | +| | | onError | EventHandle | | 用户不允许使用摄像头时触发 | >其他相关属性请看各小程序官方文档 diff --git a/docs/event.md b/docs/event.md index fe65caf57b91..5c4594cc71ac 100644 --- a/docs/event.md +++ b/docs/event.md @@ -144,7 +144,7 @@ class Title extends Component{ ### 函数式组件 -在函数式组件中,事件传参可以传入事件的引用也可以传入匿名函数,以下是函数式组件配合 [`useCallback`](docs/hooks.html#usecallback) 的一个例子: +在函数式组件中,事件传参可以传入事件的引用也可以传入匿名函数,以下是函数式组件配合 [`useCallback`](hooks.html#usecallback) 的一个例子: ```jsx const App = () => { diff --git a/docs/hooks.md b/docs/hooks.md index 9543e136932a..559ad60f6dc4 100644 --- a/docs/hooks.md +++ b/docs/hooks.md @@ -361,3 +361,32 @@ const value = useContext(MyContext) > 如果你在接触 Hook 前已经对 context API 比较熟悉,那应该可以理解,`useContext(MyContext)` 相当于 class 组件中的 `static contextType = MyContext` 或者 。 > `useContext(MyContext)` 只是让你能够读取 context 的值以及订阅 context 的变化。你仍然需要在上层组件树中使用 来为下层组件提供 context。 +## 页面及组件中相关属性设置 + +在 Taro 中,你可以为页面及组件设置一些属性来达到一些特殊的目的,例如 `config` 设置配置等等,在前面章节你已经学会如何在类中进行相关设置,同样的,使用 Hooks 时你也可以进行相关设置来达到和使用类一样的效果。 + +不同于使用类的写法,使用 Hooks 时,你需要将 `config` 或 `options` 等配置直接挂载在 Hooks 函数上,即可以达到想要的效果,例如 + +为页面设置 `config` + +```jsx +export default function Index () { + return +} + +Index.config = { + navigationBarTitleText: '首页' +} +``` + +为组件设置 `options` + +```jsx +export default function Com () { + return +} + +Com.options = { + addGlobalClass: true +} +``` diff --git a/docs/miniprogram-plugin.md b/docs/miniprogram-plugin.md index 93922b33d3d8..d6b42783f42d 100644 --- a/docs/miniprogram-plugin.md +++ b/docs/miniprogram-plugin.md @@ -90,6 +90,26 @@ export default class Index extends Component { } ``` +### Taro v1.3+ 组件插件接受外部 props 的问题 + +[#3176](https://github.com/NervJS/taro/issues/3176) + +Taro v1.3 对 props 系统进行了改造,使得不能兼容原生组件通过 properties 传入的属性。 + +目前可以通过把所有需要传入组件插件的 props,通过借助 `extraProps` 属性来解决。 + +```js +// 常规 props 传递 + + +// 在使用插件组件时需要改造成以下形式: +const extraProps = { + name: this.state.name, + desc: this.state.desc +} + +``` + ### 使用接口插件 plugin.json 的 **main** 字段加入接口插件路径: diff --git a/docs/mobx.md b/docs/mobx.md index 59d03f417612..b20bb40ed003 100644 --- a/docs/mobx.md +++ b/docs/mobx.md @@ -6,9 +6,7 @@ title: 使用 MobX [MobX](https://mobx.js.org/) 为复杂项目中状态管理提供了一种简单高效的机制;Taro 提供了 `@tarojs/mobx` 来让开发人员在使用 MobX 的过程中获得更加良好的开发体验。 -> 下文中示例代码均在 [taro-mobx-sample](https://github.com/nanjingboy/taro-mobx-sample) - -首先请安装 `mobx@4.8.0` 、 `@tarojs/mobx` 、 `@tarojs/mobx-h5` 和 `@tarojs/mobx-rn` +## 安装 ```bash $ yarn add mobx@4.8.0 @tarojs/mobx @tarojs/mobx-h5 @tarojs/mobx-rn @@ -16,168 +14,240 @@ $ yarn add mobx@4.8.0 @tarojs/mobx @tarojs/mobx-h5 @tarojs/mobx-rn $ npm install --save mobx@4.8.0 @tarojs/mobx @tarojs/mobx-h5 @tarojs/mobx-rn ``` -随后可以在项目 `src` 目录下新增一个 `store/counter.js` 文件 +## API + +### onError + +Mobx 异常监听。 ```jsx -// src/store/counter.js -import { observable } from 'mobx' - -const counterStore = observable({ - counter: 0, - counterStore() { - this.counter++ - }, - increment() { - this.counter++ - }, - decrement() { - this.counter-- - }, - incrementAsync() { - setTimeout(() => { - this.counter++ - }, 1000) - } +import { onError } from '@tarojs/mobx' + +onError(error => { + console.log('mobx global error listener:', error) }) +``` + +### isUsingStaticRendering + +> 自 `1.3.6` 开始支持 + +判断是否开启了服务端渲染(该状态为全局状态)。 -export default counterStore +```jsx +import { isUsingStaticRendering } from '@tarojs/mobx' + +if (isUsingStaticRendering()) { + //... +} ``` -接下来在项目入口文件 `app.js` 中使用 `@tarojs/mobx` 中提供的 `Provider` 组件将前面写好的 `store` 接入应用中 +### useStaticRendering + +> 自 `1.3.6` 开始支持 + +服务端渲染状态设置(该状态为全局状态)。 ```jsx -// src/app.js -import Taro, { Component } from '@tarojs/taro' -import { Provider, onError } from '@tarojs/mobx' -import Index from './pages/index' +import { useStaticRendering } from '@tarojs/mobx' -import counterStore from './store/counter' +useStaticRendering(false) +``` -import './app.scss' +### useLocalStore -const store = { - counterStore -} +> 自 `1.3.6` 开始支持 -onError(error => { - console.log('mobx global error listener:', error) -}) +将对象转换为 `observable` 对象,其中 `getter` 会被转换为 `computed` 属性,方法会与 `store` 进行绑定并自动执行 +[mobx transactions](https://mobx.js.org/refguide/action.html),比如: -class App extends Component { +```jsx +import Taro from '@tarojs/taro' +import { View, Text, Button } from '@tarojs/components' +import { useLocalStore, observer } from '@tarojs/mobx' - config = { - pages: [ - 'pages/index/index' - ], - window: { - backgroundTextStyle: 'light', - navigationBarBackgroundColor: '#fff', - navigationBarTitleText: 'WeChat', - navigationBarTextStyle: 'black' +import './index.scss' + +function Index() { + const store = useLocalStore(() => ({ + counter: 0, + increment() { + store.counter++ + }, + decrement() { + store.counter-- + }, + incrementAsync() { + setTimeout(() => store.counter++, 1000) } - } + })) + + const { counter, increment, decrement, incrementAsync } = store; + return ( + + + + + {counter} + + ) +} - componentDidMount () {} +export default observer(Index) +``` - componentDidShow () {} +### useAsObservableSource - componentDidHide () {} +> 自 `1.3.6` 开始支持 - componentDidCatchError () {} +与 `useLocalStore` 的区别是,它将纯(不包含 `getter` 或方法)对象转换为 `observable`,主要使用场景为: - render () { +* 如果对象某个属性的值需经过复杂运算才能获得,可通过该方法进行包装,这样在组件的生命周期中该运算只需要运算一次。 +* 一般情况下 `useLocalStore` 仅用于组件内部,如果 `useLocalStore` 中的对象需要依赖外部传递的属性,那么可通过 + `useAsObservableSource` 将这些属性进行转换,而后在 `useLocalStore` 对象中进行引用,这样在外部属性改变时自动通知 + `useLocalStore` 对象对变化进行响应,比如: + + ```jsx + import Taro from '@tarojs/taro' + import { View, Button, Text } from '@tarojs/components' + import { useAsObservableSource, useLocalStore, observer } from '@tarojs/mobx' + + function Multiplier(props) { + const observableProps = useAsObservableSource(props) + const store = useLocalStore(() => ({ + counter: 1, + get multiplied() { + return observableProps.multiplier * store.counter + }, + increment() { + store.counter += 1 + } + })) + const { multiplier } = observableProps + const { multiplied, counter, increment } = store return ( - - - + + multiplier({multiplier}) * counter({counter}) = {multiplied} + + ) } -} -Taro.render(, document.getElementById('app')) + export default observer(Multiplier) + ``` -``` + 该场景也可直接使用 `useLocalStore` 中的第二种用法来实现: -然后,我们在页面中可通过 `@tarojs/mobx` 提供的 `inject` 以及 `observer` 方法将 `mobx` 与我们的页面进行关联 + ```jsx + import Taro from '@tarojs/taro' + import { View, Button, Text } from '@tarojs/components' + import { useLocalStore, observer } from '@tarojs/mobx' + + function Multiplier(props) { + const store = useLocalStore(source => ({ + counter: 1, + + get multiplier() { + return source.multiplier + }, + + get multiplied() { + return source.multiplier * store.counter + }, + increment() { + store.counter += 1 + } + }), props) + const { multiplied, counter, increment, multiplier } = store + return ( + + multiplier({multiplier}) * counter({counter}) = {multiplied} + + + ) + } -```jsx -// src/pages/index/index.js -import Taro, { Component } from '@tarojs/taro' -import { View, Button, Text } from '@tarojs/components' -import { observer, inject } from '@tarojs/mobx' + export default observer(Multiplier) + ``` -import './index.scss' +### observer -@inject('counterStore') -@observer -class Index extends Component { +将组件设置为监听者,以便在可观察对象的值改变后触发页面的重新渲染。 - config = { - navigationBarTitleText: '首页' - } +注: - componentWillMount () { - console.log('componentWillMount') - } +* 不要在 `JSX` 中对可观察对象进行引用,比如: - /** - * 该方法将在 observable 对象更新时触发 - */ - componentWillReact () { - console.log('componentWillReact') - } + ```jsx + // 错误,在小程序中值改变后将无法触发重新渲染 + const { counterStore } = this.props + return ( + {counterStore.counter} + ) - componentDidMount () { - console.log('componentDidMount') - } + // 正确 + const { counterStore: { counter } } = this.props + return ( + {counter} + ) + ``` - componentWillUnmount () { - console.log('componentWillUnmount') - } + > 这是因为 `@tarojs/mobx` 通过监听组件的 `render`(小程序编译后为 `_createData`)方法来触发更新;在小程序中,`JSX` + > 的代码会被编译到 `wxml` 文件中,此时对可观察对象的引用(比如:`counterStore.counter`)早已脱离了 + > `@tarojs/mobx` 的监控,故此对该属性的更改并不会触发更新操作。 - componentDidShow () { - console.log('componentDidShow') - } +* 如使用 `@observable` 装饰器来定义可观察对象时,请确保该属性已经初始化,比如: - componentDidHide () { - console.log('componentDidHide') - } + ```js + @observable counter // 错误,值改变后将无法触发重新渲染 + @observable counter = 0 // 正确 + ``` - increment = () => { - const { counterStore } = this.props - counterStore.increment() - } +* 如果 `isUsingStaticRendering` 为 `true`,该方法不做任何事情。 - decrement = () => { - const { counterStore } = this.props - counterStore.decrement() - } +### Provider + +全局 `store` 设置,比如: + +```jsx +import Taro, { Component } from '@tarojs/taro' +import { Provider } from '@tarojs/mobx' +import Index from './pages/index' +import counterStore from './store/counter' - incrementAsync = () => { - const { counterStore } = this.props - counterStore.incrementAsync() +const store = { + counterStore +} + +class App extends Component { + config = { + pages: [ + 'pages/index/index' + ], + window: { + backgroundTextStyle: 'light', + navigationBarBackgroundColor: '#fff', + navigationBarTitleText: 'WeChat', + navigationBarTextStyle: 'black' + } } render () { - const { counterStore: { counter } } = this.props return ( - - - - - {counter} - + + + ) } } -export default Index - +Taro.render(, document.getElementById('app')) ``` -上例中 `Provider`、`inject`、 `observer`、`onError` 的使用方式基本上与 [mobx-react](https://github.com/mobxjs/mobx-react) 保持了一致,但也有以下几点需要注意: +注: -* `Provider` 不支持嵌套,即全局只能存在一个 `Provider` +* `Provider` 必须作用于入口文件(即:`src/app.js`),在其他地方使用无效。 +* 不支持嵌套,即全局只能存在一个 `Provider`。 * 在 `mobx-react` 中,可通过以下方式设置 `store`: ```jsx @@ -198,52 +268,76 @@ export default Index ``` -* `inject`、 `observer` 不能在 stateless 组件上使用 -* `observer` 不支持任何参数 -* 按照以下方式使用 `inject` 时,不能省略 `observer` 的显式调用: - ```jsx - @inject((stores, props) => ({ - counterStore: stores.counterStore - })) - @observer //这个不能省略 - ``` +### inject -注意事项: +将 `Provider` 中设置的 `store` 提取到组件的 `props` 中,该 `API` 只适用于`类组件`,比如: -* 在 `Component` 的 `render` 方法中,如果需要使用一个 `observable` 对象(该例中为 `counter`),您需要: +```jsx +import Taro, { Component } from '@tarojs/taro' +import { observer, inject } from '@tarojs/mobx' - ```js - const { counterStore: { counter } } = this.props - return ( - {counter} - ) - ``` +import './index.scss' - 而非: +@inject('counterStore') +@observer +class Index extends Component { + //... +} - ```js - const { counterStore } = this.props - return ( - {counterStore.counter} - ) - ``` +export default Index +``` -* 如果使用 `@observable` 装饰器来定义可观察对象时,请确保该属性已经初始化(这是很多情况下属性值改变,页面没刷新的根源所在),比如: +或 - ```js - @observable counter // 错误 - @observable counter = 0 // 正确 - ``` +```jsx +import Taro, { Component } from '@tarojs/taro' +import { observer, inject } from '@tarojs/mobx' -* 自 `1.2.0-beta.5` 后,`propTypes` 已从 `taro-mobx`、`taro-mobx-h5`、`taro-mobx-rn` 中剥离,如需使用,请单独进行安装: +import './index.scss' + +@inject((stores, props) => ({ + counterStore: stores.counterStore +})) +@observer +class Index extends Component { + //... +} - ```bash - $ yarn add @tarojs/mobx-prop-types - # 或者使用 npm - $ npm install --save @tarojs/mobx-prop-types +export default Index +``` + +注: + +* 无论以何种方式使用 `inject`,其后的 `observer` 均不能省略。 +* 不要在 `inject` 中引用可观察对象,这将导致属性改变后页面不更新,比如: + + ```jsx + // 错误 + @inject((stores, props) => ({ + counter: stores.counterStore.counter + })) + + // 正确 + @inject((stores, props) => ({ + counterStore: stores.counterStore + })) ``` - `propTypes` 使用与 [mobx-react](https://github.com/mobxjs/mobx-react#proptypes) 一致 +### PropTypes + +> 自 `1.3.6` 开始支持 + +`@tarojs/mobx` 提供了以下 `PropTypes` 来验证 Mobx 的结构: + +* observableArray +* observableArrayOf +* observableMap +* observableObject +* arrayOrObservableArray +* arrayOrObservableArrayOf +* objectOrObservableObject + +## 资源 - > 注:自 `1.2.27-beta.0` 后,`@tarojs/mobx-prop-types` 已被移除,请使用 [mobx-react](https://github.com/mobxjs/mobx-react#proptypes) 替代。 +示例:[taro-mobx-sample](https://github.com/nanjingboy/taro-mobx-sample) \ No newline at end of file diff --git a/docs/project-config.md b/docs/project-config.md index 64134ffc2cbb..045cd6da32d2 100644 --- a/docs/project-config.md +++ b/docs/project-config.md @@ -8,13 +8,17 @@ title: 项目配置 * 百度智能小程序,[project.swan.json](https://smartprogram.baidu.com/docs/develop/devtools/projectconfig/) * 头条小程序,project.config.json,文档暂无,大部分字段与微信小程序一致 * 支付宝小程序,暂无发现 +* 快应用,[manifest.json](https://doc.quickapp.cn/framework/manifest.html) 为了能够适配到各个小程序平台,满足不同小程序平台配置文件不同的情况,在 Taro 支持为各个小程序平台添加不同的项目配置文件。 通过 Taro 模板创建的项目都会默认拥有 `project.config.json` 这一项目配置文件,这个文件 **只能用于微信小程序**,若要兼容到其他小程序平台,请按如下对应规则来增加相应平台的配置文件,其配置与各自小程序平台要求的一致 -| 小程序平台 | 添加配置文件 | -| - | - | -| 微信小程序 | project.config.json | -| 百度智能小程序 | project.swan.json | -| 头条小程序 | project.tt.json | +| 小程序平台 | 添加配置文件 | 说明 | +| --- | --- | --- | +| 微信小程序 | project.config.json | | +| 百度智能小程序 | project.swan.json | | +| 头条小程序 | project.tt.json | | +| 快应用 | project.quickapp.json | 配置文件中请勿配置 `router` 与 `display`,这两个配置将由 Taro 生成 | + +> 注意:快应用的 `project.quickapp.json` 配置请参考[文件](https://github.com/NervJS/taro/blob/master/packages/taro-cli/src/config/manifest.default.json) diff --git a/docs/quick-app.md b/docs/quick-app.md index d26d63af5d27..f48438cf0abf 100644 --- a/docs/quick-app.md +++ b/docs/quick-app.md @@ -3,7 +3,7 @@ title: 快应用端开发流程 --- > 从 **1.3 beta** 版本开始支持快应用开发
-> 本章节主要讲解快应用端端 环境安装-开发-调试-打包-发布 原理及流程 +> 本章节主要讲解快应用端 环境安装-开发-调试-打包-发布 原理及流程 ## 简介 diff --git a/docs/react-native.md b/docs/react-native.md index 17b3ca2a9d97..e44930a7e136 100644 --- a/docs/react-native.md +++ b/docs/react-native.md @@ -290,7 +290,7 @@ rn_temp ### 启动应用 如果上一步的编译和 Metro Bundler Server 启动没问题,接下来就可以启动应用了。 -开发者可以自行整合 React Native (0.55.4) 到原生应用,同时为了方便大家开发和整合,Taro 将 React Native 工程中原生的部分剥离出来,单独放在一个工程里面 [NervJS/taro-native-shell](https://github.com/NervJS/taro-native-shell),你可以把它看成是 React Native iOS/Android 空应用的壳子。 +开发者可以自行[整合 React Native (0.55.4) 到原生应用](https://reactnative.cn/docs/0.55/integration-with-existing-apps/),同时为了方便大家开发和整合,Taro 将 React Native 工程中原生的部分剥离出来,单独放在一个工程里面 [NervJS/taro-native-shell](https://github.com/NervJS/taro-native-shell),你可以把它看成是 React Native iOS/Android 空应用的壳子。 首先将应用代码 clone 下来: diff --git a/docs/redux.md b/docs/redux.md index 74af439e75ff..7ca24634f7ca 100644 --- a/docs/redux.md +++ b/docs/redux.md @@ -205,3 +205,151 @@ export default Index - `mapStateToProps`,函数类型,接受最新的 `state` 作为参数,用于将 `state` 映射到组件的 `props` - `mapDispatchToProps`,函数类型,接收 `dispatch()` 方法并返回期望注入到展示组件的 `props` 中的回调方法 + +## Hooks + +### 在 Redux 中使用 Hooks + +使用 hooks 的基本设置和使用 `connect` 的设置是一样的,你需要设置你的 `store`,并把你的应用放在 `Provider` 组件中。 + +```jsx +const store = configreStore(rootReducer) + +class App extends Components { + render () { + return ( + + + + ) + } +} +``` + +在这样的情况下,你就可以使用 `taro-redux` 提供的 Hooks API 在函数式组件中使用。 + +### `useSelector` + +```javascript +const result : any = useSelector(selector : Function, equalityFn? : Function) +``` + +`useSelector` 允许你使用 selector 函数从一个 Redux Store 中获取数据。 + +Selector 函数大致相当于 `connect` 函数的 `mapStateToProps` 参数。Selector 会在组件每次渲染时调用。`useSelector` 同样会订阅 Redux store,在 Redux action 被 dispatch 时调用。 + +但 `useSelector` 还是和 `mapStateToProps` 有一些不同: + +* 不像 `mapStateToProps` 只返回对象一样,Selector 可能会返回任何值。 +* 当一个 action dispatch 时,`useSelector` 会把 selector 的前后返回值做一次浅对比,如果不同,组件会强制更新。 +* Selector 函数不接受 `ownProps` 参数。但 selector 可以通过闭包访问函数式组件传递下来的 props。 + + +#### 使用案例 + +基本使用: + +```jsx +import Taro, { Components } from '@tarojs/taro' +import { useSelector } from '@tarojs/redux' + +export const CounterComponent = () => { + const counter = useSelector(state => state.counter) + return {counter} +} +``` + +使用闭包决定如何 select 数据: + +```jsx +export const TodoListItem = props => { + const todo = useSelector(state => state.todos[props.id]) + return {todo.text} +} + +``` + +#### 进阶使用 + + 你还可以访问 [react-redux 文档](https://react-redux.js.org/api/hooks#using-memoizing-selectors) 了解如何使用 `reselect` 缓存 selector。 + + +### `useDispatch` + +```javascript +const dispatch = useDispatch() +``` + +这个 Hook 返回 Redux store 的 `dispatch` 引用。你可以使用它来 dispatch actions。 + +#### 使用案例 + +```jsx +import Taro, { Components } from '@tarojs/taro' +import { useDispatch } from '@tarojs/redux' + +export const CounterComponent = ({ value }) => { + const dispatch = useDispatch() + + return ( + + {value} + + + ) +} +``` + +当我们使用 `dispatch` 传递回调到一个子组件时,推荐使用 `useCallback` 把回调缓存起来,因为组件可能因为引用改变而重新渲染。 + +```jsx +// CounterComponent.js +export const CounterComponent = ({ value }) => { + const dispatch = useDispatch() + const incrementCounter = useCallback( + () => dispatch({ type: 'increment-counter' }), + [dispatch] + ) + + return ( + + {value} + + + ) +} + +// IncrementButton.js +const MyIncrementButton = ({ onIncrement }) => ( + +) + +export default Taro.memo(MyIncrementButton) +``` + +### `useStore` + +```js +const store = useStore() +``` + +`useStore` 返回一个 store 引用和 `Provider` 组件引用完全一致。 + +这个 hook 可能并不经常使用。`useSelector` 大部分情况是你的第一选择,如果需要替换 reducers 的情况下可能会使用到这个 API。 + +#### 使用案例 + +```jsx +import Taro, { Components } from '@tarojs/taro' +import { useStore } from '@tarojs/redux' + +export const CounterComponent = ({ value }) => { + const store = useStore() + + // EXAMPLE ONLY! Do not do this in a real app. + // The component will not automatically update if the store state changes + return
{store.getState()}
+} +``` diff --git a/docs/render-props.md b/docs/render-props.md new file mode 100644 index 000000000000..dcea800a77f4 --- /dev/null +++ b/docs/render-props.md @@ -0,0 +1,81 @@ +--- +title: Render Props +--- + +> 自 1.3.5 起支持 + +`render props` 是指一种在 Taro 组件之间使用一个值为函数的 prop 共享代码的简单技术。 + +具有 render prop 的组件接受一个函数,该函数返回一个 Taro 元素并调用它而不是实现自己的渲染逻辑。 + + +举个例子,假设我们有一个组件,它可以呈现一张在屏幕上追逐鼠标的猫的图片。我们或许会使用 ` 组件,它能够动态决定什么需要渲染的,而不是将 `` 硬编码到 `` 组件里,并有效地改变它的渲染结果。 + +```jsx +class Cat extends Taro.Component { + render() { + const mouse = this.props.mouse; + return ( + + ); + } +} + +class Mouse extends Taro.Component { + constructor(props) { + super(props); + this.handleMouseMove = this.handleClick.bind(this); + this.state = { x: 0, y: 0 }; + } + + handleClick(event) { + const { x, y } = event.detail + this.setState({ + x, + y + }); + } + + render() { + return ( + + + {/* + 我们可以把 prop 当成一个函数,动态地调整渲染内容。 + */} + {this.props.renderCat(this.state)} + + ); + } +} + +class MouseTracker extends React.Component { + render() { + return ( + + 点击鼠标! + {/* + 这 + */} + ( + + )}/> + + ); + } +} +``` + +现在,我们提供了一个 render 方法 让 `` 能够动态决定什么需要渲染,而不是克隆 `` 组件然后硬编码来解决特定的用例。 + +更具体地说,**render prop 是一个用于告知组件需要渲染什么内容的函数 prop**。 + +这项技术使我们共享行为非常容易。要获得这个行为,只要渲染一个带有 render prop 的 `` 组件就能够告诉它当前鼠标坐标 (x, y) 要渲染什么。 + + +### 注意事项 + +**`render props` 是基于小程序 `slot` 机制实现的。** 因此它受到的限制和 `children 与组合`的限制一样多,更多详情请查看文档[Children与组合 +](./taro/docs/children.html#注意事项)。 diff --git a/lerna.json b/lerna.json index db822ef45f97..abe7320b7159 100644 --- a/lerna.json +++ b/lerna.json @@ -53,6 +53,6 @@ "message": "chore(release): publish %s" } }, - "version": "1.3.0", + "version": "1.3.7", "npmClient": "npm" } diff --git a/packages/babel-plugin-transform-jsx-to-stylesheet/package.json b/packages/babel-plugin-transform-jsx-to-stylesheet/package.json index b62c49abd565..0c04e45fb5e6 100644 --- a/packages/babel-plugin-transform-jsx-to-stylesheet/package.json +++ b/packages/babel-plugin-transform-jsx-to-stylesheet/package.json @@ -1,6 +1,6 @@ { "name": "babel-plugin-transform-jsx-to-stylesheet", - "version": "1.3.0", + "version": "1.3.7", "description": "Transform stylesheet selector to style in JSX Elements.", "license": "MIT", "main": "src/index.js", diff --git a/packages/babel-plugin-transform-taroapi/package.json b/packages/babel-plugin-transform-taroapi/package.json index f0587c8d61f4..ee1b1470ad13 100644 --- a/packages/babel-plugin-transform-taroapi/package.json +++ b/packages/babel-plugin-transform-taroapi/package.json @@ -1,6 +1,6 @@ { "name": "babel-plugin-transform-taroapi", - "version": "1.3.0", + "version": "1.3.7", "main": "dist/index.js", "license": "MIT", "scripts": { @@ -10,7 +10,7 @@ "test": "jest" }, "devDependencies": { - "@tarojs/taro-h5": "1.3.0", + "@tarojs/taro-h5": "1.3.7", "@types/babel-core": "^6.25.5", "@types/babel-traverse": "^6.25.4", "@types/babel-types": "^7.0.4", diff --git a/packages/css-to-react-native/package.json b/packages/css-to-react-native/package.json index dd49d0e2b05d..db8193afdfc8 100644 --- a/packages/css-to-react-native/package.json +++ b/packages/css-to-react-native/package.json @@ -1,7 +1,7 @@ { "name": "taro-css-to-react-native", "description": "Convert CSS text to a React Native stylesheet object", - "version": "1.3.0", + "version": "1.3.7", "main": "dist/index.js", "license": "MIT", "scripts": { diff --git a/packages/eslint-config-taro/package.json b/packages/eslint-config-taro/package.json index 89c14f011837..6c9b83af06e9 100644 --- a/packages/eslint-config-taro/package.json +++ b/packages/eslint-config-taro/package.json @@ -1,6 +1,6 @@ { "name": "eslint-config-taro", - "version": "1.3.0", + "version": "1.3.7", "description": "Taro specific linting rules for ESLint", "main": "index.js", "files": [ @@ -27,6 +27,6 @@ "author": "O2Team", "license": "MIT", "dependencies": { - "eslint-plugin-taro": "1.3.0" + "eslint-plugin-taro": "1.3.7" } } diff --git a/packages/eslint-plugin-taro/package.json b/packages/eslint-plugin-taro/package.json index 14877634b7e6..2a2b571c36b9 100644 --- a/packages/eslint-plugin-taro/package.json +++ b/packages/eslint-plugin-taro/package.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-taro", - "version": "1.3.0", + "version": "1.3.7", "description": "Taro specific linting plugin for ESLint", "main": "index.js", "files": [ diff --git a/packages/postcss-plugin-constparse/package.json b/packages/postcss-plugin-constparse/package.json index 91847d46d509..92e5db0e2c2a 100644 --- a/packages/postcss-plugin-constparse/package.json +++ b/packages/postcss-plugin-constparse/package.json @@ -1,6 +1,6 @@ { "name": "postcss-plugin-constparse", - "version": "1.3.0", + "version": "1.3.7", "description": "parse constants defined in config", "main": "index.js", "author": "Simba", diff --git a/packages/postcss-pxtransform/package.json b/packages/postcss-pxtransform/package.json index 513383d63311..bf5cb5165481 100644 --- a/packages/postcss-pxtransform/package.json +++ b/packages/postcss-pxtransform/package.json @@ -1,6 +1,6 @@ { "name": "postcss-pxtransform", - "version": "1.3.0", + "version": "1.3.7", "description": "PostCSS plugin px 转小程序 rpx及h5 rem 单位", "keywords": [ "postcss", diff --git a/packages/postcss-unit-transform/package.json b/packages/postcss-unit-transform/package.json index af1528117b87..51b5bce7de84 100644 --- a/packages/postcss-unit-transform/package.json +++ b/packages/postcss-unit-transform/package.json @@ -1,6 +1,6 @@ { "name": "postcss-taro-unit-transform", - "version": "1.3.0", + "version": "1.3.7", "description": "小程序单位转换", "main": "index.js", "scripts": { diff --git a/packages/stylelint-config-taro-rn/package.json b/packages/stylelint-config-taro-rn/package.json index fb5b35500ebb..cfca9cf2772a 100644 --- a/packages/stylelint-config-taro-rn/package.json +++ b/packages/stylelint-config-taro-rn/package.json @@ -1,6 +1,6 @@ { "name": "stylelint-config-taro-rn", - "version": "1.3.0", + "version": "1.3.7", "description": "Shareable stylelint config for React Native CSS modules", "main": "index.js", "files": [ @@ -28,6 +28,6 @@ "jest": "^23.6.0", "npmpub": "^4.1.0", "stylelint": "9.3.0", - "stylelint-taro-rn": "1.3.0" + "stylelint-taro-rn": "1.3.7" } } diff --git a/packages/stylelint-taro-rn/package.json b/packages/stylelint-taro-rn/package.json index 3148cc2d9ad2..b6a7b3c948f5 100644 --- a/packages/stylelint-taro-rn/package.json +++ b/packages/stylelint-taro-rn/package.json @@ -1,7 +1,7 @@ { "name": "stylelint-taro-rn", "description": "A collection of React Native specific rules for stylelint", - "version": "1.3.0", + "version": "1.3.7", "main": "dist/index.js", "babel": { "presets": [ diff --git a/packages/taro-alipay/package.json b/packages/taro-alipay/package.json index 7477ae83baa1..1df5cd171319 100644 --- a/packages/taro-alipay/package.json +++ b/packages/taro-alipay/package.json @@ -1,6 +1,6 @@ { "name": "@tarojs/taro-alipay", - "version": "1.3.0", + "version": "1.3.7", "description": "Taro alipay framework", "main": "index.js", "files": [ @@ -24,8 +24,8 @@ "author": "O2Team", "license": "MIT", "dependencies": { - "@tarojs/taro": "1.3.0", - "@tarojs/utils": "1.3.0", + "@tarojs/taro": "1.3.7", + "@tarojs/utils": "1.3.7", "lodash": "^4.17.10", "prop-types": "^15.6.1" } diff --git a/packages/taro-alipay/rollup.config.js b/packages/taro-alipay/rollup.config.js index 1d2142ee9754..47b837efc94c 100644 --- a/packages/taro-alipay/rollup.config.js +++ b/packages/taro-alipay/rollup.config.js @@ -7,7 +7,7 @@ const cwd = __dirname const baseConfig = { input: join(cwd, 'src/index.js'), - external: ['nervjs'], + external: ['nervjs', '@tarojs/taro'], output: [ { file: join(cwd, 'dist/index.js'), diff --git a/packages/taro-alipay/src/create-component.js b/packages/taro-alipay/src/create-component.js index f37fcbe64d1e..aca9e8e7e834 100644 --- a/packages/taro-alipay/src/create-component.js +++ b/packages/taro-alipay/src/create-component.js @@ -1,9 +1,8 @@ import { getCurrentPageUrl } from '@tarojs/utils' -import { commitAttachRef, detachAllRef, Current } from '@tarojs/taro' -import { isEmptyObject, isFunction } from './util' +import { commitAttachRef, detachAllRef, Current, eventCenter } from '@tarojs/taro' +import { isEmptyObject, isFunction, isArray } from './util' import { mountComponent } from './lifecycle' import { cacheDataSet, cacheDataGet, cacheDataHas } from './data-cache' -import propsManager from './propsManager' const anonymousFnNamePreffix = 'funPrivate' const COLLECT_CHILDS = 'onTaroCollectChilds' @@ -174,7 +173,7 @@ export function componentTrigger (component, key, args) { if (key === 'componentWillUnmount') { if (component.$scope.props) { const compid = component.$scope.props.compid - if (compid) propsManager.delete(compid) + if (compid) my.propsManager.delete(compid) } } @@ -286,6 +285,11 @@ function createComponent (ComponentClass, isPage) { onUnload () { componentTrigger(this.$component, 'componentWillUnmount') + const component = this.$component + const events = component.$$renderPropsEvents + if (isArray(events)) { + events.forEach(e => eventCenter.off(e)) + } }, onShow () { @@ -311,7 +315,7 @@ function createComponent (ComponentClass, isPage) { Object.assign(weappComponentConf, { didMount () { const compid = this.props.compid - const props = filterProps(ComponentClass.defaultProps, propsManager.map[compid], {}) + const props = filterProps(ComponentClass.defaultProps, my.propsManager.map[compid], {}) this.$component = new ComponentClass(props, isPage) this.$component._init(this) @@ -319,7 +323,7 @@ function createComponent (ComponentClass, isPage) { this.$component.__propTypes = ComponentClass.propTypes if (compid) { - propsManager.observers[compid] = { + my.propsManager.observers[compid] = { component: this.$component, ComponentClass } diff --git a/packages/taro-alipay/src/index.js b/packages/taro-alipay/src/index.js index e37a20738346..5dd6a17f6642 100644 --- a/packages/taro-alipay/src/index.js +++ b/packages/taro-alipay/src/index.js @@ -23,6 +23,7 @@ import { createContext, memo } from '@tarojs/taro' +import { shallowEqual } from '@tarojs/utils' import Component from './component' import PureComponent from './pure-component' @@ -32,6 +33,8 @@ import initNativeApi from './native-api' import propsManager from './propsManager' import { getElementById, genCompid } from './util' +if (!my.propsManager) my.propsManager = propsManager + export const Taro = { Component, PureComponent, @@ -50,7 +53,6 @@ export const Taro = { internal_get_original, interceptors, getElementById, - propsManager, genCompid, useEffect, useLayoutEffect, @@ -62,7 +64,8 @@ export const Taro = { useImperativeHandle, useContext, createContext, - memo + memo, + shallowEqual } export default Taro diff --git a/packages/taro-alipay/src/lifecycle.js b/packages/taro-alipay/src/lifecycle.js index 75db099356d0..3a03dab991ce 100644 --- a/packages/taro-alipay/src/lifecycle.js +++ b/packages/taro-alipay/src/lifecycle.js @@ -139,15 +139,13 @@ function doUpdate (component, prevProps, prevState) { const { state, props = {} } = component let data = state || {} if (component._createData) { - // 返回null或undefined则保持不变 - const isRunLoopRef = !component.__mounted if (component.__isReady) { injectContextType(component) Current.current = component Current.index = 0 invokeEffects(component, true) } - data = component._createData(state, props, isRunLoopRef) || data + data = component._createData(state, props) || data if (component.__isReady) { Current.current = null } @@ -206,19 +204,23 @@ function doUpdate (component, prevProps, prevState) { } if (component['$$hasLoopRef']) { + Current.current = component component._disableEffect = true component._createData(component.state, component.props, true) component._disableEffect = false + Current.current = null } if (typeof component.componentDidUpdate === 'function') { component.componentDidUpdate(prevProps, prevState, snapshot) } - } - - // 解决初始化时 onLoad 最先触发,但拿不到子组件 ref 的问题 - if (component.$componentType === 'PAGE' && component['$$hasLoopRef']) { + } else if (component.$componentType === 'PAGE' && component['$$hasLoopRef']) { + // 解决初始化时 onLoad 最先触发,但拿不到子组件 ref 的问题 + Current.current = component + component._disableEffect = true component._createData(component.state, component.props, true) + component._disableEffect = false + Current.current = null } if (cbs.length) { diff --git a/packages/taro-alipay/src/native-api.js b/packages/taro-alipay/src/native-api.js index 3d619d28fc69..e6e4cc06588d 100644 --- a/packages/taro-alipay/src/native-api.js +++ b/packages/taro-alipay/src/native-api.js @@ -441,6 +441,7 @@ export default function initNativeApi (taro) { processApis(taro) taro.request = link.request.bind(link) taro.addInterceptor = link.addInterceptor.bind(link) + taro.cleanInterceptors = link.cleanInterceptors.bind(link) taro.getCurrentPages = getCurrentPages taro.getApp = getApp taro.initPxTransform = initPxTransform.bind(taro) diff --git a/packages/taro-async-await/package.json b/packages/taro-async-await/package.json index fbbb89a29fc0..aa3f5143130a 100644 --- a/packages/taro-async-await/package.json +++ b/packages/taro-async-await/package.json @@ -1,6 +1,6 @@ { "name": "@tarojs/async-await", - "version": "1.3.0", + "version": "1.3.7", "description": "taro async await", "main": "index.js", "scripts": { diff --git a/packages/taro-cli/bin/taro-build b/packages/taro-cli/bin/taro-build index 4e64438fa681..fdb7bd92071d 100755 --- a/packages/taro-cli/bin/taro-build +++ b/packages/taro-cli/bin/taro-build @@ -25,6 +25,16 @@ let { env, plugin } = program env = process.env.NODE_ENV || env +if (env) { + process.env.NODE_ENV = env +} else { + if (watch) { + process.env.NODE_ENV = 'development' + } else { + process.env.NODE_ENV = 'production' + } +} + if (ui) { console.log(chalk.green(`开始编译 UI 库`)) build(appPath, { @@ -51,16 +61,6 @@ if (!fs.existsSync(projectConfPath)) { process.exit(1) } -if (env) { - process.env.NODE_ENV = env -} else { - if (watch) { - process.env.NODE_ENV = 'development' - } else { - process.env.NODE_ENV = 'production' - } -} - process.env.TARO_ENV = type const projectConf = require(projectConfPath)(_.merge) diff --git a/packages/taro-cli/bin/taro-doctor b/packages/taro-cli/bin/taro-doctor index 9801ac55a135..a1b259cc717e 100755 --- a/packages/taro-cli/bin/taro-doctor +++ b/packages/taro-cli/bin/taro-doctor @@ -16,6 +16,11 @@ if (!fs.existsSync(PROJECT_CONF_PATH)) { } const { validators } = require('../dist/doctor').default +const abilityXMLValidator = require('../dist/doctor/abilityXMLValidator').default +const QUICKAPP_CONF_PATH = path.join(appPath, 'project.quickapp.json') +if (fs.existsSync(QUICKAPP_CONF_PATH)) { + validators.push(abilityXMLValidator) +} const NOTE_ALL_RIGHT = chalk.green('[✓] ') const NOTE_VALID = chalk.yellow('[!] ') diff --git a/packages/taro-cli/package.json b/packages/taro-cli/package.json index d577fc41b902..e767d7882473 100644 --- a/packages/taro-cli/package.json +++ b/packages/taro-cli/package.json @@ -1,6 +1,6 @@ { "name": "@tarojs/cli", - "version": "1.3.0", + "version": "1.3.7", "description": "cli tool for taro", "main": "index.js", "scripts": { @@ -30,8 +30,8 @@ "author": "O2Team", "license": "MIT", "dependencies": { - "@tarojs/taroize": "1.3.0", - "@tarojs/transformer-wx": "1.3.0", + "@tarojs/taroize": "1.3.7", + "@tarojs/transformer-wx": "1.3.7", "@types/request": "^2.48.1", "adm-zip": "^0.4.13", "autoprefixer": "^8.4.1", @@ -43,7 +43,7 @@ "babel-plugin-remove-dead-code": "^1.3.2", "babel-plugin-transform-decorators-legacy": "^1.3.4", "babel-plugin-transform-define": "^1.3.0", - "babel-plugin-transform-jsx-to-stylesheet": "1.3.0", + "babel-plugin-transform-jsx-to-stylesheet": "1.3.7", "babel-plugin-transform-react-jsx": "^6.24.1", "babel-template": "^6.26.0", "babel-traverse": "^6.26.0", @@ -54,14 +54,15 @@ "chokidar": "^2.0.3", "commander": "^2.19.0", "cross-spawn": "^6.0.5", + "crypto": "^1.0.1", "css-to-react-native-transform": "^1.4.0", "ejs": "^2.6.1", "envinfo": "^6.0.1", "eslint": "^4.15.0", - "eslint-config-taro": "1.3.0", + "eslint-config-taro": "1.3.7", "eslint-plugin-import": "^2.8.0", "eslint-plugin-react": "^7.4.0", - "eslint-plugin-taro": "1.3.0", + "eslint-plugin-taro": "1.3.7", "eslint-plugin-typescript": "^0.12.0", "fbjs": "^1.0.0", "fs-extra": "^5.0.0", @@ -83,7 +84,7 @@ "postcss-modules-resolve-imports": "^1.3.0", "postcss-modules-scope": "^1.1.0", "postcss-modules-values": "^1.3.0", - "postcss-pxtransform": "1.3.0", + "postcss-pxtransform": "1.3.7", "postcss-reporter": "^6.0.1", "postcss-taro-unit-transform": "1.2.15", "postcss-url": "^7.3.2", @@ -94,16 +95,17 @@ "semver": "^5.5.0", "shelljs": "^0.8.1", "stylelint": "9.3.0", - "stylelint-config-taro-rn": "1.3.0", - "stylelint-taro-rn": "1.3.0", - "taro-css-to-react-native": "1.3.0", + "stylelint-config-taro-rn": "1.3.7", + "stylelint-taro-rn": "1.3.7", + "taro-css-to-react-native": "1.3.7", "through2": "^2.0.3", "vinyl": "^2.1.0", "vinyl-fs": "^3.0.2", + "xxhashjs": "^0.2.2", "yauzl": "2.10.0" }, "devDependencies": { - "@tarojs/taro": "1.3.0", + "@tarojs/taro": "1.3.7", "@types/autoprefixer": "^9.1.1", "@types/babel-core": "^6.25.5", "@types/babel-generator": "^6.25.2", diff --git a/packages/taro-cli/src/config/manifest.default.json b/packages/taro-cli/src/config/manifest.default.json index 660199e37ebc..34b07c10b7fd 100644 --- a/packages/taro-cli/src/config/manifest.default.json +++ b/packages/taro-cli/src/config/manifest.default.json @@ -10,7 +10,20 @@ { "name": "system.shortcut" }, { "name": "system.fetch" }, { "name": "system.storage" }, - { "name": "system.barcode" } + { "name": "system.barcode" }, + { "name": "system.vibrator" }, + { "name": "system.clipboard" }, + { "name": "system.sensor" }, + { "name": "system.geolocation" }, + { "name": "system.share" }, + { "name": "system.notification" }, + { "name": "system.device" }, + { "name": "system.webview" }, + { "name": "system.request" }, + { "name": "system.audio" }, + { "name": "system.record" }, + { "name": "system.contact" }, + { "name": "system.sms" } ], "permissions": [ { "origin": "*" } diff --git a/packages/taro-cli/src/doctor/abilityXMLValidator.ts b/packages/taro-cli/src/doctor/abilityXMLValidator.ts new file mode 100644 index 000000000000..d620acb15ccc --- /dev/null +++ b/packages/taro-cli/src/doctor/abilityXMLValidator.ts @@ -0,0 +1,34 @@ +import * as _ from 'lodash/fp' +import * as fs from 'fs-extra' +import * as path from 'path' +import chalk from 'chalk' + +import { IErrorLine } from './interface' + +const ABILITYXML = ['ability.xml'] + +export default async function ({ appPath }) { + const PROJECT_PACKAGE_PATH = path.join(appPath, 'package.json') + const PROJECT_FOLDER_FILES = fs.readdirSync('./') + if (!fs.existsSync(PROJECT_PACKAGE_PATH)) { + console.log(chalk.red(`找不到${PROJECT_PACKAGE_PATH},请确定当前目录是Taro项目根目录!`)) + process.exit(1) + } + + const inProjectFolder = filenames => (_.intersectionBy(_.toLower, PROJECT_FOLDER_FILES, filenames)).length > 0 + const hasAbilityXML = inProjectFolder(ABILITYXML) + + const errorLines: IErrorLine[] = [] + + if (!hasAbilityXML) { + errorLines.push({ + desc: '没有检查到 ability.xml, 编写 ability.xml可以让其他应用方便地叫起应用内服务', + valid: true + }) + } + + return { + desc: '检查原子化服务规范', + lines: errorLines + } +} diff --git a/packages/taro-cli/src/h5/index.ts b/packages/taro-cli/src/h5/index.ts index dc695135b52a..95f6bcbdb20a 100644 --- a/packages/taro-cli/src/h5/index.ts +++ b/packages/taro-cli/src/h5/index.ts @@ -7,20 +7,11 @@ import generate from 'better-babel-generator' import * as chokidar from 'chokidar' import * as fs from 'fs-extra' import * as klaw from 'klaw' -import { findLastIndex, merge } from 'lodash' +import { findLastIndex, mapValues, merge } from 'lodash' import * as path from 'path' import CONFIG from '../config' -import { - isAliasPath, - isNpmPkg, - mergeVisitors, - printLog, - promoteRelativePath, - recursiveMerge, - replaceAliasPath, - resolveScriptPath -} from '../util' +import { isNpmPkg, mergeVisitors, printLog, promoteRelativePath, recursiveMerge, resolveScriptPath } from '../util' import { convertAstExpressionToVariable as toVar, convertObjectToAstExpression as objToAst, @@ -71,7 +62,6 @@ class Compiler { entryFilePath: string entryFileName: string pxTransformConfig - pathAlias pages: string[] = [] constructor (appPath) { @@ -101,7 +91,6 @@ class Compiler { this.tempPath = path.join(appPath, this.tempDir) this.entryFilePath = resolveScriptPath(path.join(this.sourcePath, CONFIG.ENTRY)) this.entryFileName = path.basename(this.entryFilePath) - this.pathAlias = projectConfig.alias || {} this.pxTransformConfig = { designWidth: projectConfig.designWidth || 750 } if (projectConfig.hasOwnProperty(deviceRatioConfigName)) { this.pxTransformConfig.deviceRatio = projectConfig.deviceRatio @@ -179,6 +168,7 @@ class Compiler { const h5Config = this.h5Config const outputDir = this.outputDir const sourceRoot = this.sourceRoot + const sourcePath = this.sourcePath const tempPath = this.tempPath const entryFile = path.basename(entryFileName, path.extname(entryFileName)) + '.js' @@ -189,7 +179,19 @@ class Compiler { if (projectConfig.env) { h5Config.env = projectConfig.env } + + const convertAlias = (filePath: string) => { + const isAbsolute = path.isAbsolute(filePath) + if (!isAbsolute) return filePath + + const relPath = path.relative(sourcePath, filePath) + return relPath.startsWith('..') + ? filePath + : path.resolve(this.tempPath, relPath) + } + recursiveMerge(h5Config, { + alias: mapValues(projectConfig.alias, convertAlias), copy: projectConfig.copy, defineConstants: projectConfig.defineConstants, designWidth: projectConfig.designWidth, @@ -232,8 +234,9 @@ class Compiler { .on('unlink', filePath => { const relativePath = path.relative(appPath, filePath) const extname = path.extname(relativePath) + const distDirname = this.getTempDir(filePath) const isScriptFile = REG_SCRIPTS.test(extname) - const dist = this.getDist(filePath, isScriptFile) + const dist = this.getDist(distDirname, filePath, isScriptFile) printLog(processTypeEnum.UNLINK, '删除文件', relativePath) fs.unlinkSync(dist) }) @@ -244,7 +247,6 @@ class Compiler { const routerMode = this.routerMode const routerBasename = this.routerBasename const customRoutes = this.customRoutes - const pathAlias = this.pathAlias const pxTransformConfig = this.pxTransformConfig let ast = wxTransformer({ @@ -267,7 +269,6 @@ class Compiler { let hasComponentDidShow = false let hasComponentDidHide = false let hasComponentWillUnmount = false - let hasJSX = false let hasNerv = false let stateNode: t.ClassProperty @@ -542,6 +543,7 @@ class Compiler { } } + // require('fs').writeFileSync('./ast.json', JSON.stringify(ast, null, 2)) traverse(ast, { ClassExpression: ClassDeclarationOrExpression, ClassDeclaration: ClassDeclarationOrExpression, @@ -564,10 +566,7 @@ class Compiler { const node = astPath.node const source = node.source const specifiers = node.specifiers - let value = source.value - if (isAliasPath(value, pathAlias)) { - source.value = value = replaceAliasPath(filePath, value, pathAlias) - } + const value = source.value if (!isNpmPkg(value)) { if (value.indexOf('.') === 0) { const pathArr = value.split('/') @@ -669,11 +668,6 @@ class Compiler { } } }, - JSXElement: { - enter (astPath: NodePath) { - hasJSX = true - } - }, JSXOpeningElement: { enter (astPath: NodePath) { const node = astPath.node @@ -709,10 +703,10 @@ class Compiler { createHistoryNode, mountApisNode ] - astPath.traverse(programExitVisitor) - if (hasJSX && !hasNerv) { + /* Taro.render() 会被移除,导致hasJSX判断错误 */ + if (!hasNerv) { extraNodes.unshift( t.importDeclaration( [t.importDefaultSpecifier(t.identifier(nervJsImportDefaultName))], @@ -744,8 +738,6 @@ class Compiler { } processOthers (code, filePath, fileType) { - const pathAlias = this.pathAlias - const componentnameMap = new Map() const taroapiMap = new Map() const isPage = fileType === FILE_TYPE.PAGE @@ -848,11 +840,8 @@ class Compiler { enter (astPath: NodePath) { const node = astPath.node const source = node.source - let value = source.value + const value = source.value const specifiers = node.specifiers - if (isAliasPath(value, pathAlias)) { - source.value = value = replaceAliasPath(filePath, value, pathAlias) - } if (!isNpmPkg(value)) { if (REG_SCRIPTS.test(value) || path.extname(value) === '') { const absolutePath = path.resolve(filePath, '..', value) @@ -887,9 +876,13 @@ class Compiler { } } }, + JSXElement: { + exit (astPath: NodePath) { + hasJSX = true + } + }, JSXOpeningElement: { exit (astPath: NodePath) { - hasJSX = true const node = astPath.node const componentName = componentnameMap.get(toVar(node.name)) const componentId = getComponentId(componentName, node) @@ -1143,16 +1136,23 @@ class Compiler { } } - processFiles (filePath) { - const sourceRoot = this.sourceRoot + getTempDir (filePath) { + const appPath = this.appPath + const sourcePath = this.sourcePath const tempDir = this.tempDir - const file = fs.readFileSync(filePath) const dirname = path.dirname(filePath) + const relPath = path.relative(sourcePath, dirname) + + return path.resolve(appPath, tempDir, relPath) + } + + processFiles (filePath) { + const file = fs.readFileSync(filePath) const extname = path.extname(filePath) - const distDirname = dirname.replace(sourceRoot, tempDir) + const distDirname = this.getTempDir(filePath) const isScriptFile = REG_SCRIPTS.test(extname) - const distPath = this.getDist(filePath, isScriptFile) + const distPath = this.getDist(distDirname, filePath, isScriptFile) try { if (isScriptFile) { @@ -1179,12 +1179,7 @@ class Compiler { } } - getDist (filename, isScriptFile) { - const sourceRoot = this.sourceRoot - const tempDir = this.tempDir - - const dirname = path.dirname(filename) - const distDirname = dirname.replace(sourceRoot, tempDir) + getDist (distDirname, filename, isScriptFile) { return isScriptFile ? path.format({ dir: distDirname, diff --git a/packages/taro-cli/src/mini/astProcess.ts b/packages/taro-cli/src/mini/astProcess.ts index 5ca3fe71235d..9a281f676619 100644 --- a/packages/taro-cli/src/mini/astProcess.ts +++ b/packages/taro-cli/src/mini/astProcess.ts @@ -7,6 +7,7 @@ import generate from 'babel-generator' import traverse, { NodePath } from 'babel-traverse' import * as _ from 'lodash' import { Config as IConfig } from '@tarojs/taro' +import getHashName from '../util/hash' const template = require('babel-template') @@ -36,7 +37,7 @@ import { isAliasPath, replaceAliasPath, traverseObjectNode, - isQuickAppPkg, + isQuickappPkg, getBabelConfig } from '../util' import { @@ -96,8 +97,10 @@ function analyzeImportUrl ({ npmOutputDir, sourceDir, outputDir, - npmConfig + npmConfig, + projectConfig } = getBuildData() + const publicPath = (projectConfig.weapp || ({} as any)).publicPath if (value.indexOf('.') === 0) { let importPath = path.resolve(path.dirname(sourceFilePath), value) importPath = resolveScriptPath(importPath) @@ -159,8 +162,11 @@ function analyzeImportUrl ({ showPath = vpath.replace(nodeModulesPath, `/${npmConfig.name}`) } else { showPath = vpath.replace(sourceDir, '') + if (publicPath) { + const hashName = getHashName(vpath) + showPath = (/\/$/.test(publicPath) ? publicPath : publicPath + '/') + hashName + } } - if (defaultSpecifier) { astPath.replaceWith(t.variableDeclaration('const', [t.variableDeclarator(t.identifier(defaultSpecifier), t.stringLiteral(showPath.replace(/\\/g, '/')))])) } else { @@ -243,9 +249,11 @@ export function parseAst ( isProduction, npmConfig, alias: pathAlias, - compileInclude, - projectConfig + compileConfig, + projectConfig, + quickappManifest } = getBuildData() + const publicPath = (projectConfig.weapp || {} as any).publicPath const notExistNpmList = getNotExistNpmList() const taroMiniAppFramework = `@tarojs/taro-${buildAdapter}` let configObj: IConfig = {} @@ -435,7 +443,8 @@ export function parseAst ( value = replaceAliasPath(sourceFilePath, value, pathAlias) source.value = value } - if (isNpmPkg(value) && !isQuickAppPkg(value) && !notExistNpmList.has(value)) { + const quickappPkgs = quickappManifest ? quickappManifest.features : [] + if (isNpmPkg(value) && !isQuickappPkg(value, quickappPkgs) && !notExistNpmList.has(value)) { if (value === taroJsComponents) { if (isQuickApp) { specifiers.forEach(specifier => { @@ -445,7 +454,9 @@ export function parseAst ( } }) } - taroSelfComponents.add('taro-page') + if (type === PARSE_AST_TYPE.PAGE) { + taroSelfComponents.add('taro-page') + } astPath.remove() } else { let isDepComponent = false @@ -491,10 +502,11 @@ export function parseAst ( buildAdapter, root: appPath, npmOutputDir, - compileInclude, + compileConfig, env: projectConfig.env || {}, uglify: projectConfig!.plugins!.uglify || { enable: true }, - babelConfig: getBabelConfig(projectConfig!.plugins!.babel) || {} + babelConfig: getBabelConfig(projectConfig!.plugins!.babel) || {}, + quickappManifest }) } else { source.value = value @@ -535,7 +547,8 @@ export function parseAst ( value = replaceAliasPath(sourceFilePath, value, pathAlias) args[0].value = value } - if (isNpmPkg(value) && !isQuickAppPkg(value) && !notExistNpmList.has(value)) { + const quickappPkgs = quickappManifest ? quickappManifest.features : [] + if (isNpmPkg(value) && !isQuickappPkg(value, quickappPkgs) && !notExistNpmList.has(value)) { if (value === taroJsComponents) { if (isQuickApp) { if (parentNode.declarations.length === 1 && parentNode.declarations[0].init) { @@ -597,10 +610,11 @@ export function parseAst ( buildAdapter, root: appPath, npmOutputDir, - compileInclude, + compileConfig, env: projectConfig.env || {}, uglify: projectConfig!.plugins!.uglify || { enable: true }, - babelConfig: getBabelConfig(projectConfig!.plugins!.babel) || {} + babelConfig: getBabelConfig(projectConfig!.plugins!.babel) || {}, + quickappManifest }) } else { args[0].value = value @@ -840,6 +854,10 @@ export function parseAst ( showPath = vpath.replace(nodeModulesPath, `/${npmConfig.name}`) } else { showPath = vpath.replace(sourceDir, '') + if (publicPath) { + const hashName = getHashName(vpath) + showPath = (/\/$/.test(publicPath) ? publicPath : publicPath + '/') + hashName + } } astPath.replaceWith(t.stringLiteral(showPath.replace(/\\/g, '/'))) } else { @@ -893,10 +911,11 @@ export function parseAst ( buildAdapter, root: appPath, npmOutputDir, - compileInclude, + compileConfig, env: projectConfig.env || {}, uglify: projectConfig!.plugins!.uglify || { enable: true }, - babelConfig: getBabelConfig(projectConfig!.plugins!.babel) || {} + babelConfig: getBabelConfig(projectConfig!.plugins!.babel) || {}, + quickappManifest }) : taroMiniAppFramework switch (type) { case PARSE_AST_TYPE.ENTRY: diff --git a/packages/taro-cli/src/mini/compileScript.ts b/packages/taro-cli/src/mini/compileScript.ts index 463647732320..64a76a1ff8f9 100644 --- a/packages/taro-cli/src/mini/compileScript.ts +++ b/packages/taro-cli/src/mini/compileScript.ts @@ -60,7 +60,7 @@ export function compileDepScripts (scriptFiles: string[], needUseBabel?: boolean } const weappConf = Object.assign({}, projectConfig.weapp) const useCompileConf = Object.assign({}, weappConf.compile) - const compileExclude = useCompileConf.exclude || [] + const compileExclude = (useCompileConf.exclude || []).filter(item => !/(?:\/|^)node_modules(\/|$)/.test(item)) let isInCompileExclude = false compileExclude.forEach(excludeItem => { if (item.indexOf(path.join(appPath, excludeItem)) >= 0) { diff --git a/packages/taro-cli/src/mini/compileStyle.ts b/packages/taro-cli/src/mini/compileStyle.ts index 6aaf54543536..d500f1f6e6c4 100644 --- a/packages/taro-cli/src/mini/compileStyle.ts +++ b/packages/taro-cli/src/mini/compileStyle.ts @@ -4,7 +4,7 @@ import * as path from 'path' import * as autoprefixer from 'autoprefixer' import * as postcss from 'postcss' import * as pxtransform from 'postcss-pxtransform' - +import getHashName from '../util/hash' import browserList from '../config/browser_list' import { resolveNpmPkgMainPath, @@ -107,6 +107,7 @@ export function processStyleUseCssModule (styleObj: IStyleObj): any { async function processStyleWithPostCSS (styleObj: IStyleObj): Promise { const { appPath, projectConfig, npmConfig, isProduction, buildAdapter } = getBuildData() const weappConf = Object.assign({}, projectConfig.weapp) + const publicPath = weappConf.publicPath const useModuleConf = weappConf.module || {} const customPostcssConf = useModuleConf.postcss || {} const customCssModulesConf = Object.assign({ @@ -119,12 +120,13 @@ async function processStyleWithPostCSS (styleObj: IStyleObj): Promise { enable: true, config: {} }, customPostcssConf.pxtransform || {}) - const customUrlConf = Object.assign({ + const customUrlConf = { enable: true, config: { limit: 10240 - } - }, customPostcssConf.url || {}) + } as any, + ...customPostcssConf.url + } const customAutoprefixerConf = Object.assign({ enable: true, config: { @@ -139,8 +141,8 @@ async function processStyleWithPostCSS (styleObj: IStyleObj): Promise { if (projectConfig.hasOwnProperty(DEVICE_RATIO_NAME)) { postcssPxtransformOption[DEVICE_RATIO_NAME] = projectConfig.deviceRatio } - const cssUrlConf = Object.assign({ limit: 10240 }, customUrlConf) - const maxSize = Math.round((customUrlConf.config.limit || cssUrlConf.limit) / 1024) + + const maxSize = (customUrlConf.config.limit || 1024) / 1024 const postcssPxtransformConf = Object.assign({}, postcssPxtransformOption, customPxtransformConf, customPxtransformConf.config) const processors: any[] = [] if (customAutoprefixerConf.enable) { @@ -149,15 +151,32 @@ async function processStyleWithPostCSS (styleObj: IStyleObj): Promise { if (customPxtransformConf.enable && buildAdapter !== BUILD_TYPES.QUICKAPP) { processors.push(pxtransform(postcssPxtransformConf)) } - if (cssUrlConf.enable) { + if (customUrlConf.enable) { + let inlineOpts = {} + const url = customUrlConf.config.url || 'inline' + if (url === 'inline' && !publicPath) { + inlineOpts = { + encodeType: 'base64', + maxSize, + url + } + } + + if (publicPath && typeof url !== 'function') { + customUrlConf.config.url = (assets) => { + if (/\./.test(assets.url)) { + const hashName = getHashName(assets.absolutePath) + assets.url = (/\/$/.test(publicPath) ? publicPath : publicPath + '/') + hashName + } + return assets.url + } + } + const cssUrlParseConf = { - url: 'inline', - maxSize, - encodeType: 'base64' + ...inlineOpts, + ...customUrlConf.config } - processors.push(cssUrlParse(cssUrlConf.config.basePath ? Object.assign(cssUrlParseConf, { - basePath: cssUrlConf.config.basePath - }) : cssUrlParseConf)) + processors.push(cssUrlParse(cssUrlParseConf)) } const defaultPostCSSPluginNames = ['autoprefixer', 'pxtransform', 'url', 'cssModules'] @@ -198,11 +217,10 @@ export function compileDepStyles (outputFilePath: string, styleFiles: string[]) if (isBuildingStyles.get(outputFilePath)) { return Promise.resolve({}) } - const { appPath, npmOutputDir, nodeModulesPath, projectConfig, npmConfig, isProduction, buildAdapter } = getBuildData() + const { appPath, npmOutputDir, nodeModulesPath, projectConfig, npmConfig, isProduction, buildAdapter, quickappManifest } = getBuildData() const pluginsConfig = projectConfig.plugins || {} const weappConf = projectConfig.weapp || {} as IMiniAppConfig const useCompileConf = Object.assign({}, weappConf.compile) - const compileInclude = useCompileConf.include || [] isBuildingStyles.set(outputFilePath, true) return Promise.all(styleFiles.map(async p => { const filePath = path.join(p) @@ -221,10 +239,11 @@ export function compileDepStyles (outputFilePath: string, styleFiles: string[]) root: appPath, rootNpm: nodeModulesPath, npmOutputDir, - compileInclude, + compileConfig: useCompileConf, env: projectConfig.env || {}, uglify: projectConfig!.plugins!.uglify || { enable: true }, - babelConfig: getBabelConfig(projectConfig!.plugins!.babel) || {} + babelConfig: getBabelConfig(projectConfig!.plugins!.babel) || {}, + quickappManifest }) const importRelativePath = promoteRelativePath(path.relative(filePath, npmInfo.main)) return str.replace(stylePath, importRelativePath) @@ -256,13 +275,15 @@ export function compileDepStyles (outputFilePath: string, styleFiles: string[]) await Promise.all(resList.map(res => processStyleWithPostCSS(res))) .then(cssList => { let resContent = cssList.map(res => res).join('\n') + // 非生产模式下用户 csso 配置不存在则默认 csso 为禁用 + let cssoPuginConfig = pluginsConfig.csso || { enable: false } if (isProduction) { - const cssoPuginConfig = pluginsConfig.csso || { enable: true } - if (cssoPuginConfig.enable) { - const cssoConfig = cssoPuginConfig.config || {} - const cssoResult = callPluginSync('csso', resContent, outputFilePath, cssoConfig, appPath) - resContent = cssoResult.css - } + cssoPuginConfig = pluginsConfig.csso || { enable: true } + } + if (cssoPuginConfig.enable) { + const cssoConfig = cssoPuginConfig.config || {} + const cssoResult = callPluginSync('csso', resContent, outputFilePath, cssoConfig, appPath) + resContent = cssoResult.css } fs.ensureDirSync(path.dirname(outputFilePath)) fs.writeFileSync(outputFilePath, resContent) diff --git a/packages/taro-cli/src/mini/component.ts b/packages/taro-cli/src/mini/component.ts index 7bec920dbb54..79b982430054 100644 --- a/packages/taro-cli/src/mini/component.ts +++ b/packages/taro-cli/src/mini/component.ts @@ -60,7 +60,8 @@ export function isFileToBeTaroComponent ( buildAdapter, sourceDir, constantsReplaceList, - jsxAttributeNameReplace + jsxAttributeNameReplace, + alias } = getBuildData() const transformResult: IWxTransformResult = wxTransformer({ code, @@ -71,7 +72,8 @@ export function isFileToBeTaroComponent ( isTyped: REG_TYPESCRIPT.test(sourcePath), adapter: buildAdapter, env: constantsReplaceList, - jsxAttributeNameReplace + jsxAttributeNameReplace, + alias }) const { ast }: IWxTransformResult = transformResult let isTaroComponent = false @@ -143,7 +145,8 @@ export async function buildSingleComponent ( outputFilesTypes, isProduction, jsxAttributeNameReplace, - projectConfig + projectConfig, + alias } = getBuildData() const isQuickApp = buildAdapter === BUILD_TYPES.QUICKAPP @@ -231,7 +234,8 @@ export async function buildSingleComponent ( isNormal: false, adapter: buildAdapter, env: constantsReplaceList, - jsxAttributeNameReplace + jsxAttributeNameReplace, + alias }) const componentWXMLContent = isProduction ? transformResult.compressedTemplate : transformResult.template const componentDepComponents = transformResult.components @@ -254,6 +258,9 @@ export async function buildSingleComponent ( }) transfromNativeComponents(outputComponentJSONPath.replace(buildConfig.outputDir || buildOutputDir, sourceDirPath), res.configObj) } + let realComponentsPathList: IComponentObj[] = [] + realComponentsPathList = getRealComponentsPathList(component, componentDepComponents) + if (!isQuickApp) { resCode = await compileScriptFile(resCode, component, outputComponentJSPath, buildAdapter) if (isProduction) { @@ -262,11 +269,16 @@ export async function buildSingleComponent ( } else { // 快应用编译,搜集创建组件 ux 文件 const importTaroSelfComponents = getImportTaroSelfComponents(outputComponentJSPath, res.taroSelfComponents) - const importCustomComponents = new Set(componentDepComponents.map(item => { - delete item.type - return item + const importCustomComponents = new Set(realComponentsPathList.map(item => { + return { + path: path.relative(path.dirname(component), item.path as string).replace(path.extname(item.path as string), ''), + name: item.name as string + } })) - const styleRelativePath = promoteRelativePath(path.relative(outputComponentJSPath, outputComponentWXSSPath)) + let styleRelativePath + if (res.styleFiles.length) { + styleRelativePath = promoteRelativePath(path.relative(outputComponentJSPath, outputComponentWXSSPath)) + } const uxTxt = generateQuickAppUx({ script: resCode, style: styleRelativePath, @@ -285,9 +297,7 @@ export async function buildSingleComponent ( media: [] } // 编译依赖的组件文件 - let realComponentsPathList: IComponentObj[] = [] - if (componentDepComponents.length) { - realComponentsPathList = getRealComponentsPathList(component, componentDepComponents) + if (realComponentsPathList.length) { res.scriptFiles = res.scriptFiles.map(item => { for (let i = 0; i < realComponentsPathList.length; i++) { const componentObj = realComponentsPathList[i] diff --git a/packages/taro-cli/src/mini/constants.ts b/packages/taro-cli/src/mini/constants.ts index 829b14276110..572b8a827ed4 100644 --- a/packages/taro-cli/src/mini/constants.ts +++ b/packages/taro-cli/src/mini/constants.ts @@ -1,5 +1,6 @@ export const QUICKAPP_SPECIAL_COMPONENTS = new Set([ 'View', - 'Text' + 'Text', + 'Block' ]) diff --git a/packages/taro-cli/src/mini/entry.ts b/packages/taro-cli/src/mini/entry.ts index 07b951e09e39..980b85508757 100644 --- a/packages/taro-cli/src/mini/entry.ts +++ b/packages/taro-cli/src/mini/entry.ts @@ -121,6 +121,25 @@ export async function buildEntry (): Promise { resCode = uglifyJS(resCode, entryFilePath, appPath, projectConfig!.plugins!.uglify as TogglableOptions) } } + // 处理res.configObj 中的tabBar配置 + const tabBar = res.configObj.tabBar + if (tabBar && typeof tabBar === 'object' && !isEmptyObject(tabBar)) { + const { + list: listConfig, + iconPath: pathConfig, + selectedIconPath: selectedPathConfig + } = CONFIG_MAP[buildAdapter] + const list = tabBar[listConfig] || [] + let tabBarIcons: string[] = [] + list.forEach(item => { + item[pathConfig] && tabBarIcons.push(item[pathConfig]) + item[selectedPathConfig] && tabBarIcons.push(item[selectedPathConfig]) + }) + tabBarIcons = tabBarIcons.map(item => path.resolve(sourceDir, item)) + if (tabBarIcons && tabBarIcons.length) { + res.mediaFiles = res.mediaFiles.concat(tabBarIcons) + } + } if (buildAdapter === BUILD_TYPES.QUICKAPP) { // 生成 快应用 ux 文件 const styleRelativePath = promoteRelativePath(path.relative(outputEntryFilePath, path.join(outputDir, `app${outputFilesTypes.STYLE}`))) @@ -137,25 +156,6 @@ export async function buildEntry (): Promise { if (res.configObj.tabBar && res.configObj.tabBar.custom) { await buildCustomTabbar() } - // 处理res.configObj 中的tabBar配置 - const tabBar = res.configObj.tabBar - if (tabBar && typeof tabBar === 'object' && !isEmptyObject(tabBar)) { - const { - list: listConfig, - iconPath: pathConfig, - selectedIconPath: selectedPathConfig - } = CONFIG_MAP[buildAdapter] - const list = tabBar[listConfig] || [] - let tabBarIcons: string[] = [] - list.forEach(item => { - item[pathConfig] && tabBarIcons.push(item[pathConfig]) - item[selectedPathConfig] && tabBarIcons.push(item[selectedPathConfig]) - }) - tabBarIcons = tabBarIcons.map(item => path.resolve(sourceDir, item)) - if (tabBarIcons && tabBarIcons.length) { - res.mediaFiles = res.mediaFiles.concat(tabBarIcons) - } - } if (appOutput) { fs.writeFileSync(path.join(outputDir, 'app.json'), JSON.stringify(res.configObj, null, 2)) printLog(processTypeEnum.GENERATE, '入口配置', `${outputDirName}/app.json`) diff --git a/packages/taro-cli/src/mini/helper.ts b/packages/taro-cli/src/mini/helper.ts index bbe553cbcd20..271dc6fb4f70 100644 --- a/packages/taro-cli/src/mini/helper.ts +++ b/packages/taro-cli/src/mini/helper.ts @@ -4,6 +4,7 @@ import * as path from 'path' import * as _ from 'lodash' import { Config } from '@tarojs/taro' import * as wxTransformer from '@tarojs/transformer-wx' +import getHashName from '../util/hash' import { BUILD_TYPES, @@ -36,7 +37,8 @@ import { IProjectConfig, IOption, INpmConfig, - IWxTransformResult + IWxTransformResult, + ITaroManifestConfig } from '../util/types' import CONFIG from '../config' @@ -69,7 +71,7 @@ export interface IBuildData { appConfig: Config, pageConfigs: Map, alias: IOption, - compileInclude: string[], + compileConfig: {[k: string]: any}, isProduction: boolean, buildAdapter: BUILD_TYPES, outputFilesTypes: IMINI_APP_FILE_TYPE, @@ -78,7 +80,8 @@ export interface IBuildData { npmOutputDir: string, jsxAttributeNameReplace?: { [key: string]: any - } + }, + quickappManifest?: ITaroManifestConfig } let BuildData: IBuildData @@ -100,6 +103,10 @@ export function setIsProduction (isProduction: boolean) { BuildData.isProduction = isProduction } +export function setQuickappManifest (quickappManifest: ITaroManifestConfig) { + BuildData.quickappManifest = quickappManifest +} + export function setBuildData (appPath: string, adapter: BUILD_TYPES): IBuildData { const configDir = path.join(appPath, PROJECT_CONFIG) const projectConfig = require(configDir)(_.merge) @@ -117,7 +124,6 @@ export function setBuildData (appPath: string, adapter: BUILD_TYPES): IBuildData dir: null }, weappConf.npm) const useCompileConf = Object.assign({}, weappConf.compile) - const compileInclude = useCompileConf.include || [] BuildData = { appPath, configDir, @@ -134,7 +140,7 @@ export function setBuildData (appPath: string, adapter: BUILD_TYPES): IBuildData isProduction: false, appConfig: {}, pageConfigs: new Map(), - compileInclude, + compileConfig: useCompileConf, buildAdapter: adapter, outputFilesTypes: MINI_APP_FILES[adapter], constantsReplaceList: Object.assign({}, generateEnvList(projectConfig.env || {}), generateConstantsList(projectConfig.defineConstants || {}), { @@ -233,7 +239,7 @@ export function getRealComponentsPathList ( ): IComponentObj[] { const { appPath, isProduction, buildAdapter, projectConfig, npmConfig } = BuildData const pathAlias = projectConfig.alias || {} - return components.map(component => { + return components.length ? components.map(component => { let componentPath = component.path if (isAliasPath(componentPath as string, pathAlias)) { componentPath = replaceAliasPath(filePath, componentPath as string, pathAlias) @@ -256,7 +262,7 @@ export function getRealComponentsPathList ( name: component.name, type: component.type } - }) + }) : [] } export function isFileToBePage (filePath: string): boolean { @@ -295,13 +301,20 @@ export function initCopyFiles () { } export function copyFilesFromSrcToOutput (files: string[], cb?: (sourceFilePath: string, outputFilePath: string) => void) { - const { nodeModulesPath, npmOutputDir, sourceDir, outputDir, appPath } = BuildData + const { nodeModulesPath, npmOutputDir, sourceDir, outputDir, appPath, projectConfig } = BuildData + const adapterConfig = Object.assign({}, projectConfig.weapp) files.forEach(file => { let outputFilePath if (NODE_MODULES_REG.test(file)) { outputFilePath = file.replace(nodeModulesPath, npmOutputDir) } else { - outputFilePath = file.replace(sourceDir, outputDir) + if (adapterConfig.publicPath && adapterConfig.staticDirectory) { + const hashName = getHashName(file) + const staticPath = path.join(appPath, adapterConfig.staticDirectory, projectConfig.projectName || '') + outputFilePath = `${staticPath}/${hashName}` + } else { + outputFilePath = file.replace(sourceDir, outputDir) + } } if (isCopyingFiles.get(outputFilePath)) { return diff --git a/packages/taro-cli/src/mini/index.ts b/packages/taro-cli/src/mini/index.ts index d77e869acbd3..2c03a6a258bb 100644 --- a/packages/taro-cli/src/mini/index.ts +++ b/packages/taro-cli/src/mini/index.ts @@ -4,8 +4,7 @@ import * as path from 'path' import chalk from 'chalk' import * as _ from 'lodash' import * as ora from 'ora' -import { exec } from 'child_process' -import * as resolvePath from 'resolve' +import { execSync } from 'child_process' import { printLog, @@ -18,14 +17,15 @@ import { } from '../util' import { processTypeEnum, BUILD_TYPES } from '../util/constants' import { IMiniAppBuildConfig } from '../util/types' -import defaultManifestJSON from '../config/manifest.default.json' +import * as defaultManifestJSON from '../config/manifest.default.json' import { setBuildData, getBuildData, setIsProduction, setAppConfig, - IBuildData + IBuildData, + setQuickappManifest } from './helper' import { buildEntry } from './entry' import { buildPages } from './page' @@ -88,8 +88,22 @@ async function buildFrameworkInfo () { } } -function generateQuickAppManifest () { - const { appConfig, pageConfigs, appPath, outputDir, projectConfig } = getBuildData() +function readQuickAppManifest () { + const { appPath } = getBuildData() + // 读取 project.quickapp.json + const quickappJSONPath = path.join(appPath, 'project.quickapp.json') + let quickappJSON + if (fs.existsSync(quickappJSONPath)) { + quickappJSON = fs.readJSONSync(quickappJSONPath) + } else { + printLog(processTypeEnum.WARNING, '缺少配置', `检测到项目目录下未添加 ${chalk.bold('project.quickapp.json')} 文件,将使用默认配置,参考文档 https://nervjs.github.io/taro/docs/project-config.html`) + quickappJSON = defaultManifestJSON + } + return quickappJSON +} + +function generateQuickAppManifest (quickappJSON: any) { + const { appConfig, pageConfigs, outputDir, projectConfig } = getBuildData() // 生成 router const pages = (appConfig.pages as string[]).concat() const routerPages = {} @@ -116,14 +130,6 @@ function generateQuickAppManifest () { display.pages[path.dirname(page)] = item } }) - // 读取 project.quickapp.json - const quickappJSONPath = path.join(appPath, 'project.quickapp.json') - let quickappJSON - if (fs.existsSync(quickappJSONPath)) { - quickappJSON = fs.readJSONSync(quickappJSONPath) - } else { - quickappJSON = defaultManifestJSON - } quickappJSON.router = router quickappJSON.display = display quickappJSON.config = Object.assign({}, quickappJSON.config, { @@ -151,9 +157,8 @@ async function prepareQuickAppEnvironment (buildData: IBuildData) { } else { console.log(`${chalk.green('✔ ')} 快应用容器已经准备好`) } - - console.log() process.chdir(originalOutputDir) + console.log() if (fs.existsSync(path.join(originalOutputDir, 'node_modules'))) { needInstall = false } else { @@ -169,20 +174,18 @@ async function prepareQuickAppEnvironment (buildData: IBuildData) { command = 'NODE_ENV=development npm install' } const installSpinner = ora(`安装快应用依赖环境, 需要一会儿...`).start() - const install = exec(command) - install.on('close', code => { - if (code === 0) { - installSpinner.color = 'green' - installSpinner.succeed('安装成功') - console.log(`${install.stderr.read()}${install.stdout.read()}`) - isReady = true - } else { - installSpinner.color = 'red' - installSpinner.fail(chalk.red(`快应用依赖环境安装失败,请进入 ${path.basename(originalOutputDir)} 重新安装!`)) - console.log(`${install.stderr.read()}${install.stdout.read()}`) - isReady = false - } - }) + try { + const stdout = execSync(command) + installSpinner.color = 'green' + installSpinner.succeed('安装成功') + console.log(`${stdout}`) + isReady = true + } catch (error) { + installSpinner.color = 'red' + installSpinner.fail(chalk.red(`快应用依赖环境安装失败,请进入 ${path.basename(originalOutputDir)} 重新安装!`)) + console.log(`${error}`) + isReady = false + } } else { console.log(`${chalk.green('✔ ')} 快应用依赖已经安装好`) isReady = true @@ -192,11 +195,9 @@ async function prepareQuickAppEnvironment (buildData: IBuildData) { async function runQuickApp (isWatch: boolean | void, buildData: IBuildData, port?: number, release?: boolean) { const originalOutputDir = buildData.originalOutputDir - const hapToolkitPath = resolvePath.sync('hap-toolkit/package.json', { basedir: originalOutputDir }) - const hapToolkitLib = path.join(path.dirname(hapToolkitPath), 'lib') - const compile = require(path.join(hapToolkitLib, 'commands/compile')) + const { compile } = require(require.resolve('hap-toolkit/lib/commands/compile', { paths: [originalOutputDir] })) if (isWatch) { - const launchServer = require(path.join(hapToolkitLib, 'server')) + const { launchServer } = require(require.resolve('@hap-toolkit/server', { paths: [originalOutputDir] })) launchServer({ port: port || 12306, watch: isWatch, @@ -216,6 +217,7 @@ async function runQuickApp (isWatch: boolean | void, buildData: IBuildData, port export async function build (appPath: string, { watch, adapter = BUILD_TYPES.WEAPP, envHasBeenSet = false, port, release }: IMiniAppBuildConfig) { const buildData = setBuildData(appPath, adapter) const isQuickApp = adapter === BUILD_TYPES.QUICKAPP + let quickappJSON process.env.TARO_ENV = adapter if (!envHasBeenSet) { setIsProduction(process.env.NODE_ENV === 'production' || !watch) @@ -224,6 +226,9 @@ export async function build (appPath: string, { watch, adapter = BUILD_TYPES.WEA if (!isQuickApp) { buildProjectConfig() await buildFrameworkInfo() + } else { + quickappJSON = readQuickAppManifest() + setQuickappManifest(quickappJSON) } copyFiles(appPath, buildData.projectConfig.copy) const appConfig = await buildEntry() @@ -233,7 +238,7 @@ export async function build (appPath: string, { watch, adapter = BUILD_TYPES.WEA watchFiles() } if (isQuickApp) { - generateQuickAppManifest() + generateQuickAppManifest(quickappJSON) const isReady = await prepareQuickAppEnvironment(buildData) if (!isReady) { console.log() diff --git a/packages/taro-cli/src/mini/page.ts b/packages/taro-cli/src/mini/page.ts index 1f39d2c563d2..5b7a105c52a9 100644 --- a/packages/taro-cli/src/mini/page.ts +++ b/packages/taro-cli/src/mini/page.ts @@ -59,7 +59,8 @@ export async function buildSinglePage (page: string) { jsxAttributeNameReplace, pageConfigs, appConfig, - projectConfig + projectConfig, + alias } = getBuildData() const pagePath = path.join(sourceDir, `${page}`) const pageJs = resolveScriptPath(pagePath) @@ -107,7 +108,8 @@ export async function buildSinglePage (page: string) { isRoot: true, isTyped: REG_TYPESCRIPT.test(pageJs), adapter: buildAdapter, - env: constantsReplaceList + env: constantsReplaceList, + alias }) const res = parseAst(PARSE_AST_TYPE.PAGE, aheadTransformResult.ast, [], pageJs, outputPageJSPath) if (res.configObj.enablePullDownRefresh || (appConfig.window && appConfig.window.enablePullDownRefresh)) { @@ -131,7 +133,8 @@ export async function buildSinglePage (page: string) { adapter: buildAdapter, env: constantsReplaceList, rootProps, - jsxAttributeNameReplace + jsxAttributeNameReplace, + alias }) const pageDepComponents = transformResult.components const pageWXMLContent = isProduction ? transformResult.compressedTemplate : transformResult.template @@ -153,6 +156,9 @@ export async function buildSinglePage (page: string) { transfromNativeComponents(outputPageJSONPath.replace(outputDir, sourceDir), res.configObj) } + let realComponentsPathList: IComponentObj[] = [] + realComponentsPathList = getRealComponentsPathList(pageJs, pageDepComponents) + if (!isQuickApp) { resCode = await compileScriptFile(resCode, pageJs, outputPageJSPath, buildAdapter) if (isProduction) { @@ -161,12 +167,17 @@ export async function buildSinglePage (page: string) { } else { // 快应用编译,搜集创建页面 ux 文件 const importTaroSelfComponents = getImportTaroSelfComponents(outputPageJSPath, res.taroSelfComponents) - const importCustomComponents = new Set(pageDepComponents.map(item => { - delete item.type - return item + const importCustomComponents = new Set(realComponentsPathList.map(item => { + return { + path: path.relative(path.dirname(pageJs), item.path as string).replace(path.extname(item.path as string), ''), + name: item.name as string + } })) // 生成页面 ux 文件 - const styleRelativePath = promoteRelativePath(path.relative(outputPageJSPath, outputPageWXSSPath)) + let styleRelativePath + if (res.styleFiles.length) { + styleRelativePath = promoteRelativePath(path.relative(outputPageJSPath, outputPageWXSSPath)) + } const uxTxt = generateQuickAppUx({ script: resCode, style: styleRelativePath, @@ -177,9 +188,7 @@ export async function buildSinglePage (page: string) { printLog(processTypeEnum.GENERATE, '页面文件', `${outputDirName}/${page}${outputFilesTypes.TEMPL}`) } // 编译依赖的组件文件 - let realComponentsPathList: IComponentObj[] = [] - if (pageDepComponents.length) { - realComponentsPathList = getRealComponentsPathList(pageJs, pageDepComponents) + if (realComponentsPathList.length) { res.scriptFiles = res.scriptFiles.map(item => { for (let i = 0; i < realComponentsPathList.length; i++) { const componentObj = realComponentsPathList[i] diff --git a/packages/taro-cli/src/util/astConvert.ts b/packages/taro-cli/src/util/astConvert.ts index 8aee0493b42f..12ef0ac07247 100644 --- a/packages/taro-cli/src/util/astConvert.ts +++ b/packages/taro-cli/src/util/astConvert.ts @@ -20,6 +20,9 @@ export function convertObjectToAstExpression (obj: object): t.ObjectProperty[] { if (Array.isArray(value)) { return t.objectProperty(t.stringLiteral(key), t.arrayExpression(convertArrayToAstExpression(value as []))) } + if (value === null) { + return t.objectProperty(t.stringLiteral(key), t.nullLiteral()) + } if (typeof value === 'object') { return t.objectProperty(t.stringLiteral(key), t.objectExpression(convertObjectToAstExpression(value))) } diff --git a/packages/taro-cli/src/util/constants.ts b/packages/taro-cli/src/util/constants.ts index d343c2fdff98..65d91e8e06cb 100644 --- a/packages/taro-cli/src/util/constants.ts +++ b/packages/taro-cli/src/util/constants.ts @@ -53,7 +53,7 @@ export const processTypeMap: IProcessTypeMap = { }, [processTypeEnum.WARNING]: { name: '警告', - color: 'yellow' + color: 'yellowBright' }, [processTypeEnum.UNLINK]: { name: '删除', @@ -234,11 +234,11 @@ export const CONFIG_MAP = { navigationBarBackgroundColor: 'titleBarBackgroundColor', navigationBarTextStyle: 'titleBarTextColor', pageOrientation: 'orientation', + list: 'list', + text: 'text', + iconPath: 'iconPath', + selectedIconPath: 'selectedIconPath', backgroundTextStyle: false, - list: false, - text: false, - iconPath: false, - selectedIconPath: false, onReachBottomDistance: false, backgroundColorBottom: false, backgroundColorTop: false, @@ -308,7 +308,6 @@ export const UPDATE_PACKAGE_LIST = [ '@tarojs/mobx-h5', '@tarojs/mobx-rn', '@tarojs/mobx-common', - '@tarojs/mobx-prop-types', 'nervjs', 'nerv-devtools' ] diff --git a/packages/taro-cli/src/util/hash.ts b/packages/taro-cli/src/util/hash.ts new file mode 100644 index 000000000000..891849d87303 --- /dev/null +++ b/packages/taro-cli/src/util/hash.ts @@ -0,0 +1,62 @@ +import crypto from 'crypto' +import * as fs from 'fs-extra' +import * as path from 'path' +import * as xxh from 'xxhashjs' + +const HEXBASE = 16 + +const defaultHashOptions = { + method: 'xxhash32', + shrink: 8, + append: false +} + +const getxxhash = (content, options) => { + const hashFunc = options.method === 'xxhash32' ? xxh.h32 : xxh.h64 + const seed = 0 + + return hashFunc(seed) + .update(content) + .digest() + .toString(HEXBASE) +} + +const getHash = (content, options) => { + if (options.method && typeof options.method === 'function') { + return options.method(content) + } + + if (options.method && options.method.indexOf('xxhash') === 0) { + return getxxhash(content, options) + } + + try { + const hashFunc = crypto.createHash(options.method) + + return hashFunc.update(content) + .digest('hex') + } catch (e) { + return null + } +} + +function hash(content, options) { + + options = options || defaultHashOptions + + let hash = getHash(content, options) + + if (hash == null) { + // bad hash method fallback to defaults + // TODO: warning/error reporting? + hash = getHash(content, defaultHashOptions) + } + + return options.shrink ? hash.substr(0, options.shrink) : hash +} + +export default (file, options? : any) => { + const content = fs.readFileSync(file) + const ext = path.extname(file) + return hash(content, options) + ext +} diff --git a/packages/taro-cli/src/util/index.ts b/packages/taro-cli/src/util/index.ts index 5569d849cd01..c1dac5cce809 100644 --- a/packages/taro-cli/src/util/index.ts +++ b/packages/taro-cli/src/util/index.ts @@ -3,7 +3,7 @@ import * as path from 'path' import * as crypto from 'crypto' import * as os from 'os' import * as child_process from 'child_process' -import * as chalk from 'chalk' +import chalk from 'chalk' import { mergeWith, isPlainObject, camelCase, flatMap } from 'lodash' import * as minimatch from 'minimatch' import * as t from 'babel-types' @@ -495,8 +495,18 @@ export function copyFiles (appPath: string, copyConfig: ICopyOptions | void) { } } -export function isQuickAppPkg (name: string): boolean { - return /@system\./.test(name) +export function isQuickappPkg (name: string, quickappPkgs: any[] = []): boolean { + const isQuickappPkg = /^@[a-zA-Z]{1,}\.[a-zA-Z]{1,}/.test(name) + let hasSetInManifest = false + quickappPkgs.forEach(item => { + if (item.name === name.replace(/^@/, '')) { + hasSetInManifest = true + } + }) + if (isQuickappPkg && !hasSetInManifest) { + printLog(processTypeEnum.ERROR, '快应用', `需要在 ${chalk.bold('project.quickapp.json')} 文件的 ${chalk.bold('features')} 配置中添加 ${chalk.bold(name)}`) + } + return isQuickappPkg } export function generateQuickAppUx ({ diff --git a/packages/taro-cli/src/util/npmExact.ts b/packages/taro-cli/src/util/npmExact.ts index 09fabfa4c8f8..81cd42da31e2 100644 --- a/packages/taro-cli/src/util/npmExact.ts +++ b/packages/taro-cli/src/util/npmExact.ts @@ -1,7 +1,7 @@ import * as path from 'path' import { resolveNpmFilesPath } from './resolve_npm_files' -import { INpmConfig, TogglableOptions } from './types' +import { INpmConfig, TogglableOptions, ITaroManifestConfig } from './types' import { BUILD_TYPES, REG_STYLE, NODE_MODULES, REG_FONT, REG_MEDIA, REG_IMAGE } from './constants' import { promoteRelativePath, recursiveFindNodeModules } from './index' @@ -14,10 +14,11 @@ interface IArgs { buildAdapter: BUILD_TYPES, root: string, npmOutputDir: string, - compileInclude: string[], + compileConfig: {[k: string]: any}, env: object, uglify: TogglableOptions, - babelConfig: object + babelConfig: object, + quickappManifest?: ITaroManifestConfig } const notExistNpmList: Set = new Set() @@ -41,10 +42,11 @@ export function getExactedNpmFilePath ({ buildAdapter, root, npmOutputDir, - compileInclude, + compileConfig, env, uglify, - babelConfig + babelConfig, + quickappManifest }: IArgs) { try { const nodeModulesPath = recursiveFindNodeModules(path.join(root, NODE_MODULES)) @@ -56,10 +58,11 @@ export function getExactedNpmFilePath ({ root, rootNpm: nodeModulesPath, npmOutputDir, - compileInclude, + compileConfig, env, uglify, - babelConfig + babelConfig, + quickappManifest }) const npmInfoMainPath = npmInfo.main let outputNpmPath diff --git a/packages/taro-cli/src/util/resolve_npm_files.ts b/packages/taro-cli/src/util/resolve_npm_files.ts index 0d9e662c1f16..bd31b5499c2d 100644 --- a/packages/taro-cli/src/util/resolve_npm_files.ts +++ b/packages/taro-cli/src/util/resolve_npm_files.ts @@ -14,7 +14,7 @@ import { printLog, recursiveFindNodeModules, generateEnvList, - isQuickAppPkg + isQuickappPkg } from './index' import { @@ -25,13 +25,15 @@ import { REG_FONT, REG_IMAGE, REG_MEDIA, - REG_JSON + REG_JSON, + taroJsFramework, + NODE_MODULES_REG } from './constants' import defaultUglifyConfig from '../config/uglify' import * as npmProcess from './npm' -import { IInstallOptions, INpmConfig, IResolvedCache, TogglableOptions } from './types' +import { IInstallOptions, INpmConfig, IResolvedCache, TogglableOptions, ITaroManifestConfig } from './types' const excludeNpmPkgs = ['ReactPropTypes'] @@ -70,10 +72,11 @@ export function resolveNpmFilesPath ({ root, rootNpm, npmOutputDir, - compileInclude = [], + compileConfig = {}, env, uglify, - babelConfig + babelConfig, + quickappManifest }: { pkgName: string, isProduction: boolean, @@ -82,10 +85,11 @@ export function resolveNpmFilesPath ({ root: string, rootNpm: string, npmOutputDir: string, - compileInclude: string[], + compileConfig: {[k: string]: any}, env: object, uglify: TogglableOptions, - babelConfig: object + babelConfig: object, + quickappManifest?: ITaroManifestConfig }) { if (!resolvedCache[pkgName]) { const res = resolveNpmPkgMainPath(pkgName, isProduction, npmConfig, buildAdapter, root) @@ -102,15 +106,115 @@ export function resolveNpmFilesPath ({ buildAdapter, rootNpm, npmOutputDir: npmOutputDir, - compileInclude, + compileConfig, env, uglify, - babelConfig + babelConfig, + quickappManifest }) } return resolvedCache[pkgName] } +function analyzeImportUrl ({ + requirePath, + excludeRequire, + source, + filePath, + files, + isProduction, + npmConfig, + rootNpm, + npmOutputDir, + buildAdapter, + compileConfig = [], + env, + uglify, + babelConfig, + quickappManifest +}: { + requirePath: string, + excludeRequire: string[], + source: any, + filePath: string, + files: string[], + isProduction: boolean, + npmConfig: INpmConfig, + rootNpm: string, + npmOutputDir: string, + buildAdapter: BUILD_TYPES, + compileConfig: {[k: string]: any}, + env: object, + uglify: TogglableOptions, + babelConfig: object, + quickappManifest?: ITaroManifestConfig +}) { + if (excludeRequire.indexOf(requirePath) < 0) { + const quickappPkgs = quickappManifest ? quickappManifest.features : [] + if (isQuickappPkg(requirePath, quickappPkgs)) { + return + } + if (isNpmPkg(requirePath)) { + if (excludeNpmPkgs.indexOf(requirePath) < 0) { + const taroMiniAppFramework = `@tarojs/taro-${buildAdapter}` + if (requirePath === taroJsFramework + && (!NODE_MODULES_REG.test(filePath) || filePath.indexOf(taroMiniAppFramework) < 0)) { + requirePath = taroMiniAppFramework + } + const res = resolveNpmFilesPath({ + pkgName: requirePath, + isProduction, + npmConfig, + buildAdapter, + root: path.dirname(recursiveFindNodeModules(filePath)), + rootNpm, + npmOutputDir, + compileConfig, + env, + uglify, + babelConfig, + quickappManifest + }) + let relativeRequirePath = promoteRelativePath(path.relative(filePath, res.main)) + relativeRequirePath = relativeRequirePath.replace(/node_modules/g, npmConfig.name) + if (buildAdapter === BUILD_TYPES.ALIPAY) { + relativeRequirePath = relativeRequirePath.replace(/@/g, '_') + } + source.value = relativeRequirePath + } + } else { + let realRequirePath = path.resolve(path.dirname(filePath), requirePath) + const tempPathWithJS = `${realRequirePath}.js` + const tempPathWithIndexJS = `${realRequirePath}${path.sep}index.js` + if (fs.existsSync(tempPathWithJS)) { + realRequirePath = tempPathWithJS + requirePath += '.js' + } else if (fs.existsSync(tempPathWithIndexJS)) { + realRequirePath = tempPathWithIndexJS + requirePath += '/index.js' + } + if (files.indexOf(realRequirePath) < 0) { + files.push(realRequirePath) + recursiveRequire({ + filePath: realRequirePath, + files, + isProduction, + npmConfig, + buildAdapter, + rootNpm, + npmOutputDir, + compileConfig, + env, + uglify, + babelConfig, + quickappManifest + }) + } + source.value = requirePath + } + } +} + function parseAst ({ ast, filePath, @@ -120,10 +224,11 @@ function parseAst ({ rootNpm, npmOutputDir, buildAdapter, - compileInclude = [], + compileConfig = [], env, uglify, - babelConfig + babelConfig, + quickappManifest }: { ast: t.File, filePath: string, @@ -133,12 +238,14 @@ function parseAst ({ rootNpm: string, npmOutputDir: string, buildAdapter: BUILD_TYPES, - compileInclude: string[], + compileConfig: {[k: string]: any}, env: object, uglify: TogglableOptions, - babelConfig: object + babelConfig: object, + quickappManifest?: ITaroManifestConfig }) { const excludeRequire: string[] = [] + traverse(ast, { IfStatement (astPath) { astPath.traverse({ @@ -168,74 +275,58 @@ function parseAst ({ Program: { exit (astPath) { astPath.traverse({ + ImportDeclaration (astPath) { + const node = astPath.node + const source = node.source + const value = source.value + analyzeImportUrl({ + requirePath: value, + excludeRequire, + source, + filePath, + files, + isProduction, + npmConfig, + rootNpm, + npmOutputDir, + buildAdapter, + compileConfig, + env, + uglify, + babelConfig, + quickappManifest + }) + }, CallExpression (astPath) { const node = astPath.node const callee = node.callee as t.Identifier if (callee.name === 'require') { const args = node.arguments as Array - let requirePath = args[0].value - if (excludeRequire.indexOf(requirePath) < 0) { - if (isQuickAppPkg(requirePath)) { - return - } - if (isNpmPkg(requirePath)) { - if (excludeNpmPkgs.indexOf(requirePath) < 0) { - const res = resolveNpmFilesPath({ - pkgName: requirePath, - isProduction, - npmConfig, - buildAdapter, - root: path.dirname(recursiveFindNodeModules(filePath)), - rootNpm, - npmOutputDir, - compileInclude, - env, - uglify, - babelConfig - }) - let relativeRequirePath = promoteRelativePath(path.relative(filePath, res.main)) - relativeRequirePath = relativeRequirePath.replace(/node_modules/g, npmConfig.name) - if (buildAdapter === BUILD_TYPES.ALIPAY) { - relativeRequirePath = relativeRequirePath.replace(/@/g, '_') - } - args[0].value = relativeRequirePath - } - } else { - let realRequirePath = path.resolve(path.dirname(filePath), requirePath) - const tempPathWithJS = `${realRequirePath}.js` - const tempPathWithIndexJS = `${realRequirePath}${path.sep}index.js` - if (fs.existsSync(tempPathWithJS)) { - realRequirePath = tempPathWithJS - requirePath += '.js' - } else if (fs.existsSync(tempPathWithIndexJS)) { - realRequirePath = tempPathWithIndexJS - requirePath += '/index.js' - } - if (files.indexOf(realRequirePath) < 0) { - files.push(realRequirePath) - recursiveRequire({ - filePath: realRequirePath, - files, - isProduction, - npmConfig, - buildAdapter, - rootNpm, - npmOutputDir, - compileInclude, - env, - uglify, - babelConfig - }) - } - args[0].value = requirePath - } - } + const requirePath = args[0].value + analyzeImportUrl({ + requirePath, + excludeRequire, + source: args[0], + filePath, + files, + isProduction, + npmConfig, + rootNpm, + npmOutputDir, + buildAdapter, + compileConfig, + env, + uglify, + babelConfig, + quickappManifest + }) } } }) } } }) + return generate(ast).code } @@ -247,10 +338,11 @@ async function recursiveRequire ({ buildAdapter, npmOutputDir, rootNpm, - compileInclude = [], + compileConfig = {}, env, uglify, - babelConfig + babelConfig, + quickappManifest }: { filePath: string, files: string[], @@ -259,10 +351,11 @@ async function recursiveRequire ({ buildAdapter: BUILD_TYPES, rootNpm: string, npmOutputDir: string, - compileInclude: string[], + compileConfig: {[k: string]: any}, env: object, uglify: TogglableOptions, - babelConfig: object + babelConfig: object, + quickappManifest?: ITaroManifestConfig }) { let fileContent = fs.readFileSync(filePath).toString() let outputNpmPath = filePath.replace(rootNpm, npmOutputDir).replace(/node_modules/g, npmConfig.name) @@ -281,49 +374,71 @@ async function recursiveRequire ({ return } fileContent = npmCodeHack(filePath, fileContent, buildAdapter) - try { - const constantsReplaceList = Object.assign({ - 'process.env.TARO_ENV': buildAdapter - }, generateEnvList(env || {})) - const transformResult = wxTransformer({ - code: fileContent, - sourcePath: filePath, - outputPath: outputNpmPath, - isNormal: true, - adapter: buildAdapter, - isTyped: REG_TYPESCRIPT.test(filePath), - env: constantsReplaceList - }) - const ast = babel.transformFromAst(transformResult.ast, '', { - plugins: [ - [require('babel-plugin-transform-define').default, constantsReplaceList] - ] - }).ast as t.File - fileContent = parseAst({ - ast, - filePath, - files, - isProduction, - npmConfig, - rootNpm, - buildAdapter, - compileInclude, - npmOutputDir, - env, - uglify, - babelConfig - }) - } catch (err) { - console.log(err) + + const npmExclude = (compileConfig.exclude || []).filter(item => /(?:\/|^)node_modules(\/|$)/.test(item)) + let isNpmInCompileExclude = false + for (const item of npmExclude) { + isNpmInCompileExclude = filePath.indexOf(item) !== -1 + if (isNpmInCompileExclude) { + break + } } + if (!isNpmInCompileExclude) { + try { + const constantsReplaceList = Object.assign({ + 'process.env.TARO_ENV': buildAdapter + }, generateEnvList(env || {})) + const transformResult = wxTransformer({ + code: fileContent, + sourcePath: filePath, + outputPath: outputNpmPath, + isNormal: true, + adapter: buildAdapter, + isTyped: REG_TYPESCRIPT.test(filePath), + env: constantsReplaceList + }) + const ast = babel.transformFromAst(transformResult.ast, '', { + plugins: [ + [require('babel-plugin-transform-define').default, constantsReplaceList] + ] + }).ast as t.File + fileContent = parseAst({ + ast, + filePath, + files, + isProduction, + npmConfig, + rootNpm, + buildAdapter, + compileConfig, + npmOutputDir, + env, + uglify, + babelConfig, + quickappManifest + }) + } catch (err) { + console.log(err) + } + } + if (!copyedFiles[outputNpmPath]) { + const compileInclude = compileConfig.include if (compileInclude && compileInclude.length) { const filePathArr = filePath.split(path.sep) const nodeModulesIndex = filePathArr.indexOf('node_modules') - const npmPkgName = filePathArr[nodeModulesIndex + 1] - if (compileInclude.indexOf(npmPkgName) >= 0) { - const compileScriptRes = await npmProcess.callPlugin('babel', fileContent, filePath, babelConfig, rootNpm) - fileContent = compileScriptRes.code + if (nodeModulesIndex >= 0) { + const npmFilePath = filePathArr.slice(nodeModulesIndex + 1).join('/') + let needCompile = false + compileInclude.forEach(item => { + if (npmFilePath.indexOf(item) >= 0) { + needCompile = true + } + }) + if (needCompile) { + const compileScriptRes = await npmProcess.callPlugin('babel', fileContent, filePath, babelConfig, rootNpm) + fileContent = compileScriptRes.code + } } } if (isProduction && buildAdapter !== BUILD_TYPES.QUICKAPP) { diff --git a/packages/taro-cli/src/util/types.ts b/packages/taro-cli/src/util/types.ts index 193dadeba9a5..3903e4d3478e 100644 --- a/packages/taro-cli/src/util/types.ts +++ b/packages/taro-cli/src/util/types.ts @@ -123,7 +123,9 @@ export interface IMiniAppConfig { postcss?: IPostcssOption }, compile?: ICompileOption, - customFilesTypes: IMINI_APP_FILE_TYPE + customFilesTypes: IMINI_APP_FILE_TYPE, + publicPath?: string, + staticDirectory?: string } export type TogglableOptions = { diff --git a/packages/taro-cli/yarn.lock b/packages/taro-cli/yarn.lock index b53d2020fd64..7ba25f25be84 100644 --- a/packages/taro-cli/yarn.lock +++ b/packages/taro-cli/yarn.lock @@ -2622,6 +2622,11 @@ crypto-random-string@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" +crypto@^1.0.1: + version "1.0.1" + resolved "https://registry.npm.taobao.org/crypto/download/crypto-1.0.1.tgz#2af1b7cad8175d24c8a1b0778255794a21803037" + integrity sha1-KvG3ytgXXSTIobB3glV5SiGAMDc= + css-color-keywords@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05" @@ -8757,7 +8762,7 @@ xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: version "4.0.1" resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" -xxhashjs@^0.2.1: +xxhashjs@^0.2.1, xxhashjs@^0.2.2: version "0.2.2" resolved "https://registry.npmjs.org/xxhashjs/-/xxhashjs-0.2.2.tgz#8a6251567621a1c46a5ae204da0249c7f8caa9d8" dependencies: diff --git a/packages/taro-components-qa/package.json b/packages/taro-components-qa/package.json index d5be2b013e39..a210da10233c 100644 --- a/packages/taro-components-qa/package.json +++ b/packages/taro-components-qa/package.json @@ -1,6 +1,6 @@ { "name": "@tarojs/components-qa", - "version": "1.3.0", + "version": "1.3.7", "description": "多端解决方案基础组件(快应用)", "main": "./index.js", "files": [ diff --git a/packages/taro-components-qa/src/components/scroll-view/index.ux b/packages/taro-components-qa/src/components/scroll-view/index.ux new file mode 100644 index 000000000000..eafb3d2cb5fe --- /dev/null +++ b/packages/taro-components-qa/src/components/scroll-view/index.ux @@ -0,0 +1,70 @@ + + + + + + \ No newline at end of file diff --git a/packages/taro-components-qa/src/components/swiper-item/index.ux b/packages/taro-components-qa/src/components/swiper-item/index.ux new file mode 100644 index 000000000000..27c06d2b79d9 --- /dev/null +++ b/packages/taro-components-qa/src/components/swiper-item/index.ux @@ -0,0 +1,42 @@ + + + + + + \ No newline at end of file diff --git a/packages/taro-components-qa/src/components/taro-page/index.ux b/packages/taro-components-qa/src/components/taro-page/index.ux index 7d3d181ed2d5..3bd31bcc8cb0 100644 --- a/packages/taro-components-qa/src/components/taro-page/index.ux +++ b/packages/taro-components-qa/src/components/taro-page/index.ux @@ -21,10 +21,10 @@ -
-
+
+
- + {{item.text}}
@@ -43,7 +43,7 @@ height: 110px; } - .taro-tabbar .tab { + .taro-tabbar .taro-tabbar_item { flex: 1; margin: 10px; flex-direction: column; @@ -51,12 +51,12 @@ align-items: center; } - .taro-tabbar .tab image { + .taro-tabbar .taro-tabbar_item image { width: 45px; height: 45px; } - .taro-tabbar .tab a { + .taro-tabbar .taro-tabbar_item a { margin: 10px; border: 1px solid #eeeeee; } @@ -64,6 +64,9 @@ diff --git a/packages/taro-components-qa/src/components/web-view/index.ux b/packages/taro-components-qa/src/components/web-view/index.ux new file mode 100644 index 000000000000..4010b3511f98 --- /dev/null +++ b/packages/taro-components-qa/src/components/web-view/index.ux @@ -0,0 +1,58 @@ + + + + + + \ No newline at end of file diff --git a/packages/taro-components-rn/README.md b/packages/taro-components-rn/README.md index dcd3c9e38005..dca56c383c39 100644 --- a/packages/taro-components-rn/README.md +++ b/packages/taro-components-rn/README.md @@ -38,3 +38,5 @@ react-native run-ios ## 未来可能的升级 目前 react-native 版本为 0.55.4 + +- 0.58.x ScrollView 支持 snapToOffsets,Swiper 关注 diff --git a/packages/taro-components-rn/TCRNExample/App.experimental.js b/packages/taro-components-rn/TCRNExample/App.experimental.js new file mode 100644 index 000000000000..2382a56b407a --- /dev/null +++ b/packages/taro-components-rn/TCRNExample/App.experimental.js @@ -0,0 +1,157 @@ +import React, { Component } from 'react' +import { StyleSheet } from 'react-native' +import { + Provider, + Block, + // ScrollView, + View, + Text, + Button, + Image +} from '../dist' +import ScrollView from '../dist/components/ScrollView/ScrollViewExperimental' +// import EXAudio from './example/EXAudio' +import EXButton from './example/EXButton' +import EXCheckbox from './example/EXCheckbox' +import EXForm from './example/EXForm' +import EXIcon from './example/EXIcon' +import EXImage from './example/EXImage' +import EXInput from './example/EXInput' +// import EXMap from './example/EXMap' +import EXPicker from './example/EXPicker' +import EXProgress from './example/EXProgress' +import EXRadio from './example/EXRadio' +import EXRichText from './example/EXRichText' +import EXSlider from './example/EXSlider' +import EXSwiper from './example/EXSwiper' +import EXSwitch from './example/EXSwitch' +// import EXVideo from './example/EXVideo' +import EXWebView from './example/EXWebView' + +export default class App extends Component { + state = { + // 更改 scrollTop 可滚动 + scrollTop: 0 + } + + onViewTouchstart = () => { + console.log('view toucstart') + } + + onViewTouchmove = () => { + console.log('view touchmove') + } + + onViewTouchend = () => { + console.log('view touchend') + } + + componentDidMount () { + // setTimeout(() => { + // this.setState({ scrollTop: 2200 }) + // }, 0) + } + + render () { + return ( + + { + console.log('to upper') + }} + onScrollToLower={() => { + console.log('to lower') + }} + lowerThreshold={500} + onScroll={(e) => { + // console.log('onScroll', e) + }} + bounces={false} + + // Experimental + data={[{ height: 50 }, { height: 80 }, { height: 60 }, { height: 50 }, { height: 80 }, { height: 60 }, { height: 50 }, { height: 80 }, { height: 60 }, { height: 50 }, { height: 80 }, { height: 60 }, { height: 50 }, { height: 80 }, { height: 60 }, { height: 50 }, { height: 80 }, { height: 60 }, { height: 50 }, { height: 80 }, { height: 60 }, { height: 50 }, { height: 80 }, { height: 60 }, { height: 50 }, { height: 80 }, { height: 60 }, { height: 50 }, { height: 80 }, { height: 60 }, { height: 50 }, { height: 80 }, { height: 60 }, { height: 50 }, { height: 80 }, { height: 60 }, { height: 50 }, { height: 80 }, { height: 60 }, { height: 50 }, { height: 80 }, { height: 60 }, { height: 50 }, { height: 80 }, { height: 60 }, { height: 50 }, { height: 80 }, { height: 60 }, { height: 50 }, { height: 80 }, { height: 60 }, { height: 50 }, { height: 80 }, { height: 60 }, { height: 50 }, { height: 80 }, { height: 60 }, { height: 50 }, { height: 80 }, { height: 60 }, { height: 50 }, { height: 80 }, { height: 60 }, { height: 50 }, { height: 80 }, { height: 60 }, { height: 50 }, { height: 80 }, { height: 60 }, { height: 50 }, { height: 80 }, { height: 60 }]} + heightForItem={(item) => item.height} + renderHeader={() => ( + + Welcome to React Native! + + + Block + + + + + + Button + + + + + + Checkbox + + + + + + Form + + + + + + + Icon + + + + + + + Image + + + + + )} + renderItem={(item, index) => { + return ( + + ) + }} + /> + + ) + } +} + +const styles = StyleSheet.create({ + section: { + alignItems: 'center', + width: '100%', + paddingBottom: 10, + marginBottom: 10, + borderBottomWidth: 1, + borderBottomColor: 'gold' + }, + sectionTit: { + marginBottom: 10, + paddingVertical: 4, + paddingHorizontal: 8, + backgroundColor: 'tomato', + borderRadius: 4, + borderLeftWidth: 3, + borderLeftColor: '#666', + borderRightWidth: 3, + borderRightColor: '#666' + }, + sectionTitTxt: { + fontSize: 18, + color: 'white' + } +}) diff --git a/packages/taro-components-rn/TCRNExample/App.flatlist.js b/packages/taro-components-rn/TCRNExample/App.flatlist.js new file mode 100644 index 000000000000..681c89eaa639 --- /dev/null +++ b/packages/taro-components-rn/TCRNExample/App.flatlist.js @@ -0,0 +1,157 @@ +import React, { Component } from 'react' +import { StyleSheet } from 'react-native' +import { + Provider, + Block, + ScrollView, + View, + Text, + Button, + Image +} from '../dist' +// import EXAudio from './example/EXAudio' +import EXButton from './example/EXButton' +import EXCheckbox from './example/EXCheckbox' +import EXForm from './example/EXForm' +import EXIcon from './example/EXIcon' +import EXImage from './example/EXImage' +import EXInput from './example/EXInput' +// import EXMap from './example/EXMap' +import EXPicker from './example/EXPicker' +import EXProgress from './example/EXProgress' +import EXRadio from './example/EXRadio' +import EXRichText from './example/EXRichText' +import EXSlider from './example/EXSlider' +import EXSwiper from './example/EXSwiper' +import EXSwitch from './example/EXSwitch' +// import EXVideo from './example/EXVideo' +import EXWebView from './example/EXWebView' + +export default class App extends Component { + state = { + // 更改 scrollTop 可滚动 + scrollTop: 0 + } + + onViewTouchstart = () => { + console.log('view toucstart') + } + + onViewTouchmove = () => { + console.log('view touchmove') + } + + onViewTouchend = () => { + console.log('view touchend') + } + + componentDidMount () { + // setTimeout(() => { + // this.setState({ scrollTop: 2200 }) + // }, 0) + } + + renderItem = ({ item }) => { + switch (item.name) { + case 'welcome': + return Welcome to React Native! + case 'Block': + return ( + + + Block + + + + ) + case 'Button': + return ( + + + Button + + + + ) + case 'Checkbox': + return ( + + + Checkbox + + + + ) + case 'Form': + return ( + + + Form + + + + ) + } + } + + render () { + return ( + + { + console.log('to upper') + }} + onScrollToLower={() => { + console.log('to lower') + }} + onScroll={(e) => { + console.log('onScroll', e) + }} + bounces={false} + data={[ + { name: 'welcome' }, + { name: 'Block' }, + { name: 'Button' }, + { name: 'Checkbox' }, + { name: 'Form' }, + ]} + renderItem={this.renderItem} + /> + + ) + } +} + +const styles = StyleSheet.create({ + section: { + alignItems: 'center', + width: '100%', + paddingBottom: 10, + marginBottom: 10, + borderBottomWidth: 1, + borderBottomColor: 'gold' + }, + sectionTit: { + marginBottom: 10, + paddingVertical: 4, + paddingHorizontal: 8, + backgroundColor: 'tomato', + borderRadius: 4, + borderLeftWidth: 3, + borderLeftColor: '#666', + borderRightWidth: 3, + borderRightColor: '#666' + }, + sectionTitTxt: { + fontSize: 18, + color: 'white' + } +}) diff --git a/packages/taro-components-rn/TCRNExample/App.js b/packages/taro-components-rn/TCRNExample/App.js index 6919e38a8feb..cf3d7d7829d2 100644 --- a/packages/taro-components-rn/TCRNExample/App.js +++ b/packages/taro-components-rn/TCRNExample/App.js @@ -45,6 +45,12 @@ export default class App extends Component { console.log('view touchend') } + componentDidMount () { + // setTimeout(() => { + // this.setState({ scrollTop: 2200 }) + // }, 0) + } + render () { return ( diff --git a/packages/taro-components-rn/TCRNExample/example/EXSwiper.js b/packages/taro-components-rn/TCRNExample/example/EXSwiper.js index f1824b3a7476..e733dbc12a2f 100644 --- a/packages/taro-components-rn/TCRNExample/example/EXSwiper.js +++ b/packages/taro-components-rn/TCRNExample/example/EXSwiper.js @@ -1,46 +1,82 @@ import React, { Component } from 'react' -import { View, Text, Swiper, SwiperItem, Image } from '../../dist' +import { View, Swiper, SwiperItem, Image } from '../../dist' export default class EXSwiper extends Component { + state = { + data: [] + } + + componentDidMount () { + setTimeout(() => { + this.setState({ + data: [ + { + image: 'https://imgcps.jd.com/ling4/4635736/5Lqs6YCJ5aW96LSn/5L2g5YC85b6X5oul5pyJ/p-5c17126882acdd181dd53ce0/95c21515/cr_1125x549_0_72/s1125x690/q70.jpg', + clickUrl: 'https://m.jd.com/' + }, + { + image: 'https://m.360buyimg.com/mobilecms/s750x366_jfs/t1/54392/1/2538/95587/5d064ea3E74ca0763/dc1d10fbd105d8a0.jpg!cr_1125x549_0_72!q70.jpg.dpg', + clickUrl: 'https://m.jd.com/' + } + ] + }) + }, 300) + setTimeout(() => { + this.setState({ + data: [ + { + image: 'https://imgcps.jd.com/ling4/4635736/5Lqs6YCJ5aW96LSn/5L2g5YC85b6X5oul5pyJ/p-5c17126882acdd181dd53ce0/95c21515/cr_1125x549_0_72/s1125x690/q70.jpg', + clickUrl: 'https://m.jd.com/' + }, + { + image: 'https://m.360buyimg.com/mobilecms/s750x366_jfs/t1/30451/34/12138/108202/5cb7720aE6ebf11ec/9945f5b3b9f9547f.jpg!cr_1125x549_0_72!q70.jpg.dpg', + clickUrl: 'https://m.jd.com/' + }, + { + image: 'https://m.360buyimg.com/mobilecms/s750x366_jfs/t1/54392/1/2538/95587/5d064ea3E74ca0763/dc1d10fbd105d8a0.jpg!cr_1125x549_0_72!q70.jpg.dpg', + clickUrl: 'https://m.jd.com/' + }, + { + image: 'https://m.360buyimg.com/mobilecms/s750x366_jfs/t1/81508/17/1849/124012/5d01f580E0fee0c3f/1839eac6ba834f3e.jpg!cr_1125x549_0_72!q70.jpg.dpg', + clickUrl: 'https://m.jd.com/' + } + ] + }) + }, 600) + } + render () { return ( - + null} + onChange={(event) => { console.log('Swiper: onChange', event.detail.current) }} onAnimationFinish={() => null} style={{ + marginTop: 30, + width: 280.5, + height: 200, backgroundColor: 'black' }} > - { alert('click item') }} style={{ backgroundColor: 'red' }}> - Hello Swiper - - - Beautiful - - - And simple - + {this.state.data.map((item, index) => { + return ( + { console.log('click item') }} + > + + + ) + })} - {/* - - - - - - - - - - */} ) } diff --git a/packages/taro-components-rn/jest.config.js b/packages/taro-components-rn/jest.config.js index 4afdc4b45124..38e7beacce42 100644 --- a/packages/taro-components-rn/jest.config.js +++ b/packages/taro-components-rn/jest.config.js @@ -6,7 +6,8 @@ module.exports = { '^.+\\.tsx?$': 'ts-jest' }, transformIgnorePatterns: [ - 'node_modules/(?!(react-native|react-native-swiper|react-native-vertical-view-pager|react-native-animatable|react-native-collapsible|@bang88/react-native-ultimate-listview|react-native-modal-popover|react-native-modal-popover|react-native-safe-area-view)/)' + 'node_modules/(?!(react-native|react-native-swiper|react-native-vertical-view-pager|react-native-animatable|react-native-collapsible|@bang88/react-native-ultimate-listview|react-native-modal-popover|react-native-modal-popover|react-native-safe-area-view)/)', + 'node_modules/(?!(@manjiz/react-native-swiper)/)' ], testMatch: [ '**/__tests__/**/*.ts?(x)', diff --git a/packages/taro-components-rn/package.json b/packages/taro-components-rn/package.json index 664057d9f2aa..e141d46417a2 100644 --- a/packages/taro-components-rn/package.json +++ b/packages/taro-components-rn/package.json @@ -1,6 +1,6 @@ { "name": "@tarojs/components-rn", - "version": "1.3.0", + "version": "1.3.7", "description": "多端解决方案基础组件(RN)", "main": "./dist/index.js", "scripts": { @@ -29,6 +29,7 @@ "license": "MIT", "dependencies": { "@ant-design/react-native": "^3.1.9", + "@manjiz/react-native-swiper": "^0.0.3", "prop-types": "^15.6.2", "react-dom": "^16.4.0", "react-mixin": "^5.0.0", diff --git a/packages/taro-components-rn/src/components/Button/index.tsx b/packages/taro-components-rn/src/components/Button/index.tsx index 75065aa25692..2c7c2651f3bc 100644 --- a/packages/taro-components-rn/src/components/Button/index.tsx +++ b/packages/taro-components-rn/src/components/Button/index.tsx @@ -30,7 +30,7 @@ import * as React from 'react' import { - TouchableOpacity, + TouchableWithoutFeedback, Text, View, Image, @@ -52,7 +52,7 @@ class _Button extends React.Component { hoverStayTime: 70 } - $touchable = React.createRef() + $touchable = React.createRef() state: ButtonState = { valve: new Animated.Value(0), @@ -139,9 +139,7 @@ class _Button extends React.Component { }) return ( - { {children} : children} - + ) } } diff --git a/packages/taro-components-rn/src/components/ClickableSimplified/index.tsx b/packages/taro-components-rn/src/components/ClickableSimplified/index.tsx index 2ae72d3e0712..9ba834885411 100644 --- a/packages/taro-components-rn/src/components/ClickableSimplified/index.tsx +++ b/packages/taro-components-rn/src/components/ClickableSimplified/index.tsx @@ -47,6 +47,7 @@ export default function (WrappedComponent: React.ComponentType) { } = this.props return !!(hoverStyle || onClick || onLongPress || onTouchstart || onTouchend) }, + onShouldBlockNativeResponder: () => false, // onMoveShouldSetPanResponder: (evt: GestureResponderEvent, gestureState) => { // const { onTouchmove, onTouchcancel, onTouchend } = this.props // return !!(onTouchmove || onTouchcancel || onTouchend) diff --git a/packages/taro-components-rn/src/components/Image/index.tsx b/packages/taro-components-rn/src/components/Image/index.tsx index 2838271f1bff..4ba6d0c3aabd 100644 --- a/packages/taro-components-rn/src/components/Image/index.tsx +++ b/packages/taro-components-rn/src/components/Image/index.tsx @@ -10,7 +10,7 @@ * @warn Pass require(LOCAL IMAGE) to SRC, otherwise a string-type parameter. * @warn The width/height would be undefined in onLoad. * @warn Avoid using HTTP source image. - * @warn unstable + * @warn Image.resolveAssetSource 会造成重复请求 */ import * as React from 'react' @@ -55,7 +55,8 @@ class _Image extends React.Component { } onLoad = () => { - const { src, onLoad = noop } = this.props + const { src, onLoad } = this.props + if (!onLoad) return if (typeof src === 'string') { Image.getSize(src as string, (width: number, height: number) => { onLoad({ @@ -120,12 +121,8 @@ class _Image extends React.Component { return true } - getSnapshotBeforeUpdate (prevProps: ImageProps, prevState: ImageState) { - return prevProps.src !== this.props.src - } - - componentDidUpdate (prevProps: ImageProps, prevState: ImageState, snapshot: boolean) { - if (snapshot) { + componentDidUpdate (prevProps: ImageProps, prevState: ImageState) { + if (prevProps.src !== this.props.src) { this.loadImg(this.props) } } diff --git a/packages/taro-components-rn/src/components/ScrollView/PropsType.tsx b/packages/taro-components-rn/src/components/ScrollView/PropsType.tsx index fc38857cf139..465ea9c60f01 100644 --- a/packages/taro-components-rn/src/components/ScrollView/PropsType.tsx +++ b/packages/taro-components-rn/src/components/ScrollView/PropsType.tsx @@ -1,5 +1,5 @@ import * as React from 'react' -import { StyleProp, ViewStyle } from 'react-native' +import { StyleProp, ViewStyle, ListRenderItem } from 'react-native' export type ScrollMetrics = { contentLength: number; @@ -37,7 +37,7 @@ export interface ScrollViewState { snapScrollLeft: number; } -export interface ScrollViewProps { +export interface ScrollViewProps { children?: React.ReactNode; style?: StyleProp; scrollX?: boolean; @@ -52,4 +52,6 @@ export interface ScrollViewProps { onScroll?: (evt: EventOnScroll) => void; // RN 属性 contentContainerStyle?: StyleProp; + data?: ReadonlyArray | null; + renderItem?: ListRenderItem; } diff --git a/packages/taro-components-rn/src/components/ScrollView/PropsTypeExperimental.tsx b/packages/taro-components-rn/src/components/ScrollView/PropsTypeExperimental.tsx new file mode 100644 index 000000000000..ea23dce596ed --- /dev/null +++ b/packages/taro-components-rn/src/components/ScrollView/PropsTypeExperimental.tsx @@ -0,0 +1,59 @@ +import * as React from 'react' +import { StyleProp, ViewStyle, ListRenderItem } from 'react-native' +import { LoadingFooter } from 'react-native-spring-scrollview' + +export type ScrollMetrics = { + contentLength: number; + dOffset: number; + dt: number; + offset: number; + offsetX: number; + offsetY: number; + timestamp: number; + velocity: number; + visibleLength: number; +} + +export type EventOnScrollToUpper = { + distanceFromTop: number; +} + +export type EventOnScrollToLower = { + distanceFromEnd: number; +} + +export type EventOnScroll = { + detail: { + scrollLeft: number; + scrollTop: number; + scrollHeight: number; + scrollWidth: number; + deltaX: number; + deltaY: number; + } +} + +export interface ScrollViewState { + snapScrollTop: number; + snapScrollLeft: number; +} + +export interface ScrollViewProps { + style?: StyleProp; + data: any[]; + heightForItem: (item:any,index:number) => number; + renderHeader?: () => React.ReactElement; + renderFooter?: () => React.ReactElement; + renderItem: (item:any, index:number) => React.ReactElement + + scrollX?: boolean; + upperThreshold: number; + lowerThreshold: number; + scrollTop: number; + scrollLeft: number; + onScrollToUpper?: (evt: EventOnScrollToUpper) => void; + onScrollToLower?: (evt: EventOnScrollToLower) => void; + onScroll?: (evt: EventOnScroll) => void; + // RN 属性 + contentContainerStyle?: StyleProp; +} diff --git a/packages/taro-components-rn/src/components/ScrollView/ScrollViewExperimental.tsx b/packages/taro-components-rn/src/components/ScrollView/ScrollViewExperimental.tsx new file mode 100644 index 000000000000..caa55af06332 --- /dev/null +++ b/packages/taro-components-rn/src/components/ScrollView/ScrollViewExperimental.tsx @@ -0,0 +1,225 @@ +/** + * ScrollViewExperimental + */ + +import * as React from 'react' +import { + ScrollView, + FlatList, + NativeSyntheticEvent, + NativeScrollEvent, + LayoutChangeEvent, + StyleSheet, + ViewStyle, + View, + Text +} from 'react-native' +import { WaterfallList } from 'react-native-largelist-v3' +import { omit, noop } from '../../utils' +import { ScrollViewProps, ScrollViewState, ScrollMetrics } from './PropsTypeExperimental' + +class _ScrollView extends React.Component, ScrollViewState> { + static defaultProps = { + upperThreshold: 50, + lowerThreshold: 50, + scrollTop: 0, + scrollLeft: 0, + } + + static getDerivedStateFromProps (props: ScrollViewProps, state: ScrollViewState) { + return state.snapScrollTop !== props.scrollTop || state.snapScrollLeft !== props.scrollLeft ? { + snapScrollTop: props.scrollTop, + snapScrollLeft: props.scrollLeft + } : null + } + + state: ScrollViewState = { + snapScrollTop: 0, + snapScrollLeft: 0 + } + + _scrollMetrics: ScrollMetrics = { + contentLength: 0, + dOffset: 0, + dt: 10, + offset: 0, + offsetX: 0, + offsetY: 0, + timestamp: 0, + velocity: 0, + visibleLength: 0, + } + $scrollView = React.createRef>() + _hasDataChangedSinceEndReached: boolean + _sentEndForContentLength: number = 0 + _scrollEventThrottle: number = 50 + _hasCallScrollToUpperInRange: boolean = false + _hasCallScrollToLowerInRange: boolean = false + _initialScrollIndexTimeout: any + + _selectLength = (metrics: { height: number, width: number }): number => { + return !this.props.scrollX ? metrics.height : metrics.width + } + + _selectOffset = (metrics: {x: number, y: number}): number => { + return !this.props.scrollX ? metrics.y : metrics.x + } + + _onContentSizeChange = (width: number, height: number): void => { + this._scrollMetrics.contentLength = this._selectLength({ height, width }) + } + + _onScrollEndDrag = (e: NativeSyntheticEvent): void => { + const { velocity } = e.nativeEvent + if (velocity) { + this._scrollMetrics.velocity = this._selectOffset(velocity) + } + } + + _onMomentumScrollEnd = (): void => { + this._scrollMetrics.velocity = 0 + } + + _onLayout = (e: LayoutChangeEvent): void => { + this._scrollMetrics.visibleLength = this._selectLength(e.nativeEvent.layout) + } + + _maybeCallOnStartReached = (): void => { + const { onScrollToUpper, upperThreshold } = this.props + const { offset } = this._scrollMetrics + if (onScrollToUpper && offset < upperThreshold) { + if (!this._hasCallScrollToUpperInRange) { + onScrollToUpper({ distanceFromTop: offset }) + this._hasCallScrollToUpperInRange = true + } + } else { + this._hasCallScrollToUpperInRange = false + } + } + + _maybeCallOnEndReached = (): void => { + const { onScrollToLower, lowerThreshold } = this.props + const { contentLength, visibleLength, offset } = this._scrollMetrics + const distanceFromEnd = contentLength - visibleLength - offset + if (onScrollToLower && + distanceFromEnd < lowerThreshold && + (this._hasDataChangedSinceEndReached || contentLength !== this._sentEndForContentLength)) { + if (!this._hasCallScrollToLowerInRange) { + this._hasDataChangedSinceEndReached = false + this._hasCallScrollToLowerInRange = true + this._sentEndForContentLength = this._scrollMetrics.contentLength + onScrollToLower({ distanceFromEnd }) + } + } else { + this._hasCallScrollToLowerInRange = false + } + } + + _onScroll = (e: NativeSyntheticEvent): void => { + const { onScroll = noop } = this.props + const scrollLeft: number = e.nativeEvent.contentOffset.x + const scrollTop: number = e.nativeEvent.contentOffset.y + const scrollHeight: number = e.nativeEvent.contentSize.height + const scrollWidth: number = e.nativeEvent.contentSize.width + onScroll({ + detail: { + scrollLeft, + scrollTop, + scrollHeight, + scrollWidth, + deltaX: scrollLeft - this._scrollMetrics.offsetX, + deltaY: scrollTop - this._scrollMetrics.offsetY, + } + }) + + const timestamp: number = e.timeStamp + const visibleLength: number = this._selectLength(e.nativeEvent.layoutMeasurement) + const contentLength: number = this._selectLength(e.nativeEvent.contentSize) + const offset: number = this._selectOffset(e.nativeEvent.contentOffset) + const dt: number = Math.max(1, timestamp - this._scrollMetrics.timestamp) + const dOffset: number = offset - this._scrollMetrics.offset + const velocity: number = dOffset / dt + this._scrollMetrics = { + contentLength, + dt, + dOffset, + offset, + offsetX: scrollLeft, + offsetY: scrollTop, + timestamp, + velocity, + visibleLength, + } + this._maybeCallOnStartReached() + this._maybeCallOnEndReached() + } + + scrollToOffset = (x: number = 0, y: number = 0): void => { + const node = this.$scrollView.current + node && node.scrollTo({ x, y }) + } + + componentDidMount () { + if (this.state.snapScrollTop || this.state.snapScrollLeft) { + this._initialScrollIndexTimeout = setTimeout(() => { + this.scrollToOffset(this.state.snapScrollLeft, this.state.snapScrollTop) + }, 0) + } + } + + getSnapshotBeforeUpdate (prevProps: ScrollViewProps, prevState: ScrollViewState) { + return prevState.snapScrollTop !== this.state.snapScrollTop || prevState.snapScrollLeft !== this.state.snapScrollLeft + } + + componentDidUpdate (prevProps: ScrollViewProps, prevState: ScrollViewState, snapshot: boolean) { + if (snapshot) { + this.scrollToOffset(this.state.snapScrollLeft, this.state.snapScrollTop) + } + } + + componentWillUnmount () { + this._initialScrollIndexTimeout && clearTimeout(this._initialScrollIndexTimeout) + } + + render () { + const { + style, + data, + heightForItem, + renderHeader, + renderFooter, + renderItem, + contentContainerStyle, + } = this.props + + const flattenStyle: ViewStyle & { [key: string]: any } = StyleSheet.flatten(style) + const wrapperStyle: ViewStyle = omit(flattenStyle, [ + 'alignItems', + 'justifyContent' + ]) + const _contentContainerStyle: ViewStyle & { [key: string]: any } = {} + if (flattenStyle) { + flattenStyle.alignItems && (_contentContainerStyle.alignItems = flattenStyle.alignItems) + flattenStyle.justifyContent && (_contentContainerStyle.justifyContent = flattenStyle.justifyContent) + } + + return ( + + ) + } +} + +export default _ScrollView diff --git a/packages/taro-components-rn/src/components/ScrollView/index.tsx b/packages/taro-components-rn/src/components/ScrollView/index.tsx index 4a5e0fb3e38c..9ee100aa7615 100644 --- a/packages/taro-components-rn/src/components/ScrollView/index.tsx +++ b/packages/taro-components-rn/src/components/ScrollView/index.tsx @@ -22,6 +22,7 @@ import * as React from 'react' import { ScrollView, + FlatList, NativeSyntheticEvent, NativeScrollEvent, LayoutChangeEvent, @@ -38,7 +39,7 @@ import { ScrollViewProps, ScrollViewState, ScrollMetrics } from './PropsType' // // Other // ] -class _ScrollView extends React.Component { +class _ScrollView extends React.Component, ScrollViewState> { static defaultProps = { upperThreshold: 50, lowerThreshold: 50, @@ -47,7 +48,7 @@ class _ScrollView extends React.Component { enableBackToTop: false, } - static getDerivedStateFromProps (props: ScrollViewProps, state: ScrollViewState) { + static getDerivedStateFromProps (props: ScrollViewProps, state: ScrollViewState) { return state.snapScrollTop !== props.scrollTop || state.snapScrollLeft !== props.scrollLeft ? { snapScrollTop: props.scrollTop, snapScrollLeft: props.scrollLeft @@ -70,7 +71,7 @@ class _ScrollView extends React.Component { velocity: 0, visibleLength: 0, } - $scrollView = React.createRef() + $scrollView = React.createRef() _hasDataChangedSinceEndReached: boolean _sentEndForContentLength: number = 0 _scrollEventThrottle: number = 50 @@ -180,8 +181,15 @@ class _ScrollView extends React.Component { } scrollToOffset = (x: number = 0, y: number = 0): void => { + const { scrollX, data, renderItem } = this.props const node = this.$scrollView.current - node && node.scrollTo({ x, y, animated: !!this.props.scrollWithAnimation }) + if (node) { + if (data && renderItem) { + (node as FlatList).scrollToOffset({ offset: scrollX ? x : y, animated: !!this.props.scrollWithAnimation }) + } else { + (node as ScrollView).scrollTo({ x, y, animated: !!this.props.scrollWithAnimation }) + } + } } componentDidMount () { @@ -192,11 +200,11 @@ class _ScrollView extends React.Component { } } - getSnapshotBeforeUpdate (prevProps: ScrollViewProps, prevState: ScrollViewState) { + getSnapshotBeforeUpdate (prevProps: ScrollViewProps, prevState: ScrollViewState) { return prevState.snapScrollTop !== this.state.snapScrollTop || prevState.snapScrollLeft !== this.state.snapScrollLeft } - componentDidUpdate (prevProps: ScrollViewProps, prevState: ScrollViewState, snapshot: boolean) { + componentDidUpdate (prevProps: ScrollViewProps, prevState: ScrollViewState, snapshot: boolean) { if (snapshot) { this.scrollToOffset(this.state.snapScrollLeft, this.state.snapScrollTop) } @@ -213,6 +221,8 @@ class _ScrollView extends React.Component { scrollX, enableBackToTop, contentContainerStyle, + data, + renderItem, } = this.props const flattenStyle: ViewStyle & { [key: string]: any } = StyleSheet.flatten(style) @@ -226,45 +236,59 @@ class _ScrollView extends React.Component { flattenStyle.justifyContent && (_contentContainerStyle.justifyContent = flattenStyle.justifyContent) } - return ( + const scrollElementProps = { + horizontal: scrollX, + onContentSizeChange: this._onContentSizeChange, + onLayout: this._onLayout, + onScroll: this._onScroll, + onScrollEndDrag: this._onScrollEndDrag, + onMomentumScrollEnd: this._onMomentumScrollEnd, + scrollEventThrottle: this._scrollEventThrottle, + scrollsToTop: !!enableBackToTop, + style: wrapperStyle, + contentContainerStyle: [_contentContainerStyle, contentContainerStyle], + ...omit(this.props, [ + // props + 'style', + 'scrollX', + 'upperThreshold', + 'lowerThreshold', + 'scrollTop', + 'scrollLeft', + 'scrollWithAnimation', + 'enableBackToTop', + 'onScrollToUpper', + 'onScrollToLower', + 'onScroll', + 'contentContainerStyle', + // SProps + 'horizontal', + 'onContentSizeChange', + 'onLayout', + 'onScroll', + 'onScrollEndDrag', + 'onMomentumScrollEnd', + 'scrollEventThrottle', + 'scrollsToTop', + 'style', + 'contentContainerStyle', + 'data', + 'renderItem', + 'keyExtractor', + ]), + ref: this.$scrollView + } + + return data && renderItem ? ( + index + ''} + /> + ) : ( {children} diff --git a/packages/taro-components-rn/src/components/Swiper/index.tsx b/packages/taro-components-rn/src/components/Swiper/index.tsx index 357c268decae..951acec06ae3 100644 --- a/packages/taro-components-rn/src/components/Swiper/index.tsx +++ b/packages/taro-components-rn/src/components/Swiper/index.tsx @@ -23,7 +23,7 @@ * * @example * { vertical, } = this.props - let styleHeight: number | undefined + // 从样式中取出部分常用样式 let formattedStyle: ViewStyle | undefined + const containerStyle: { [key: string]: any } = {} if (style) { const flattenStyle: ViewStyle = StyleSheet.flatten(style) if (flattenStyle) { - styleHeight = flattenStyle.height as number - delete flattenStyle.height + for (let key in flattenStyle) { + if (/width|height|margin.*/.test(key)) { + containerStyle[key] = flattenStyle[key as keyof ViewStyle] + delete flattenStyle[key as keyof ViewStyle] + } + } + if (containerStyle.width || containerStyle.height) { + containerStyle.flex = 0 + } formattedStyle = flattenStyle } } @@ -114,7 +123,7 @@ class _Swiper extends React.Component { horizontal={!vertical} onIndexChanged={this.onIndexChanged} onMomentumScrollEnd={this.onMomentumScrollEnd} - height={styleHeight} + containerStyle={containerStyle} style={formattedStyle || style} > {children} diff --git a/packages/taro-components-rn/tsconfig.json b/packages/taro-components-rn/tsconfig.json index 71d5dea0fa4e..37f930e6db7f 100644 --- a/packages/taro-components-rn/tsconfig.json +++ b/packages/taro-components-rn/tsconfig.json @@ -4,6 +4,10 @@ "src/**/*.tsx", "src/**/*.ts" ], + "exclude": [ + "src/**/ScrollViewExperimental.tsx", + "src/**/PropsTypeExperimental.tsx" + ], "compilerOptions": { "rootDir": "./src", "outDir": "./dist", diff --git a/packages/taro-components-rn/yarn.lock b/packages/taro-components-rn/yarn.lock index a6e16ffd3a36..11b7da85f2dd 100644 --- a/packages/taro-components-rn/yarn.lock +++ b/packages/taro-components-rn/yarn.lock @@ -519,6 +519,11 @@ resolved "https://registry.npm.taobao.org/@bang88/react-native-ultimate-listview/download/@bang88/react-native-ultimate-listview-3.3.0.tgz#b09199105b942aee4ae05729e4bd229353217ab6" integrity sha1-sJGZEFuUKu5K4Fcp5L0ik1MherY= +"@manjiz/react-native-swiper@^0.0.3": + version "0.0.3" + resolved "https://registry.npm.taobao.org/@manjiz/react-native-swiper/download/@manjiz/react-native-swiper-0.0.3.tgz#bcc03e573121751d50579050ef38461e21f33233" + integrity sha1-vMA+VzEhdR1QV5BQ7zhGHiHzMjM= + "@sinonjs/commons@^1", "@sinonjs/commons@^1.0.2": version "1.4.0" resolved "http://registry.npm.taobao.org/@sinonjs/commons/download/@sinonjs/commons-1.4.0.tgz#7b3ec2d96af481d7a0321252e7b1c94724ec5a78" diff --git a/packages/taro-components/package.json b/packages/taro-components/package.json index befc57b9242d..d21e5faead1f 100644 --- a/packages/taro-components/package.json +++ b/packages/taro-components/package.json @@ -1,6 +1,6 @@ { "name": "@tarojs/components", - "version": "1.3.0", + "version": "1.3.7", "description": "", "main:h5": "src/index.js", "main": "dist/index.js", @@ -49,14 +49,14 @@ "@babel/plugin-proposal-object-rest-spread": "^7.0.0", "@babel/plugin-transform-react-jsx": "^7.0.0", "@babel/preset-env": "^7.1.5", - "@tarojs/taro-h5": "1.3.0", + "@tarojs/taro-h5": "1.3.7", "@types/react": "^16.4.6", "@types/urijs": "^1.15.38", "babel-core": "^7.0.0-bridge.0", "babel-eslint": "10.0.1", "babel-jest": "^22.4.4", "babel-loader": "^8.0.5", - "babel-plugin-transform-taroapi": "1.3.0", + "babel-plugin-transform-taroapi": "1.3.7", "css-loader": "^2.1.1", "file-loader": "^3.0.1", "jest": "^22.4.4", diff --git a/packages/taro-components/src/components/camera/index.js b/packages/taro-components/src/components/camera/index.js index 0884abdc32f3..d6516e91dbcd 100644 --- a/packages/taro-components/src/components/camera/index.js +++ b/packages/taro-components/src/components/camera/index.js @@ -1,84 +1,17 @@ -import 'weui' import Nerv from 'nervjs' class Camera extends Nerv.Component { constructor () { super(...arguments) } - componentDidMount () { - this.initCamera() - let context = this.show.getContext('2d') - - // 绑定事件 - this.getCamera.addEventListener('click', () => { - context.drawImage(this.vide, 0, 0, 480, 320) - }) - } - initCamera () { - // 区分前后摄像头 - const {devicePosition} = this.props - let device - if (devicePosition === 'front') { - device = 'user' - } else { - device = 'environment' - } - - if (navigator.mediaDevices.getUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia) { - // 调用用户媒体设备,访问摄像头 - this.getUserMedia({ - audio: true, - video: { facingMode: device } - }, (stream) => { - // 兼容webkit内核浏览器 - let CompatibleURL = window.URL || window.webkitURL - this.vide.src = CompatibleURL.createObjectURL(stream) - // 播放视频 - this.vide.play() - }, (error) => { - if (error.name === 'NotAllowedError') { - this.props.binderror(error) - } else { - this.props.bindstop(error) - } - }) - } else { - alert('你的浏览器不支持访问用户媒体设备') - } - } - - // 访问用户媒体设备的兼容方法 - getUserMedia (constrains, success, error) { - if (navigator.mediaDevices.getUserMedia) { - // 最新标准API - navigator.mediaDevices.getUserMedia(constrains).then(success).catch(error) - } else if (navigator.webkitGetUserMedia) { - // webkit内核浏览器 - navigator.webkitGetUserMedia(constrains).then(success).catch(error) - } else if (navigator.getUserMedia) { - // 旧版API - navigator.getUserMedia(constrains).then(success).catch(error) - } + componentDidMount () { + console.error('h5 暂不支持 Camera 组件') } render () { - return ( -
-
- ) + return
} } -// 默认配置 -Camera.defaultProps = { - devicePosition: 'back' -} - export default Camera diff --git a/packages/taro-components/src/components/image/index.js b/packages/taro-components/src/components/image/index.js index be721bbe6c3a..6e23925eab74 100644 --- a/packages/taro-components/src/components/image/index.js +++ b/packages/taro-components/src/components/image/index.js @@ -6,20 +6,152 @@ import './style/index.scss' class Image extends Nerv.Component { constructor () { super(...arguments) + this.state = { + isLoaded: false + } + this._handleScroll = this._handleScroll.bind(this) + this.handleScroll = this.throttle(this._handleScroll, 100) + } + + componentDidMount () { + if (this.props.lazyLoad) { + window.addEventListener('scroll', this.handleScroll) + window.addEventListener('resize', this.handleScroll) + this._handleScroll() + } + } + + componentWillUnMount () { + if (this.props.lazyLoad) { + window.removeEventListener('scroll', this.handleScroll) + window.removeEventListener('resize', this.handleScroll) + } + } + + getClientHeight () { + let clientHeight = 0 + if (document.body.clientHeight && document.documentElement.clientHeight) { + clientHeight = Math.min( + document.body.clientHeight, + document.documentElement.clientHeight + ) + } else { + clientHeight = Math.max( + document.body.clientHeight, + document.documentElement.clientHeight + ) + } + return clientHeight + } + + getScrollTop () { + let scrollTop = 0 + if (document.documentElement && document.documentElement.scrollTop) { + scrollTop = document.documentElement.scrollTop + } else if (document.body) { + scrollTop = document.body.scrollTop + } else { + scrollTop = window.scrollY || window.pageYOffset + } + + return scrollTop + } + + throttle (fn, delay) { + let timer = null + + return function () { + let context = this + let args = arguments + clearTimeout(timer) + timer = setTimeout(function () { + fn.apply(context, args) + }, delay) + } + } + + _handleScroll () { + const { offset = 0 } = this.props // 偏移量 + + const { nodeTop, nodeBottom } = this.getNodeTop() + + const viewTop = this.getScrollTop() + const viewBottom = viewTop + this.getClientHeight() + + // 当图片出现在视野范围内,设置真正的图片,同时移除监听 + if (nodeBottom + offset >= viewTop && nodeTop - offset <= viewBottom) { + this.setState( + { + isLoaded: true + }, + () => { + Nerv.findDOMNode(this).children[0].src = this.props.src + } + ) + window.removeEventListener('scroll', this.handleScroll) + window.removeEventListener('resize', this.handleScroll) + } + } + + getNodeTop () { + const viewTop = this.getScrollTop() + + const img = Nerv.findDOMNode(this) // 当前节点 + const nodeTop = img.getBoundingClientRect().top + viewTop + const nodeBottom = nodeTop + img.offsetHeight + return { + nodeTop: nodeTop, + nodeBottom: nodeBottom + } } render () { - const { className, src, style, mode, onLoad, onError, ...reset } = this.props - const cls = classNames('taro-img', { - 'taro-img__widthfix': mode === 'widthFix' - }, className) - const imgCls = + const { + className, + src, + style, + mode, + onLoad, + onError, + lazyLoad, + ...reset + } = this.props + const cls = classNames( + 'taro-img', + { + 'taro-img__widthfix': mode === 'widthFix' + }, + className + ) + const imgCls = classNames( 'taro-img__mode-' + - (mode || 'scaleToFill').toLowerCase().replace(/\s/g, '') + (mode || 'scaleToFill').toLowerCase().replace(/\s/g, '') + ) + + let currenSrc = src + + if (lazyLoad) { + const { isLoaded } = this.state + currenSrc = isLoaded ? src : '' + } return (
- + {lazyLoad ? ( + + ) : ( + + )}
) } diff --git a/packages/taro-components/src/components/image/style/index.scss b/packages/taro-components/src/components/image/style/index.scss index d4e86dd7f368..0d64e943571e 100644 --- a/packages/taro-components/src/components/image/style/index.scss +++ b/packages/taro-components/src/components/image/style/index.scss @@ -1,3 +1,6 @@ +img[src=""] { + opacity: 0; +} .taro-img { display: inline-block; overflow: hidden; diff --git a/packages/taro-components/src/components/progress/index.js b/packages/taro-components/src/components/progress/index.js index a7ffaa2eca52..26eaee4422fb 100644 --- a/packages/taro-components/src/components/progress/index.js +++ b/packages/taro-components/src/components/progress/index.js @@ -16,7 +16,8 @@ function parseType (props) { strokeWidth, activeColor, backgroundColor, - active + active, + borderRadius } = props // 抛出错误信息 @@ -33,6 +34,8 @@ function parseType (props) { if (backgroundColor) { isString(backgroundColor) ? '' : throwErrorMsg('backgroundColor') } + + if (borderRadius) isString(borderRadius) ? '' : throwErrorMsg('borderRadius') } const Progress = (props) => { @@ -44,7 +47,8 @@ const Progress = (props) => { activeColor, backgroundColor, active, - percent + percent, + borderRadius } = props let pgPercent = percent > 100 ? 100 : percent < 0 ? 0 : percent const cls = classNames('weui-progress', className) @@ -52,7 +56,8 @@ const Progress = (props) => { width: pgPercent + '%', backgroundColor: activeColor, WebkitTransition: active ? `width 1s ease-in-out` : 'none', - transition: active ? `width 1s ease-in-out` : 'none' + transition: active ? `width 1s ease-in-out` : 'none', + borderRadius: borderRadius ? `${borderRadius}px` : 0 } let pgHeight = { height: strokeWidth + 'px', diff --git a/packages/taro-components/src/components/progress/index.md b/packages/taro-components/src/components/progress/index.md index 3ae8a1e55812..76635c141cf2 100644 --- a/packages/taro-components/src/components/progress/index.md +++ b/packages/taro-components/src/components/progress/index.md @@ -12,3 +12,4 @@ progress | √ | backgroundColor | Color | 6 | 未选择的进度条的颜色 | | √ | active | Boolean | false | 进度条从左往右的动画 | | | active-mode | String | backwards | backwards: 动画从头播;forwards:动画从上次结束点接着播 | +| | borderRadius | Number | 0 | 圆角大小, 单位 px | diff --git a/packages/taro-components/src/components/scroll-view/index.js b/packages/taro-components/src/components/scroll-view/index.js index 9e4011bae60f..97a35484a78a 100644 --- a/packages/taro-components/src/components/scroll-view/index.js +++ b/packages/taro-components/src/components/scroll-view/index.js @@ -4,19 +4,19 @@ import omit from 'omit.js' import classNames from 'classnames' import './style/index.scss' -function easeOutScroll (from, to, callback) { +function easeOutScroll(from, to, callback) { if (from === to || typeof from !== 'number') { return } let change = to - from const dur = 500 const sTime = +new Date() - function linear (t, b, c, d) { + function linear(t, b, c, d) { return c * t / d + b } const isLarger = to >= from - function step () { + function step() { from = linear(+new Date() - sTime, from, change, dur) if ((isLarger && from >= to) || (!isLarger && to >= from)) { callback(to) @@ -27,7 +27,7 @@ function easeOutScroll (from, to, callback) { } step() } -function throttle (fn, delay) { +function throttle(fn, delay) { let timer = null return function () { clearTimeout(timer) @@ -37,15 +37,15 @@ function throttle (fn, delay) { } } class ScrollView extends Nerv.Component { - constructor () { + constructor() { super(...arguments) } onTouchMove = e => { - e.stopPropagation() + e.stopPropagation(); } - componentDidMount () { + componentDidMount() { setTimeout(() => { const props = this.props if (props.scrollY && typeof props.scrollTop === 'number') { @@ -71,7 +71,7 @@ class ScrollView extends Nerv.Component { }, 10) } - componentWillReceiveProps (nextProps) { + componentWillReceiveProps(nextProps) { const props = this.props // Y 轴滚动 if ( @@ -105,12 +105,13 @@ class ScrollView extends Nerv.Component { } } - render () { + render() { const { className, onScroll, onScrollToUpper, onScrollToLower, + onTouchMove, scrollX, scrollY } = this.props @@ -170,15 +171,22 @@ class ScrollView extends Nerv.Component { uperAndLowerThrottle() onScroll && onScroll(e) } + const _onTouchMove = e => { + onTouchMove ? onTouchMove(e) : this.onTouchMove(e) + } return (
{ this.container = container }} - {...omit(this.props, ['className', 'scrollTop', 'scrollLeft'])} + { + ...omit(this.props, ['className', 'scrollTop', 'scrollLeft']) + } className={cls} onScroll={_onScroll} - onTouchMove={this.onTouchMove}> + onTouchMove={ + _onTouchMove + } > {this.props.children}
) diff --git a/packages/taro-components/src/components/swiper/index.js b/packages/taro-components/src/components/swiper/index.js index 40bc4738ea4e..4fbfe6174bb8 100644 --- a/packages/taro-components/src/components/swiper/index.js +++ b/packages/taro-components/src/components/swiper/index.js @@ -18,10 +18,10 @@ class SwiperItem extends Nerv.Component { const createEvent = type => { let e try { - e = new TouchEvent(type); + e = new TouchEvent(type) } catch (err) { - e = document.createEvent('Event'); - e.initEvent(type, true, true); + e = document.createEvent('Event') + e.initEvent(type, true, true) } return e } @@ -107,7 +107,12 @@ class Swiper extends Nerv.Component { componentWillReceiveProps (nextProps) { if (this.mySwiper) { - const nextCurrent = nextProps.current || this._$current || 0 + let nextCurrent = 0 + if (nextProps.current === 0) { + nextCurrent = this._$current || 0 + } else { + nextCurrent = nextProps.current || this._$current || 0 + } // 是否衔接滚动模式 if (nextProps.circular) { this.mySwiper.slideToLoop(parseInt(nextCurrent, 10)) // 更新下标 @@ -128,6 +133,13 @@ class Swiper extends Nerv.Component { let defaultIndicatorColor = indicatorColor || 'rgba(0, 0, 0, .3)' let defaultIndicatorActiveColor = indicatorActiveColor || '#000' const cls = classNames(`taro-swiper-${this._id}`, 'swiper-container', className) + const paginationCls = classNames( + 'swiper-pagination', + { + 'swiper-pagination-hidden': !this.props.indicatorDots, + 'swiper-pagination-bullets': this.props.indicatorDots + } + ) return (
{ this.$el = el }}>
{this.props.children}
- {this.props.indicatorDots ?
: null} +
) } diff --git a/packages/taro-components/src/components/video/index.js b/packages/taro-components/src/components/video/index.js index 77e114984f7b..d39bd1ea7cce 100644 --- a/packages/taro-components/src/components/video/index.js +++ b/packages/taro-components/src/components/video/index.js @@ -210,6 +210,7 @@ class Video extends Component { } onLoadedMetadata = e => { + if (this.props.poster) return this.setState({ duration: this.videoRef.duration }) diff --git a/packages/taro-components/types/Form.d.ts b/packages/taro-components/types/Form.d.ts index a592d76ce6c2..0472ba27ad56 100644 --- a/packages/taro-components/types/Form.d.ts +++ b/packages/taro-components/types/Form.d.ts @@ -3,21 +3,49 @@ import { StandardProps, CommonEventFunction } from './common' export interface FormProps extends StandardProps { /** - * 是否返回 formId 用于发送模板消息 + * 是否返回 `formId` 用于发送模板消息。 + * + * @default false */ reportSubmit?: boolean, + /** + * 等待一段时间(毫秒数)以确认 `formId` 是否生效。 + * 如果未指定这个参数,`formId` 有很小的概率是无效的(如遇到网络失败的情况)。 + * 指定这个参数将可以检测 `formId` 是否有效, + * 以这个参数的时间作为这项检测的超时时间。 + * 如果失败,将返回 `requestFormId:fail` 开头的 `formId`。 + * + * @default 0 + * + * @since 2.6.2 + */ + reportSubmitTimeout?: number, + /** * 携带 form 中的数据触发 submit 事件 * * event.detail = {value : {'name': 'value'} , formId: ''} */ - onSubmit?: CommonEventFunction, + onSubmit?: CommonEventFunction<{ + /** + * 当点击 `
` 表单中 `form-type` 为 `submit` 的 ` + *
+ * ) + * } + */ +export function useDispatch () { + const store = useStore() + return store.dispatch +} diff --git a/packages/taro-redux/src/hooks/use-redux-context.js b/packages/taro-redux/src/hooks/use-redux-context.js new file mode 100644 index 000000000000..7e8099dc1d24 --- /dev/null +++ b/packages/taro-redux/src/hooks/use-redux-context.js @@ -0,0 +1,24 @@ +import { useContext } from '@tarojs/taro' +import { ReduxContext } from './context' + +/** + * A hook to access the value of the `ReactReduxContext`. This is a low-level + * hook that you should usually not need to call directly. + * + * @returns {any} the value of the `ReactReduxContext` + * + * @example + * + * import React from 'react' + * import { useReduxContext } from 'react-redux' + * + * export const CounterComponent = ({ value }) => { + * const { store } = useReduxContext() + * return
{store.getState()}
+ * } + */ +export function useReduxContext () { + const contextValue = useContext(ReduxContext) + + return contextValue +} diff --git a/packages/taro-redux/src/hooks/use-selector.js b/packages/taro-redux/src/hooks/use-selector.js new file mode 100644 index 000000000000..9f4092cd4133 --- /dev/null +++ b/packages/taro-redux/src/hooks/use-selector.js @@ -0,0 +1,110 @@ +import { useReducer, useRef, useMemo, useEffect } from '@tarojs/taro' +import { useReduxContext } from './use-redux-context' +import Subscription from '../utils/subscription' +import invariant from '../utils/invariant' + +const refEquality = (a, b) => a === b + +/** + * A hook to access the redux store's state. This hook takes a selector function + * as an argument. The selector is called with the store state. + * + * This hook takes an optional equality comparison function as the second parameter + * that allows you to customize the way the selected state is compared to determine + * whether the component needs to be re-rendered. + * + * @param {Function} selector the selector function + * @param {Function=} equalityFn the function that will be used to determine equality + * + * @returns {any} the selected state + * + * @example + * + * import React from 'react' + * import { useSelector } from 'react-redux' + * + * export const CounterComponent = () => { + * const counter = useSelector(state => state.counter) + * return
{counter}
+ * } + */ +export function useSelector (selector, equalityFn = refEquality) { + invariant(selector, `You must pass a selector to useSelectors`) + + const { store, subscription: contextSub } = useReduxContext() + const [, forceRender] = useReducer(s => s + 1, 0) + + const subscription = useMemo(() => new Subscription(store, contextSub), [ + store, + contextSub + ]) + + const latestSubscriptionCallbackError = useRef() + const latestSelector = useRef() + const latestSelectedState = useRef() + + let selectedState + + try { + if ( + selector !== latestSelector.current || + latestSubscriptionCallbackError.current + ) { + selectedState = selector(store.getState()) + } else { + selectedState = latestSelectedState.current + } + } catch (err) { + let errorMessage = `An error occured while selecting the store state: ${ + err.message + }.` + + if (latestSubscriptionCallbackError.current) { + errorMessage += `\nThe error may be correlated with this previous error:\n${ + latestSubscriptionCallbackError.current.stack + }\n\nOriginal stack trace:` + } + + throw new Error(errorMessage) + } + + useEffect(() => { + latestSelector.current = selector + latestSelectedState.current = selectedState + latestSubscriptionCallbackError.current = undefined + }) + + useEffect( + () => { + function checkForUpdates () { + try { + const newSelectedState = latestSelector.current(store.getState()) + + if (equalityFn(newSelectedState, latestSelectedState.current)) { + return + } + + latestSelectedState.current = newSelectedState + } catch (err) { + // we ignore all errors here, since when the component + // is re-rendered, the selectors are called again, and + // will throw again, if neither props nor store state + // changed + latestSubscriptionCallbackError.current = err + } + + forceRender({}) + } + + subscription.onStateChange = checkForUpdates + subscription.trySubscribe() + + checkForUpdates() + + return () => subscription.tryUnsubscribe() + }, + [store, subscription] + ) + + return selectedState +} diff --git a/packages/taro-redux/src/hooks/use-store.js b/packages/taro-redux/src/hooks/use-store.js new file mode 100644 index 000000000000..3f276bb88af1 --- /dev/null +++ b/packages/taro-redux/src/hooks/use-store.js @@ -0,0 +1,21 @@ +import { useReduxContext } from './use-redux-context' + +/** + * A hook to access the redux store. + * + * @returns {any} the redux store + * + * @example + * + * import React from 'react' + * import { useStore } from 'react-redux' + * + * export const ExampleComponent = () => { + * const store = useStore() + * return
{store.getState()}
+ * } + */ +export function useStore () { + const { store } = useReduxContext() + return store +} diff --git a/packages/taro-redux/src/index.js b/packages/taro-redux/src/index.js index 01143147c6df..e8beb0dba95c 100644 --- a/packages/taro-redux/src/index.js +++ b/packages/taro-redux/src/index.js @@ -1,17 +1,29 @@ import { getStore, setStore } from './utils/store' import connect from './connect/connect' import Provider from './connect/Provider' +import { useDispatch } from './hooks/use-dispatch' +import { useSelector } from './hooks/use-selector' +import { useStore } from './hooks/use-store' +import { ReduxContext } from './hooks/context' export default { connect, Provider, getStore, - setStore + setStore, + useDispatch, + useSelector, + useStore, + ReduxContext } export { connect, Provider, getStore, - setStore + setStore, + useDispatch, + useSelector, + useStore, + ReduxContext } diff --git a/packages/taro-redux/src/utils/batch.js b/packages/taro-redux/src/utils/batch.js new file mode 100644 index 000000000000..439a06d831c3 --- /dev/null +++ b/packages/taro-redux/src/utils/batch.js @@ -0,0 +1,12 @@ +// Default to a dummy "batch" implementation that just runs the callback +function defaultNoopBatch (callback) { + callback() +} + +let batch = defaultNoopBatch + +// Allow injecting another batching function later +export const setBatch = newBatch => (batch = newBatch) + +// Supply a getter just to skip dealing with ESM bindings +export const getBatch = () => batch diff --git a/packages/taro-redux/src/utils/invariant.js b/packages/taro-redux/src/utils/invariant.js new file mode 100644 index 000000000000..7afabca56ebd --- /dev/null +++ b/packages/taro-redux/src/utils/invariant.js @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +'use strict' +/** + * Use invariant() to assert state which your program assumes to be true. + * + * Provide sprintf-style format (only %s is supported) and arguments + * to provide information about what broke and what you were + * expecting. + * + * The invariant message will be stripped in production, but the invariant + * will remain to ensure logic does not differ in production. + */ + +export default function invariant (condition, format, a, b, c, d, e, f) { + if (!condition) { + var error + if (format === undefined) { + error = new Error( + 'Minified exception occurred; use the non-minified dev environment ' + + 'for the full error message and additional helpful warnings.' + ) + } else { + var args = [a, b, c, d, e, f] + var argIndex = 0 + error = new Error( + format.replace(/%s/g, function () { + return args[argIndex++] + }) + ) + error.name = 'Invariant Violation' + } + + error.framesToPop = 1 // we don't care about invariant's own frame + throw error + } +} diff --git a/packages/taro-redux/src/utils/store.js b/packages/taro-redux/src/utils/store.js index ec08d90ae709..a56ee04dc8fe 100644 --- a/packages/taro-redux/src/utils/store.js +++ b/packages/taro-redux/src/utils/store.js @@ -4,6 +4,8 @@ const globalRef = Object.getPrototypeOf(appGlobal) || appGlobal export function getStore () { if (process.env.TARO_ENV === 'quickapp') { return globalRef.store || null + } else if (process.env.TARO_ENV === 'alipay') { + return my.taroReduxStore || null } return store } @@ -11,6 +13,8 @@ export function getStore () { export function setStore (arg) { if (process.env.TARO_ENV === 'quickapp') { globalRef.store = arg + } else if (process.env.TARO_ENV === 'alipay') { + my.taroReduxStore = arg } else { store = arg } diff --git a/packages/taro-redux/src/utils/subscription.js b/packages/taro-redux/src/utils/subscription.js new file mode 100644 index 000000000000..38628d3cfe3d --- /dev/null +++ b/packages/taro-redux/src/utils/subscription.js @@ -0,0 +1,99 @@ +import { getBatch } from './batch' + +// encapsulates the subscription logic for connecting a component to the redux store, as +// well as nesting subscriptions of descendant components, so that we can ensure the +// ancestor components re-render before descendants + +const CLEARED = null +const nullListeners = { notify () {} } + +function createListenerCollection () { + const batch = getBatch() + // the current/next pattern is copied from redux's createStore code. + // TODO: refactor+expose that code to be reusable here? + let current = [] + let next = [] + + return { + clear () { + next = CLEARED + current = CLEARED + }, + + notify () { + const listeners = (current = next) + batch(() => { + for (let i = 0; i < listeners.length; i++) { + listeners[i]() + } + }) + }, + + get () { + return next + }, + + subscribe (listener) { + let isSubscribed = true + if (next === current) next = current.slice() + next.push(listener) + + return function unsubscribe () { + if (!isSubscribed || current === CLEARED) return + isSubscribed = false + + if (next === current) next = current.slice() + next.splice(next.indexOf(listener), 1) + } + } + } +} + +export default class Subscription { + constructor (store, parentSub) { + this.store = store + this.parentSub = parentSub + this.unsubscribe = null + this.listeners = nullListeners + + this.handleChangeWrapper = this.handleChangeWrapper.bind(this) + } + + addNestedSub (listener) { + this.trySubscribe() + return this.listeners.subscribe(listener) + } + + notifyNestedSubs () { + this.listeners.notify() + } + + handleChangeWrapper () { + if (this.onStateChange) { + this.onStateChange() + } + } + + isSubscribed () { + return Boolean(this.unsubscribe) + } + + trySubscribe () { + if (!this.unsubscribe) { + this.unsubscribe = this.parentSub + ? this.parentSub.addNestedSub(this.handleChangeWrapper) + : this.store.subscribe(this.handleChangeWrapper) + + this.listeners = createListenerCollection() + } + } + + tryUnsubscribe () { + if (this.unsubscribe) { + this.unsubscribe() + this.unsubscribe = null + this.listeners.clear() + this.listeners = nullListeners + } + } +} diff --git a/packages/taro-redux/types/index.d.ts b/packages/taro-redux/types/index.d.ts index ebeab1621443..d9618cea7673 100644 --- a/packages/taro-redux/types/index.d.ts +++ b/packages/taro-redux/types/index.d.ts @@ -62,3 +62,85 @@ export interface ProviderProps { } export class Provider extends Component, any> { } + + +/** + * A hook to access the redux store's state. This hook takes a selector function + * as an argument. The selector is called with the store state. + * + * This hook takes an optional equality comparison function as the second parameter + * that allows you to customize the way the selected state is compared to determine + * whether the component needs to be re-rendered. + * + * If you do not want to have to specify the root state type for whenever you use + * this hook with an inline selector you can use the `TypedUseSelectorHook` interface + * to create a version of this hook that is properly typed for your root state. + * + * @param selector the selector function + * @param equalityFn the function that will be used to determine equality + * + * @returns the selected state + * + * @example + * + * import React from 'react' + * import { useSelector } from 'react-redux' + * import { RootState } from './store' + * + * export const CounterComponent = () => { + * const counter = useSelector((state: RootState) => state.counter) + * return
{counter}
+ * } + */ +export function useSelector( + selector: (state: TState) => TSelected, + equalityFn?: (left: TSelected, right: TSelected) => boolean +): TSelected; + +/** + * A hook to access the redux store. + * + * @returns the redux store + * + * @example + * + * import React from 'react' + * import { useStore } from 'react-redux' + * + * export const ExampleComponent = () => { + * const store = useStore() + * return
{store.getState()}
+ * } + */ +export function useStore(): Store; + +/** + * A hook to access the redux `dispatch` function. + * + * Note for `redux-thunk` users: the return type of the returned `dispatch` functions for thunks is incorrect. + * However, it is possible to get a correctly typed `dispatch` function by creating your own custom hook typed + * from the store's dispatch function like this: `const useThunkDispatch = () => useDispatch();` + * + * @returns redux store's `dispatch` function + * + * @example + * + * import React, { useCallback } from 'react' + * import { useDispatch } from 'react-redux' + * + * export const CounterComponent = ({ value }) => { + * const dispatch = useDispatch() + * return ( + *
+ * {value} + * + *
+ * ) + * } + */ +// NOTE: the first overload below and note above can be removed if redux-thunk typings add an overload for +// the Dispatch function (see also this PR: https://github.com/reduxjs/redux-thunk/pull/247) +export function useDispatch>(): TDispatch; +export function useDispatch
(): Dispatch; diff --git a/packages/taro-rn-runner/package.json b/packages/taro-rn-runner/package.json index fdfd17171740..c7b24b385e48 100644 --- a/packages/taro-rn-runner/package.json +++ b/packages/taro-rn-runner/package.json @@ -1,6 +1,6 @@ { "name": "@tarojs/rn-runner", - "version": "1.3.0", + "version": "1.3.7", "description": "ReactNative build tool for taro", "main": "index.js", "scripts": { diff --git a/packages/taro-rn/package.json b/packages/taro-rn/package.json index 84cc37a2a837..8f9904c441ee 100644 --- a/packages/taro-rn/package.json +++ b/packages/taro-rn/package.json @@ -1,6 +1,6 @@ { "name": "@tarojs/taro-rn", - "version": "1.3.0", + "version": "1.3.7", "description": "Taro RN framework", "main": "./index.js", "files": [ @@ -27,7 +27,7 @@ "author": "O2Team", "license": "MIT", "dependencies": { - "@tarojs/taro": "1.3.0", + "@tarojs/taro": "1.3.7", "base64-js": "^1.3.0", "react-native-image-crop-picker": "^0.23.1", "react-native-image-zoom-viewer": "^2.2.13", diff --git a/packages/taro-rn/src/api/interface/toast.js b/packages/taro-rn/src/api/interface/toast.js index 60353668a979..2a81544fa5de 100644 --- a/packages/taro-rn/src/api/interface/toast.js +++ b/packages/taro-rn/src/api/interface/toast.js @@ -118,7 +118,7 @@ function showToast (options) { } else if (icon === 'loading') { - ToastView = + ToastView = } else if (icon === 'none') { ToastView = diff --git a/packages/taro-rn/src/component.js b/packages/taro-rn/src/component.js index dc70b2dbd186..c7f3c2c1b0e6 100644 --- a/packages/taro-rn/src/component.js +++ b/packages/taro-rn/src/component.js @@ -7,7 +7,7 @@ class Component extends React.Component { constructor (props, context) { super(props, context) if (props.navigation) { - this.$router = {params: props.navigation.state.params || {}} + this.$router = {params: props.navigation.state.params || {}, path: props.navigation.state.routeName ? ('/' + props.navigation.state.routeName) : null} } } @@ -25,7 +25,7 @@ class PureComponent extends React.PureComponent { constructor (props, context) { super(props, context) if (props.navigation) { - this.$router = {params: props.navigation.state.params || {}} + this.$router = {params: props.navigation.state.params || {}, path: props.navigation.state.routeName ? ('/' + props.navigation.state.routeName) : null} } } @@ -39,5 +39,4 @@ class PureComponent extends React.PureComponent { } } - export { Component, PureComponent } diff --git a/packages/taro-rn/src/index.ts b/packages/taro-rn/src/index.ts index dedb36604ddf..dc41d76637a8 100644 --- a/packages/taro-rn/src/index.ts +++ b/packages/taro-rn/src/index.ts @@ -12,6 +12,18 @@ import { import initNativeApi from './native-api' import { Component, PureComponent } from './component' +import { + createContext, + useState, + useEffect, + useReducer, + useCallback, + useMemo, + useRef, + useLayoutEffect, + useContext +} from 'react' + const Taro = { getEnv, ENV_TYPE, @@ -22,7 +34,16 @@ const Taro = { internal_safe_get, internal_safe_set, Component, - PureComponent + PureComponent, + createContext, + useState, + useEffect, + useReducer, + useCallback, + useMemo, + useRef, + useLayoutEffect, + useContext } export { @@ -35,7 +56,16 @@ export { internal_safe_get, internal_safe_set, Component, - PureComponent + PureComponent, + createContext, + useState, + useEffect, + useReducer, + useCallback, + useMemo, + useRef, + useLayoutEffect, + useContext } initNativeApi(Taro) diff --git a/packages/taro-router-rn/package.json b/packages/taro-router-rn/package.json index bfdd69501897..17d3df9cd4de 100644 --- a/packages/taro-router-rn/package.json +++ b/packages/taro-router-rn/package.json @@ -1,6 +1,6 @@ { "name": "@tarojs/taro-router-rn", - "version": "1.3.0", + "version": "1.3.7", "description": "taro-router-rn", "main": "./index.js", "files": [ diff --git a/packages/taro-router-rn/src/TaroProvider.js b/packages/taro-router-rn/src/TaroProvider.js index 16827c8648f2..46847f0555ad 100644 --- a/packages/taro-router-rn/src/TaroProvider.js +++ b/packages/taro-router-rn/src/TaroProvider.js @@ -10,22 +10,31 @@ class TaroProvider extends React.Component { this.refreshProviderRef = React.createRef() } - componentDidMount () { + navigationMethodInit () { let {Taro} = this.props + Taro.navigateTo = this.wxNavigateTo.bind(this) + Taro.redirectTo = this.wxRedirectTo.bind(this) + Taro.navigateBack = this.wxNavigateBack.bind(this) + Taro.switchTab = this.wxSwitchTab.bind(this) + Taro.getCurrentPages = this.wxGetCurrentPages.bind(this) + Taro.showTabBar = this.showTabBar.bind(this) + Taro.hideTabBar = this.hideTabBar.bind(this) + } + + componentWillMount () { + this.navigationMethodInit() // didFocus this.didFocusSubscription = this.props.navigation.addListener( 'didFocus', payload => { // 页面进入后回退并不会调用 React 生命周期,需要在路由生命周期中绑定 this - Taro.navigateTo = this.wxNavigateTo.bind(this) - Taro.redirectTo = this.wxRedirectTo.bind(this) - Taro.navigateBack = this.wxNavigateBack.bind(this) - Taro.switchTab = this.wxSwitchTab.bind(this) - Taro.getCurrentPages = this.wxGetCurrentPages.bind(this) - Taro.showTabBar = this.showTabBar.bind(this) - Taro.hideTabBar = this.hideTabBar.bind(this) + this.navigationMethodInit() } ) + } + + componentDidMount () { + let {Taro} = this.props try { Taro.startPullDownRefresh = this.refreshProviderRef.current && this.refreshProviderRef.current.handlePullDownRefresh Taro.stopPullDownRefresh = this.refreshProviderRef.current && this.refreshProviderRef.current.stopPullDownRefresh diff --git a/packages/taro-router-rn/src/getWrappedScreen.js b/packages/taro-router-rn/src/getWrappedScreen.js index 390e0c7bede8..0a1a87d3eb0f 100644 --- a/packages/taro-router-rn/src/getWrappedScreen.js +++ b/packages/taro-router-rn/src/getWrappedScreen.js @@ -116,16 +116,21 @@ function getWrappedScreen (Screen, Taro, globalNavigationOptions = {}) { } } - componentDidMount () { + navigationMethodInit () { + Taro.setNavigationBarTitle = this.setNavigationBarTitle.bind(this) + Taro.setNavigationBarColor = this.setNavigationBarColor.bind(this) + Taro.showNavigationBarLoading = this.showNavigationBarLoading.bind(this) + Taro.hideNavigationBarLoading = this.hideNavigationBarLoading.bind(this) + } + + componentWillMount () { + this.navigationMethodInit() // didFocus this.didFocusSubscription = this.props.navigation.addListener( 'didFocus', payload => { // 页面进入后回退并不会调用 React 生命周期,需要在路由生命周期中绑定 this - Taro.setNavigationBarTitle = this.setNavigationBarTitle.bind(this) - Taro.setNavigationBarColor = this.setNavigationBarColor.bind(this) - Taro.showNavigationBarLoading = this.showNavigationBarLoading.bind(this) - Taro.hideNavigationBarLoading = this.hideNavigationBarLoading.bind(this) + this.navigationMethodInit() // 页面聚焦时,调用 componentDidShow this.getScreenInstance().componentDidShow && this.getScreenInstance().componentDidShow() } @@ -148,6 +153,11 @@ function getWrappedScreen (Screen, Taro, globalNavigationOptions = {}) { this.willBlurSubscription && this.willBlurSubscription.remove() } + onPullDownRefresh () { + this.getScreenInstance().onPullDownRefresh && + this.getScreenInstance().onPullDownRefresh() + } + render () { const {globalEnablePullDownRefresh = false} = globalNavigationOptions const {enablePullDownRefresh, disableScroll} = getNavigationOptions(Screen.config) @@ -160,7 +170,7 @@ function getWrappedScreen (Screen, Taro, globalNavigationOptions = {}) { Taro={Taro} enablePullDownRefresh={isScreenEnablePullDownRefresh} disableScroll={disableScroll} - onPullDownRefresh={screenInstance.onPullDownRefresh && screenInstance.onPullDownRefresh.bind(screenInstance)} + onPullDownRefresh={this.onPullDownRefresh.bind(this)} onReachBottom={screenInstance.onReachBottom} onScroll={screenInstance.onScroll} {...this.props} diff --git a/packages/taro-router/jest.config.js b/packages/taro-router/jest.config.js index 352c5e73eeee..c2e9a47b83ab 100644 --- a/packages/taro-router/jest.config.js +++ b/packages/taro-router/jest.config.js @@ -4,5 +4,8 @@ module.exports = { testURL: 'https://taro.aotu.io', globals: { window: true + }, + moduleNameMapper: { + 'nervjs': '/node_modules/nervjs' } } diff --git a/packages/taro-router/package.json b/packages/taro-router/package.json index 21583fd936b5..b74b561a0176 100644 --- a/packages/taro-router/package.json +++ b/packages/taro-router/package.json @@ -1,6 +1,6 @@ { "name": "@tarojs/router", - "version": "1.3.0", + "version": "1.3.7", "description": "Taro-router", "main:h5": "dist/index.esm.js", "main": "index.js", @@ -41,7 +41,7 @@ "@babel/plugin-syntax-dynamic-import": "7.0.0", "@babel/plugin-transform-react-jsx": "7.0.0", "@babel/preset-env": "7.1.5", - "@tarojs/taro-h5": "1.3.0", + "@tarojs/taro-h5": "1.3.7", "@types/history": "4.7.2", "@types/jasmine": "2.8.11", "@types/jest": "23.3.9", diff --git a/packages/taro-router/src/__tests__/router-test.tsx b/packages/taro-router/src/__tests__/router-test.tsx index 528f04292e9a..48eb0914e608 100644 --- a/packages/taro-router/src/__tests__/router-test.tsx +++ b/packages/taro-router/src/__tests__/router-test.tsx @@ -21,7 +21,7 @@ beforeEach(() => { firstPagePath: '/pages/index/index', customRoutes: { '/pages/index/index': '/index', - '/pages/about/about': '/about' + '/pages/about/index': '/about' } }) mountApis(mockHistory) @@ -83,7 +83,7 @@ describe('router component', () => { await wait(100) expect(window.getComputedStyle(dom.childNodes[0]).display).toEqual('block') Taro.navigateTo({ - url: '/pages/about/about' + url: '/pages/about/index' }) await wait(100) expect(getComputedStyle(dom.childNodes[0]).display).toEqual('none') @@ -133,7 +133,7 @@ describe('router component', () => { await wait(100) expect(routerParams).toMatchObject({}) Taro.navigateTo({ - url: '/pages/about/about' + url: '/pages/about/index' }) await wait(100) expect(routerParams).toMatchObject({}) diff --git a/packages/taro-router/src/router/route.tsx b/packages/taro-router/src/router/route.tsx index 3a3fdcb5b61a..400a90b1210a 100644 --- a/packages/taro-router/src/router/route.tsx +++ b/packages/taro-router/src/router/route.tsx @@ -1,5 +1,5 @@ import Taro from '@tarojs/taro-h5' -import Nerv from 'nervjs' +import Nerv, { nextTick } from 'nervjs' import { tryToCall } from '../utils' import { Location, RouteObj } from '../utils/types' @@ -49,8 +49,11 @@ class Route extends Taro.Component { const path = currentLocation.path; const key = currentLocation.state.key; const isIndex = this.props.isIndex; - if (isIndex && path === '/') return true - return key === this.props.key + if (key !== undefined) { + return key === this.props.key + } else { + return isIndex && path === '/' + } } getWrapRef = ref => { @@ -76,13 +79,10 @@ class Route extends Taro.Component { }) } - componentWillMount () { - this.updateComponent() - } - componentDidMount () { scroller = scroller || getScroller() scroller.set(0) + this.updateComponent() } componentWillReceiveProps (nProps, nContext) { @@ -98,19 +98,21 @@ class Route extends Taro.Component { this.matched = nextMatched - if (nextMatched) { - this.showPage() - if (!isRedirect) { + nextTick(() => { + if (nextMatched) { + this.showPage() + if (!isRedirect) { + scroller = scroller || getScroller() + scroller.set(this.scrollPos) + tryToCall(this.componentRef.componentDidShow, this.componentRef) + } + } else { scroller = scroller || getScroller() - scroller.set(this.scrollPos) - tryToCall(this.componentRef.componentDidShow, this.componentRef) + this.scrollPos = scroller.get() + this.hidePage() + tryToCall(this.componentRef.componentDidHide, this.componentRef) } - } else { - scroller = scroller || getScroller() - this.scrollPos = scroller.get() - this.hidePage() - tryToCall(this.componentRef.componentDidHide, this.componentRef) - } + }) } shouldComponentUpdate () { @@ -129,7 +131,7 @@ class Route extends Taro.Component { hidePage () { const dom = this.containerRef if (!dom) { - return console.error(`showPage:fail Received a falsy component for route "${this.props.path}". Forget to export it?`) + return console.error(`hidePage:fail Received a falsy component for route "${this.props.path}". Forget to export it?`) } dom.style.display = 'none' } diff --git a/packages/taro-router/src/router/router.tsx b/packages/taro-router/src/router/router.tsx index 42d3b88ad7c1..f92143054aae 100644 --- a/packages/taro-router/src/router/router.tsx +++ b/packages/taro-router/src/router/router.tsx @@ -102,10 +102,15 @@ class Router extends Taro.Component { } collectComponent = (comp, k) => { - this.currentPages[k] = comp + if(this.currentPages[k]){ + this.currentPages[k] = comp; + } + else{ + this.currentPages.push(comp); + } } - componentWillMount () { + componentDidMount () { const { history, customRoutes } = this.props this.mountApis() @@ -138,9 +143,7 @@ class Router extends Taro.Component { } render () { - const router = this const currentLocation = Taro._$router - router.currentPages.length = this.state.routeStack.length return (
eventCenter.off(e)) + } } } if (isPage) { diff --git a/packages/taro-swan/src/index.js b/packages/taro-swan/src/index.js index e37a20738346..44a1e3423e29 100644 --- a/packages/taro-swan/src/index.js +++ b/packages/taro-swan/src/index.js @@ -23,6 +23,7 @@ import { createContext, memo } from '@tarojs/taro' +import { shallowEqual } from '@tarojs/utils' import Component from './component' import PureComponent from './pure-component' @@ -62,7 +63,8 @@ export const Taro = { useImperativeHandle, useContext, createContext, - memo + memo, + shallowEqual } export default Taro diff --git a/packages/taro-swan/src/lifecycle.js b/packages/taro-swan/src/lifecycle.js index 3d188368a522..653f6c84b3e1 100644 --- a/packages/taro-swan/src/lifecycle.js +++ b/packages/taro-swan/src/lifecycle.js @@ -139,15 +139,13 @@ function doUpdate (component, prevProps, prevState) { const { state, props = {} } = component let data = state || {} if (component._createData) { - // 返回null或undefined则保持不变 - const isRunLoopRef = !component.__mounted if (component.__isReady) { injectContextType(component) Current.current = component Current.index = 0 invokeEffects(component, true) } - data = component._createData(state, props, isRunLoopRef) || data + data = component._createData(state, props) || data if (component.__isReady) { Current.current = null } @@ -208,9 +206,11 @@ function doUpdate (component, prevProps, prevState) { } if (component['$$hasLoopRef']) { + Current.current = component component._disableEffect = true component._createData(component.state, component.props, true) component._disableEffect = false + Current.current = null } if (typeof component.componentDidUpdate === 'function') { diff --git a/packages/taro-swan/src/native-api.js b/packages/taro-swan/src/native-api.js index 9e1a5002e176..cde1d856011b 100644 --- a/packages/taro-swan/src/native-api.js +++ b/packages/taro-swan/src/native-api.js @@ -164,6 +164,7 @@ export default function initNativeApi (taro) { processApis(taro) taro.request = link.request.bind(link) taro.addInterceptor = link.addInterceptor.bind(link) + taro.cleanInterceptors = link.cleanInterceptors.bind(link) taro.getCurrentPages = getCurrentPages taro.getApp = getApp taro.initPxTransform = initPxTransform.bind(taro) diff --git a/packages/taro-transformer-wx/package.json b/packages/taro-transformer-wx/package.json index 7243f24e4f5b..caf9e8777415 100644 --- a/packages/taro-transformer-wx/package.json +++ b/packages/taro-transformer-wx/package.json @@ -1,6 +1,6 @@ { "name": "@tarojs/transformer-wx", - "version": "1.3.0", + "version": "1.3.7", "description": "Transfrom Nerv Component to Wechat mini program.", "repository": { "type": "git", @@ -62,14 +62,14 @@ "babel-types": "^6.26.0", "eslint": "^4.15.0", "eslint-plugin-react": "7.10.0", - "eslint-plugin-taro": "1.3.0", + "eslint-plugin-taro": "1.3.7", "html": "^1.0.0", "lodash": "^4.17.5", "prettier": "^1.14.2", "typescript": "^3.2.2" }, "devDependencies": { - "@tarojs/taro": "1.3.0", + "@tarojs/taro": "1.3.7", "@types/babel-core": "^6.25.5", "@types/babel-generator": "^6.25.1", "@types/babel-template": "^6.25.0", diff --git a/packages/taro-transformer-wx/src/class-method-renamer.ts b/packages/taro-transformer-wx/src/class-method-renamer.ts new file mode 100644 index 000000000000..21e2437139f0 --- /dev/null +++ b/packages/taro-transformer-wx/src/class-method-renamer.ts @@ -0,0 +1,60 @@ +import { Visitor, NodePath } from 'babel-traverse' +import * as t from 'babel-types' +import { isDerivedFromThis } from './utils' + +function buildMethodName (n: string) { + return `render${n}` +} + +export const buildVistor = () => { + const renameMap = new Map() + + const classMethodRenamer: () => { + visitor: Visitor + } = () => { + return { + visitor: { + JSXElement (path) { + let methodName = '' + const classMethod = path.findParent(p => p.isClassMethod()) + if (classMethod && classMethod.isClassMethod() && t.isIdentifier(classMethod.node.key)) { + if (methodName.startsWith('render')) { + return + } + methodName = classMethod.node.key.name + } + + const classProp = path.findParent(p => p.isClassProperty()) + if (classProp && classProp.isClassProperty()) { + methodName = classProp.node.key.name + } + + if (methodName.length > 0 && !methodName.startsWith('render')) { + renameMap.set(methodName, buildMethodName(methodName)) + } + }, + Identifier (path: NodePath) { + const name = path.node.name + if (renameMap.has(name)) { + const memberExpr = path.parentPath + if (memberExpr.isMemberExpression() && memberExpr.parentPath.isCallExpression()) { + const object = memberExpr.get('object') + if (object.isThisExpression()) { + path.replaceWith(t.identifier(buildMethodName(name))) + } else if (object.isIdentifier() && isDerivedFromThis(path.scope, object.node.name)) { + memberExpr.replaceWith(t.memberExpression( + t.thisExpression(), + t.identifier(buildMethodName(name)) + )) + } + } else if (memberExpr.isCallExpression() && isDerivedFromThis(path.scope, name)) { + path.scope.rename(name, buildMethodName(name)) + } + } + } + } + } + } + + return classMethodRenamer +} diff --git a/packages/taro-transformer-wx/src/class.ts b/packages/taro-transformer-wx/src/class.ts index 893462260937..00c4564a91d3 100644 --- a/packages/taro-transformer-wx/src/class.ts +++ b/packages/taro-transformer-wx/src/class.ts @@ -25,6 +25,8 @@ import { Adapters, Adapter, isNewPropsSystem } from './adapter' import { LoopRef } from './interface' import generate from 'babel-generator' import { isTestEnv } from './env' +import { Status } from './functional' +import { injectRenderPropsEmiter } from './render-props' type ClassMethodsMap = Map> @@ -269,32 +271,48 @@ class Transformer { ] ) )]) - stemParent.insertBefore(indexKeyDecl) - const arrayFunc = t.memberExpression( - t.memberExpression(t.thisExpression(), t.identifier(anonymousFuncName + 'Map')), - t.identifier(indexKey), - true - ) - classBody.push( - t.classMethod('method', t.identifier(anonymousFuncName), [t.identifier(indexKey), t.identifier('e')], t.blockStatement([ - isCatch ? t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('e'), t.identifier('stopPropagation')), [])) : t.emptyStatement(), - t.returnStatement(t.logicalExpression('&&', arrayFunc, t.callExpression(arrayFunc, [t.identifier('e')]))) - ])) - ) - exprPath.replaceWith(t.callExpression( - t.memberExpression( - t.memberExpression(t.thisExpression(), t.identifier(anonymousFuncName)), - t.identifier('bind') - ), - [t.thisExpression(), t.identifier(indexKey)] - )) - stemParent.insertBefore( - t.expressionStatement(t.assignmentExpression( - '=', - arrayFunc, - expr + + const func = loopCallExpr.node.arguments[0] + if (t.isArrowFunctionExpression(func)) { + const body = loopCallExpr.get('arguments')[0].get('body.body') + if (!t.isBlockStatement(func.body)) { + func.body = t.blockStatement([ + indexKeyDecl, + t.returnStatement(func.body) + ]) + } else { + // func.body.body.push(indexKeyDecl) + // 只有 path 的方法才能触发 traverse + body[body.length - 1].insertBefore(indexKeyDecl) + } + const arrayFunc = t.memberExpression( + t.memberExpression(t.thisExpression(), t.identifier(anonymousFuncName + 'Map')), + t.identifier(indexKey), + true + ) + classBody.push( + t.classMethod('method', t.identifier(anonymousFuncName), [t.identifier(indexKey), t.restElement(t.identifier('e'))], t.blockStatement([ + isCatch ? t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('e'), t.identifier('stopPropagation')), [])) : t.emptyStatement(), + t.returnStatement(t.logicalExpression('&&', arrayFunc, t.callExpression(arrayFunc, [t.spreadElement(t.identifier('e'))]))) + ])) + ) + exprPath.replaceWith(t.callExpression( + t.memberExpression( + t.memberExpression(t.thisExpression(), t.identifier(anonymousFuncName)), + t.identifier('bind') + ), + [t.thisExpression(), t.identifier(indexKey)] )) - ) + body[body.length - 1].insertBefore( + t.expressionStatement(t.assignmentExpression( + '=', + arrayFunc, + expr + )) + ) + } else { + throw codeFrameError(func, '返回 JSX 的循环语句必须使用箭头函数') + } } else { classBody.push( t.classMethod('method', t.identifier(anonymousFuncName), [t.identifier('e')], t.blockStatement([ @@ -449,7 +467,8 @@ class Transformer { self.methods.set(methodName, classMethodPath) if (methodName.startsWith('render')) { if (!isContainJSXElement(classMethodPath)) { - throw codeFrameError(classMethodPath.node, '以 render 开头的类函数必须返回 JSX,否则会导致渲染失败。如果是为了渲染字符串,建议更名。') + throw codeFrameError(classMethodPath.node, '以 render 开头的类函数必须返回 JSX,否则会导致渲染失败。如果是为了渲染字符串,建议更名。\n' + + '以 VSCode 为例:右键点击选择方法名,点击 rename symbol(重命名符号),输入新方法名。') } hasRender = true self.renderJSX.set(methodName, classMethodPath) @@ -459,7 +478,7 @@ class Transformer { const arg = returnPath.node.argument const ifStem = returnPath.findParent(p => p.isIfStatement()) // tslint:disable-next-line: strict-type-predicates - if (ifStem && ifStem.isIfStatement() && arg === null) { + if (ifStem && classMethodPath.node.body.body.some(s => s === ifStem.node) && ifStem.isIfStatement() && arg === null) { const consequent = ifStem.get('consequent') if (consequent.isBlockStatement() && consequent.node.body.includes(returnPath.node)) { returnPath.get('argument').replaceWith(t.nullLiteral()) @@ -626,6 +645,10 @@ class Transformer { calleeExpr.get('object').isMemberExpression() && calleeExpr.get('property').isIdentifier({ name: 'bind' })) // is not bind ) { + const calleeName = calleeExpr.isIdentifier() && calleeExpr.node.name + if (typeof calleeName === 'string' && isDerivedFromProps(calleeExpr.scope, calleeName)) { + return + } generateAnonymousState(scope, expression, jsxReferencedIdentifiers) } else { if (parentPath.isJSXAttribute()) { @@ -648,7 +671,8 @@ class Transformer { if ( t.isCallExpression(expr) && t.isMemberExpression(expr.callee) && - t.isIdentifier(expr.callee.property, { name: 'bind' }) + t.isIdentifier(expr.callee.property, { name: 'bind' }) && + !Status.isSFC ) { if ( (!isNewPropsSystem()) || @@ -660,7 +684,7 @@ class Transformer { if ( (!isNewPropsSystem()) || (t.isJSXIdentifier(jsx.node.name) && DEFAULT_Component_SET.has(jsx.node.name.name)) - ) { + ) { self.buildPropsAnonymousFunc(attr, expr as any, false) } } else if (!t.isLiteral(expr)) { @@ -674,10 +698,15 @@ class Transformer { if (!t.isJSXIdentifier(jsxName)) return if (expression.isJSXElement()) return if (DEFAULT_Component_SET.has(jsxName.name) || expression.isIdentifier() || expression.isMemberExpression() || expression.isLiteral() || expression.isLogicalExpression() || expression.isConditionalExpression() || key.name.startsWith('on') || expression.isCallExpression()) return + if (isContainJSXElement(path)) return generateAnonymousState(scope, expression, jsxReferencedIdentifiers) }, Identifier (path) { const isStartWithRender = /^render[A-Z]/.test(path.node.name) + const isInJSXExprContainer = !!path.findParent(p => p.isJSXExpressionContainer()) + if (!isInJSXExprContainer) { + return + } if (path.node.name === 'children' || isStartWithRender) { const parentPath = path.parentPath const slot = t.jSXElement(t.jSXOpeningElement(t.jSXIdentifier('slot'), [], true), t.jSXClosingElement(t.jSXIdentifier('slot')), [], true) @@ -685,6 +714,12 @@ class Transformer { slot.openingElement.attributes.push(t.jSXAttribute(t.jSXIdentifier('name'), t.stringLiteral(getSlotName(path.node.name)))) self.setMultipleSlots() } + if (parentPath.isCallExpression() && parentPath.parentPath.isJSXExpressionContainer()) { + if (isDerivedFromProps(path.scope, path.node.name)) { + injectRenderPropsEmiter(parentPath, path.node.name) + parentPath.replaceWith(slot) + } + } if (parentPath.isMemberExpression() && parentPath.isReferenced() && parentPath.parentPath.isJSXExpressionContainer()) { const object = parentPath.get('object') if (object.isIdentifier()) { @@ -726,7 +761,7 @@ class Transformer { } if (id.name.endsWith(CONTEXT_PROVIDER)) { - const valueAttr = path.node.openingElement.attributes.find(a => a.name.name === 'value') + const valueAttr = path.node.openingElement.attributes.find(a => t.isJSXIdentifier(a.name) && a.name.name === 'value') const contextName = id.name.slice(0, id.name.length - CONTEXT_PROVIDER.length) if (valueAttr) { if (t.isJSXElement(valueAttr.value)) { @@ -768,9 +803,16 @@ class Transformer { parentPath.replaceWith(t.jSXElement(t.jSXOpeningElement(t.jSXIdentifier('slot'), [], true), t.jSXClosingElement(t.jSXIdentifier('slot')), [], true)) } else if (/^render[A-Z]/.test(name)) { const slotName = getSlotName(name) - parentPath.replaceWith(t.jSXElement(t.jSXOpeningElement(t.jSXIdentifier('slot'), [ - t.jSXAttribute(t.jSXIdentifier('name'), t.stringLiteral(slotName)) - ], true), t.jSXClosingElement(t.jSXIdentifier('slot')), [])) + if (parentPath.parentPath.isCallExpression()) { + injectRenderPropsEmiter(parentPath.parentPath, name) + parentPath.parentPath.replaceWith(t.jSXElement(t.jSXOpeningElement(t.jSXIdentifier('slot'), [ + t.jSXAttribute(t.jSXIdentifier('name'), t.stringLiteral(slotName)) + ], true), t.jSXClosingElement(t.jSXIdentifier('slot')), [])) + } else { + parentPath.replaceWith(t.jSXElement(t.jSXOpeningElement(t.jSXIdentifier('slot'), [ + t.jSXAttribute(t.jSXIdentifier('name'), t.stringLiteral(slotName)) + ], true), t.jSXClosingElement(t.jSXIdentifier('slot')), [])) + } this.setMultipleSlots() } else { self.componentProperies.add(siblingProp.node.name) diff --git a/packages/taro-transformer-wx/src/functional.ts b/packages/taro-transformer-wx/src/functional.ts index ed9e6356aa63..ba04d5e0a522 100644 --- a/packages/taro-transformer-wx/src/functional.ts +++ b/packages/taro-transformer-wx/src/functional.ts @@ -3,6 +3,8 @@ import { codeFrameError, buildConstVariableDeclaration } from './utils' import * as t from 'babel-types' import { cloneDeep } from 'lodash' import generate from 'babel-generator' +import { DEFAULT_Component_SET } from './constant' +import { injectRenderPropsListener } from './render-props' function initialIsCapital (word: string) { return word[0] !== word[0].toLowerCase() @@ -19,10 +21,16 @@ export const functionalComponent: () => { visitor: { JSXElement (path) { const arrowFuncExpr = path.findParent(p => p.isArrowFunctionExpression()) + const funcExpr = path.findParent(p => p.isFunctionExpression()) + if (funcExpr && funcExpr.isFunctionExpression() && funcExpr.parentPath.isVariableDeclarator()) { + const { params, body, async } = funcExpr.node + funcExpr.replaceWith(t.arrowFunctionExpression(params, body, async)) + return + } if (arrowFuncExpr && arrowFuncExpr.isArrowFunctionExpression()) { if (arrowFuncExpr.parentPath.isVariableDeclarator()) { const valDecl = arrowFuncExpr.parentPath.parentPath - if (!valDecl.isVariableDeclaration()) { + if (!valDecl.isVariableDeclaration() && !valDecl.isFunctionDeclaration()) { throw codeFrameError(valDecl.node, '函数式组件不能同时定义多个值') } const id = arrowFuncExpr.parentPath.node.id @@ -91,11 +99,27 @@ const ${id.name} = ${generate(t.arrowFunctionExpression(params, body)).code} if (t.isIdentifier(arg)) { cloneBody.body.unshift(buildConstVariableDeclaration(arg.name, t.memberExpression(t.thisExpression(), t.identifier('props')))) } else if (t.isObjectPattern(arg)) { + let hasChildren = false + for (const [index, p] of arg.properties.entries()) { + if (t.isObjectProperty(p) && t.isIdentifier(p.key, { name: 'children' })) { + hasChildren = true + arg.properties.splice(index, 1) + } + } cloneBody.body.unshift( t.variableDeclaration('const', [ t.variableDeclarator(arg, t.memberExpression(t.thisExpression(), t.identifier('props'))) ]) ) + if (hasChildren) { + cloneBody.body.unshift( + t.variableDeclaration('const', [ + t.variableDeclarator(t.objectPattern([ + t.objectProperty(t.identifier('children'), t.identifier('children')) as any + ]), t.memberExpression(t.thisExpression(), t.identifier('props'))) + ]) + ) + } } else if (t.isAssignmentPattern(arg)) { throw codeFrameError(arg, '给函数式组件的第一个参数设置默认参数是没有意义的,因为 props 永远都有值(不传 props 的时候是个空对象),所以默认参数永远都不会执行。') } else { @@ -108,6 +132,22 @@ const ${id.name} = ${generate(t.arrowFunctionExpression(params, body)).code} ]), []) functionDecl.replaceWith(classDecl) } + }, + JSXAttribute (path) { + const { name, value } = path.node + const jsxElementPath = path.parentPath.parentPath + if (t.isJSXIdentifier(name) && jsxElementPath.isJSXElement()) { + const componentName = (jsxElementPath.node.openingElement as any).name.name + if (/^render[A-Z]/.test(name.name) && !DEFAULT_Component_SET.has(componentName)) { + if (!t.isJSXExpressionContainer(value)) { + throw codeFrameError(value, '以 render 开头的 props 只能传入包含一个 JSX 元素的 JSX 表达式。') + } + const expression = value.expression + if (t.isArrowFunctionExpression(expression)) { + injectRenderPropsListener(path, name.name, expression, componentName) + } + } + } } } } diff --git a/packages/taro-transformer-wx/src/index.ts b/packages/taro-transformer-wx/src/index.ts index d3ad4922f1ad..a6e912fe9fa1 100644 --- a/packages/taro-transformer-wx/src/index.ts +++ b/packages/taro-transformer-wx/src/index.ts @@ -39,7 +39,7 @@ import { } from './constant' import { Adapters, setAdapter, Adapter } from './adapter' import { Options, setTransformOptions, buildBabelTransformOptions } from './options' -import { get as safeGet, cloneDeep } from 'lodash' +import { get as safeGet, cloneDeep, snakeCase } from 'lodash' import { isTestEnv } from './env' const template = require('babel-template') @@ -108,7 +108,7 @@ function handleClosureJSXFunc (jsx: NodePath, mainClass: NodePath< const parentPath = arrowFunc.parentPath if (parentPath.isVariableDeclarator()) { const id = parentPath.node.id - if (t.isIdentifier(id) && id.name.startsWith('render')) { + if (t.isIdentifier(id) && /^render[A-Z]/.test(id.name)) { const funcName = `renderClosure${id.name.slice(6, id.name.length)}` mainClass.node.body.body.push( t.classProperty( @@ -222,6 +222,7 @@ export default function transform (options: Options): TransformResult { options.env = Object.assign({ 'process.env.TARO_ENV': options.adapter || 'weapp' }, options.env || {}) setTransformOptions(options) setting.sourceCode = code + let hasReduxBinding = false // babel-traverse 无法生成 Hub // 导致 Path#getSource|buildCodeFrameError 都无法直接使用 // 原因大概是 babylon.parse 没有生成 File 实例导致 scope 和 path 原型上都没有 `file` @@ -514,9 +515,15 @@ export default function transform (options: Options): TransformResult { } } } - if (name === 'View' && Adapter.type === Adapters.quickapp) { - path.node.name = t.jSXIdentifier('div') + if (Adapter.type === Adapters.quickapp) { + if (name === 'View') { + path.node.name = t.jSXIdentifier('div') + } + if (name === 'Block') { + path.node.name = t.jSXIdentifier('block') + } } + if (name === 'Provider') { const modules = path.scope.getAllBindings('module') const providerBinding = Object.values(modules).some((m: Binding) => m.identifier.name === 'Provider') @@ -605,6 +612,43 @@ export default function transform (options: Options): TransformResult { // @TODO: bind 的处理待定 } }, + ClassProperty (path) { + if (Adapter.type !== Adapters.quickapp) { + return + } + if (path.node.key.name === 'defaultProps' && t.isObjectExpression(path.node.value)) { + const props = path.node.value.properties + for (const prop of props) { + if (t.isObjectProperty(prop)) { + if (t.isStringLiteral(prop.key) && /[A-Z]/.test(prop.key.value) && !prop.key.value.startsWith('on')) { + prop.key = t.stringLiteral(snakeCase(prop.key.value)) + } + if (t.isIdentifier(prop.key) && /[A-Z]/.test(prop.key.name) && !prop.key.name.startsWith('on')) { + prop.key = t.identifier(snakeCase(prop.key.name)) + } + } + } + } + }, + AssignmentExpression (path) { + if (Adapter.type !== Adapters.quickapp) { + return + } + const { left, right } = path.node + if (t.isMemberExpression(left) && t.isIdentifier(left.property, { name: 'defaultProps' }) && t.isObjectExpression(right)) { + const props = right.properties + for (const prop of props) { + if (t.isObjectProperty(prop)) { + if (t.isStringLiteral(prop.key) && /[A-Z]/.test(prop.key.value) && !prop.key.value.startsWith('on')) { + prop.key = t.stringLiteral(snakeCase(prop.key.value)) + } + if (t.isIdentifier(prop.key) && /[A-Z]/.test(prop.key.name) && !prop.key.name.startsWith('on')) { + prop.key = t.identifier(snakeCase(prop.key.name)) + } + } + } + } + }, ImportDeclaration (path) { const source = path.node.source.value if (importSources.has(source)) { @@ -632,10 +676,14 @@ export default function transform (options: Options): TransformResult { t.importSpecifier(t.identifier(INTERNAL_GET_ORIGNAL), t.identifier(INTERNAL_GET_ORIGNAL)), t.importSpecifier(t.identifier(INTERNAL_INLINE_STYLE), t.identifier(INTERNAL_INLINE_STYLE)), t.importSpecifier(t.identifier(GEL_ELEMENT_BY_ID), t.identifier(GEL_ELEMENT_BY_ID)), - t.importSpecifier(t.identifier(PROPS_MANAGER), t.identifier(PROPS_MANAGER)), t.importSpecifier(t.identifier(GEN_COMP_ID), t.identifier(GEN_COMP_ID)), t.importSpecifier(t.identifier(GEN_LOOP_COMPID), t.identifier(GEN_LOOP_COMPID)) ) + if (Adapter.type !== Adapters.alipay) { + path.node.specifiers.push( + t.importSpecifier(t.identifier(PROPS_MANAGER), t.identifier(PROPS_MANAGER)) + ) + } } if ( source === REDUX_PACKAGE_NAME || source === MOBX_PACKAGE_NAME @@ -646,6 +694,12 @@ export default function transform (options: Options): TransformResult { specs.push( t.importSpecifier(t.identifier('setStore'), t.identifier('setStore')) ) + if (source === REDUX_PACKAGE_NAME) { + hasReduxBinding = true + specs.push( + t.importSpecifier(t.identifier('ReduxContext'), t.identifier('ReduxContext')) + ) + } } }) } @@ -667,17 +721,20 @@ export default function transform (options: Options): TransformResult { }) if (!isImportTaro) { + const specifiers = [ + t.importDefaultSpecifier(t.identifier('Taro')), + t.importSpecifier(t.identifier(INTERNAL_SAFE_GET), t.identifier(INTERNAL_SAFE_GET)), + t.importSpecifier(t.identifier(INTERNAL_GET_ORIGNAL), t.identifier(INTERNAL_GET_ORIGNAL)), + t.importSpecifier(t.identifier(INTERNAL_INLINE_STYLE), t.identifier(INTERNAL_INLINE_STYLE)), + t.importSpecifier(t.identifier(GEL_ELEMENT_BY_ID), t.identifier(GEL_ELEMENT_BY_ID)), + t.importSpecifier(t.identifier(GEN_COMP_ID), t.identifier(GEN_COMP_ID)), + t.importSpecifier(t.identifier(GEN_LOOP_COMPID), t.identifier(GEN_LOOP_COMPID)) + ] + if (Adapter.type !== Adapters.alipay) { + specifiers.push(t.importSpecifier(t.identifier(PROPS_MANAGER), t.identifier(PROPS_MANAGER))) + } ast.program.body.unshift( - t.importDeclaration([ - t.importDefaultSpecifier(t.identifier('Taro')), - t.importSpecifier(t.identifier(INTERNAL_SAFE_GET), t.identifier(INTERNAL_SAFE_GET)), - t.importSpecifier(t.identifier(INTERNAL_GET_ORIGNAL), t.identifier(INTERNAL_GET_ORIGNAL)), - t.importSpecifier(t.identifier(INTERNAL_INLINE_STYLE), t.identifier(INTERNAL_INLINE_STYLE)), - t.importSpecifier(t.identifier(GEL_ELEMENT_BY_ID), t.identifier(GEL_ELEMENT_BY_ID)), - t.importSpecifier(t.identifier(PROPS_MANAGER), t.identifier(PROPS_MANAGER)), - t.importSpecifier(t.identifier(GEN_COMP_ID), t.identifier(GEN_COMP_ID)), - t.importSpecifier(t.identifier(GEN_LOOP_COMPID), t.identifier(GEN_LOOP_COMPID)) - ], t.stringLiteral('@tarojs/taro')) + t.importDeclaration(specifiers, t.stringLiteral('@tarojs/taro')) ) } @@ -685,20 +742,52 @@ export default function transform (options: Options): TransformResult { throw new Error('未找到 Taro.Component 的类定义') } + if (Adapter.type === Adapters.alipay) { + const body = ast.program.body + for (const i in body) { + if (t.isImportDeclaration(body[i]) && !t.isImportDeclaration(body[Number(i) + 1])) { + body.splice(Number(i) + 1, 0, t.variableDeclaration( + 'const', + [t.variableDeclarator( + t.identifier('propsManager'), + t.memberExpression( + t.identifier('my'), + t.identifier('propsManager') + ) + )] + )) + break + } + } + } + mainClass.node.body.body.forEach(handleThirdPartyComponent) const storeBinding = mainClass.scope.getBinding(storeName) mainClass.scope.rename('Component', '__BaseComponent') if (storeBinding) { const statementPath = storeBinding.path.getStatementParent() if (statementPath) { - ast.program.body.forEach((node, index, body) => { + ast.program.body.every((node, index, body) => { if (node === statementPath.node) { + const settingReduxProvider = t.expressionStatement( + t.callExpression(t.memberExpression(t.identifier('ReduxContext'), t.identifier('Provider')), [ + t.objectExpression([ + t.objectProperty(t.identifier('store'), t.identifier(storeName)) + ]) + ]) + ) + const ifStem = t.ifStatement(t.memberExpression(t.identifier('ReduxContext'), t.identifier('Provider')), t.blockStatement([ + settingReduxProvider, + settingReduxProvider // 第一次调用初始化,第二次赋值 + ])) body.splice(index + 1, 0, t.expressionStatement( t.callExpression(t.identifier('setStore'), [ t.identifier(storeName) ]) - )) + ), hasReduxBinding ? ifStem : t.emptyStatement()) + return false } + return true }) } } diff --git a/packages/taro-transformer-wx/src/jsx.ts b/packages/taro-transformer-wx/src/jsx.ts index 637de1dc0f88..3de686937377 100644 --- a/packages/taro-transformer-wx/src/jsx.ts +++ b/packages/taro-transformer-wx/src/jsx.ts @@ -1,7 +1,7 @@ import generate from 'babel-generator' import { NodePath } from 'babel-traverse' import * as t from 'babel-types' -import { kebabCase } from 'lodash' +import { kebabCase, snakeCase } from 'lodash' import { DEFAULT_Component_SET, SPECIAL_COMPONENT_PROPS, @@ -9,7 +9,8 @@ import { THIRD_PARTY_COMPONENTS, TRANSFORM_COMPONENT_PROPS, lessThanSignPlacehold, - FN_PREFIX + FN_PREFIX, + DEFAULT_Component_SET_COPY } from './constant' import { createHTMLElement } from './create-html-element' import { codeFrameError, decodeUnicode } from './utils' @@ -82,8 +83,12 @@ export function setJSXAttr ( value?: t.StringLiteral | t.JSXExpressionContainer | t.JSXElement, path?: NodePath ) { + if ((name === Adapter.forIndex || name === Adapter.forItem) && Adapter.type === Adapters.quickapp) { + return + } const element = jsx.openingElement - if (!t.isJSXIdentifier(element.name)) { + // tslint:disable-next-line: strict-type-predicates + if (element == null || !t.isJSXIdentifier(element.name)) { return } if (element.name.name === 'Block' || element.name.name === 'block' || !path) { @@ -119,8 +124,11 @@ export function isAllLiteral (...args) { return args.every(p => t.isLiteral(p)) } -export function buildBlockElement (attrs: t.JSXAttribute[] = []) { - const blockName = Adapter.type === Adapters.quickapp ? 'div' : 'block' +export function buildBlockElement (attrs: t.JSXAttribute[] = [], isView = false) { + let blockName = Adapter.type === Adapters.quickapp ? 'div' : 'block' + if (isView) { + blockName = 'View' + } return t.jSXElement( t.jSXOpeningElement(t.jSXIdentifier(blockName), attrs), t.jSXClosingElement(t.jSXIdentifier(blockName)), @@ -205,6 +213,9 @@ export function parseJSXElement (element: t.JSXElement, isFirstEmit = false): st name = name.toLowerCase() } } + if (Adapters.quickapp === Adapter.type && !DEFAULT_Component_SET_COPY.has(componentName) && typeof name === 'string' && !/(^on[A-Z_])|(^catch[A-Z_])/.test(name)) { + name = snakeCase(name) + } let value: string | boolean = true let attrValue = attr.value if (typeof name === 'string') { diff --git a/packages/taro-transformer-wx/src/options.ts b/packages/taro-transformer-wx/src/options.ts index 023b3f039061..426669de7778 100644 --- a/packages/taro-transformer-wx/src/options.ts +++ b/packages/taro-transformer-wx/src/options.ts @@ -3,6 +3,7 @@ import { eslintValidation } from './eslint' import { TransformOptions } from 'babel-core' import { functionalComponent, Status } from './functional' import { isTestEnv } from './env' +import { buildVistor } from './class-method-renamer' export interface Options { isRoot?: boolean, @@ -31,6 +32,15 @@ export const setTransformOptions = (options: Options) => { export const buildBabelTransformOptions: () => TransformOptions = () => { Status.isSFC = false + let plugins = [ + require('babel-plugin-transform-do-expressions'), + require('babel-plugin-transform-export-extensions'), + require('babel-plugin-transform-flow-strip-types'), + [require('babel-plugin-transform-define').default, transformOptions.env] + ] + if (!transformOptions.isNormal) { + plugins.push(buildVistor(), functionalComponent) + } return { parserOpts: { sourceType: 'module', @@ -50,13 +60,8 @@ export const buildBabelTransformOptions: () => TransformOptions = () => { 'exportExtensions' ] as any[] }, - plugins: [ - require('babel-plugin-transform-do-expressions'), - require('babel-plugin-transform-export-extensions'), - require('babel-plugin-transform-flow-strip-types'), - functionalComponent, - [require('babel-plugin-transform-define').default, transformOptions.env] - ].concat(process.env.ESLINT === 'false' || transformOptions.isNormal || transformOptions.isTyped ? [] : eslintValidation) - .concat((isTestEnv) ? [] : require('babel-plugin-remove-dead-code').default) + plugins: plugins + .concat(process.env.ESLINT === 'false' || transformOptions.isNormal || transformOptions.isTyped ? [] : eslintValidation) + .concat((isTestEnv) ? [] : require('babel-plugin-remove-dead-code').default) } } diff --git a/packages/taro-transformer-wx/src/render-props.ts b/packages/taro-transformer-wx/src/render-props.ts new file mode 100644 index 000000000000..e76855ec74ea --- /dev/null +++ b/packages/taro-transformer-wx/src/render-props.ts @@ -0,0 +1,102 @@ +import * as t from 'babel-types' +import { buildConstVariableDeclaration, createRandomLetters, codeFrameError } from './utils' +import { NodePath } from 'babel-traverse' +import { buildBlockElement } from './jsx' +import { get as safeGet } from 'lodash' + +const renderPropsMap = new Map() + +const RENDER_PROPS_EVENTS = '$$renderPropsEvents' + +export function injectRenderPropsListener (attrPath: NodePath, attrName: string, attrExpr: t.ArrowFunctionExpression, componentName: string) { + const randomLetters = createRandomLetters(5) + const renderClosureFuncName = attrName + randomLetters + const jsxDecl = buildConstVariableDeclaration(renderClosureFuncName, attrExpr) + const block = buildBlockElement([], true) + const renderPropsArgs = t.memberExpression(t.thisExpression(), t.identifier(renderClosureFuncName)) + renderPropsMap.set(componentName + '_' + attrName, renderClosureFuncName) + block.children = [ + t.jSXExpressionContainer(t.callExpression(t.identifier(renderClosureFuncName), [renderPropsArgs])) + ] + const listener = buildListener(renderClosureFuncName, renderPropsArgs) + const stemParent = attrPath.getStatementParent() + stemParent.insertBefore(listener) + stemParent.insertBefore(jsxDecl) + attrPath.get('value').replaceWith(t.jSXExpressionContainer(block)) + setRenderPropsEvents(attrPath, renderClosureFuncName) +} + +function setRenderPropsEvents (attrPath: NodePath, renderClosureFuncName: string) { + const classDecl = attrPath.findParent(p => p.isClassDeclaration()) + if (classDecl && classDecl.isClassDeclaration()) { + let hasEvent = false + for (const s of classDecl.node.body.body) { + if (t.isClassProperty(s) && s.key.name === RENDER_PROPS_EVENTS && t.isArrayExpression(s.value)) { + hasEvent = true + if (s.value.elements.some(e => t.isStringLiteral(e) && e.value === renderClosureFuncName)) { + break + } + s.value.elements.push(t.stringLiteral(renderClosureFuncName)) + } + } + + if (!hasEvent) { + classDecl.node.body.body.push(t.classProperty( + t.identifier(RENDER_PROPS_EVENTS), + t.arrayExpression([t.stringLiteral(renderClosureFuncName)]) + )) + } + } +} + +export function injectRenderPropsEmiter (callExpr: NodePath, attrName: string) { + const classDecl = callExpr.findParent(p => p.isClassDeclaration()) + const classDeclName = classDecl && classDecl.isClassDeclaration() && safeGet(classDecl, 'node.id.name', '') + if (typeof classDeclName !== 'string') { + throw codeFrameError(classDecl, '使用 render props 必须指定 class 的名称。') + } + const renderClosureFuncName = renderPropsMap.get(classDeclName + '_' + attrName) || '' + const args: (t.Expression | t.SpreadElement)[] = [t.stringLiteral(renderClosureFuncName)] + if (Array.isArray(callExpr.node.arguments) && callExpr.node.arguments.length) { + args.push(callExpr.node.arguments[0]) + } + const emiter = t.callExpression( + t.memberExpression(buildEventCenterMemberExpr(), t.identifier('trigger')), + args + ) + const stemParent = callExpr.getStatementParent() + stemParent.insertBefore(t.expressionStatement(emiter)) +} + +function buildListener (renderClosureFuncName: string, renderPropsArgs: t.MemberExpression) { + return t.expressionStatement( + t.callExpression( + t.memberExpression( + buildEventCenterMemberExpr(), + t.identifier('on') + ), + [t.stringLiteral(renderClosureFuncName), t.arrowFunctionExpression([t.identifier('e')], t.blockStatement([ + t.ifStatement( + t.unaryExpression('!', t.callExpression( + t.memberExpression(t.identifier('Taro'), t.identifier('shallowEqual')), + [t.identifier('e'), renderPropsArgs] + )), + t.blockStatement([ + t.expressionStatement(t.assignmentExpression('=', renderPropsArgs, t.identifier('e'))), + t.expressionStatement(t.callExpression( + t.memberExpression(t.thisExpression(), t.identifier('setState')), + [t.objectExpression([])] + )) + ]) + ) + ]))] + ) + ) +} + +function buildEventCenterMemberExpr () { + return t.memberExpression( + t.identifier('Taro'), + t.identifier('eventCenter') + ) +} diff --git a/packages/taro-transformer-wx/src/render.ts b/packages/taro-transformer-wx/src/render.ts index b1f46b3b8d1e..204183ab8228 100644 --- a/packages/taro-transformer-wx/src/render.ts +++ b/packages/taro-transformer-wx/src/render.ts @@ -29,9 +29,10 @@ import { findParentLoops, setAncestorCondition, replaceJSXTextWithTextComponent, - createRandomLetters + createRandomLetters, + isDerivedFromProps } from './utils' -import { difference, get as safeGet, cloneDeep, uniq } from 'lodash' +import { difference, get as safeGet, cloneDeep, uniq, snakeCase } from 'lodash' import { setJSXAttr, buildBlockElement, @@ -151,6 +152,7 @@ export class RenderParser { private usedState: Set private componentProperies: Set private loopRefs: Map + private upperCaseComponentProps: Set private finalReturnElement!: t.JSXElement @@ -331,6 +333,10 @@ export class RenderParser { } else if (t.isJSXElement(alternate) && t.isCallExpression(consequent) && !isArrayMapCallExpression(parentPath.get('consequent'))) { const id = generateAnonymousState(this.renderScope, parentPath.get('consequent') as any, this.referencedIdentifiers, true) parentPath.get('consequent').replaceWith(id) + } else if (t.isJSXElement(alternate) && isArrayMapCallExpression(parentPath.get('consequent'))) { + // + } else if (t.isJSXElement(consequent) && isArrayMapCallExpression(parentPath.get('alternate'))) { + // } else { block.children = [t.jSXExpressionContainer(consequent)] newJSXIfAttr(block, test) @@ -356,8 +362,9 @@ export class RenderParser { } const properties: t.ObjectProperty[] = [] this.componentProperies.forEach((propName) => { + const p = Adapters.quickapp === Adapters.quickapp && this.upperCaseComponentProps.has(propName) && !propName.startsWith('prv-fn') ? snakeCase(propName) : propName properties.push( - t.objectProperty(t.stringLiteral(propName), t.objectExpression([ + t.objectProperty(t.stringLiteral(p), t.objectExpression([ t.objectProperty(t.stringLiteral('type'), t.nullLiteral()), t.objectProperty(t.stringLiteral('value'), t.nullLiteral()) ])) @@ -502,7 +509,7 @@ export class RenderParser { } } const block = buildBlockElement() - const hasIfAttr = jsxElementPath.node.openingElement.attributes.find(a => a.name.name === Adapter.if) + const hasIfAttr = jsxElementPath.node.openingElement.attributes.find(a => t.isJSXIdentifier(a.name) && a.name.name === Adapter.if) const needWrapper = Adapters.swan === Adapter.type && hasIfAttr if (needWrapper) { block.children = [jsxElementPath.node] @@ -573,7 +580,7 @@ export class RenderParser { } else { forExpr = `(${indexName}, ${itemName}) in ${code}` } - setJSXAttr(jsxElementPath.node, Adapter.for, t.stringLiteral(forExpr)) + setJSXAttr(jsxElementPath.node, Adapter.for, t.stringLiteral(`{{${forExpr}}}`)) } // if (itemName && !indexName) { // const forExpr = gene @@ -769,8 +776,8 @@ export class RenderParser { } if (t.isIdentifier(parentNode.left)) { const assignmentName = parentNode.left.name - const renderScope = isIfStemInLoop ? jsxElementPath.findParent(p => isArrayMapCallExpression(p)).get('arguments')[0].get('body').scope : this.renderScope - const bindingNode = renderScope.getOwnBinding(assignmentName).path.node + const renderScope: Scope = isIfStemInLoop ? jsxElementPath.findParent(p => isArrayMapCallExpression(p)).get('arguments')[0].get('body').scope : this.renderScope + const bindingNode = renderScope.getOwnBinding(assignmentName)!.path.node // tslint:disable-next-line const parallelIfStems = this.findParallelIfStem(ifStatement) const parentIfStatement = ifStatement.findParent(p => @@ -872,7 +879,7 @@ export class RenderParser { newJSXIfAttr(jsxElementPath.node, test, jsxElementPath) } } - const ifAttr = block.openingElement.attributes.find(a => a.name.name === Adapter.if) + const ifAttr = block.openingElement.attributes.find(a => t.isJSXIdentifier(a.name) && a.name.name === Adapter.if) if (ifAttr && t.isJSXExpressionContainer(ifAttr.value, { expression: test })) { const newBlock = buildBlockElement() newBlock.children = [block, jsxElementPath.node] @@ -883,7 +890,7 @@ export class RenderParser { let hasNest = false this.handleNestedIfStatement(block, jsxElementPath.node, parentIfStatement.node.test, hasNest, isElse || !!ifStatement.findParent(p => p.node === parentIfStatement.node.alternate)) if (!hasNest && parentIfStatement.get('alternate') !== ifStatement) { - const ifAttr = block.openingElement.attributes.find(a => a.name.name === Adapter.if) + const ifAttr = block.openingElement.attributes.find(a => t.isJSXIdentifier(a.name) && a.name.name === Adapter.if) if (ifAttr && t.isJSXExpressionContainer(ifAttr.value, { expression: parentIfStatement.node.test })) { const newBlock = buildBlockElement() block.children.push(jsxElementPath.node) @@ -897,6 +904,7 @@ export class RenderParser { // setTemplate(name, path, templates) assignmentName && this.templates.set(assignmentName, block) if (isIfStemInLoop) { + this.replaceIdWithTemplate()(renderScope.path) this.returnedPaths.push(parentPath) } } @@ -921,8 +929,8 @@ export class RenderParser { if (!t.isJSXElement(child)) { continue } - const ifAttr = child.openingElement.attributes.find(a => a.name.name === Adapter.if) - const ifElseAttr = child.openingElement.attributes.find(a => a.name.name === Adapter.elseif) + const ifAttr = child.openingElement.attributes.find(a => t.isJSXIdentifier(a.name) && a.name.name === Adapter.if) + const ifElseAttr = child.openingElement.attributes.find(a => t.isJSXIdentifier(a.name) && a.name.name === Adapter.elseif) if ( (ifAttr && t.isJSXExpressionContainer(ifAttr.value, { expression: test })) || @@ -945,8 +953,8 @@ export class RenderParser { if (!t.isJSXElement(child)) { continue } - const ifAttr = child.openingElement.attributes.find(a => a.name.name === Adapter.if) - const ifElseAttr = child.openingElement.attributes.find(a => a.name.name === Adapter.elseif) + const ifAttr = child.openingElement.attributes.find(a => t.isJSXIdentifier(a.name) && a.name.name === Adapter.if) + const ifElseAttr = child.openingElement.attributes.find(a => t.isJSXIdentifier(a.name) && a.name.name === Adapter.elseif) if ( (ifAttr && t.isJSXExpressionContainer(ifAttr.value, { expression: test })) || @@ -989,11 +997,13 @@ export class RenderParser { if (t.isJSXIdentifier(name) && name.name !== 'key' && name.name !== 'id' + && !(name.name === 'extraProps' && Adapter.type === Adapters.weapp) && name.name !== Adapter.for && name.name !== Adapter.forItem && name.name !== Adapter.forIndex && name.name.indexOf('render') !== 0 && !t.isJSXElement(value) + && !name.name.includes('-') ) { // tslint:disable-next-line: strict-type-predicates const v: t.StringLiteral | t.Expression | t.BooleanLiteral = value === null @@ -1429,7 +1439,7 @@ export class RenderParser { } } - if (t.isThisExpression(object) && t.isIdentifier(property)) { + if (t.isThisExpression(object) && t.isIdentifier(property) && /^render[A-Z]/.test(this.renderMethodName)) { const s = new Set(['state', 'props']) if (s.has(property.name) && path.parentPath.isMemberExpression()) { const p = path.parentPath.node.property @@ -1528,6 +1538,30 @@ export class RenderParser { JSXExpressionContainer: this.replaceIdWithTemplate(true) } + handleQuickappProps () { + if (Adapter.type !== Adapters.quickapp) { + return + } + + this.renderPath.traverse({ + Identifier: (path) => { + if (!this.upperCaseComponentProps.has(path.node.name)) { + return + } + + if (isDerivedFromProps(this.renderScope, path.node.name)) { + this.renderScope.rename(path.node.name, snakeCase(path.node.name)) + path.replaceWith(t.identifier(snakeCase(path.node.name))) + } + + const sibling = path.getSibling('object') + if (sibling && sibling.isMemberExpression() && sibling.get('object').isThisExpression() && sibling.get('property').isIdentifier({ name: 'props' })) { + path.replaceWith(t.identifier(snakeCase(path.node.name))) + } + } + }) + } + /** * * @param renderPath @@ -1556,6 +1590,7 @@ export class RenderParser { const renderBody = renderPath.get('body') this.renderScope = renderBody.scope this.isDefaultRender = methodName === 'render' + this.upperCaseComponentProps = new Set(Array.from(this.componentProperies).filter(p => /[A-Z]/.test(p) && !p.startsWith('on'))) const [, error] = renderPath.node.body.body.filter(s => t.isReturnStatement(s)) if (error) { @@ -1568,6 +1603,8 @@ export class RenderParser { throw codeFrameError(this.renderPath.node, '类函数对象必须指明函数名') } + this.handleQuickappProps() + renderBody.traverse(this.loopComponentVisitor) if (this.hasNoReturnLoopStem) { renderBody.traverse({ @@ -1642,7 +1679,9 @@ export class RenderParser { isEmptyProps = (attrs: (t.JSXAttribute | t.JSXSpreadAttribute)[]) => attrs.filter(a => { if (t.isJSXSpreadAttribute(a)) return true - return ![Adapter.for, Adapter.forIndex, Adapter.forItem, 'id'].includes(a.name.name as string) + const list = [Adapter.for, Adapter.forIndex, Adapter.forItem, 'id'] + Adapter.type === Adapters.weapp && list.push('extraProps') + return !list.includes(a.name.name as string) }).length === 0 findParentIndices (callee: NodePath, indexId: t.Identifier) { @@ -1715,9 +1754,13 @@ export class RenderParser { }) const [ func ] = callee.node.arguments let indexId: t.Identifier | null = null + let itemId: t.Identifier | null = null if (t.isFunctionExpression(func) || t.isArrowFunctionExpression(func)) { const params = func.params as t.Identifier[] - indexId = params[1] + if (Array.isArray(params)) { + indexId = params[1] + itemId = params[0] + } } if (this.loopRefs.has(component.node) || loopRefComponent!) { hasLoopRef = true @@ -1963,7 +2006,7 @@ export class RenderParser { return } } - if (this.ancestorConditions.has(parentCondition.node)) { + if (path.findParent(p => this.ancestorConditions.has(p.node))) { return } } @@ -2049,7 +2092,21 @@ export class RenderParser { // setJSXAttr(returned, Adapter.for, t.identifier(stateName)) this.addRefIdentifier(callee, t.identifier(stateName)) // this.referencedIdentifiers.add(t.identifier(stateName)) - setJSXAttr(component.node, Adapter.for, t.jSXExpressionContainer(t.identifier(stateName))) + if (Adapters.quickapp === Adapter.type) { + let itemName = indexId!.name + let indexName = itemId!.name + if (itemName || indexName) { + let forExpr: string + if (itemName && !indexName) { + forExpr = `${itemName} in ${stateName}` + } else { + forExpr = `(${indexName}, ${itemName}) in ${stateName}` + } + setJSXAttr(component.node, Adapter.for, t.stringLiteral(`{{${forExpr}}}`)) + } + } else { + setJSXAttr(component.node, Adapter.for, t.jSXExpressionContainer(t.identifier(stateName))) + } const returnBody = this.renderPath.node.body.body const ifStem = callee.findParent(p => p.isIfStatement()) // @TEST @@ -2213,7 +2270,7 @@ export class RenderParser { } } - const componentProperies = cloneDeep(this.componentProperies) + let componentProperies = cloneDeep(this.componentProperies) componentProperies.forEach(s => { if (s.startsWith(FN_PREFIX)) { @@ -2225,8 +2282,12 @@ export class RenderParser { } }) + if (Adapter.type === Adapters.quickapp) { + componentProperies = new Set(Array.from(componentProperies).map(p => this.upperCaseComponentProps.has(p) && !p.startsWith('on') && !p.startsWith('prv-fn') ? snakeCase(p) : p)) + } + Array.from(this.reserveStateWords).forEach(this.setReserveWord) - const usedState = Array.from( + let usedState = Array.from( new Set( Array.from(this.referencedIdentifiers) .map(i => i.name) @@ -2241,6 +2302,12 @@ export class RenderParser { .filter(i => !this.templates.has(i)) .filter(Boolean) + if (Adapter.type === Adapters.quickapp) { + usedState = usedState + .filter(i => !new Set([...this.upperCaseComponentProps].map(i => i.toLowerCase())).has(i)) + .filter(i => !this.upperCaseComponentProps.has(i)) + } + const classPath = this.renderPath.findParent(isClassDcl) as NodePath classPath.node.body.body.unshift(t.classProperty(t.identifier('$usedState'), t.arrayExpression( [...new Set( diff --git a/packages/taro-transformer-wx/src/utils.ts b/packages/taro-transformer-wx/src/utils.ts index c39385230036..d396dc16a94c 100644 --- a/packages/taro-transformer-wx/src/utils.ts +++ b/packages/taro-transformer-wx/src/utils.ts @@ -32,6 +32,20 @@ export function isDerivedFromProps (scope: Scope, bindingName: string) { return true } } + if (init.isIdentifier()) { + return isDerivedFromProps(scope, init.node.name) + } + } + return false +} + +export function isDerivedFromThis (scope: Scope, bindingName: string) { + const binding = scope.getBinding(bindingName) + if (binding && binding.path.isVariableDeclarator()) { + const init = binding.path.get('init') + if (init.isThisExpression()) { + return true + } } return false } @@ -177,7 +191,7 @@ export function setParentCondition (jsx: NodePath, expr: t.Expression, a Adapter.if, Adapter.else ]) - const logicalJSX = jsx.findParent(p => p.isJSXElement() && p.node.openingElement.attributes.some(a => ifAttrSet.has(a.name.name as string))) as NodePath + const logicalJSX = jsx.findParent(p => p.isJSXElement() && p.node.openingElement.attributes.some(a => t.isJSXIdentifier(a.name) && ifAttrSet.has(a.name.name))) as NodePath if (logicalJSX) { const attr = logicalJSX.node.openingElement.attributes.find(a => ifAttrSet.has(a.name.name as string)) if (attr) { @@ -246,7 +260,8 @@ export function generateAnonymousState ( if (isArrowFunctionInJSX) { return } - if (t.isIdentifier(id) && !id.name.startsWith(LOOP_STATE) && !id.name.startsWith('_$')) { + // tslint:disable-next-line: strict-type-predicates + if (t.isIdentifier(id) && !id.name.startsWith(LOOP_STATE) && !id.name.startsWith('_$') && init != null) { const newId = scope.generateDeclaredUidIdentifier('$' + id.name) refIds.forEach((refId) => { if (refId.name === variableName && !variableName.startsWith('_$')) { @@ -647,7 +662,7 @@ export function setAncestorCondition (jsx: NodePath, expr: t.Expression) Adapter.if, Adapter.else ]) - const logicalJSX = jsx.findParent(p => p.isJSXElement() && p.node.openingElement.attributes.some(a => ifAttrSet.has(a.name.name as string))) as NodePath + const logicalJSX = jsx.findParent(p => p.isJSXElement() && p.node.openingElement.attributes.some(a => t.isJSXIdentifier(a.name) && ifAttrSet.has(a.name.name))) as NodePath if (logicalJSX) { const attr = logicalJSX.node.openingElement.attributes.find(a => ifAttrSet.has(a.name.name as string)) if (attr) { diff --git a/packages/taro-tt/package.json b/packages/taro-tt/package.json index 105054f24e2b..6d67b908b9f1 100644 --- a/packages/taro-tt/package.json +++ b/packages/taro-tt/package.json @@ -1,6 +1,6 @@ { "name": "@tarojs/taro-tt", - "version": "1.3.0", + "version": "1.3.7", "description": "Taro toutiao framework", "main": "index.js", "files": [ @@ -24,8 +24,8 @@ "author": "O2Team", "license": "MIT", "dependencies": { - "@tarojs/taro": "1.3.0", - "@tarojs/utils": "1.3.0", + "@tarojs/taro": "1.3.7", + "@tarojs/utils": "1.3.7", "lodash": "^4.17.10", "prop-types": "^15.6.1" } diff --git a/packages/taro-tt/rollup.config.js b/packages/taro-tt/rollup.config.js index f799916a5a6d..7e99cca186c4 100644 --- a/packages/taro-tt/rollup.config.js +++ b/packages/taro-tt/rollup.config.js @@ -7,7 +7,7 @@ const cwd = __dirname const baseConfig = { input: join(cwd, 'src/index.js'), - external: ['nervjs'], + external: ['nervjs', '@tarojs/taro'], output: [ { file: join(cwd, 'dist/index.js'), diff --git a/packages/taro-tt/src/create-component.js b/packages/taro-tt/src/create-component.js index a04bcd535c8e..27b0a3151eb6 100644 --- a/packages/taro-tt/src/create-component.js +++ b/packages/taro-tt/src/create-component.js @@ -1,6 +1,6 @@ import { getCurrentPageUrl } from '@tarojs/utils' -import { commitAttachRef, detachAllRef, Current } from '@tarojs/taro' -import { isEmptyObject, isFunction } from './util' +import { commitAttachRef, detachAllRef, Current, eventCenter } from '@tarojs/taro' +import { isEmptyObject, isFunction, isArray } from './util' import { mountComponent } from './lifecycle' import { cacheDataSet, cacheDataGet, cacheDataHas } from './data-cache' import propsManager from './propsManager' @@ -300,6 +300,13 @@ function createComponent (ComponentClass, isPage) { }) .catch(err => console.error(err)) } + if (component['$$hasLoopRef']) { + Current.current = component + component._disableEffect = true + component._createData(component.state, component.props, true) + component._disableEffect = false + Current.current = null + } }, 0) }, detached () { @@ -310,6 +317,10 @@ function createComponent (ComponentClass, isPage) { hook.cleanup() } }) + const events = component.$$renderPropsEvents + if (isArray(events)) { + events.forEach(e => eventCenter.off(e)) + } } } if (isPage) { diff --git a/packages/taro-tt/src/index.js b/packages/taro-tt/src/index.js index 87336b9e0097..418cbe714337 100644 --- a/packages/taro-tt/src/index.js +++ b/packages/taro-tt/src/index.js @@ -23,6 +23,7 @@ import { createContext, memo } from '@tarojs/taro' +import { shallowEqual } from '@tarojs/utils' import Component from './component' import PureComponent from './pure-component' @@ -62,7 +63,8 @@ export const Taro = { useImperativeHandle, useContext, createContext, - memo + memo, + shallowEqual } export default Taro diff --git a/packages/taro-tt/src/lifecycle.js b/packages/taro-tt/src/lifecycle.js index 76c250e9c16c..a1f519bec331 100644 --- a/packages/taro-tt/src/lifecycle.js +++ b/packages/taro-tt/src/lifecycle.js @@ -139,15 +139,13 @@ function doUpdate (component, prevProps, prevState) { const { state, props = {} } = component let data = state || {} if (component._createData) { - // 返回null或undefined则保持不变 - const isRunLoopRef = !component.__mounted if (component.__isReady) { injectContextType(component) Current.current = component Current.index = 0 invokeEffects(component, true) } - data = component._createData(state, props, isRunLoopRef) || data + data = component._createData(state, props) || data if (component.__isReady) { Current.current = null } @@ -209,9 +207,11 @@ function doUpdate (component, prevProps, prevState) { } if (component['$$hasLoopRef']) { + Current.current = component component._disableEffect = true component._createData(component.state, component.props, true) component._disableEffect = false + Current.current = null } if (typeof component.componentDidUpdate === 'function') { diff --git a/packages/taro-tt/src/native-api.js b/packages/taro-tt/src/native-api.js index bbd19f7014f7..f212ceaefa16 100644 --- a/packages/taro-tt/src/native-api.js +++ b/packages/taro-tt/src/native-api.js @@ -189,6 +189,7 @@ export default function initNativeApi (taro) { processApis(taro) taro.request = link.request.bind(link) taro.addInterceptor = link.addInterceptor.bind(link) + taro.cleanInterceptors = link.cleanInterceptors.bind(link) taro.getCurrentPages = getCurrentPages taro.getApp = getApp taro.initPxTransform = initPxTransform.bind(taro) diff --git a/packages/taro-utils/package.json b/packages/taro-utils/package.json index d5feae82d6ec..ce3b870a81c7 100644 --- a/packages/taro-utils/package.json +++ b/packages/taro-utils/package.json @@ -1,6 +1,6 @@ { "name": "@tarojs/utils", - "version": "1.3.0", + "version": "1.3.7", "description": "Utils for Taro", "main": "index.js", "scripts": { diff --git a/packages/taro-utils/src/shallow-equal.js b/packages/taro-utils/src/shallow-equal.js index 25f5cd9f687c..52ad4c946ed2 100644 --- a/packages/taro-utils/src/shallow-equal.js +++ b/packages/taro-utils/src/shallow-equal.js @@ -1,5 +1,5 @@ /* eslint-disable */ -Object.is = Object.is || function (x, y) { +const objectIs = Object.is || function (x, y) { if (x === y) { return x !== 0 || 1 / x === 1 / y } @@ -13,7 +13,7 @@ export default function shallowEqual (obj1, obj2) { if (obj1 === null || obj2 === null) { return false } - if (Object.is(obj1, obj2)) { + if (objectIs(obj1, obj2)) { return true } const obj1Keys = obj1 ? Object.keys(obj1) : [] @@ -24,7 +24,7 @@ export default function shallowEqual (obj1, obj2) { for (let i = 0; i < obj1Keys.length; i++) { const obj1KeyItem = obj1Keys[i] - if (!obj2.hasOwnProperty(obj1KeyItem) || !Object.is(obj1[obj1KeyItem], obj2[obj1KeyItem])) { + if (!obj2.hasOwnProperty(obj1KeyItem) || !objectIs(obj1[obj1KeyItem], obj2[obj1KeyItem])) { return false } } diff --git a/packages/taro-weapp/package.json b/packages/taro-weapp/package.json index d94a028f6155..193d3c2a61f2 100644 --- a/packages/taro-weapp/package.json +++ b/packages/taro-weapp/package.json @@ -1,6 +1,6 @@ { "name": "@tarojs/taro-weapp", - "version": "1.3.0", + "version": "1.3.7", "description": "Taro weapp framework", "main": "index.js", "files": [ @@ -24,8 +24,8 @@ "author": "O2Team", "license": "MIT", "dependencies": { - "@tarojs/taro": "1.3.0", - "@tarojs/utils": "1.3.0", + "@tarojs/taro": "1.3.7", + "@tarojs/utils": "1.3.7", "lodash": "^4.17.10", "prop-types": "^15.6.1" } diff --git a/packages/taro-weapp/rollup.config.js b/packages/taro-weapp/rollup.config.js index 4af44972956b..11641f2133a3 100644 --- a/packages/taro-weapp/rollup.config.js +++ b/packages/taro-weapp/rollup.config.js @@ -7,7 +7,7 @@ const cwd = __dirname const baseConfig = { input: join(cwd, 'src/index.js'), - external: ['nervjs'], + external: ['nervjs', '@tarojs/taro'], output: [ { file: join(cwd, 'dist/index.js'), diff --git a/packages/taro-weapp/src/create-component.js b/packages/taro-weapp/src/create-component.js index bcb2f9f737a7..1f993414fe70 100644 --- a/packages/taro-weapp/src/create-component.js +++ b/packages/taro-weapp/src/create-component.js @@ -1,8 +1,9 @@ import { getCurrentPageUrl } from '@tarojs/utils' -import { commitAttachRef, detachAllRef, Current } from '@tarojs/taro' -import { isEmptyObject, isFunction } from './util' -import { mountComponent } from './lifecycle' +import { commitAttachRef, detachAllRef, Current, eventCenter } from '@tarojs/taro' +import { isEmptyObject, isFunction, isArray } from './util' +import { mountComponent, updateComponent } from './lifecycle' import { cacheDataSet, cacheDataGet, cacheDataHas } from './data-cache' +import nextTick from './next-tick' import propsManager from './propsManager' const anonymousFnNamePreffix = 'funPrivate' @@ -40,6 +41,22 @@ function bindProperties (weappComponentConf, ComponentClass, isPage) { initComponent.apply(this, [ComponentClass, isPage]) } } + weappComponentConf.properties.extraProps = { + type: null, + value: null, + observer () { + // update Component + if (!this.$component || !this.$component.__isReady) return + + const nextProps = filterProps(ComponentClass.defaultProps, {}, this.$component.props, this.data.extraProps) + this.$component.props = nextProps + nextTick(() => { + this.$component._unsafeCallUpdate = true + updateComponent(this.$component) + this.$component._unsafeCallUpdate = false + }) + } + } } function bindBehaviors (weappComponentConf, ComponentClass) { @@ -172,7 +189,7 @@ function bindEvents (weappComponentConf, events, isPage) { }) } -export function filterProps (defaultProps = {}, propsFromPropsManager = {}, curAllProps = {}) { +export function filterProps (defaultProps = {}, propsFromPropsManager = {}, curAllProps = {}, extraProps) { let newProps = Object.assign({}, curAllProps, propsFromPropsManager) if (!isEmptyObject(defaultProps)) { @@ -182,6 +199,11 @@ export function filterProps (defaultProps = {}, propsFromPropsManager = {}, curA } } } + + if (extraProps) { + newProps = Object.assign({}, newProps, extraProps) + } + return newProps } @@ -213,6 +235,13 @@ export function componentTrigger (component, key, args) { }) component.refs = Object.assign({}, component.refs || {}, refs) } + if (component['$$hasLoopRef']) { + Current.current = component + component._disableEffect = true + component._createData(component.state, component.props, true) + component._disableEffect = false + Current.current = null + } } if (key === 'componentWillUnmount') { @@ -257,7 +286,7 @@ function initComponent (ComponentClass, isPage) { ComponentClass } } - const nextProps = filterProps(ComponentClass.defaultProps, propsManager.map[compid], this.$component.props) + const nextProps = filterProps(ComponentClass.defaultProps, propsManager.map[compid], this.$component.props, this.data.extraProps) this.$component.props = nextProps } else { this.$component.$router.path = getCurrentPageUrl() @@ -339,6 +368,10 @@ function createComponent (ComponentClass, isPage) { hook.cleanup() } }) + const events = component.$$renderPropsEvents + if (isArray(events)) { + events.forEach(e => eventCenter.off(e)) + } } } if (isPage) { diff --git a/packages/taro-weapp/src/index.js b/packages/taro-weapp/src/index.js index ad8d06ded568..023f116d9622 100644 --- a/packages/taro-weapp/src/index.js +++ b/packages/taro-weapp/src/index.js @@ -23,6 +23,7 @@ import { createContext, memo } from '@tarojs/taro' +import { shallowEqual } from '@tarojs/utils' import Component from './component' import PureComponent from './pure-component' @@ -62,7 +63,8 @@ export const Taro = { useImperativeHandle, useContext, createContext, - memo + memo, + shallowEqual } export default Taro diff --git a/packages/taro-weapp/src/lifecycle.js b/packages/taro-weapp/src/lifecycle.js index d8bd01587f0f..31e8663d5917 100644 --- a/packages/taro-weapp/src/lifecycle.js +++ b/packages/taro-weapp/src/lifecycle.js @@ -139,15 +139,13 @@ function doUpdate (component, prevProps, prevState) { const { state, props = {} } = component let data = state || {} if (component._createData) { - // 返回null或undefined则保持不变 - const runLoopRef = !component.__mounted if (component.__isReady) { injectContextType(component) Current.current = component Current.index = 0 invokeEffects(component, true) } - data = component._createData(state, props, runLoopRef) || data + data = component._createData(state, props) || data if (component.__isReady) { Current.current = null } @@ -209,9 +207,11 @@ function doUpdate (component, prevProps, prevState) { } if (component['$$hasLoopRef']) { + Current.current = component component._disableEffect = true component._createData(component.state, component.props, true) component._disableEffect = false + Current.current = null } if (isFunction(component.componentDidUpdate)) { component.componentDidUpdate(prevProps, prevState, snapshot) diff --git a/packages/taro-weapp/src/native-api.js b/packages/taro-weapp/src/native-api.js index fe46846b413d..86f049c18080 100644 --- a/packages/taro-weapp/src/native-api.js +++ b/packages/taro-weapp/src/native-api.js @@ -234,6 +234,7 @@ export default function initNativeApi (taro) { processApis(taro) taro.request = link.request.bind(link) taro.addInterceptor = link.addInterceptor.bind(link) + taro.cleanInterceptors = link.cleanInterceptors.bind(link) taro.getCurrentPages = getCurrentPages taro.getApp = getApp taro.requirePlugin = requirePlugin diff --git a/packages/taro-weapp/src/propsManager.js b/packages/taro-weapp/src/propsManager.js index 96f61fae9658..9b59db7615ac 100644 --- a/packages/taro-weapp/src/propsManager.js +++ b/packages/taro-weapp/src/propsManager.js @@ -23,7 +23,8 @@ class Manager { const ComponentClass = observers[compid] && observers[compid].ComponentClass if (!component || !ComponentClass || !component.__isReady) return - const nextProps = filterProps(ComponentClass.defaultProps, props, component.props) + const extraProps = (component.$scope && component.$scope.data && component.$scope.data.extraProps) || null + const nextProps = filterProps(ComponentClass.defaultProps, props, component.props, extraProps) component.props = nextProps nextTick(() => { component._unsafeCallUpdate = true diff --git a/packages/taro-webpack-runner/package.json b/packages/taro-webpack-runner/package.json index cec29418a962..b79782cf34be 100644 --- a/packages/taro-webpack-runner/package.json +++ b/packages/taro-webpack-runner/package.json @@ -1,6 +1,6 @@ { "name": "@tarojs/webpack-runner", - "version": "1.3.0", + "version": "1.3.7", "description": "webpack runner for taro", "main": "index.js", "scripts": { @@ -32,13 +32,13 @@ }, "homepage": "https://github.com/NervJS/taro#readme", "dependencies": { - "@tarojs/taro-h5": "1.3.0", + "@tarojs/taro-h5": "1.3.7", "autoprefixer": "8.6.4", "babel-core": "6.26.0", "babel-loader": "7.1.4", "babel-plugin-syntax-dynamic-import": "6.18.0", "babel-plugin-transform-react-jsx": "6.24.1", - "babel-plugin-transform-taroapi": "1.3.0", + "babel-plugin-transform-taroapi": "1.3.7", "babel-types": "6.26.0", "chalk": "2.4.2", "copy-webpack-plugin": "^5.0.3", @@ -55,8 +55,8 @@ "opn": "5.3.0", "ora": "2.1.0", "postcss-loader": "2.1.6", - "postcss-plugin-constparse": "1.3.0", - "postcss-pxtransform": "1.3.0", + "postcss-plugin-constparse": "1.3.7", + "postcss-pxtransform": "1.3.7", "resolve": "1.8.1", "resolve-url-loader": "2.3.0", "sass-loader": "7.1.0", diff --git a/packages/taro-webpack-runner/src/config/base.conf.ts b/packages/taro-webpack-runner/src/config/base.conf.ts index 1e12327c6fdf..ea16560085ee 100644 --- a/packages/taro-webpack-runner/src/config/base.conf.ts +++ b/packages/taro-webpack-runner/src/config/base.conf.ts @@ -8,7 +8,7 @@ export default (appPath: string) => { chain.merge({ resolve: { extensions: ['.js', '.jsx', '.ts', '.tsx'], - mainFields: ['main:h5', 'module', 'main'], + mainFields: ['main:h5', 'browser', 'module', 'main'], symlinks: true, modules: [ path.join(appPath, 'node_modules'), diff --git a/packages/taro-with-weapp/package.json b/packages/taro-with-weapp/package.json index a042137f9c67..7c7b8dbf86e2 100644 --- a/packages/taro-with-weapp/package.json +++ b/packages/taro-with-weapp/package.json @@ -1,6 +1,6 @@ { "name": "@tarojs/with-weapp", - "version": "1.3.0", + "version": "1.3.7", "description": "taroize 之后的运行时", "main": "index.js", "scripts": { @@ -22,7 +22,7 @@ "author": "yuche", "license": "MIT", "dependencies": { - "@tarojs/taro": "1.3.0", + "@tarojs/taro": "1.3.7", "lodash": "^4.17.11" }, "devDependencies": { diff --git a/packages/taro/package.json b/packages/taro/package.json index c993d47471d1..14403e57b2fc 100644 --- a/packages/taro/package.json +++ b/packages/taro/package.json @@ -1,6 +1,6 @@ { "name": "@tarojs/taro", - "version": "1.3.0", + "version": "1.3.7", "description": "Taro framework", "module": "dist/index.esm.js", "main": "index.js", diff --git a/packages/taro/src/hooks.js b/packages/taro/src/hooks.js index 9cea214eb67d..a2cd7b035a2e 100644 --- a/packages/taro/src/hooks.js +++ b/packages/taro/src/hooks.js @@ -102,7 +102,7 @@ function invokeScheduleEffects (component) { function useEffectImpl (effect, deps, delay) { const hook = getHooks(Current.index++) - if (Current.current._disableHooks || !Current.current.__isReady) { + if (Current.current._disableEffect || !Current.current.__isReady) { return } if (areDepsChanged(hook.deps, deps)) { diff --git a/packages/taro/src/index.js b/packages/taro/src/index.js index e0cf74ebdba7..b0f78638ba28 100644 --- a/packages/taro/src/index.js +++ b/packages/taro/src/index.js @@ -33,7 +33,15 @@ import { Current } from './current' import { createContext } from './create-context' import { memo } from './memo' -const eventCenter = new Events() +let eventCenter +if (process.env.TARO_ENV === 'alipay') { + if (!my.taroEventCenter) { + my.taroEventCenter = new Events() + } + eventCenter = my.taroEventCenter +} else { + eventCenter = new Events() +} export { Component, diff --git a/packages/taro/src/interceptor/chain.js b/packages/taro/src/interceptor/chain.js index dc959849bfce..fee90abc9a71 100644 --- a/packages/taro/src/interceptor/chain.js +++ b/packages/taro/src/interceptor/chain.js @@ -12,7 +12,10 @@ export default class Chain { } const nextInterceptor = this._getNextInterceptor() const nextChain = this._getNextChain() - return nextInterceptor(nextChain).catch(err => Promise.reject(err)) + const p = nextInterceptor(nextChain) + const res = p.catch(err => Promise.reject(err)) + if (typeof p.abort === 'function') res.abort = p.abort + return res } _getNextInterceptor () { diff --git a/packages/taro/src/interceptor/index.js b/packages/taro/src/interceptor/index.js index 5c905e11a82e..c1380bfd159b 100644 --- a/packages/taro/src/interceptor/index.js +++ b/packages/taro/src/interceptor/index.js @@ -14,4 +14,8 @@ export default class Link { addInterceptor (interceptor) { this.chain.interceptors.push(interceptor) } + + cleanInterceptors () { + this.chain = new Chain() + } } diff --git a/packages/taro/src/memo.js b/packages/taro/src/memo.js index 5f1266b25a8a..3b2629c6abb3 100644 --- a/packages/taro/src/memo.js +++ b/packages/taro/src/memo.js @@ -1,8 +1,11 @@ import { isFunction, objectIs } from './util' export function memo (component, propsAreEqual) { - component.prototype.shouldComponentUpdate = function (nextProps) { - return isFunction(propsAreEqual) ? !propsAreEqual(this.props, nextProps) : !objectIs(this.props, nextProps) + component.prototype.shouldComponentUpdate = function (nextProps, nextState) { + return ( + !objectIs(this.state, nextState) || + (isFunction(propsAreEqual) ? !propsAreEqual(this.props, nextProps) : !objectIs(this.props, nextProps)) + ) } return component diff --git a/packages/taro/src/polyfill.js b/packages/taro/src/polyfill.js index 16bc86dff07b..9f087cc2254d 100644 --- a/packages/taro/src/polyfill.js +++ b/packages/taro/src/polyfill.js @@ -22,3 +22,59 @@ if (typeof Object.assign !== 'function') { return to } } + +if (typeof Object.defineProperties !== 'function') { + Object.defineProperties = function (obj, properties) { + function convertToDescriptor (desc) { + function hasProperty (obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop) + } + + function isCallable (v) { + // NB: modify as necessary if other values than functions are callable. + return typeof v === 'function' + } + + if (typeof desc !== 'object' || desc === null) { throw new TypeError('bad desc') } + + var d = {} + + if (hasProperty(desc, 'enumerable')) d.enumerable = !!desc.enumerable + if (hasProperty(desc, 'configurable')) { d.configurable = !!desc.configurable } + if (hasProperty(desc, 'value')) d.value = desc.value + if (hasProperty(desc, 'writable')) d.writable = !!desc.writable + if (hasProperty(desc, 'get')) { + var g = desc.get + + if (!isCallable(g) && typeof g !== 'undefined') { throw new TypeError('bad get') } + d.get = g + } + if (hasProperty(desc, 'set')) { + var s = desc.set + if (!isCallable(s) && typeof s !== 'undefined') { throw new TypeError('bad set') } + d.set = s + } + + if (('get' in d || 'set' in d) && ('value' in d || 'writable' in d)) { throw new TypeError('identity-confused descriptor') } + + return d + } + + if (typeof obj !== 'object' || obj === null) throw new TypeError('bad obj') + + properties = Object(properties) + + var keys = Object.keys(properties) + var descs = [] + + for (var i = 0; i < keys.length; i++) { + descs.push([keys[i], convertToDescriptor(properties[keys[i]])]) + } + + for (var i = 0; i < descs.length; i++) { + Object.defineProperty(obj, descs[i][0], descs[i][1]) + } + + return obj + } +} diff --git a/packages/taro/types/index.d.ts b/packages/taro/types/index.d.ts index a6f5b79c91f4..7ecff383413b 100644 --- a/packages/taro/types/index.d.ts +++ b/packages/taro/types/index.d.ts @@ -353,6 +353,10 @@ declare namespace Taro { $scope?: any } + interface FunctionComponent

{ + (props: Readonly

): JSX.Element + } + interface ComponentClass

extends StaticLifecycle { new (...args: any[]): Component propTypes?: any @@ -695,8 +699,35 @@ declare namespace Taro { $componentType: 'PAGE' | 'COMPONENT' $router: { - params: any - preload: any + /** + * 在跳转成功的目标页的生命周期方法里通过 `this.$router.params` 获取到传入的参数 + * + * @example + * componentWillMount () { + * console.log(this.$router.params) + * } + * + * @see 参考[路由功能:路由传参](https://nervjs.github.io/taro/docs/router.html#%E8%B7%AF%E7%94%B1%E4%BC%A0%E5%8F%82)一节 + */ + params: { + [key: string]: string + } + /** + * 可以于 `this.$router.preload` 中访问到 `this.$preload` 传入的参数 + * + * **注意** 上一页面没有使用 `this.$preload` 传入任何参数时 `this.$router` 不存在 `preload` 字段 + * 请开发者在使用时自行判断 + * + * @example + * componentWillMount () { + * console.log('preload: ', this.$router.preload) + * } + * + * @see 参考[性能优化实践:在小程序中,可以使用 `this.$preload` 函数进行页面跳转传参](https://nervjs.github.io/taro/docs/optimized-practice.html#%E5%9C%A8%E5%B0%8F%E7%A8%8B%E5%BA%8F%E4%B8%AD-%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8-this-preload-%E5%87%BD%E6%95%B0%E8%BF%9B%E8%A1%8C%E9%A1%B5%E9%9D%A2%E8%B7%B3%E8%BD%AC%E4%BC%A0%E5%8F%82)一节 + */ + preload?: { + [key: string]: string + } } $preloadData: any @@ -729,6 +760,11 @@ declare namespace Taro { class PureComponent

extends Component {} + function memo

( + FunctionComponent: FunctionComponent

, + compare?: (oldProps: P, newProps: P) => Boolean + ): FunctionComponent

+ // Events class Events { /** @@ -862,6 +898,17 @@ declare namespace Taro { */ header: any } + /** + * 网络请求任务对象 + * @see https://developers.weixin.qq.com/miniprogram/dev/api/network/request/RequestTask.html + */ + interface requestTask extends Promise> { + /** + * 中断请求任务 + * @see https://developers.weixin.qq.com/miniprogram/dev/api/network/request/RequestTask.abort.html + */ + abort(): void + } type Param < P extends any | string | ArrayBuffer = any > = { /** * 开发者服务器接口地址 @@ -992,11 +1039,11 @@ declare namespace Taro { * 发起网络请求。**使用前请先阅读[说明](https://developers.weixin.qq.com/miniprogram/dev/api/network/request/wx.request.html)**。 * * **返回值:** + * + * @returns {request.requestTask} 返回一个 `requestTask` 对象,通过 `requestTask`,可中断请求任务。 * * @since 1.4.0 * - * 返回一个 `requestTask` 对象,通过 `requestTask`,可中断请求任务。 - * * **Bug & Tip:** * * 1. `tip`: content-type 默认为 'application/json'; @@ -1004,44 +1051,54 @@ declare namespace Taro { * 3. `bug`: 开发者工具 `0.10.102800` 版本,`header` 的 `content-type` 设置异常; * * **示例代码:** + * + * @example + * // 回调函数(Callback)用法: + * const requestTask = Taro.request({ + * url: 'test.php', //仅为示例,并非真实的接口地址 + * data: { + * x: '' , + * y: '' + * }, + * header: { + * 'content-type': 'application/json' // 默认值 + * }, + * success: function(res) { + * console.log(res.data) + * } + * }) + * requestTask.abort() + * + * // Promise 用法: + * const requestTask = Taro.request({ + * url: 'test.php', //仅为示例,并非真实的接口地址 + * data: { + * x: '' , + * y: '' + * }, + * header: { + * 'content-type': 'application/json' // 默认值 + * }, + * success: function(res) { + * console.log(res.data) + * } + * }) + * requestTask.then(res => { + * console.log(res.data) + * }) + * requestTask.abort() + * + * // async/await 用法: + * const requestTask = Taro.request(params) + * const res = await requestTask + * requestTask.abort() + * + * // 不需要 abort 的 async/await 用法: + * const res = await Taro.request(params) * - ```javascript - Taro.request({ - url: 'test.php', //仅为示例,并非真实的接口地址 - data: { - x: '' , - y: '' - }, - header: { - 'content-type': 'application/json' // 默认值 - }, - success: function(res) { - console.log(res.data) - } - }) - ``` - * - * **示例代码:** - * - ```javascript - const requestTask = Taro.request({ - url: 'test.php', //仅为示例,并非真实的接口地址 - data: { - x: '' , - y: '' - }, - header: { - 'content-type': 'application/json' - }, - success: function(res) { - console.log(res.data) - } - }) - requestTask.abort() // 取消请求任务 - ``` * @see https://developers.weixin.qq.com/miniprogram/dev/api/network/request/wx.request.html */ - function request(OBJECT: request.Param): Promise> + function request(OBJECT: request.Param): request.requestTask type arrayBuffer = Uint8Array | Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | ArrayBuffer @@ -9965,6 +10022,50 @@ declare namespace Taro { */ function reportAnalytics(eventName: string, data: any): void + /** + * @since 2.2.2 + * + * 获取当前帐号信息 + * + * **示例代码:** + * + ```javascript + const accountInfo = wx.getAccountInfoSync(); + console.log(accountInfo.miniProgram.appId) // 小程序 appId + console.log(accountInfo.plugin.appId) // 插件 appId + console.log(accountInfo.plugin.version) // 插件版本号, 'a.b.c' 这样的形式 + ``` + * @see https://developers.weixin.qq.com/miniprogram/dev/api/open-api/account-info/wx.getAccountInfoSync.html + */ + function getAccountInfoSync(): getAccountInfoSync.Return + + namespace getAccountInfoSync { + interface Return { + /** + * 小程序帐号信息 + */ + miniProgram: { + /** + * 小程序 appId + */ + appId: string + } + /** + * 插件帐号信息(仅在插件中调用时包含这一项) + */ + plugin?: { + /** + * 插件 appId + */ + appId: string + /** + * 插件版本号 + */ + version: string + } + } + } + /** * @since 1.9.90 * diff --git a/packages/taroize/package.json b/packages/taroize/package.json index 188e55579075..86d984f37081 100644 --- a/packages/taroize/package.json +++ b/packages/taroize/package.json @@ -1,6 +1,6 @@ { "name": "@tarojs/taroize", - "version": "1.3.0", + "version": "1.3.7", "description": "转换原生微信小程序代码为 Taro 代码", "main": "index.js", "files": [ diff --git a/packages/taroize/src/script.ts b/packages/taroize/src/script.ts index 1ad5c2caec50..7288cdbf98b0 100644 --- a/packages/taroize/src/script.ts +++ b/packages/taroize/src/script.ts @@ -316,7 +316,9 @@ function parsePage ( } if (prop.isObjectMethod()) { const body = prop.get('body') - return t.classMethod('method', t.identifier(lifecycle), params, body.node) + const cm = t.classMethod('method', t.identifier(lifecycle), params, body.node) + cm.async = isAsync + return cm } const node = value.node const method = t.isFunctionExpression(node) || t.isArrowFunctionExpression(node) diff --git a/packages/taroize/src/template.ts b/packages/taroize/src/template.ts index 587e58175ad0..8df0fec7141c 100644 --- a/packages/taroize/src/template.ts +++ b/packages/taroize/src/template.ts @@ -10,7 +10,7 @@ function isNumeric (n) { return !isNaN(parseFloat(n)) && isFinite(n) } -const NumberWords = ['z', 'a','b','c','d','e', 'f','g','h','i','j'] +const NumberWords = ['z', 'b','c','d','e', 'f','g','h','i','j','k'] function buildTemplateName (name: string) { if (/wx/i.test(name)) { diff --git a/packages/taroize/src/utils.ts b/packages/taroize/src/utils.ts index cf46febf2acb..802ff01d2530 100644 --- a/packages/taroize/src/utils.ts +++ b/packages/taroize/src/utils.ts @@ -79,7 +79,7 @@ export function buildRender ( const stateDecl = t.variableDeclaration('const', [ t.variableDeclarator( t.objectPattern(Array.from(new Set(stateKeys)).filter(s => !propsKeys.includes(s)).map(s => - t.objectProperty(t.identifier(s), t.identifier(s)) + t.objectProperty(t.identifier(s), t.identifier(s), false, true) ) as any), t.memberExpression(t.thisExpression(), t.identifier('state')) ) @@ -89,7 +89,7 @@ export function buildRender ( if (propsKeys.length) { let patterns = t.objectPattern(Array.from(new Set(propsKeys)).map(s => - t.objectProperty(t.identifier(s), t.identifier(s)) + t.objectProperty(t.identifier(s), t.identifier(s), false, true) ) as any) if (typeof templateType === 'string') { patterns = t.objectPattern([ diff --git a/packages/taroize/src/wxml.ts b/packages/taroize/src/wxml.ts index cf8e09489c7b..3f43947eee56 100644 --- a/packages/taroize/src/wxml.ts +++ b/packages/taroize/src/wxml.ts @@ -7,7 +7,7 @@ import { specialEvents } from './events' import { parseTemplate, parseModule } from './template' import { usedComponents, errors, globals } from './global' import { reserveKeyWords } from './constant' -import { parseExpression } from 'babylon' +import { parse as parseFile } from 'babylon' const allCamelCase = (str: string) => str.charAt(0).toUpperCase() + camelCase(str.substr(1)) @@ -734,21 +734,9 @@ function parseAttribute (attr: Attribute) { } else { throw new Error(err) } - } else if (content.includes(':')) { - const [ key, value ] = pureContent.split(':') - expr = t.objectExpression([t.objectProperty(t.stringLiteral(key), parseExpression(value))]) - } else if (content.includes('...') && content.includes(',')) { - const objExpr = content.slice(1, content.length - 1).split(',') - const props: (t.SpreadProperty | t.ObjectProperty)[] = [] - for (const str of objExpr) { - const s = str.trim() - if (s.includes('...')) { - props.push(t.spreadProperty(t.identifier(s.slice(3)))) - } else { - props.push(t.objectProperty(t.identifier(s), t.identifier(s))) - } - } - expr = t.objectExpression(props) + } else if (content.includes(':') || (content.includes('...') && content.includes(','))) { + const file = parseFile(`var a = ${attr.value!.slice(1, attr.value!.length - 1)}`, { plugins: ['objectRestSpread'] }) + expr = file.program.body[0].declarations[0].init } else { const err = `转换模板参数: \`${key}: ${value}\` 报错` throw new Error(err) @@ -770,7 +758,7 @@ function parseAttribute (attr: Attribute) { ) } - if (key.startsWith('catch') && value && value === 'true') { + if (key.startsWith('catch') && value && (value === 'true' || value.trim() === '')) { jsxValue = t.jSXExpressionContainer( t.memberExpression(t.thisExpression(), t.identifier('privateStopNoop')) ) diff --git a/website/sidebars.json b/website/sidebars.json index 1f071b837642..52e5ff81acdd 100644 --- a/website/sidebars.json +++ b/website/sidebars.json @@ -28,6 +28,7 @@ "context", "hooks", "children", + "render-props", "ref", "envs", "relations", diff --git a/yarn.lock b/yarn.lock index afb9818bfde4..7e4aa065e5e3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -777,6 +777,11 @@ dependencies: any-observable "^0.3.0" +"@sindresorhus/is@^0.7.0": + version "0.7.0" + resolved "https://registry.npm.taobao.org/@sindresorhus/is/download/@sindresorhus/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" + integrity sha1-mgb08TfuhNffBGDB/bETX/psUP0= + "@types/acorn@^4.0.3": version "4.0.3" resolved "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.3.tgz#d1f3e738dde52536f9aad3d3380d14e448820afd" @@ -795,6 +800,11 @@ version "0.0.38" resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.38.tgz#c1be40aa933723c608820a99a373a16d215a1ca2" +"@types/q@^1.5.1": + version "1.5.2" + resolved "https://registry.npm.taobao.org/@types/q/download/@types/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" + integrity sha1-aQoUdbhPKohP0HzXl8APXzE1bqg= + JSONStream@^1.0.4: version "1.3.5" resolved "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" @@ -909,12 +919,6 @@ ansi-escapes@^3.0.0: version "3.1.0" resolved "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" -ansi-gray@^0.1.1: - version "0.1.1" - resolved "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" - dependencies: - ansi-wrap "0.1.0" - ansi-html@0.0.7: version "0.0.7" resolved "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" @@ -966,11 +970,17 @@ aproba@^1.0.3: version "1.2.0" resolved "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" -archive-type@^3.0.0, archive-type@^3.0.1: - version "3.2.0" - resolved "https://registry.npmjs.org/archive-type/-/archive-type-3.2.0.tgz#9cd9c006957ebe95fadad5bd6098942a813737f6" +arch@^2.1.0: + version "2.1.1" + resolved "https://registry.npm.taobao.org/arch/download/arch-2.1.1.tgz#8f5c2731aa35a30929221bb0640eed65175ec84e" + integrity sha1-j1wnMao1owkpIhuwZA7tZRdeyE4= + +archive-type@^4.0.0: + version "4.0.0" + resolved "https://registry.npm.taobao.org/archive-type/download/archive-type-4.0.0.tgz#f92e72233056dfc6969472749c267bdb046b1d70" + integrity sha1-+S5yIzBW38aWlHJ0nCZ72wRrHXA= dependencies: - file-type "^3.1.0" + file-type "^4.2.0" are-we-there-yet@~1.1.2: version "1.1.5" @@ -1055,10 +1065,15 @@ array-union@^1.0.1: dependencies: array-uniq "^1.0.1" -array-uniq@^1.0.0, array-uniq@^1.0.1, array-uniq@^1.0.2: +array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" +array-uniq@^2.1.0: + version "2.1.0" + resolved "https://registry.npm.taobao.org/array-uniq/download/array-uniq-2.1.0.tgz#46603d5e28e79bfd02b046fcc1d77c6820bd8e98" + integrity sha1-RmA9Xijnm/0CsEb8wdd8aCC9jpg= + array-unique@^0.2.1: version "0.2.1" resolved "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" @@ -1107,10 +1122,6 @@ ast-types@0.9.2: version "0.9.2" resolved "http://registry.npmjs.org/ast-types/-/ast-types-0.9.2.tgz#2cc19979d15c655108bf565323b8e7ee38751f6b" -async-each-series@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/async-each-series/-/async-each-series-1.1.0.tgz#f42fd8155d38f21a5b8ea07c28e063ed1700b138" - async-each@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" @@ -1817,57 +1828,57 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" -beeper@^1.0.0: - version "1.1.1" - resolved "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" - big.js@^3.1.3: version "3.2.0" resolved "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" -bin-build@^2.0.0: - version "2.2.0" - resolved "http://registry.npmjs.org/bin-build/-/bin-build-2.2.0.tgz#11f8dd61f70ffcfa2bdcaa5b46f5e8fedd4221cc" +bin-build@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/bin-build/download/bin-build-3.0.0.tgz#c5780a25a8a9f966d8244217e6c1f5082a143861" + integrity sha1-xXgKJaip+WbYJEIX5sH1CCoUOGE= dependencies: - archive-type "^3.0.1" - decompress "^3.0.0" - download "^4.1.2" - exec-series "^1.0.0" - rimraf "^2.2.6" - tempfile "^1.0.0" - url-regex "^3.0.0" + decompress "^4.0.0" + download "^6.2.2" + execa "^0.7.0" + p-map-series "^1.0.0" + tempfile "^2.0.0" -bin-check@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/bin-check/-/bin-check-2.0.0.tgz#86f8e6f4253893df60dc316957f5af02acb05930" +bin-check@^4.1.0: + version "4.1.0" + resolved "https://registry.npm.taobao.org/bin-check/download/bin-check-4.1.0.tgz#fc495970bdc88bb1d5a35fc17e65c4a149fc4a49" + integrity sha1-/ElZcL3Ii7HVo1/BfmXEoUn8Skk= dependencies: - executable "^1.0.0" + execa "^0.7.0" + executable "^4.1.0" -bin-version-check@^2.1.0: - version "2.1.0" - resolved "http://registry.npmjs.org/bin-version-check/-/bin-version-check-2.1.0.tgz#e4e5df290b9069f7d111324031efc13fdd11a5b0" +bin-version-check@^4.0.0: + version "4.0.0" + resolved "https://registry.npm.taobao.org/bin-version-check/download/bin-version-check-4.0.0.tgz#7d819c62496991f80d893e6e02a3032361608f71" + integrity sha1-fYGcYklpkfgNiT5uAqMDI2Fgj3E= dependencies: - bin-version "^1.0.0" - minimist "^1.1.0" - semver "^4.0.3" - semver-truncate "^1.0.0" + bin-version "^3.0.0" + semver "^5.6.0" + semver-truncate "^1.1.2" -bin-version@^1.0.0: - version "1.0.4" - resolved "http://registry.npmjs.org/bin-version/-/bin-version-1.0.4.tgz#9eb498ee6fd76f7ab9a7c160436f89579435d78e" +bin-version@^3.0.0: + version "3.1.0" + resolved "https://registry.npm.taobao.org/bin-version/download/bin-version-3.1.0.tgz#5b09eb280752b1bd28f0c9db3f96f2f43b6c0839" + integrity sha1-WwnrKAdSsb0o8MnbP5by9DtsCDk= dependencies: - find-versions "^1.0.0" + execa "^1.0.0" + find-versions "^3.0.0" -bin-wrapper@^3.0.0: - version "3.0.2" - resolved "http://registry.npmjs.org/bin-wrapper/-/bin-wrapper-3.0.2.tgz#67d3306262e4b1a5f2f88ee23464f6a655677aeb" +bin-wrapper@^4.0.0: + version "4.1.0" + resolved "https://registry.npm.taobao.org/bin-wrapper/download/bin-wrapper-4.1.0.tgz#99348f2cf85031e3ef7efce7e5300aeaae960605" + integrity sha1-mTSPLPhQMePvfvzn5TAK6q6WBgU= dependencies: - bin-check "^2.0.0" - bin-version-check "^2.1.0" - download "^4.0.0" - each-async "^1.1.1" - lazy-req "^1.0.0" - os-filter-obj "^1.0.0" + bin-check "^4.1.0" + bin-version-check "^4.0.0" + download "^7.1.0" + import-lazy "^3.1.0" + os-filter-obj "^2.0.0" + pify "^4.0.1" binary-extensions@^1.0.0: version "1.12.0" @@ -2065,10 +2076,6 @@ buffer-fill@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" -buffer-from@^0.1.1: - version "0.1.2" - resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz#15f4b9bcef012044df31142c14333caf6e0260d0" - buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -2077,15 +2084,6 @@ buffer-indexof@^1.0.0: version "1.1.1" resolved "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" -buffer-to-vinyl@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/buffer-to-vinyl/-/buffer-to-vinyl-1.1.0.tgz#00f15faee3ab7a1dda2cde6d9121bffdd07b2262" - dependencies: - file-type "^3.1.0" - readable-stream "^2.0.2" - uuid "^2.0.1" - vinyl "^1.0.0" - buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" @@ -2098,6 +2096,14 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" +buffer@^5.2.1: + version "5.2.1" + resolved "https://registry.npm.taobao.org/buffer/download/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6" + integrity sha1-3Vf6DxCaxZxgJHkETcp7iz0LcdY= + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + builtin-modules@^1.0.0: version "1.1.1" resolved "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" @@ -2136,6 +2142,19 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +cacheable-request@^2.1.1: + version "2.1.4" + resolved "https://registry.npm.taobao.org/cacheable-request/download/cacheable-request-2.1.4.tgz#0d808801b6342ad33c91df9d0b44dc09b91e5c3d" + integrity sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0= + dependencies: + clone-response "1.0.2" + get-stream "3.0.0" + http-cache-semantics "3.8.1" + keyv "3.0.0" + lowercase-keys "1.0.0" + normalize-url "2.0.1" + responselike "1.0.2" + call-me-maybe@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" @@ -2233,14 +2252,15 @@ caseless@~0.12.0: version "0.12.0" resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" -caw@^1.0.1: - version "1.2.0" - resolved "https://registry.npmjs.org/caw/-/caw-1.2.0.tgz#ffb226fe7efc547288dc62ee3e97073c212d1034" +caw@^2.0.0, caw@^2.0.1: + version "2.0.1" + resolved "https://registry.npm.taobao.org/caw/download/caw-2.0.1.tgz#6c3ca071fc194720883c2dc5da9b074bfc7e9e95" + integrity sha1-bDygcfwZRyCIPC3F2psHS/x+npU= dependencies: - get-proxy "^1.0.1" - is-obj "^1.0.0" - object-assign "^3.0.0" - tunnel-agent "^0.4.0" + get-proxy "^2.0.0" + isurl "^1.0.0-alpha5" + tunnel-agent "^0.6.0" + url-to-options "^1.0.1" center-align@^0.1.1: version "0.1.3" @@ -2465,6 +2485,13 @@ clone-deep@^2.0.1: kind-of "^6.0.0" shallow-clone "^1.0.0" +clone-response@1.0.2: + version "1.0.2" + resolved "https://registry.npm.taobao.org/clone-response/download/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" + integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + dependencies: + mimic-response "^1.0.0" + clone-stats@^0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" @@ -2473,10 +2500,6 @@ clone-stats@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" -clone@^0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz#c6126a90ad4f72dbf5acdb243cc37724fe93fc1f" - clone@^1.0.0, clone@^1.0.2: version "1.0.4" resolved "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" @@ -2500,23 +2523,22 @@ cmd-shim@^2.0.2: graceful-fs "^4.1.2" mkdirp "~0.5.0" -co@3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/co/-/co-3.1.0.tgz#4ea54ea5a08938153185e15210c68d9092bc1b78" - co@^4.6.0: version "4.6.0" resolved "https://registry.npmjs.org/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" -coa@~1.0.1: - version "1.0.4" - resolved "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz#a9ef153660d6a86a8bdec0289a5c684d217432fd" +coa@^2.0.2: + version "2.0.2" + resolved "https://registry.npm.taobao.org/coa/download/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" + integrity sha1-Q/bCEVG07yv1cYfbDXPeIp4+fsM= dependencies: + "@types/q" "^1.5.1" + chalk "^2.4.1" q "^1.1.2" -coa@~2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/coa/-/coa-2.0.1.tgz#f3f8b0b15073e35d70263fb1042cb2c023db38af" +coa@~1.0.1: + version "1.0.4" + resolved "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz#a9ef153660d6a86a8bdec0289a5c684d217432fd" dependencies: q "^1.1.2" @@ -2562,10 +2584,6 @@ color-string@^1.5.2: color-name "^1.0.0" simple-swizzle "^0.2.2" -color-support@^1.1.3: - version "1.1.3" - resolved "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" - color@^0.11.0: version "0.11.4" resolved "http://registry.npmjs.org/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764" @@ -2673,7 +2691,7 @@ concat-map@0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" -concat-stream@^1.4.10, concat-stream@^1.4.6, concat-stream@^1.4.7, concat-stream@^1.5.2, concat-stream@^1.6.0: +concat-stream@^1.4.10, concat-stream@^1.4.7, concat-stream@^1.5.2, concat-stream@^1.6.0: version "1.6.2" resolved "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" dependencies: @@ -2688,6 +2706,14 @@ concat-with-sourcemaps@^1.0.5: dependencies: source-map "^0.6.1" +config-chain@^1.1.11: + version "1.1.12" + resolved "https://registry.npm.taobao.org/config-chain/download/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" + integrity sha1-D96NCRIA616AjK8l/mGMAvSOTvo= + dependencies: + ini "^1.3.4" + proto-list "~1.2.1" + connect-history-api-fallback@^1.3.0: version "1.5.0" resolved "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz#b06873934bc5e344fef611a196a6faae0aee015a" @@ -2718,6 +2744,13 @@ content-disposition@0.5.2: version "0.5.2" resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" +content-disposition@^0.5.2: + version "0.5.3" + resolved "https://registry.npm.taobao.org/content-disposition/download/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" + integrity sha1-4TDK9+cnkIfFYWwgB9BIVpiYT70= + dependencies: + safe-buffer "5.1.2" + content-type@~1.0.4: version "1.0.4" resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" @@ -3007,7 +3040,7 @@ conventional-recommended-bump@^1.2.1: meow "^3.3.0" object-assign "^4.0.1" -convert-source-map@^1.1.0, convert-source-map@^1.1.1, convert-source-map@^1.5.1: +convert-source-map@^1.1.0, convert-source-map@^1.5.1: version "1.6.0" resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" dependencies: @@ -3078,7 +3111,7 @@ create-ecdh@^4.0.0: bn.js "^4.1.0" elliptic "^6.0.0" -create-error-class@^3.0.0, create-error-class@^3.0.1: +create-error-class@^3.0.0: version "3.0.2" resolved "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" dependencies: @@ -3188,9 +3221,10 @@ css-modules-loader-core@^1.1.0: postcss-modules-scope "1.1.0" postcss-modules-values "1.3.0" -css-select-base-adapter@~0.1.0: +css-select-base-adapter@^0.1.1: version "0.1.1" - resolved "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" + resolved "https://registry.npm.taobao.org/css-select-base-adapter/download/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" + integrity sha1-Oy/0lyzDYquIVhUHqVQIoUMhNdc= css-select@^1.1.0, css-select@~1.2.0: version "1.2.0" @@ -3290,9 +3324,10 @@ cssnano@^3.10.0: postcss-value-parser "^3.2.3" postcss-zindex "^2.0.1" -csso@^3.5.0: +csso@^3.5.1: version "3.5.1" - resolved "https://registry.npmjs.org/csso/-/csso-3.5.1.tgz#7b9eb8be61628973c1b261e169d2f024008e758b" + resolved "https://registry.npm.taobao.org/csso/download/csso-3.5.1.tgz#7b9eb8be61628973c1b261e169d2f024008e758b" + integrity sha1-e564vmFiiXPBsmHhadLwJACOdYs= dependencies: css-tree "1.0.0-alpha.29" @@ -3402,71 +3437,64 @@ decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" -decompress-response@^3.2.0: +decompress-response@^3.2.0, decompress-response@^3.3.0: version "3.3.0" resolved "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" dependencies: mimic-response "^1.0.0" -decompress-tar@^3.0.0: - version "3.1.0" - resolved "https://registry.npmjs.org/decompress-tar/-/decompress-tar-3.1.0.tgz#217c789f9b94450efaadc5c5e537978fc333c466" +decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: + version "4.1.1" + resolved "https://registry.npm.taobao.org/decompress-tar/download/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" + integrity sha1-cYy9P8sWIJcW5womuE57pFkuWvE= dependencies: - is-tar "^1.0.0" - object-assign "^2.0.0" - strip-dirs "^1.0.0" - tar-stream "^1.1.1" - through2 "^0.6.1" - vinyl "^0.4.3" + file-type "^5.2.0" + is-stream "^1.1.0" + tar-stream "^1.5.2" -decompress-tarbz2@^3.0.0: - version "3.1.0" - resolved "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-3.1.0.tgz#8b23935681355f9f189d87256a0f8bdd96d9666d" +decompress-tarbz2@^4.0.0: + version "4.1.1" + resolved "https://registry.npm.taobao.org/decompress-tarbz2/download/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" + integrity sha1-MIKluIDqQEOBY0nzeLVsUWvho5s= dependencies: - is-bzip2 "^1.0.0" - object-assign "^2.0.0" - seek-bzip "^1.0.3" - strip-dirs "^1.0.0" - tar-stream "^1.1.1" - through2 "^0.6.1" - vinyl "^0.4.3" + decompress-tar "^4.1.0" + file-type "^6.1.0" + is-stream "^1.1.0" + seek-bzip "^1.0.5" + unbzip2-stream "^1.0.9" -decompress-targz@^3.0.0: - version "3.1.0" - resolved "https://registry.npmjs.org/decompress-targz/-/decompress-targz-3.1.0.tgz#b2c13df98166268991b715d6447f642e9696f5a0" +decompress-targz@^4.0.0: + version "4.1.1" + resolved "https://registry.npm.taobao.org/decompress-targz/download/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" + integrity sha1-wJvDXE0R894J8tLaU+neI+fOHu4= dependencies: - is-gzip "^1.0.0" - object-assign "^2.0.0" - strip-dirs "^1.0.0" - tar-stream "^1.1.1" - through2 "^0.6.1" - vinyl "^0.4.3" + decompress-tar "^4.1.1" + file-type "^5.2.0" + is-stream "^1.1.0" -decompress-unzip@^3.0.0: - version "3.4.0" - resolved "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-3.4.0.tgz#61475b4152066bbe3fee12f9d629d15fe6478eeb" +decompress-unzip@^4.0.1: + version "4.0.1" + resolved "https://registry.npm.taobao.org/decompress-unzip/download/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" + integrity sha1-3qrM39FK6vhVePczroIQ+bSEj2k= dependencies: - is-zip "^1.0.0" - read-all-stream "^3.0.0" - stat-mode "^0.2.0" - strip-dirs "^1.0.0" - through2 "^2.0.0" - vinyl "^1.0.0" - yauzl "^2.2.1" + file-type "^3.8.0" + get-stream "^2.2.0" + pify "^2.3.0" + yauzl "^2.4.2" -decompress@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/decompress/-/decompress-3.0.0.tgz#af1dd50d06e3bfc432461d37de11b38c0d991bed" - dependencies: - buffer-to-vinyl "^1.0.0" - concat-stream "^1.4.6" - decompress-tar "^3.0.0" - decompress-tarbz2 "^3.0.0" - decompress-targz "^3.0.0" - decompress-unzip "^3.0.0" - stream-combiner2 "^1.1.1" - vinyl-assign "^1.0.1" - vinyl-fs "^2.2.0" +decompress@^4.0.0, decompress@^4.2.0: + version "4.2.0" + resolved "https://registry.npm.taobao.org/decompress/download/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d" + integrity sha1-eu3YVCflqS2s/lVnSnxQXpbQH50= + dependencies: + decompress-tar "^4.0.0" + decompress-tarbz2 "^4.0.0" + decompress-targz "^4.0.0" + decompress-unzip "^4.0.1" + graceful-fs "^4.1.10" + make-dir "^1.0.0" + pify "^2.3.0" + strip-dirs "^2.0.0" dedent@^0.7.0: version "0.7.0" @@ -3492,10 +3520,6 @@ deep-is@~0.1.3: version "0.1.3" resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" -deepmerge@^2.1.1: - version "2.2.1" - resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170" - default-gateway@^2.6.0: version "2.7.2" resolved "https://registry.npmjs.org/default-gateway/-/default-gateway-2.7.2.tgz#b7ef339e5e024b045467af403d50348db4642d0f" @@ -3509,7 +3533,7 @@ defaults@^1.0.3: dependencies: clone "^1.0.2" -define-properties@^1.1.2: +define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" dependencies: @@ -3662,9 +3686,10 @@ doctrine@^2.1.0: dependencies: esutils "^2.0.2" -docusaurus@^1.3.2: - version "1.5.1" - resolved "https://registry.npmjs.org/docusaurus/-/docusaurus-1.5.1.tgz#ce1dc0f3531d6812f2b4a9e9a0151d885d076d78" +docusaurus@^1.9.0: + version "1.10.0" + resolved "https://registry.npm.taobao.org/docusaurus/download/docusaurus-1.10.0.tgz#f32f8a3a7f2c3da38e48ccbc7a0fb148311e413d" + integrity sha1-8y+KOn8sPaOOSMy8eg+xSDEeQT0= dependencies: "@babel/core" "^7.0.0" "@babel/plugin-proposal-class-properties" "^7.0.0" @@ -3684,7 +3709,6 @@ docusaurus@^1.3.2: cross-spawn "^6.0.5" crowdin-cli "^0.3.0" cssnano "^3.10.0" - deepmerge "^2.1.1" escape-string-regexp "^1.0.5" express "^4.15.3" feed "^1.1.0" @@ -3692,11 +3716,11 @@ docusaurus@^1.3.2: gaze "^1.1.2" glob "^7.1.3" highlight.js "^9.12.0" - imagemin "^5.3.1" - imagemin-gifsicle "^5.2.0" - imagemin-jpegtran "^5.0.2" - imagemin-optipng "^5.2.1" - imagemin-svgo "^6.0.0" + imagemin "^6.0.0" + imagemin-gifsicle "^6.0.1" + imagemin-jpegtran "^6.0.0" + imagemin-optipng "^6.0.0" + imagemin-svgo "^7.0.0" lodash "^4.17.11" markdown-toc "^1.2.0" mkdirp "^0.5.1" @@ -3708,7 +3732,7 @@ docusaurus@^1.3.2: react-dom "^16.5.0" remarkable "^1.7.1" request "^2.87.0" - shelljs "^0.7.8" + shelljs "^0.8.3" sitemap "^1.13.0" tcp-port-used "^0.1.2" tiny-lr "^1.1.1" @@ -3782,37 +3806,40 @@ dot-prop@^3.0.0: dependencies: is-obj "^1.0.0" -download@^4.0.0, download@^4.1.2: - version "4.4.3" - resolved "https://registry.npmjs.org/download/-/download-4.4.3.tgz#aa55fdad392d95d4b68e8c2be03e0c2aa21ba9ac" - dependencies: - caw "^1.0.1" - concat-stream "^1.4.7" - each-async "^1.0.0" - filenamify "^1.0.1" - got "^5.0.0" - gulp-decompress "^1.2.0" - gulp-rename "^1.2.0" - is-url "^1.2.0" - object-assign "^4.0.1" - read-all-stream "^3.0.0" - readable-stream "^2.0.2" - stream-combiner2 "^1.1.1" - vinyl "^1.0.0" - vinyl-fs "^2.2.0" - ware "^1.2.0" - -duplexer2@0.0.2: - version "0.0.2" - resolved "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" - dependencies: - readable-stream "~1.1.9" +download@^6.2.2: + version "6.2.5" + resolved "https://registry.npm.taobao.org/download/download/download-6.2.5.tgz#acd6a542e4cd0bb42ca70cfc98c9e43b07039714" + integrity sha1-rNalQuTNC7Qspwz8mMnkOwcDlxQ= + dependencies: + caw "^2.0.0" + content-disposition "^0.5.2" + decompress "^4.0.0" + ext-name "^5.0.0" + file-type "5.2.0" + filenamify "^2.0.0" + get-stream "^3.0.0" + got "^7.0.0" + make-dir "^1.0.0" + p-event "^1.0.0" + pify "^3.0.0" -duplexer2@^0.1.4, duplexer2@~0.1.0: - version "0.1.4" - resolved "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" - dependencies: - readable-stream "^2.0.2" +download@^7.1.0: + version "7.1.0" + resolved "https://registry.npm.taobao.org/download/download/download-7.1.0.tgz#9059aa9d70b503ee76a132897be6dec8e5587233" + integrity sha1-kFmqnXC1A+52oTKJe+beyOVYcjM= + dependencies: + archive-type "^4.0.0" + caw "^2.0.1" + content-disposition "^0.5.2" + decompress "^4.2.0" + ext-name "^5.0.0" + file-type "^8.1.0" + filenamify "^2.0.0" + get-stream "^3.0.0" + got "^8.3.1" + make-dir "^1.2.0" + p-event "^2.1.0" + pify "^3.0.0" duplexer3@^0.1.4: version "0.1.4" @@ -3822,22 +3849,6 @@ duplexer@^0.1.1: version "0.1.1" resolved "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" -duplexify@^3.2.0: - version "3.6.1" - resolved "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz#b1a7a29c4abfd639585efaecce80d666b1e34125" - dependencies: - end-of-stream "^1.0.0" - inherits "^2.0.1" - readable-stream "^2.0.0" - stream-shift "^1.0.0" - -each-async@^1.0.0, each-async@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/each-async/-/each-async-1.1.1.tgz#dee5229bdf0ab6ba2012a395e1b869abf8813473" - dependencies: - onetime "^1.0.0" - set-immediate-shim "^1.0.0" - ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -3936,7 +3947,19 @@ error@^7.0.0, error@^7.0.2: string-template "~0.2.1" xtend "~4.0.0" -es-abstract@^1.4.3, es-abstract@^1.5.1, es-abstract@^1.6.1, es-abstract@^1.7.0: +es-abstract@^1.12.0: + version "1.13.0" + resolved "https://registry.npm.taobao.org/es-abstract/download/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" + integrity sha1-rIYUX91QmdjdSVWMy6Lq+biOJOk= + dependencies: + es-to-primitive "^1.2.0" + function-bind "^1.1.1" + has "^1.0.3" + is-callable "^1.1.4" + is-regex "^1.0.4" + object-keys "^1.0.12" + +es-abstract@^1.4.3, es-abstract@^1.5.1, es-abstract@^1.7.0: version "1.12.0" resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" dependencies: @@ -3946,7 +3969,7 @@ es-abstract@^1.4.3, es-abstract@^1.5.1, es-abstract@^1.6.1, es-abstract@^1.7.0: is-callable "^1.1.3" is-regex "^1.0.4" -es-to-primitive@^1.1.1: +es-to-primitive@^1.1.1, es-to-primitive@^1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" dependencies: @@ -4266,13 +4289,6 @@ exec-buffer@^3.0.0: rimraf "^2.5.4" tempfile "^2.0.0" -exec-series@^1.0.0: - version "1.0.3" - resolved "https://registry.npmjs.org/exec-series/-/exec-series-1.0.3.tgz#6d257a9beac482a872c7783bc8615839fc77143a" - dependencies: - async-each-series "^1.1.0" - object-assign "^4.1.0" - execa@^0.10.0: version "0.10.0" resolved "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50" @@ -4321,11 +4337,12 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" -executable@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/executable/-/executable-1.1.0.tgz#877980e9112f3391066da37265de7ad8434ab4d9" +executable@^4.1.0: + version "4.1.1" + resolved "https://registry.npm.taobao.org/executable/download/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c" + integrity sha1-QVMr/zYdPlevTXY7cFgtsY9dEzw= dependencies: - meow "^3.1.0" + pify "^2.2.0" exit-hook@^1.0.0: version "1.1.1" @@ -4396,6 +4413,21 @@ express@^4.15.3, express@^4.16.2: utils-merge "1.0.1" vary "~1.1.2" +ext-list@^2.0.0: + version "2.2.2" + resolved "https://registry.npm.taobao.org/ext-list/download/ext-list-2.2.2.tgz#0b98e64ed82f5acf0f2931babf69212ef52ddd37" + integrity sha1-C5jmTtgvWs8PKTG6v2khLvUt3Tc= + dependencies: + mime-db "^1.28.0" + +ext-name@^5.0.0: + version "5.0.0" + resolved "https://registry.npm.taobao.org/ext-name/download/ext-name-5.0.0.tgz#70781981d183ee15d13993c8822045c506c8f0a6" + integrity sha1-cHgZgdGD7hXROZPIgiBFxQbI8KY= + dependencies: + ext-list "^2.0.0" + sort-keys-length "^1.0.0" + extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" @@ -4464,14 +4496,6 @@ extsprintf@^1.2.0: version "1.4.0" resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" -fancy-log@^1.1.0: - version "1.3.2" - resolved "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz#f41125e3d84f2e7d89a43d06d958c8f78be16be1" - dependencies: - ansi-gray "^0.1.1" - color-support "^1.1.3" - time-stamp "^1.0.0" - fast-deep-equal@^1.0.0: version "1.1.0" resolved "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" @@ -4547,13 +4571,35 @@ file-entry-cache@^2.0.0: flat-cache "^1.2.1" object-assign "^4.0.1" -file-type@^3.1.0: +file-type@5.2.0, file-type@^5.2.0: + version "5.2.0" + resolved "https://registry.npm.taobao.org/file-type/download/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" + integrity sha1-LdvqfHP/42No365J3DOMBYwritY= + +file-type@^10.4.0, file-type@^10.7.0: + version "10.11.0" + resolved "https://registry.npm.taobao.org/file-type/download/file-type-10.11.0.tgz#2961d09e4675b9fb9a3ee6b69e9cd23f43fd1890" + integrity sha1-KWHQnkZ1ufuaPua2npzSP0P9GJA= + +file-type@^3.8.0: version "3.9.0" - resolved "http://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" + resolved "https://registry.npm.taobao.org/file-type/download/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" + integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek= -file-type@^4.1.0: +file-type@^4.2.0: version "4.4.0" - resolved "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz#1b600e5fca1fbdc6e80c0a70c71c8dba5f7906c5" + resolved "https://registry.npm.taobao.org/file-type/download/file-type-4.4.0.tgz#1b600e5fca1fbdc6e80c0a70c71c8dba5f7906c5" + integrity sha1-G2AOX8ofvcboDApwxxyNul95BsU= + +file-type@^6.1.0: + version "6.2.0" + resolved "https://registry.npm.taobao.org/file-type/download/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" + integrity sha1-5QzXXTVv/tTjBtxPW89Sp5kDqRk= + +file-type@^8.1.0: + version "8.1.0" + resolved "https://registry.npm.taobao.org/file-type/download/file-type-8.1.0.tgz#244f3b7ef641bbe0cca196c7276e4b332399f68c" + integrity sha1-JE87fvZBu+DMoZbHJ25LMyOZ9ow= filename-regex@^2.0.0: version "2.0.1" @@ -4563,6 +4609,11 @@ filename-reserved-regex@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-1.0.0.tgz#e61cf805f0de1c984567d0386dc5df50ee5af7e4" +filename-reserved-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/filename-reserved-regex/download/filename-reserved-regex-2.0.0.tgz#abf73dfab735d045440abfea2d91f389ebbfa229" + integrity sha1-q/c9+rc10EVECr/qLZHzieu/oik= + filenamify-url@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/filenamify-url/-/filenamify-url-1.0.0.tgz#b32bd81319ef5863b73078bed50f46a4f7975f50" @@ -4570,7 +4621,7 @@ filenamify-url@^1.0.0: filenamify "^1.0.0" humanize-url "^1.0.0" -filenamify@^1.0.0, filenamify@^1.0.1: +filenamify@^1.0.0: version "1.2.1" resolved "https://registry.npmjs.org/filenamify/-/filenamify-1.2.1.tgz#a9f2ffd11c503bed300015029272378f1f1365a5" dependencies: @@ -4578,6 +4629,15 @@ filenamify@^1.0.0, filenamify@^1.0.1: strip-outer "^1.0.0" trim-repeated "^1.0.0" +filenamify@^2.0.0: + version "2.1.0" + resolved "https://registry.npm.taobao.org/filenamify/download/filenamify-2.1.0.tgz#88faf495fb1b47abfd612300002a16228c677ee9" + integrity sha1-iPr0lfsbR6v9YSMAACoWIoxnfuk= + dependencies: + filename-reserved-regex "^2.0.0" + strip-outer "^1.0.0" + trim-repeated "^1.0.0" + filesize@3.5.11: version "3.5.11" resolved "https://registry.npmjs.org/filesize/-/filesize-3.5.11.tgz#1919326749433bb3cf77368bd158caabcc19e9ee" @@ -4652,18 +4712,13 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" -find-versions@^1.0.0: - version "1.2.1" - resolved "http://registry.npmjs.org/find-versions/-/find-versions-1.2.1.tgz#cbde9f12e38575a0af1be1b9a2c5d5fd8f186b62" +find-versions@^3.0.0: + version "3.1.0" + resolved "https://registry.npm.taobao.org/find-versions/download/find-versions-3.1.0.tgz#10161f29cf3eb4350dec10a29bdde75bff0df32d" + integrity sha1-EBYfKc8+tDUN7BCim93nW/8N8y0= dependencies: - array-uniq "^1.0.0" - get-stdin "^4.0.1" - meow "^3.5.0" - semver-regex "^1.0.0" - -first-chunk-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e" + array-uniq "^2.1.0" + semver-regex "^2.0.0" first-chunk-stream@^2.0.0: version "2.0.0" @@ -4740,6 +4795,14 @@ fresh@0.5.2: version "0.5.2" resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" +from2@^2.1.1: + version "2.3.0" + resolved "https://registry.npm.taobao.org/from2/download/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" + integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.0" + front-matter@^2.1.2: version "2.3.0" resolved "https://registry.npmjs.org/front-matter/-/front-matter-2.3.0.tgz#7203af896ce357ee04e2aa45169ea91ed7f67504" @@ -4792,7 +4855,7 @@ fstream@^1.0.0, fstream@^1.0.2: mkdirp ">=0.5 0" rimraf "2" -function-bind@^1.0.2, function-bind@^1.1.0, function-bind@^1.1.1: +function-bind@^1.0.2, function-bind@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -4855,11 +4918,12 @@ get-port@^3.2.0: version "3.2.0" resolved "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" -get-proxy@^1.0.1: - version "1.1.0" - resolved "https://registry.npmjs.org/get-proxy/-/get-proxy-1.1.0.tgz#894854491bc591b0f147d7ae570f5c678b7256eb" +get-proxy@^2.0.0: + version "2.1.0" + resolved "https://registry.npm.taobao.org/get-proxy/download/get-proxy-2.1.0.tgz#349f2b4d91d44c4d4d4e9cba2ad90143fac5ef93" + integrity sha1-NJ8rTZHUTE1NTpy6KtkBQ/rF75M= dependencies: - rc "^1.1.2" + npm-conf "^1.1.0" get-stdin@5.0.1: version "5.0.1" @@ -4873,10 +4937,18 @@ get-stdin@^6.0.0: version "6.0.0" resolved "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" -get-stream@^3.0.0: +get-stream@3.0.0, get-stream@^3.0.0: version "3.0.0" resolved "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" +get-stream@^2.2.0: + version "2.3.1" + resolved "https://registry.npm.taobao.org/get-stream/download/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" + integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4= + dependencies: + object-assign "^4.0.1" + pinkie-promise "^2.0.0" + get-stream@^4.0.0: version "4.1.0" resolved "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -4912,12 +4984,14 @@ gh-pages@^1.1.0: graceful-fs "4.1.11" rimraf "^2.6.2" -gifsicle@^3.0.0: - version "3.0.4" - resolved "http://registry.npmjs.org/gifsicle/-/gifsicle-3.0.4.tgz#f45cb5ed10165b665dc929e0e9328b6c821dfa3b" +gifsicle@^4.0.0: + version "4.0.1" + resolved "https://registry.npm.taobao.org/gifsicle/download/gifsicle-4.0.1.tgz#30e1e61e3ee4884ef702641b2e98a15c2127b2e2" + integrity sha1-MOHmHj7kiE73AmQbLpihXCEnsuI= dependencies: - bin-build "^2.0.0" - bin-wrapper "^3.0.0" + bin-build "^3.0.0" + bin-wrapper "^4.0.0" + execa "^1.0.0" logalot "^2.0.0" git-raw-commits@2.0.0: @@ -4986,40 +5060,17 @@ glob-parent@^2.0.0: dependencies: is-glob "^2.0.0" -glob-parent@^3.0.0, glob-parent@^3.1.0: +glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" dependencies: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-stream@^5.3.2: - version "5.3.5" - resolved "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz#a55665a9a8ccdc41915a87c701e32d4e016fad22" - dependencies: - extend "^3.0.0" - glob "^5.0.3" - glob-parent "^3.0.0" - micromatch "^2.3.7" - ordered-read-streams "^0.3.0" - through2 "^0.6.0" - to-absolute-glob "^0.1.1" - unique-stream "^2.0.2" - glob-to-regexp@^0.3.0: version "0.3.0" resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" -glob@^5.0.3: - version "5.0.15" - resolved "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@^6.0.1: version "6.0.4" resolved "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" @@ -5114,38 +5165,12 @@ globule@^1.0.0: lodash "~4.17.10" minimatch "~3.0.2" -glogg@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz#dcf758e44789cc3f3d32c1f3562a3676e6a34810" - dependencies: - sparkles "^1.0.0" - good-listener@^1.2.2: version "1.2.2" resolved "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50" dependencies: delegate "^3.1.2" -got@^5.0.0: - version "5.7.1" - resolved "http://registry.npmjs.org/got/-/got-5.7.1.tgz#5f81635a61e4a6589f180569ea4e381680a51f35" - dependencies: - create-error-class "^3.0.1" - duplexer2 "^0.1.4" - is-redirect "^1.0.0" - is-retry-allowed "^1.0.0" - is-stream "^1.0.0" - lowercase-keys "^1.0.0" - node-status-codes "^1.0.0" - object-assign "^4.0.1" - parse-json "^2.1.0" - pinkie-promise "^2.0.0" - read-all-stream "^3.0.0" - readable-stream "^2.0.5" - timed-out "^3.0.0" - unzip-response "^1.0.2" - url-parse-lax "^1.0.0" - got@^6.7.1: version "6.7.1" resolved "http://registry.npmjs.org/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" @@ -5181,11 +5206,34 @@ got@^7.0.0, got@^7.1.0: url-parse-lax "^1.0.0" url-to-options "^1.0.1" +got@^8.3.1: + version "8.3.2" + resolved "https://registry.npm.taobao.org/got/download/got-8.3.2.tgz#1d23f64390e97f776cac52e5b936e5f514d2e937" + integrity sha1-HSP2Q5Dpf3dsrFLluTbl9RTS6Tc= + dependencies: + "@sindresorhus/is" "^0.7.0" + cacheable-request "^2.1.1" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^3.0.0" + into-stream "^3.1.0" + is-retry-allowed "^1.1.0" + isurl "^1.0.0-alpha5" + lowercase-keys "^1.0.0" + mimic-response "^1.0.0" + p-cancelable "^0.4.0" + p-timeout "^2.0.1" + pify "^3.0.0" + safe-buffer "^5.1.1" + timed-out "^4.0.1" + url-parse-lax "^3.0.0" + url-to-options "^1.0.1" + graceful-fs@4.1.11: version "4.1.11" resolved "http://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" -graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6: +graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6: version "4.1.15" resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" @@ -5209,58 +5257,6 @@ grouped-queue@^0.3.0, grouped-queue@^0.3.3: dependencies: lodash "^4.17.2" -gulp-decompress@^1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/gulp-decompress/-/gulp-decompress-1.2.0.tgz#8eeb65a5e015f8ed8532cafe28454960626f0dc7" - dependencies: - archive-type "^3.0.0" - decompress "^3.0.0" - gulp-util "^3.0.1" - readable-stream "^2.0.2" - -gulp-rename@^1.2.0: - version "1.4.0" - resolved "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.4.0.tgz#de1c718e7c4095ae861f7296ef4f3248648240bd" - -gulp-sourcemaps@1.6.0: - version "1.6.0" - resolved "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz#b86ff349d801ceb56e1d9e7dc7bbcb4b7dee600c" - dependencies: - convert-source-map "^1.1.1" - graceful-fs "^4.1.2" - strip-bom "^2.0.0" - through2 "^2.0.0" - vinyl "^1.0.0" - -gulp-util@^3.0.1: - version "3.0.8" - resolved "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" - dependencies: - array-differ "^1.0.0" - array-uniq "^1.0.2" - beeper "^1.0.0" - chalk "^1.0.0" - dateformat "^2.0.0" - fancy-log "^1.1.0" - gulplog "^1.0.0" - has-gulplog "^0.1.0" - lodash._reescape "^3.0.0" - lodash._reevaluate "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.template "^3.0.0" - minimist "^1.1.0" - multipipe "^0.1.2" - object-assign "^3.0.0" - replace-ext "0.0.1" - through2 "^2.0.0" - vinyl "^0.5.0" - -gulplog@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" - dependencies: - glogg "^1.0.0" - gzip-size@3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/gzip-size/-/gzip-size-3.0.0.tgz#546188e9bdc337f673772f81660464b389dce520" @@ -5314,12 +5310,6 @@ has-flag@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" -has-gulplog@^0.1.0: - version "0.1.0" - resolved "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" - dependencies: - sparkles "^1.0.0" - has-symbol-support-x@^1.4.1: version "1.4.2" resolved "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" @@ -5483,6 +5473,11 @@ htmlparser2@~3.3.0: domutils "1.1" readable-stream "1.0" +http-cache-semantics@3.8.1: + version "3.8.1" + resolved "https://registry.npm.taobao.org/http-cache-semantics/download/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" + integrity sha1-ObDhat2bYFvwqe89nar0hDtMrNI= + http-deceiver@^1.2.7: version "1.2.7" resolved "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" @@ -5587,47 +5582,51 @@ ignore@^3.3.3, ignore@^3.3.5, ignore@^3.3.6: version "3.3.10" resolved "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" -imagemin-gifsicle@^5.2.0: - version "5.2.0" - resolved "https://registry.npmjs.org/imagemin-gifsicle/-/imagemin-gifsicle-5.2.0.tgz#3781524c457612ef04916af34241a2b42bfcb40a" +imagemin-gifsicle@^6.0.1: + version "6.0.1" + resolved "https://registry.npm.taobao.org/imagemin-gifsicle/download/imagemin-gifsicle-6.0.1.tgz#6abad4e95566d52e5a104aba1c24b4f3b48581b3" + integrity sha1-arrU6VVm1S5aEEq6HCS087SFgbM= dependencies: exec-buffer "^3.0.0" - gifsicle "^3.0.0" - is-gif "^1.0.0" + gifsicle "^4.0.0" + is-gif "^3.0.0" -imagemin-jpegtran@^5.0.2: - version "5.0.2" - resolved "http://registry.npmjs.org/imagemin-jpegtran/-/imagemin-jpegtran-5.0.2.tgz#e6882263b8f7916fddb800640cf75d2e970d2ad6" +imagemin-jpegtran@^6.0.0: + version "6.0.0" + resolved "https://registry.npm.taobao.org/imagemin-jpegtran/download/imagemin-jpegtran-6.0.0.tgz#c8d3bcfb6ec9c561c20a987142854be70d90b04f" + integrity sha1-yNO8+27JxWHCCphxQoVL5w2QsE8= dependencies: exec-buffer "^3.0.0" - is-jpg "^1.0.0" - jpegtran-bin "^3.0.0" + is-jpg "^2.0.0" + jpegtran-bin "^4.0.0" -imagemin-optipng@^5.2.1: - version "5.2.1" - resolved "http://registry.npmjs.org/imagemin-optipng/-/imagemin-optipng-5.2.1.tgz#d22da412c09f5ff00a4339960b98a88b1dbe8695" +imagemin-optipng@^6.0.0: + version "6.0.0" + resolved "https://registry.npm.taobao.org/imagemin-optipng/download/imagemin-optipng-6.0.0.tgz#a6bfc7b542fc08fc687e83dfb131249179a51a68" + integrity sha1-pr/HtUL8CPxofoPfsTEkkXmlGmg= dependencies: exec-buffer "^3.0.0" is-png "^1.0.0" - optipng-bin "^3.0.0" + optipng-bin "^5.0.0" -imagemin-svgo@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/imagemin-svgo/-/imagemin-svgo-6.0.0.tgz#2dd8c82946be42a8e2cbcae3c5bf007bc2b8b9e8" +imagemin-svgo@^7.0.0: + version "7.0.0" + resolved "https://registry.npm.taobao.org/imagemin-svgo/download/imagemin-svgo-7.0.0.tgz#a22d0a5917a0d0f37e436932c30f5e000fa91b1c" + integrity sha1-oi0KWReg0PN+Q2kyww9eAA+pGxw= dependencies: - buffer-from "^0.1.1" - is-svg "^2.0.0" - svgo "^1.0.0" + is-svg "^3.0.0" + svgo "^1.0.5" -imagemin@^5.3.1: - version "5.3.1" - resolved "https://registry.npmjs.org/imagemin/-/imagemin-5.3.1.tgz#f19c2eee1e71ba6c6558c515f9fc96680189a6d4" +imagemin@^6.0.0: + version "6.1.0" + resolved "https://registry.npm.taobao.org/imagemin/download/imagemin-6.1.0.tgz#62508b465728fea36c03cdc07d915fe2d8cf9e13" + integrity sha1-YlCLRlco/qNsA83AfZFf4tjPnhM= dependencies: - file-type "^4.1.0" - globby "^6.1.0" + file-type "^10.7.0" + globby "^8.0.1" make-dir "^1.0.0" p-pipe "^1.1.0" - pify "^2.3.0" + pify "^4.0.1" replace-ext "^1.0.0" import-cwd@^2.1.0: @@ -5649,6 +5648,11 @@ import-from@^2.1.0: dependencies: resolve-from "^3.0.0" +import-lazy@^3.1.0: + version "3.1.0" + resolved "https://registry.npm.taobao.org/import-lazy/download/import-lazy-3.1.0.tgz#891279202c8a2280fdbd6674dbd8da1a1dfc67cc" + integrity sha1-iRJ5ICyKIoD9vWZ029jaGh38Z8w= + import-local@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" @@ -5768,6 +5772,14 @@ interpret@^1.0.0, interpret@^1.0.4: version "1.1.0" resolved "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" +into-stream@^3.1.0: + version "3.1.0" + resolved "https://registry.npm.taobao.org/into-stream/download/into-stream-3.1.0.tgz#96fb0a936c12babd6ff1752a17d05616abd094c6" + integrity sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY= + dependencies: + from2 "^2.1.1" + p-is-promise "^1.1.0" + invariant@^2.2.2: version "2.2.4" resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" @@ -5782,10 +5794,6 @@ invert-kv@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" -ip-regex@^1.0.1: - version "1.0.3" - resolved "https://registry.npmjs.org/ip-regex/-/ip-regex-1.0.3.tgz#dc589076f659f419c222039a33316f1c7387effd" - ip-regex@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" @@ -5806,12 +5814,6 @@ is-absolute-url@^2.0.0: version "2.1.0" resolved "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" -is-absolute@^0.1.5: - version "0.1.7" - resolved "https://registry.npmjs.org/is-absolute/-/is-absolute-0.1.7.tgz#847491119fccb5fb436217cc737f7faad50f603f" - dependencies: - is-relative "^0.1.0" - is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" @@ -5848,10 +5850,6 @@ is-builtin-module@^1.0.0: dependencies: builtin-modules "^1.0.0" -is-bzip2@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/is-bzip2/-/is-bzip2-1.0.0.tgz#5ee58eaa5a2e9c80e21407bedf23ae5ac091b3fc" - is-callable@^1.1.3, is-callable@^1.1.4: version "1.1.4" resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" @@ -5942,9 +5940,12 @@ is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" -is-gif@^1.0.0: - version "1.0.0" - resolved "http://registry.npmjs.org/is-gif/-/is-gif-1.0.0.tgz#a6d2ae98893007bffa97a1d8c01d63205832097e" +is-gif@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/is-gif/download/is-gif-3.0.0.tgz#c4be60b26a301d695bb833b20d9b5d66c6cf83b1" + integrity sha1-xL5gsmowHWlbuDOyDZtdZsbPg7E= + dependencies: + file-type "^10.4.0" is-glob@^2.0.0, is-glob@^2.0.1: version "2.0.1" @@ -5964,21 +5965,19 @@ is-glob@^4.0.0: dependencies: is-extglob "^2.1.1" -is-gzip@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz#6ca8b07b99c77998025900e555ced8ed80879a83" - -is-jpg@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/is-jpg/-/is-jpg-1.0.1.tgz#296d57fdd99ce010434a7283e346ab9a1035e975" +is-jpg@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/is-jpg/download/is-jpg-2.0.0.tgz#2e1997fa6e9166eaac0242daae443403e4ef1d97" + integrity sha1-LhmX+m6RZuqsAkLarkQ0A+TvHZc= is-module@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" -is-natural-number@^2.0.0: - version "2.1.1" - resolved "https://registry.npmjs.org/is-natural-number/-/is-natural-number-2.1.1.tgz#7d4c5728377ef386c3e194a9911bf57c6dc335e7" +is-natural-number@^4.0.1: + version "4.0.1" + resolved "https://registry.npm.taobao.org/is-natural-number/download/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" + integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg= is-number@^2.1.0: version "2.1.0" @@ -6072,15 +6071,11 @@ is-regexp@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" -is-relative@^0.1.0: - version "0.1.3" - resolved "https://registry.npmjs.org/is-relative/-/is-relative-0.1.3.tgz#905fee8ae86f45b3ec614bc3c15c869df0876e82" - is-resolvable@^1.0.0: version "1.1.0" resolved "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" -is-retry-allowed@^1.0.0: +is-retry-allowed@^1.0.0, is-retry-allowed@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" @@ -6094,7 +6089,7 @@ is-scoped@^1.0.0: dependencies: scoped-regex "^1.0.0" -is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: +is-stream@^1.0.0, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" @@ -6108,16 +6103,19 @@ is-svg@^2.0.0: dependencies: html-comment-regex "^1.1.0" +is-svg@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/is-svg/download/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" + integrity sha1-kyHb0pwhLlypnE+peUxxS8r6L3U= + dependencies: + html-comment-regex "^1.1.0" + is-symbol@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" dependencies: has-symbols "^1.0.0" -is-tar@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/is-tar/-/is-tar-1.0.0.tgz#2f6b2e1792c1f5bb36519acaa9d65c0d26fe853d" - is-text-path@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz#4e1aa0fb51bfbcb3e92688001397202c1775b66e" @@ -6128,18 +6126,10 @@ is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" -is-url@^1.2.0: - version "1.2.4" - resolved "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" - is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" -is-valid-glob@^0.3.0: - version "0.3.0" - resolved "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz#d4b55c69f51886f9b65c70d6c2622d37e29f48fe" - is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" @@ -6148,10 +6138,6 @@ is-wsl@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" -is-zip@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/is-zip/-/is-zip-1.0.0.tgz#47b0a8ff4d38a76431ccfd99a8e15a4c86ba2325" - is2@0.0.9: version "0.0.9" resolved "https://registry.npmjs.org/is2/-/is2-0.0.9.tgz#119556d1d1651a41ba105af803267c80b299f629" @@ -6240,12 +6226,13 @@ jest-validate@^23.5.0: leven "^2.1.0" pretty-format "^23.6.0" -jpegtran-bin@^3.0.0: - version "3.2.0" - resolved "http://registry.npmjs.org/jpegtran-bin/-/jpegtran-bin-3.2.0.tgz#f60ecf4ae999c0bdad2e9fbcdf2b6f0981e7a29b" +jpegtran-bin@^4.0.0: + version "4.0.0" + resolved "https://registry.npm.taobao.org/jpegtran-bin/download/jpegtran-bin-4.0.0.tgz#d00aed809fba7aa6f30817e59eee4ddf198f8f10" + integrity sha1-0ArtgJ+6eqbzCBflnu5N3xmPjxA= dependencies: - bin-build "^2.0.0" - bin-wrapper "^3.0.0" + bin-build "^3.0.0" + bin-wrapper "^4.0.0" logalot "^2.0.0" js-base64@^2.1.8, js-base64@^2.1.9: @@ -6264,13 +6251,21 @@ js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" -js-yaml@^3.10.0, js-yaml@^3.12.0, js-yaml@^3.4.3, js-yaml@^3.8.1, js-yaml@^3.9.0, js-yaml@^3.9.1: +js-yaml@^3.10.0, js-yaml@^3.4.3, js-yaml@^3.8.1, js-yaml@^3.9.0, js-yaml@^3.9.1: version "3.12.0" resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" dependencies: argparse "^1.0.7" esprima "^4.0.0" +js-yaml@^3.13.1: + version "3.13.1" + resolved "https://registry.npm.taobao.org/js-yaml/download/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha1-r/FRswv9+o5J4F2iLnQV6d+jeEc= + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + js-yaml@~3.7.0: version "3.7.0" resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80" @@ -6314,6 +6309,11 @@ jsesc@~0.5.0: version "0.5.0" resolved "http://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/json-buffer/download/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + json-loader@^0.5.4: version "0.5.7" resolved "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d" @@ -6338,12 +6338,6 @@ json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" -json-stable-stringify@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - dependencies: - jsonify "~0.0.0" - json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -6391,6 +6385,13 @@ jsx-ast-utils@^2.0.1: dependencies: array-includes "^3.0.3" +keyv@3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/keyv/download/keyv-3.0.0.tgz#44923ba39e68b12a7cec7df6c3268c031f2ef373" + integrity sha1-RJI7o55osSp87H32wyaMAx8u83M= + dependencies: + json-buffer "3.0.0" + killable@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" @@ -6425,16 +6426,6 @@ lazy-cache@^2.0.2: dependencies: set-getter "^0.1.0" -lazy-req@^1.0.0: - version "1.1.0" - resolved "http://registry.npmjs.org/lazy-req/-/lazy-req-1.1.0.tgz#bdaebead30f8d824039ce0ce149d4daa07ba1fac" - -lazystream@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" - dependencies: - readable-stream "^2.0.5" - lcid@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" @@ -6702,42 +6693,10 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" -lodash._basecopy@^3.0.0: - version "3.0.1" - resolved "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" - -lodash._basetostring@^3.0.0: - version "3.0.1" - resolved "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5" - -lodash._basevalues@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7" - -lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - -lodash._isiterateecall@^3.0.0: - version "3.0.9" - resolved "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" - -lodash._reescape@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz#2b1d6f5dfe07c8a355753e5f27fac7f1cde1616a" - -lodash._reevaluate@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz#58bc74c40664953ae0b124d806996daca431e2ed" - -lodash._reinterpolate@^3.0.0, lodash._reinterpolate@~3.0.0: +lodash._reinterpolate@~3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" -lodash._root@^3.0.0: - version "3.0.1" - resolved "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" - lodash.assign@^4.2.0: version "4.2.0" resolved "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" @@ -6766,12 +6725,6 @@ lodash.defaults@^4.0.1: version "4.2.0" resolved "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" -lodash.escape@^3.0.0: - version "3.2.0" - resolved "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" - dependencies: - lodash._root "^3.0.0" - lodash.filter@^4.4.0: version "4.6.0" resolved "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace" @@ -6784,30 +6737,10 @@ lodash.foreach@^4.3.0: version "4.5.0" resolved "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" -lodash.isarguments@^3.0.0: - version "3.1.0" - resolved "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" - -lodash.isarray@^3.0.0: - version "3.0.4" - resolved "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" - -lodash.isequal@^4.0.0: - version "4.5.0" - resolved "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" - lodash.kebabcase@4.1.1: version "4.1.1" resolved "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36" -lodash.keys@^3.0.0: - version "3.1.2" - resolved "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" - dependencies: - lodash._getnative "^3.0.0" - lodash.isarguments "^3.0.0" - lodash.isarray "^3.0.0" - lodash.map@^4.4.0: version "4.6.0" resolved "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" @@ -6840,10 +6773,6 @@ lodash.reject@^4.4.0: version "4.6.0" resolved "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz#80d6492dc1470864bbf583533b651f42a9f52415" -lodash.restparam@^3.0.0: - version "3.6.1" - resolved "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" - lodash.snakecase@4.1.1: version "4.1.1" resolved "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d" @@ -6860,20 +6789,6 @@ lodash.tail@^4.1.1: version "4.1.1" resolved "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664" -lodash.template@^3.0.0: - version "3.6.2" - resolved "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f" - dependencies: - lodash._basecopy "^3.0.0" - lodash._basetostring "^3.0.0" - lodash._basevalues "^3.0.0" - lodash._isiterateecall "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - lodash.keys "^3.0.0" - lodash.restparam "^3.0.0" - lodash.templatesettings "^3.0.0" - lodash.template@^4.0.2: version "4.4.0" resolved "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz#e73a0385c8355591746e020b99679c690e68fba0" @@ -6881,13 +6796,6 @@ lodash.template@^4.0.2: lodash._reinterpolate "~3.0.0" lodash.templatesettings "^4.0.0" -lodash.templatesettings@^3.0.0: - version "3.1.1" - resolved "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5" - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - lodash.templatesettings@^4.0.0: version "4.1.0" resolved "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz#2b4d4e95ba440d915ff08bc899e4553666713316" @@ -6969,6 +6877,11 @@ lower-case@^1.1.1: version "1.1.4" resolved "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" +lowercase-keys@1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/lowercase-keys/download/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" + integrity sha1-TjNms55/VFfjXxMkvfb4jQv8cwY= + lowercase-keys@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" @@ -6995,7 +6908,7 @@ magic-string@^0.25.1: dependencies: sourcemap-codec "^1.4.1" -make-dir@^1.0.0: +make-dir@^1.0.0, make-dir@^1.2.0: version "1.3.0" resolved "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" dependencies: @@ -7138,7 +7051,7 @@ meow@5.0.0: trim-newlines "^2.0.0" yargs-parser "^10.0.0" -meow@^3.1.0, meow@^3.3.0, meow@^3.5.0, meow@^3.7.0: +meow@^3.3.0, meow@^3.7.0: version "3.7.0" resolved "http://registry.npmjs.org/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" dependencies: @@ -7171,12 +7084,6 @@ merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" -merge-stream@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" - dependencies: - readable-stream "^2.0.1" - merge2@^1.2.3: version "1.2.3" resolved "https://registry.npmjs.org/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5" @@ -7232,6 +7139,11 @@ miller-rabin@^4.0.0: version "1.37.0" resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8" +mime-db@^1.28.0: + version "1.40.0" + resolved "https://registry.npm.taobao.org/mime-db/download/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" + integrity sha1-plBX6ZjbCQ9zKmj2wnbTh9QSbDI= + mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.19: version "2.1.21" resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz#28995aa1ecb770742fe6ae7e58f9181c744b3f96" @@ -7289,7 +7201,7 @@ minimist@^0.1.0: version "0.1.0" resolved "http://registry.npmjs.org/minimist/-/minimist-0.1.0.tgz#99df657a52574c21c9057497df742790b2b4c0de" -minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0: +minimist@^1.1.3, minimist@^1.2.0: version "1.2.0" resolved "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" @@ -7366,12 +7278,6 @@ multimatch@^2.0.0: arrify "^1.0.0" minimatch "^3.0.0" -multipipe@^0.1.2: - version "0.1.2" - resolved "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" - dependencies: - duplexer2 "0.0.2" - mute-stream@0.0.6: version "0.0.6" resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.6.tgz#48962b19e169fd1dfc240b3f1e7317627bbc47db" @@ -7552,10 +7458,6 @@ node-sass@^4.7.2: stdout-stream "^1.4.0" "true-case-path" "^1.0.2" -node-status-codes@^1.0.0: - version "1.0.0" - resolved "http://registry.npmjs.org/node-status-codes/-/node-status-codes-1.0.0.tgz#5ae5541d024645d32a58fcddc9ceecea7ae3ac2f" - nomnom@^1.8.1: version "1.8.1" resolved "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz#2151f722472ba79e50a76fc125bb8c8f2e4dc2a7" @@ -7595,6 +7497,15 @@ normalize-range@^0.1.2: version "0.1.2" resolved "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" +normalize-url@2.0.1: + version "2.0.1" + resolved "https://registry.npm.taobao.org/normalize-url/download/normalize-url-2.0.1.tgz#835a9da1551fa26f70e92329069a23aa6574d7e6" + integrity sha1-g1qdoVUfom9w6SMpBpojqmV01+Y= + dependencies: + prepend-http "^2.0.0" + query-string "^5.0.1" + sort-keys "^2.0.0" + normalize-url@^1.0.0, normalize-url@^1.4.0: version "1.9.1" resolved "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" @@ -7608,6 +7519,14 @@ npm-bundled@^1.0.1: version "1.0.5" resolved "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.5.tgz#3c1732b7ba936b3a10325aef616467c0ccbcc979" +npm-conf@^1.1.0: + version "1.1.3" + resolved "https://registry.npm.taobao.org/npm-conf/download/npm-conf-1.1.3.tgz#256cc47bd0e218c259c4e9550bf413bc2192aff9" + integrity sha1-JWzEe9DiGMJZxOlVC/QTvCGSr/k= + dependencies: + config-chain "^1.1.11" + pify "^3.0.0" + npm-packlist@^1.1.6: version "1.1.12" resolved "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.1.12.tgz#22bde2ebc12e72ca482abd67afc51eb49377243a" @@ -7676,15 +7595,7 @@ oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" -object-assign@^2.0.0: - version "2.1.1" - resolved "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz#43c36e5d569ff8e4816c4efa8be02d26967c18aa" - -object-assign@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" - -object-assign@^4.0.0, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -7730,14 +7641,15 @@ object.pick@^1.2.0, object.pick@^1.3.0: dependencies: isobject "^3.0.1" -object.values@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/object.values/-/object.values-1.0.4.tgz#e524da09b4f66ff05df457546ec72ac99f13069a" +object.values@^1.1.0: + version "1.1.0" + resolved "https://registry.npm.taobao.org/object.values/download/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" + integrity sha1-v2gQ712j5TJXkOqqK+IT6oRiTak= dependencies: - define-properties "^1.1.2" - es-abstract "^1.6.1" - function-bind "^1.1.0" - has "^1.0.1" + define-properties "^1.1.3" + es-abstract "^1.12.0" + function-bind "^1.1.1" + has "^1.0.3" obuf@^1.0.0, obuf@^1.1.2: version "1.1.2" @@ -7799,12 +7711,13 @@ optionator@^0.8.2: type-check "~0.3.2" wordwrap "~1.0.0" -optipng-bin@^3.0.0: - version "3.1.4" - resolved "https://registry.npmjs.org/optipng-bin/-/optipng-bin-3.1.4.tgz#95d34f2c488704f6fd70606bfea0c659f1d95d84" +optipng-bin@^5.0.0: + version "5.1.0" + resolved "https://registry.npm.taobao.org/optipng-bin/download/optipng-bin-5.1.0.tgz#a7c7ab600a3ab5a177dae2f94c2d800aa386b5a9" + integrity sha1-p8erYAo6taF32uL5TC2ACqOGtak= dependencies: - bin-build "^2.0.0" - bin-wrapper "^3.0.0" + bin-build "^3.0.0" + bin-wrapper "^4.0.0" logalot "^2.0.0" ora@^0.2.3: @@ -7827,13 +7740,6 @@ ora@^2.1.0: strip-ansi "^4.0.0" wcwidth "^1.0.1" -ordered-read-streams@^0.3.0: - version "0.3.0" - resolved "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz#7137e69b3298bb342247a1bbee3881c80e2fd78b" - dependencies: - is-stream "^1.0.1" - readable-stream "^2.0.1" - original@>=0.0.5, original@^1.0.0: version "1.0.2" resolved "https://registry.npmjs.org/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f" @@ -7844,9 +7750,12 @@ os-browserify@^0.3.0: version "0.3.0" resolved "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" -os-filter-obj@^1.0.0: - version "1.0.3" - resolved "https://registry.npmjs.org/os-filter-obj/-/os-filter-obj-1.0.3.tgz#5915330d90eced557d2d938a31c6dd214d9c63ad" +os-filter-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/os-filter-obj/download/os-filter-obj-2.0.0.tgz#1c0b62d5f3a2442749a2d139e6dddee6e81d8d16" + integrity sha1-HAti1fOiRCdJotE55t3e5ugdjRY= + dependencies: + arch "^2.1.0" os-homedir@^1.0.0, os-homedir@^1.0.1: version "1.0.2" @@ -7893,6 +7802,11 @@ p-cancelable@^0.3.0: version "0.3.0" resolved "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" +p-cancelable@^0.4.0: + version "0.4.1" + resolved "https://registry.npm.taobao.org/p-cancelable/download/p-cancelable-0.4.1.tgz#35f363d67d52081c8d9585e37bcceb7e0bbcb2a0" + integrity sha1-NfNj1n1SCByNlYXje8zrfgu8sqA= + p-defer@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" @@ -7903,6 +7817,20 @@ p-each-series@^1.0.0: dependencies: p-reduce "^1.0.0" +p-event@^1.0.0: + version "1.3.0" + resolved "https://registry.npm.taobao.org/p-event/download/p-event-1.3.0.tgz#8e6b4f4f65c72bc5b6fe28b75eda874f96a4a085" + integrity sha1-jmtPT2XHK8W2/ii3XtqHT5akoIU= + dependencies: + p-timeout "^1.1.1" + +p-event@^2.1.0: + version "2.3.1" + resolved "https://registry.npm.taobao.org/p-event/download/p-event-2.3.1.tgz#596279ef169ab2c3e0cae88c1cfbb08079993ef6" + integrity sha1-WWJ57xaassPgyuiMHPuwgHmZPvY= + dependencies: + p-timeout "^2.0.1" + p-finally@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" @@ -7939,6 +7867,13 @@ p-locate@^3.0.0: dependencies: p-limit "^2.0.0" +p-map-series@^1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/p-map-series/download/p-map-series-1.0.0.tgz#bf98fe575705658a9e1351befb85ae4c1f07bdca" + integrity sha1-v5j+V1cFZYqeE1G++4WuTB8Hvco= + dependencies: + p-reduce "^1.0.0" + p-map@^1.1.1: version "1.2.0" resolved "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" @@ -7965,6 +7900,13 @@ p-timeout@^1.1.1: dependencies: p-finally "^1.0.0" +p-timeout@^2.0.1: + version "2.0.1" + resolved "https://registry.npm.taobao.org/p-timeout/download/p-timeout-2.0.1.tgz#d8dd1979595d2dc0139e1fe46b8b646cb3cdf038" + integrity sha1-2N0ZeVldLcATnh/ka4tkbLPN8Dg= + dependencies: + p-finally "^1.0.0" + p-try@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" @@ -8015,7 +7957,7 @@ parse-glob@^3.0.4: is-extglob "^1.0.0" is-glob "^2.0.0" -parse-json@^2.1.0, parse-json@^2.2.0: +parse-json@^2.2.0: version "2.2.0" resolved "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" dependencies: @@ -8124,7 +8066,7 @@ pidtree@^0.3.0: version "0.3.0" resolved "https://registry.npmjs.org/pidtree/-/pidtree-0.3.0.tgz#f6fada10fccc9f99bf50e90d0b23d72c9ebc2e6b" -pify@^2.0.0, pify@^2.3.0: +pify@^2.0.0, pify@^2.2.0, pify@^2.3.0: version "2.3.0" resolved "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -8132,6 +8074,11 @@ pify@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.npm.taobao.org/pify/download/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha1-SyzSXFDVmHNcUCkiJP2MbfQeMjE= + pinkie-promise@^2.0.0: version "2.0.1" resolved "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" @@ -8496,6 +8443,11 @@ prepend-http@^1.0.0, prepend-http@^1.0.1: version "1.0.4" resolved "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/prepend-http/download/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= + preserve@^0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" @@ -8574,6 +8526,11 @@ prop-types@^15.6.2: loose-envify "^1.3.1" object-assign "^4.1.1" +proto-list@~1.2.1: + version "1.2.4" + resolved "https://registry.npm.taobao.org/proto-list/download/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" + integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= + proxy-addr@~2.0.4: version "2.0.4" resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93" @@ -8646,6 +8603,15 @@ query-string@^4.1.0: object-assign "^4.1.0" strict-uri-encode "^1.0.0" +query-string@^5.0.1: + version "5.1.1" + resolved "https://registry.npm.taobao.org/query-string/download/query-string-5.1.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fquery-string%2Fdownload%2Fquery-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" + integrity sha1-p4wBK3HBfgXy4/ojGd0zBoLvs8s= + dependencies: + decode-uri-component "^0.2.0" + object-assign "^4.1.0" + strict-uri-encode "^1.0.0" + querystring-es3@^0.2.0: version "0.2.1" resolved "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" @@ -8703,7 +8669,7 @@ raw-body@~1.1.0: bytes "1" string_decoder "0.10" -rc@^1.0.1, rc@^1.1.2, rc@^1.1.6, rc@^1.2.7: +rc@^1.0.1, rc@^1.1.6, rc@^1.2.7: version "1.2.8" resolved "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" dependencies: @@ -8757,13 +8723,6 @@ react@^16.5.0: prop-types "^15.6.2" scheduler "^0.11.2" -read-all-stream@^3.0.0: - version "3.1.0" - resolved "https://registry.npmjs.org/read-all-stream/-/read-all-stream-3.1.0.tgz#35c3e177f2078ef789ee4bfafa4373074eaef4fa" - dependencies: - pinkie-promise "^2.0.0" - readable-stream "^2.0.0" - read-chunk@^2.0.0: version "2.1.0" resolved "https://registry.npmjs.org/read-chunk/-/read-chunk-2.1.0.tgz#6a04c0928005ed9d42e1a6ac5600e19cbc7ff655" @@ -8830,7 +8789,7 @@ read-pkg@^4.0.1: parse-json "^4.0.0" pify "^3.0.0" -readable-stream@1.0, "readable-stream@>=1.0.33-1 <1.1.0-0": +readable-stream@1.0: version "1.0.34" resolved "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" dependencies: @@ -8839,7 +8798,7 @@ readable-stream@1.0, "readable-stream@>=1.0.33-1 <1.1.0-0": isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: +readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.6" resolved "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" dependencies: @@ -8859,15 +8818,6 @@ readable-stream@^3.0.6: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@~1.1.9: - version "1.1.14" - resolved "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - readdirp@^2.0.0: version "2.2.1" resolved "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" @@ -9192,6 +9142,13 @@ resolve@^1.1.6, resolve@^1.3.2, resolve@^1.3.3, resolve@^1.5.0, resolve@^1.6.0, dependencies: path-parse "^1.0.5" +responselike@1.0.2: + version "1.0.2" + resolved "https://registry.npm.taobao.org/responselike/download/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= + dependencies: + lowercase-keys "^1.0.0" + restore-cursor@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" @@ -9216,7 +9173,7 @@ right-align@^0.1.1: dependencies: align-text "^0.1.1" -rimraf@2, rimraf@^2.2.0, rimraf@^2.2.6, rimraf@^2.2.8, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@~2.6.2: +rimraf@2, rimraf@^2.2.0, rimraf@^2.2.8, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@~2.6.2: version "2.6.2" resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" dependencies: @@ -9423,9 +9380,10 @@ scss-tokenizer@^0.2.3: js-base64 "^2.1.8" source-map "^0.4.2" -seek-bzip@^1.0.3: +seek-bzip@^1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" + resolved "https://registry.npm.taobao.org/seek-bzip/download/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" + integrity sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w= dependencies: commander "~2.8.1" @@ -9447,13 +9405,15 @@ semver-compare@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" -semver-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/semver-regex/-/semver-regex-1.0.0.tgz#92a4969065f9c70c694753d55248fc68f8f652c9" +semver-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/semver-regex/download/semver-regex-2.0.0.tgz#a93c2c5844539a770233379107b38c7b4ac9d338" + integrity sha1-qTwsWERTmncCMzeRB7OMe0rJ0zg= -semver-truncate@^1.0.0: +semver-truncate@^1.1.2: version "1.1.2" - resolved "https://registry.npmjs.org/semver-truncate/-/semver-truncate-1.1.2.tgz#57f41de69707a62709a7e0104ba2117109ea47e8" + resolved "https://registry.npm.taobao.org/semver-truncate/download/semver-truncate-1.1.2.tgz#57f41de69707a62709a7e0104ba2117109ea47e8" + integrity sha1-V/Qd5pcHpicJp+AQS6IRcQnqR+g= dependencies: semver "^5.3.0" @@ -9461,10 +9421,6 @@ semver-truncate@^1.0.0: version "5.6.0" resolved "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" -semver@^4.0.3: - version "4.3.6" - resolved "http://registry.npmjs.org/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" - semver@~5.3.0: version "5.3.0" resolved "http://registry.npmjs.org/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" @@ -9518,10 +9474,6 @@ set-getter@^0.1.0: dependencies: to-object-path "^0.3.0" -set-immediate-shim@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" - set-value@^0.4.3: version "0.4.3" resolved "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" @@ -9582,7 +9534,7 @@ shell-quote@1.6.1, shell-quote@^1.6.1: array-reduce "~0.0.0" jsonify "~0.0.0" -shelljs@^0.7.0, shelljs@^0.7.8: +shelljs@^0.7.0: version "0.7.8" resolved "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" dependencies: @@ -9590,9 +9542,10 @@ shelljs@^0.7.0, shelljs@^0.7.8: interpret "^1.0.0" rechoir "^0.6.2" -shelljs@^0.8.1: +shelljs@^0.8.1, shelljs@^0.8.3: version "0.8.3" - resolved "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz#a7f3319520ebf09ee81275b2368adb286659b097" + resolved "https://registry.npm.taobao.org/shelljs/download/shelljs-0.8.3.tgz#a7f3319520ebf09ee81275b2368adb286659b097" + integrity sha1-p/MxlSDr8J7oEnWyNorbKGZZsJc= dependencies: glob "^7.0.0" interpret "^1.0.0" @@ -9699,6 +9652,13 @@ sockjs@0.3.19: faye-websocket "^0.10.0" uuid "^3.0.1" +sort-keys-length@^1.0.0: + version "1.0.1" + resolved "https://registry.npm.taobao.org/sort-keys-length/download/sort-keys-length-1.0.1.tgz#9cb6f4f4e9e48155a6aa0671edd336ff1479a188" + integrity sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg= + dependencies: + sort-keys "^1.0.0" + sort-keys@^1.0.0: version "1.1.2" resolved "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" @@ -9760,10 +9720,6 @@ sourcemap-codec@^1.4.1: version "1.4.4" resolved "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.4.tgz#c63ea927c029dd6bd9a2b7fa03b3fec02ad56e9f" -sparkles@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz#008db65edce6c50eec0c5e228e1945061dd0437c" - spawn-sync@^1.0.15: version "1.0.15" resolved "https://registry.npmjs.org/spawn-sync/-/spawn-sync-1.0.15.tgz#b00799557eb7fb0c8376c29d44e8a1ea67e57476" @@ -9858,18 +9814,15 @@ sshpk@^1.7.0: safer-buffer "^2.0.2" tweetnacl "~0.14.0" -stable@~0.1.6: +stable@^0.1.8: version "0.1.8" - resolved "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + resolved "https://registry.npm.taobao.org/stable/download/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + integrity sha1-g26zyDgv4pNv6vVEYxAXzn1Ho88= staged-git-files@1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/staged-git-files/-/staged-git-files-1.1.2.tgz#4326d33886dc9ecfa29a6193bf511ba90a46454b" -stat-mode@^0.2.0: - version "0.2.2" - resolved "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz#e6c80b623123d7d80cf132ce538f346289072502" - static-extend@^0.1.1: version "0.1.2" resolved "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" @@ -9898,13 +9851,6 @@ stream-browserify@^2.0.1: inherits "~2.0.1" readable-stream "^2.0.2" -stream-combiner2@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz#fb4d8a1420ea362764e21ad4780397bebcb41cbe" - dependencies: - duplexer2 "~0.1.0" - readable-stream "^2.0.2" - stream-http@^2.7.2: version "2.8.3" resolved "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" @@ -9915,10 +9861,6 @@ stream-http@^2.7.2: to-arraybuffer "^1.0.0" xtend "^4.0.0" -stream-shift@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" - stream-to-observable@^0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/stream-to-observable/-/stream-to-observable-0.1.0.tgz#45bf1d9f2d7dc09bed81f1c307c430e68b84cffe" @@ -9996,13 +9938,6 @@ strip-ansi@~0.1.0: version "0.1.1" resolved "http://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz#39e8a98d044d150660abe4a6808acf70bb7bc991" -strip-bom-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz#e7144398577d51a6bed0fa1994fa05f43fd988ee" - dependencies: - first-chunk-stream "^1.0.0" - strip-bom "^2.0.0" - strip-bom-stream@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz#f87db5ef2613f6968aa545abfe1ec728b6a829ca" @@ -10024,16 +9959,12 @@ strip-color@^0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/strip-color/-/strip-color-0.1.0.tgz#106f65d3d3e6a2d9401cac0eb0ce8b8a702b4f7b" -strip-dirs@^1.0.0: - version "1.1.1" - resolved "http://registry.npmjs.org/strip-dirs/-/strip-dirs-1.1.1.tgz#960bbd1287844f3975a4558aa103a8255e2456a0" +strip-dirs@^2.0.0: + version "2.1.0" + resolved "https://registry.npm.taobao.org/strip-dirs/download/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" + integrity sha1-SYdzYmT8NEzyD2w0rKnRPR1O1sU= dependencies: - chalk "^1.0.0" - get-stdin "^4.0.1" - is-absolute "^0.1.5" - is-natural-number "^2.0.0" - minimist "^1.1.0" - sum-up "^1.0.1" + is-natural-number "^4.0.1" strip-eof@^1.0.0: version "1.0.0" @@ -10084,12 +10015,6 @@ style-loader@^0.20.3: loader-utils "^1.1.0" schema-utils "^0.4.5" -sum-up@^1.0.1: - version "1.0.3" - resolved "https://registry.npmjs.org/sum-up/-/sum-up-1.0.3.tgz#1c661f667057f63bcb7875aa1438bc162525156e" - dependencies: - chalk "^1.0.0" - supports-color@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -10124,22 +10049,23 @@ svgo@^0.7.0: sax "~1.2.1" whet.extend "~0.9.9" -svgo@^1.0.0: - version "1.1.1" - resolved "https://registry.npmjs.org/svgo/-/svgo-1.1.1.tgz#12384b03335bcecd85cfa5f4e3375fed671cb985" +svgo@^1.0.5: + version "1.2.2" + resolved "https://registry.npm.taobao.org/svgo/download/svgo-1.2.2.tgz#0253d34eccf2aed4ad4f283e11ee75198f9d7316" + integrity sha1-AlPTTszyrtStTyg+Ee51GY+dcxY= dependencies: - coa "~2.0.1" - colors "~1.1.2" + chalk "^2.4.1" + coa "^2.0.2" css-select "^2.0.0" - css-select-base-adapter "~0.1.0" + css-select-base-adapter "^0.1.1" css-tree "1.0.0-alpha.28" css-url-regex "^1.1.0" - csso "^3.5.0" - js-yaml "^3.12.0" + csso "^3.5.1" + js-yaml "^3.13.1" mkdirp "~0.5.1" - object.values "^1.0.4" + object.values "^1.1.0" sax "~1.2.4" - stable "~0.1.6" + stable "^0.1.8" unquote "~1.1.1" util.promisify "~1.0.0" @@ -10170,9 +10096,10 @@ tapable@^1.0.0: version "1.1.0" resolved "https://registry.npmjs.org/tapable/-/tapable-1.1.0.tgz#0d076a172e3d9ba088fd2272b2668fb8d194b78c" -tar-stream@^1.1.1: +tar-stream@^1.5.2: version "1.6.2" - resolved "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" + resolved "https://registry.npm.taobao.org/tar-stream/download/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" + integrity sha1-jqVdqzeXIlPZqa+Q/c1VmuQ1xVU= dependencies: bl "^1.0.0" buffer-alloc "^1.2.0" @@ -10232,7 +10159,7 @@ temp@^0.8.1: os-tmpdir "^1.0.0" rimraf "~2.2.6" -tempfile@^1.0.0, tempfile@^1.1.1: +tempfile@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/tempfile/-/tempfile-1.1.1.tgz#5bcc4eaecc4ab2c707d8bc11d99ccc9a2cb287f2" dependencies: @@ -10258,28 +10185,14 @@ textextensions@^2.4.0: version "2.4.0" resolved "https://registry.npmjs.org/textextensions/-/textextensions-2.4.0.tgz#6a143a985464384cc2cff11aea448cd5b018e72b" -through2-filter@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz#60bc55a0dacb76085db1f9dae99ab43f83d622ec" - dependencies: - through2 "~2.0.0" - xtend "~4.0.0" - -through2@^0.6.0, through2@^0.6.1: - version "0.6.5" - resolved "http://registry.npmjs.org/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" - dependencies: - readable-stream ">=1.0.33-1 <1.1.0-0" - xtend ">=4.0.0 <4.1.0-0" - -through2@^2.0.0, through2@^2.0.2, through2@~2.0.0: +through2@^2.0.0, through2@^2.0.2: version "2.0.5" resolved "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" dependencies: readable-stream "~2.3.6" xtend "~4.0.1" -through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6: +through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6, through@^2.3.8: version "2.3.8" resolved "http://registry.npmjs.org/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -10287,19 +10200,11 @@ thunky@^1.0.2: version "1.0.3" resolved "https://registry.npmjs.org/thunky/-/thunky-1.0.3.tgz#f5df732453407b09191dae73e2a8cc73f381a826" -time-stamp@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" - time-zone@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/time-zone/-/time-zone-1.0.0.tgz#99c5bf55958966af6d06d83bdf3800dc82faec5d" -timed-out@^3.0.0: - version "3.1.3" - resolved "https://registry.npmjs.org/timed-out/-/timed-out-3.1.3.tgz#95860bfcc5c76c277f8f8326fd0f5b2e20eba217" - -timed-out@^4.0.0: +timed-out@^4.0.0, timed-out@^4.0.1: version "4.0.1" resolved "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" @@ -10336,12 +10241,6 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" -to-absolute-glob@^0.1.1: - version "0.1.1" - resolved "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz#1cdfa472a9ef50c239ee66999b662ca0eb39937f" - dependencies: - extend-shallow "^2.0.1" - to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" @@ -10444,10 +10343,6 @@ tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" -tunnel-agent@^0.4.0: - version "0.4.3" - resolved "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" - tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -10507,6 +10402,14 @@ uglifyjs-webpack-plugin@^0.4.6: uglify-js "^2.8.29" webpack-sources "^1.0.1" +unbzip2-stream@^1.0.9: + version "1.3.3" + resolved "https://registry.npm.taobao.org/unbzip2-stream/download/unbzip2-stream-1.3.3.tgz#d156d205e670d8d8c393e1c02ebd506422873f6a" + integrity sha1-0VbSBeZw2NjDk+HALr1QZCKHP2o= + dependencies: + buffer "^5.2.1" + through "^2.3.8" + underscore.string@~2.4.0: version "2.4.0" resolved "http://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz#8cdd8fbac4e2d2ea1e7e2e8097c42f442280f85b" @@ -10559,13 +10462,6 @@ uniqs@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" -unique-stream@^2.0.2: - version "2.2.1" - resolved "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz#5aa003cfbe94c5ff866c4e7d668bb1c4dbadb369" - dependencies: - json-stable-stringify "^1.0.0" - through2-filter "^2.0.0" - universalify@^0.1.0: version "0.1.2" resolved "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" @@ -10595,10 +10491,6 @@ untildify@^3.0.3: version "3.0.3" resolved "https://registry.npmjs.org/untildify/-/untildify-3.0.3.tgz#1e7b42b140bcfd922b22e70ca1265bfe3634c7c9" -unzip-response@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/unzip-response/-/unzip-response-1.0.2.tgz#b984f0877fc0a89c2c773cc1ef7b5b232b5b06fe" - unzip-response@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" @@ -10631,6 +10523,13 @@ url-parse-lax@^1.0.0: dependencies: prepend-http "^1.0.1" +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/url-parse-lax/download/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= + dependencies: + prepend-http "^2.0.0" + url-parse@^1.1.8, url-parse@^1.4.3: version "1.4.4" resolved "https://registry.npmjs.org/url-parse/-/url-parse-1.4.4.tgz#cac1556e95faa0303691fec5cf9d5a1bc34648f8" @@ -10638,12 +10537,6 @@ url-parse@^1.1.8, url-parse@^1.4.3: querystringify "^2.0.0" requires-port "^1.0.0" -url-regex@^3.0.0: - version "3.2.0" - resolved "https://registry.npmjs.org/url-regex/-/url-regex-3.2.0.tgz#dbad1e0c9e29e105dd0b1f09f6862f7fdb482724" - dependencies: - ip-regex "^1.0.1" - url-to-options@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" @@ -10698,10 +10591,6 @@ uuid@^3.0.1, uuid@^3.3.2: version "3.3.2" resolved "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" -vali-date@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6" - validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" @@ -10725,13 +10614,6 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -vinyl-assign@^1.0.1: - version "1.2.1" - resolved "https://registry.npmjs.org/vinyl-assign/-/vinyl-assign-1.2.1.tgz#4d198891b5515911d771a8cd9c5480a46a074a45" - dependencies: - object-assign "^4.0.1" - readable-stream "^2.0.0" - vinyl-file@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/vinyl-file/-/vinyl-file-2.0.0.tgz#a7ebf5ffbefda1b7d18d140fcb07b223efb6751a" @@ -10743,44 +10625,7 @@ vinyl-file@^2.0.0: strip-bom-stream "^2.0.0" vinyl "^1.1.0" -vinyl-fs@^2.2.0: - version "2.4.4" - resolved "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz#be6ff3270cb55dfd7d3063640de81f25d7532239" - dependencies: - duplexify "^3.2.0" - glob-stream "^5.3.2" - graceful-fs "^4.0.0" - gulp-sourcemaps "1.6.0" - is-valid-glob "^0.3.0" - lazystream "^1.0.0" - lodash.isequal "^4.0.0" - merge-stream "^1.0.0" - mkdirp "^0.5.0" - object-assign "^4.0.0" - readable-stream "^2.0.4" - strip-bom "^2.0.0" - strip-bom-stream "^1.0.0" - through2 "^2.0.0" - through2-filter "^2.0.0" - vali-date "^1.0.0" - vinyl "^1.0.0" - -vinyl@^0.4.3: - version "0.4.6" - resolved "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" - dependencies: - clone "^0.2.0" - clone-stats "^0.0.1" - -vinyl@^0.5.0: - version "0.5.3" - resolved "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde" - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -vinyl@^1.0.0, vinyl@^1.1.0: +vinyl@^1.1.0: version "1.2.0" resolved "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" dependencies: @@ -10809,12 +10654,6 @@ vm-browserify@0.0.4: dependencies: indexof "0.0.1" -ware@^1.2.0: - version "1.3.0" - resolved "https://registry.npmjs.org/ware/-/ware-1.3.0.tgz#d1b14f39d2e2cb4ab8c4098f756fe4b164e473d4" - dependencies: - wrap-fn "^0.1.0" - watchpack@^1.4.0: version "1.6.0" resolved "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" @@ -11024,12 +10863,6 @@ wrap-ansi@^3.0.1: string-width "^2.1.1" strip-ansi "^4.0.0" -wrap-fn@^0.1.0: - version "0.1.5" - resolved "https://registry.npmjs.org/wrap-fn/-/wrap-fn-0.1.5.tgz#f21b6e41016ff4a7e31720dbc63a09016bdf9845" - dependencies: - co "3.1.0" - wrappy@1: version "1.0.2" resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -11082,7 +10915,7 @@ xregexp@4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz#e698189de49dd2a18cc5687b05e17c8e43943020" -"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@~4.0.0, xtend@~4.0.1: +xtend@^4.0.0, xtend@~4.0.0, xtend@~4.0.1: version "4.0.1" resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" @@ -11209,9 +11042,10 @@ yargs@~3.10.0: decamelize "^1.0.0" window-size "0.1.0" -yauzl@^2.2.1: +yauzl@^2.4.2: version "2.10.0" - resolved "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + resolved "https://registry.npm.taobao.org/yauzl/download/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= dependencies: buffer-crc32 "~0.2.3" fd-slicer "~1.1.0"