From 6aba83c8449372cce5b0117ee347b4dbc04207c7 Mon Sep 17 00:00:00 2001 From: yuche Date: Fri, 25 Oct 2019 18:31:24 +0800 Subject: [PATCH] =?UTF-8?q?chore(shared):=20=E7=BB=B4=E6=8A=A4=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E5=8C=85=E5=90=AB=E6=89=80=E6=9C=89=E5=86=85=E7=BD=AE?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E5=92=8C=E5=B1=9E=E6=80=A7=E7=9A=84=E5=93=88?= =?UTF-8?q?=E5=B8=8C=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jest.config.js | 6 +- .../src/template/component.ts | 460 +++++++++++++++++- .../mini-app-webpack-plugin/tsconfig.json | 5 +- packages/shared/src/index.ts | 25 + packages/taro-runtime/src/dom/element.ts | 2 +- packages/taro-runtime/src/dom/style.ts | 19 +- packages/taro-runtime/src/render.ts | 1 + 7 files changed, 476 insertions(+), 42 deletions(-) diff --git a/jest.config.js b/jest.config.js index 28caecade94b..c7c0f20d1938 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,5 +1,6 @@ // eslint-disable-next-line @typescript-eslint/no-var-requires const { jsWithTs: tsjPreset } = require('ts-jest/presets') +const path = require('path') module.exports = { testEnvironment: 'node', @@ -29,5 +30,8 @@ module.exports = { 'node_modules', 'utils' ], - testMatch: ['**/__tests__/?(*.)+(spec|test).[jt]s?(x)'] + testMatch: ['**/__tests__/?(*.)+(spec|test).[jt]s?(x)'], + moduleNameMapper: { + '@tarojs/shared': path.join(__dirname, './packages/shared/src') + } } diff --git a/packages/mini-app-webpack-plugin/src/template/component.ts b/packages/mini-app-webpack-plugin/src/template/component.ts index ff090dc8bfc2..4ec164b75798 100644 --- a/packages/mini-app-webpack-plugin/src/template/component.ts +++ b/packages/mini-app-webpack-plugin/src/template/component.ts @@ -1,4 +1,5 @@ import { Shortcuts } from './shortcuts' +import { toDashed, hasOwn, toCamelCase } from '@tarojs/shared' const styles = { style: `i.${Shortcuts.Style}`, @@ -9,37 +10,454 @@ const events = { bindtap: 'eh' } -const view = { +const common = { ...styles, ...events } -const image = { - ...styles, - src: `i.${Shortcuts.Src}` +const View = { + 'hover-class': 'none', + 'hover-stop-propagation': 'false', + 'hover-start-time': '50', + 'hover-stay-time': '400' } -const text = { - ...styles, - selectable: 'i.selectable', - space: 'i.space', - decode: 'i.decode' +const Icon = { + type: '', + size: '23', + color: '' } -const input = { - ...styles, - bindinput: 'eh' +const Progress = { + percent: '', + 'show-info': 'fasle', + 'border-radius': '0', + 'font-size': '16', + 'stroke-width': '6', + color: singleQuote('#09BB07'), + activeColor: singleQuote('#09BB07'), + backgroundColor: singleQuote('#EBEBEB'), + active: 'false', + 'active-mode': 'backwards', + duration: '30', + bindactiveend: '' } -const button = { - ...styles, - ...events +const RichText = { + nodes: '[]', + space: '' +} + +const Text = { + selectable: 'false', + space: '', + decode: 'false' +} + +const Button = { + size: 'default', + type: 'default', + plain: 'false', + disabled: 'false', + loading: 'false', + 'form-type': '', + 'open-type': '', + 'hover-class': 'button-hover', + 'hover-stop-propagation': 'false', + 'hover-start-time': '20', + 'hover-stay-time': '70', + lang: 'en', + 'session-from': '', + 'send-message-title': '', + 'send-message-path': '', + 'send-message-img': '', + 'app-parameter': '', + 'show-message-card': 'false', + bindgetuserinfo: '', + bindcontact: '', + bindgetphonenumber: '', + binderror: '', + bindopensetting: '', + bindlaunchapp: '' +} + +const Checkbox = { + value: '', + disabled: 'false', + checked: 'false', + color: singleQuote('#09BB07') +} + +const CheckboxGroup = { + bindchange: '' +} + +const Editor = { + 'read-only': 'false', + placeholder: '', + 'show-img-size': 'false', + 'show-img-toolbar': 'false', + 'show-img-resize': 'false', + bindready: '', + bindfocus: '', + bindblur: '', + bindinput: '', + bindstatuschange: '' +} + +const Form = { + 'report-submit': 'false', + 'report-submit-timeout': '0', + bindsubmit: '', + bindreset: '' +} + +const Input = { + value: '', + type: 'text', + password: 'false', + placeholder: '', + 'placeholder-style': '', + 'placeholder-class': singleQuote('input-placeholder'), + disabled: 'false', + maxlength: '140', + 'cursor-spacing': '0', + 'auto-focus': 'false', + focus: 'false', + 'confirm-type': singleQuote('done'), + 'confirm-hold': 'false', + cursor: '', + 'selection-start': '-1', + 'selection-end': '-1', + 'adjust-position': 'true', + 'hold-keyboard': 'false', + bindinput: '', + bindfocus: '', + bindblur: '', + bindconfirm: '', + bindkeyboardheightchange: '' +} + +const Label = { + for: '' +} + +const Picker = { + mode: singleQuote('selector'), + disabled: 'false', + bindcancel: '' +} + +const PickerView = { + value: '', + 'indicator-style': '', + 'indicator-class': '', + 'mask-style': '', + 'mask-class': '', + bindchange: '', + bindpickstart: '', + bindpickend: '' +} + +const PickerViewColumn = { + // +} + +const Radio = { + value: '', + checked: 'false', + disabled: 'false', + color: singleQuote('#09BB07') +} + +const RadioGroup = { + bindchange: '' +} + +const Slider = { + min: '0', + max: '100', + step: '1', + disabled: 'false', + value: '0', + color: singleQuote('#e9e9e9'), + 'selected-color': singleQuote('#1aad19'), + activeColor: singleQuote('#1aad19'), + backgroundColor: singleQuote('#e9e9e9'), + 'block-size': '28', + 'block-color': singleQuote('#ffffff'), + 'show-value': 'false', + bindchange: '', + bindchanging: '' +} + +const Switch = { + checked: 'false', + disabled: 'false', + type: singleQuote('switch'), + color: singleQuote('#04BE02'), + bindchange: '' +} + +const CoverImage = { + src: '', + bindload: 'eh', + binderror: 'eh' +} + +const Textarea = { + value: '', + placeholder: '', + 'placeholder-style': '', + 'placeholder-class': singleQuote('textarea-placeholder'), + disabled: 'false', + maxlength: '140', + 'auto-focus': 'false', + focus: 'false', + 'auto-height': 'false', + fixed: 'false', + 'cursor-spacing': '0', + cursor: '-1', + 'show-confirm-bar': 'true', + 'selection-start': '-1', + 'selection-end': '-1', + 'adjust-position': 'true', + 'hold-keyboard': 'false', + bindfocus: '', + bindblur: '', + bindlinechange: '', + bindinput: '', + bindconfirm: '', + bindkeyboardheightchange: '' +} + +const CoverView = { + 'scroll-top': 'false' +} + +const MoveableArea = { + 'scale-area': 'false' +} + +const MoveableView = { + direction: 'none', + inertia: 'false', + 'out-of-bounds': 'false', + x: '', + y: '', + damping: '20', + friction: '2', + disabled: 'fasle', + scale: 'false', + 'scale-min': '0.5', + 'scale-max': '10', + 'scale-value': '1', + animation: 'true', + bindchange: '', + bindscale: '', + htouchmove: '', + vtouchmove: '', + width: '10px', + height: '10px' +} + +const ScrollView = { + 'scroll-x': 'false', + 'scroll-y': 'false', + 'upper-threshold': '50', + 'lower-threshold': '50', + 'scroll-top': '', + 'scroll-left': '', + 'scroll-into-view': '', + 'scroll-with-animation': 'false', + 'enable-back-to-top': 'false', + 'enable-flex': 'false', + 'scroll-anchoring': ' false', + bindscrolltoupper: '', + bindscrolltolower: '', + bindscroll: '' +} + +function singleQuote (s: string) { + return `'${s}'` +} + +const Swiper = { + 'indicator-dots': 'false', + 'indicator-color': '\'rgba(0, 0, 0, .3)\'', + 'indicator-active-color': '\'#000000\'', + autoplay: 'fasle', + current: '0', + interval: '5000', + duration: '500', + circular: 'false', + vertical: 'fasle', + 'previous-margin': '\'0px\'', + 'next-margin': '\'0px\'', + 'display-multiple-items': '1', + 'skip-hidden-item-layout': 'false', + 'easing-function': singleQuote('default'), + bindchange: '', + bindtransition: '', + bindanimationfinish: '' +} + +const SwiperItem = { + 'item-id': '' +} + +const FunctionalPageNavigator = { + version: singleQuote('release'), + name: '', + args: '', + bindsuccess: '', + bindfail: '', + bindcancel: '' +} + +const Navigator = { + target: singleQuote('self'), + url: '', + 'open-type': singleQuote('navigate'), + delta: '1', + 'app-id': '', + path: '', + 'extra-data': '', + version: singleQuote('version'), + 'hover-class': singleQuote('navigator-hover'), + 'hover-stop-propagation': 'false', + 'hover-start-time': '50', + 'hover-stay-time': '600', + bindsuccess: '', + bindfail: '', + bindcomplete: '' +} + +const Audio = { + id: '', + src: '', + loop: 'false', + controls: 'false', + poster: '', + name: '', + author: '', + binderror: '', + bindplay: '', + bindpause: '', + bindtimeupdate: '', + bindended: '' +} + +const specialEvents = new Set([ + 'htouchmove', + 'vtouchmove' +]) + +const Camera = { + mode: singleQuote('normal'), + 'device-position': singleQuote('back'), + flash: singleQuote('auto'), + 'frame-size': singleQuote('medium'), + bindstop: '', + binderror: '', + bindinitdone: '', + bindscancode: '' +} + +const Image = { + src: '', + mode: singleQuote('scaleToFill'), + webp: 'false', + 'lazy-load': 'false', + 'show-menu-by-longpress': 'false', + binderror: '', + bindload: '' +} + +const LivePlayer = { + src: '', + mode: singleQuote('live'), + autoplay: 'false', + muted: 'false', + orientation: singleQuote('vertical'), + 'object-fit': singleQuote('contain'), + 'background-mute': 'false', + 'min-cache': '1', + 'max-cache': '3', + 'sound-mode': singleQuote('speaker'), + 'auto-pause-if-navigate': 'true', + 'auto-pause-if-open-native': 'true', + bindstatechange: '', + bindfullscreenchange: '', + bindnetstatus: '' } -export const standComponents = { - view, - image, - text, - button, - input +interface Components { + [key: string]: Record; } + +function createComponents (components: Components) { + const result: Components = Object.create(null) + + for (const key in components) { + if (hasOwn(components, key)) { + const component = components[key] + const compName = toDashed(key) + const newComp: Record = Object.create(null) + for (const prop in component) { + if (hasOwn(component, prop)) { + let propValue = component[prop] + if (prop.startsWith('bind') || specialEvents.has(prop)) { + propValue = 'eh' + } else if (propValue === '') { + propValue = `i.${toCamelCase(prop)}` + } else { + propValue = `i.${toCamelCase(prop)} || ${propValue}` + } + + newComp[prop] = propValue + } + } + Object.assign(newComp, common) + result[compName] = newComp + } + } + + return result +} + +export const standComponents = createComponents({ + View, + Icon, + Progress, + RichText, + Text, + Button, + Checkbox, + CheckboxGroup, + Editor, + Form, + Input, + Label, + Picker, + PickerView, + PickerViewColumn, + Radio, + RadioGroup, + Slider, + Switch, + CoverImage, + Textarea, + CoverView, + MoveableArea, + MoveableView, + ScrollView, + Swiper, + SwiperItem, + FunctionalPageNavigator, + Navigator, + Audio, + Camera, + Image, + LivePlayer +}) diff --git a/packages/mini-app-webpack-plugin/tsconfig.json b/packages/mini-app-webpack-plugin/tsconfig.json index df809391d264..30e6e5573510 100644 --- a/packages/mini-app-webpack-plugin/tsconfig.json +++ b/packages/mini-app-webpack-plugin/tsconfig.json @@ -16,7 +16,10 @@ "sourceMap": true, "baseUrl": ".", "rootDir": ".", - "allowJs": true + "allowJs": true, + "paths": { + "@tarojs/shared": ["../shared/src"] + } }, "include": ["src", "src/tmpl/*.json"], "exclude": [ diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index 4f3ddf123863..105c7f9b0944 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -56,3 +56,28 @@ export const box = (v: T) => ({ v }) * @returns Value. */ export const unbox = (b: Box) => b.v + +export function toDashed (s: string) { + return s.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase() +} + +export function toCamelCase (s: string) { + let camel = '' + let nextCap = false + for (let i = 0; i < s.length; i++) { + if (s[i] !== '-') { + camel += nextCap ? s[i].toUpperCase() : s[i] + nextCap = false + } else { + nextCap = true + } + } + return camel +} + +const hasOwnProperty = Object.prototype.hasOwnProperty + +export const hasOwn = ( + val: object, + key: string | symbol +) => hasOwnProperty.call(val, key) diff --git a/packages/taro-runtime/src/dom/element.ts b/packages/taro-runtime/src/dom/element.ts index c2252eb24dc0..8e935f36af8f 100644 --- a/packages/taro-runtime/src/dom/element.ts +++ b/packages/taro-runtime/src/dom/element.ts @@ -11,7 +11,7 @@ interface Attributes { } export class TaroElement extends TaroNode { - private props: Record = {} + public props: Record = {} public tagName: string diff --git a/packages/taro-runtime/src/dom/style.ts b/packages/taro-runtime/src/dom/style.ts index 4388baf69e1e..54325240f252 100644 --- a/packages/taro-runtime/src/dom/style.ts +++ b/packages/taro-runtime/src/dom/style.ts @@ -1,24 +1,7 @@ -import { isUndefined } from '@tarojs/shared' +import { isUndefined, toCamelCase, toDashed } from '@tarojs/shared' import { styleProperties } from './style_properties' import { TaroElement } from './element' -function toDashed (s: string) { - return s.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase() -} -function toCamelCase (s: string) { - let camel = '' - let nextCap = false - for (let i = 0; i < s.length; i++) { - if (s[i] !== '-') { - camel += nextCap ? s[i].toUpperCase() : s[i] - nextCap = false - } else { - nextCap = true - } - } - return camel -} - export class Style { private _usedStyleProp: Set diff --git a/packages/taro-runtime/src/render.ts b/packages/taro-runtime/src/render.ts index f7fc17c2c58e..86d595f0e963 100644 --- a/packages/taro-runtime/src/render.ts +++ b/packages/taro-runtime/src/render.ts @@ -17,6 +17,7 @@ export function hydrate (node: TaroElement | TaroText) { } return { + ...node.props, cn: node.childNodes.map(hydrate), nodeName: node.nodeName, cl: node.className,